MFC树控件通知被触发两次

时间:2014-03-12 13:12:40

标签: c++ loops mfc treecontrol

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

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);

不会被执行。如何在单击内部节点时使代码生效?

2 个答案:

答案 0 :(得分:2)

我知道这是一个肮脏的黑客,但它应该阻止你的代码被执行两次。将以下成员添加到您的班级:

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;
}

答案 1 :(得分: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);
    }
}

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