c++ - 在 TTreeView 上点击 TListView(在 TForm 上)触发 TTreeView OnChange 事件

标签 c++ c++builder vcl

使用 Borland C++ Builder

我有一个带有自行创建的 Breadcrumb 控件的应用程序,位于 TTreeView 控件之上,带有 TListView 控件(alClientTForms) 作为下拉菜单。

enter image description here

控件的位置是新的。意思是,该实现较旧,并且之前运行良好,但我只是将面包屑控件移动到 TTreeView 控件之上。

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

这在我的设计中引起了冲突,因为 TListView 项目点击和 TTreeView Onchange 导致显示不同的东西/完毕。 哪个事件最终“获胜”也不是 100%,因此结果也是可变的。

我可以考虑尝试在执行面包屑代码时禁用 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 发生。老实说,我现在什么都不确定了。

这是您所期望的吗?或者这仅仅是副作用,问题仍然存在?

另外......我怎么才能执行回调并从 View 中隐藏/删除弹出窗口,而不会“扰乱”TTreeView

暂时禁用 TTreeView 仍然是一个选项,但我宁愿解决这个问题,以免下次我将控件移动到其他位置时再次遇到麻烦。

最佳答案

我最终通过将消息发布到队列末尾来“修复”它,以便 TListView OnClick 事件可以尽快完成,这样通过在 OnClick 事件期间避免 Hide()Release(),鼠标事件被完全吸收。

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

}

关于c++ - 在 TTreeView 上点击 TListView(在 TForm 上)触发 TTreeView OnChange 事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43609664/

相关文章:

c++ - 使用 C++ Builder 10 西雅图时出现很多歧义错误

用于原生 C++ 开发的 C++ Builder 或 Visual Studio?

windows - 在 Delphi 2K9 中运行时禁用和启用组件。奇怪的问题

delphi - Delphi 6中带有自定义TRadioButton控件的TRadioGroup吗?

delphi - 让 C++Builder/Delphi 在启动时创建 TForms,还是手动创建?

c++ - QListWidget,为较长的文本插入换行符

C++ 根据条件初始化变量

java - 具有延迟初始化的随机数数组

c++ - 贾拉利日历

c++ - 如何在 C++ 中使用 dll 文件?