通过TTreeView触发TTreeView(在TForm上)触发TTreeView OnChange事件

时间:2017-04-25 11:40:06

标签: c++ c++builder vcl

使用Borland C ++ Builder

我有一个带有自创的Breadcrumb控件的应用程序,位于TTreeView控件上方,TListView控件(alClient内部TForms)作为下拉菜单。< / p>

enter image description here

控件的位置是新的。意思是,实现更旧,之前工作得很好,但我只是将面包屑控件移到TTreeView控件之上。

现在我注意到点击面包屑控件中的TListView项,会触发TTreeView OnChange事件! 并且所选节点是顶级节点。

这导致我的设计发生冲突,因为TListView项目点击和TTreeView Onchange两个事件都会导致显示/完成不同的事情。 它也不是100%哪个事件最终会赢得&#39;所以结果也是可变的。

我可以尝试在执行面包屑代码时尝试禁用TTreeView,以便忽略点击,但我想知道这是正常的还是我错过了什么?

两个控件在相互显示时触发是否正常?

ListView项目点击是通过以下功能分配的OnClick事件处理的:

void __fastcall TBreadcrumbListViewEx::InternalListViewClick(TObject *Sender)
{

if (FListView->Selected && FOnBreadcrumbListItemClick)
    {
    TPoint pt;
    pt = FListView->ScreenToClient(Mouse->CursorPos);

    THitTests HitTests = FListView->GetHitTestInfoAt(pt.x, pt.y);
    if ( (HitTests.Contains(htOnIcon)) || (HitTests.Contains(htOnItem)) ||
         (HitTests.Contains(htOnLabel)) || (HitTests.Contains(htOnStateIcon)) )
        {
        // This is a very precarious situation, because the FOnBreadcrumbListItemClick callback will most likely trigger building a new Breadcrumbs layout (Different Items)
        // Which causes OnData events from this control to want to access Breadcrumbs that have been deleted already
        // Therefore, get the selected Item (which will trigger OnData) and use its Index and Data members

        TListItem *Item = FListView->Selected ;

        // Next prevent any OnData event to get through and wreak havoc
        // This needs to be done *before* Hide() is called

        _releasing = true ;

        // Hide is necesary because if the FOnBreadcrumbListItemClick event takes a long time, for instance it shows a dialog,
        // this control will still be visible, yet it cannot show proper content anymore, since the OnData event is disabled
        // Hence Hide() to no show it anymore when, for instance, a dialog is showing

        Hide() ;

        FOnBreadcrumbListItemClick(this, Item->Index, BreadcrumbItem, Item->Data);

        Release(); // Close();
        }
    }

}

我一直在进行测试。 首先,我禁用了事件/回调FOnBreadcrumbListItemClick(),但问题仍然存在,即使单击该项目时没有发生任何事情。 我一直在玩Hide()Release(),将Release()替换为Close()等。但如果其中一个仍然存在,问题仍然存在。

只有当我同时停用Hide()Release() / Close()时,我似乎才会遇到麻烦。只有这样我才在测试中看不到TTreeView OnChange。说实话,我现在不再确定任何事情了。

这是你所期望的吗?或者这仅仅是副作用,问题仍然是其他问题?

另外......我将如何能够执行回调并隐藏/删除视图中的弹出窗口,而不会让人感到沮丧。 TTreeView

暂时停用TTreeView仍然是一种选择,但我宁愿解决此问题,也不要在下次将控件移动到其他位置时再次遇到麻烦。

1 个答案:

答案 0 :(得分:1)

我最后通过在队列末尾发布消息来“修复”它,以便TListView OnClick事件尽可能快地完成,从而完全吸收鼠标事件,在Hide()事件期间避免Release()OnClick

void __fastcall TBreadcrumbListViewEx::InternalListViewClick(TObject *Sender)
{

if (FListView->Selected && FOnBreadcrumbListItemClick)
    {
    TPoint pt = FListView->ScreenToClient(Mouse->CursorPos);

    THitTests HitTests = FListView->GetHitTestInfoAt(pt.x, pt.y);
    if ( (HitTests.Contains(htOnIcon)) || (HitTests.Contains(htOnItem)) ||
         (HitTests.Contains(htOnLabel)) || (HitTests.Contains(htOnStateIcon)) )
        {
        PostMessage(Handle /*Destination*/, WM_APP, 0, (LPARAM)FListView->Selected);
        }
    }

}

//------------

void __fastcall TBreadcrumbListViewEx::WmApp(TMessage &Msg)
{

TListItem *ClickedItem = (TListItem*)Msg.LParam ;

if (ClickedItem)
    {

    // Next prevent any more OnData events to get through and wreak havoc
    // This needs to be done *before* Hide() is called

    _releasing = true ;

    // Hide is necesary because if the FOnBreadcrumbListItemClick event takes a long time, for instance it shows a dialog,
    // this control will still be visible, yet it cannot show proper content anymore, since the OnData event is disabled
    // Hence Hide() to no show it anymore when, for instance, a dialog is showing

    Hide() ;

    // Disable the entire breadcrumb control to avoid clicks while a dialog is up or during a lengthy process to get the data for next
    // breadcrumb layout

    BBar->Enabled = false ;

    FOnBreadcrumbListItemClick(this, ClickedItem->Index, BreadcrumbItem, ClickedItem->Data);

    BBar->Enabled = true ;

    Release();
    }

}
相关问题