使用Borland C ++ Builder
我有一个带有自创的Breadcrumb控件的应用程序,位于TTreeView
控件上方,TListView
控件(alClient
内部TForms
)作为下拉菜单。< / p>
控件的位置是新的。意思是,实现更旧,之前工作得很好,但我只是将面包屑控件移到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
仍然是一种选择,但我宁愿解决此问题,也不要在下次将控件移动到其他位置时再次遇到麻烦。
答案 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();
}
}