【问题标题】:MFC tree control notification is triggered twiceMFC树控件通知被触发两次
【发布时间】:2014-03-12 13:12:40
【问题描述】:

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

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

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

【问题讨论】:

    标签: c++ loops mfc treecontrol


    【解决方案1】:

    我知道这是一个肮脏的 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;
    }
    

    【讨论】:

    • 是的,我正在考虑那个解决方案......也许我必须使用它......也许有人会写出更好的解决方案,但现在对我来说还可以。谢谢
    【解决方案2】:

    最终我找到了一些解决类似问题的代码。在该代码中,我处理了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() 不会对我造成问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-26
      • 1970-01-01
      • 1970-01-01
      • 2011-03-05
      • 1970-01-01
      • 2011-04-28
      • 1970-01-01
      相关资源
      最近更新 更多