My problem is that the following function is called twice:

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

I need my code to automatically go to a child element of the tree. (In future I will write some code to detect what has been selected and it will cause some actions.)

My code works correctly when I click on a leaf, because:

if (hItem && hItemm)

ensures that:

pCtrl->SelectItem(hChild);

won't be executed. How can I make my code work when an internal node is clicked?

有帮助吗?

解决方案

I know this is a dirty hack, but it should prevent your code from being executed twice. Add the following member to your class:

bool ignoreNextSelChange = false;

Then modify your function as follows:

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

其他提示

Eventually I found some code where I solved a similar problem. In that code I handled TVN_SELCHANGING instead of 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);
    }
}

Calling SelectItem() in the TVN_SELCHANGING message handler doesn't cause a problem for me.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top