MFC树控制通知触发两次

MFC tree control notification is triggered twice

本文关键字:两次 控制 通知 MFC      更新时间:2023-10-16

我的问题是下面的函数被调用了两次:

ON_NOTIFY(TVN_SELCHANGED, IDC_TREE1, &MainHamsterDlg::OnClickTree)
void MainHamsterDlg::OnClickTree(NMHDR* pNMHDR, LRESULT* pResult)
{
    CTreeCtrl* pCtrl = (CTreeCtrl*)GetDlgItem(IDC_TREE1);
    HTREEITEM hItem = pCtrl->GetSelectedItem();
    BOOL hItemm = pCtrl->ItemHasChildren(hItem);
    if (hItem && hItemm)
    {
        HTREEITEM hChild = pCtrl->GetChildItem(hItem);
        pCtrl->SelectItem(hChild);                           <--- Cause of the "loop"
    }
    *pResult = 1;
}

我需要我的代码自动转到树的子元素。(以后我会写一些代码来检测被选中的是什么,这会导致一些动作。)

当我点击一个叶子时,我的代码可以正常工作,因为:

if (hItem && hItemm)

确保:

pCtrl->SelectItem(hChild);

不会被执行。当单击内部节点时,如何使代码工作?

我知道这是一个肮脏的hack,但它应该防止你的代码被执行两次。向类中添加以下成员:

bool ignoreNextSelChange = false;

然后修改函数如下:

void MainHamsterDlg::OnClickTree(NMHDR* pNMHDR, LRESULT* pResult)
{
    if (ignoreNextSelChange)
    {
        // Don't do anything, but make sure that the else block below will be executed
        // again with the next (expected) call of this function.
        ignoreNextSelChange = false;
    }
    else
    {
        CTreeCtrl* pCtrl = (CTreeCtrl*)GetDlgItem(IDC_TREE1);
        HTREEITEM hItem = pCtrl->GetSelectedItem();
        BOOL hItemm = pCtrl->ItemHasChildren(hItem);
        if (hItem && hItemm)
        {
            HTREEITEM hChild = pCtrl->GetChildItem(hItem);
            // Make sure that this else block won't be executed again when the function
            // SelectItem() is called below.
            ignoreNextSelChange = true;
            pCtrl->SelectItem(hChild);
        }
    }
    *pResult = 1;
}

最后我找到了一些代码,在那里我解决了一个类似的问题。在该代码中,我处理了TVN_SELCHANGING而不是TVN_SELCHANGED:

ON_NOTIFY(TVN_SELCHANGING, IDC_TREE1, &MainHamsterDlg::OnSelChanging)
void MainHamsterDlg::OnSelChanging(NMHDR* pNMHDR, LRESULT* pResult)
{
    // Initially assume that the selection change is allowed.
    *pResult = 0;
    CTreeCtrl* pCtrl = (CTreeCtrl*)GetDlgItem(IDC_TREE1);
    HTREEITEM hItem = pCtrl->GetSelectedItem();
    BOOL hItemm = pCtrl->ItemHasChildren(hItem);
    if (hItem && hItemm)
    {
        // Set *pResult to TRUE to prevent the selection from changing.
        *pResult = TRUE;
        // Make an own selection.
        HTREEITEM hChild = pCtrl->GetChildItem(hItem);
        pCtrl->SelectItem(hChild);
    }
}

TVN_SELCHANGING消息处理程序中调用SelectItem()不会对我造成问题。