如何检测TListView组标题的鼠标单击事件?

3

我正在使用Delphi 10.1和VCL。如何检测单击或双击TListView中的组标题?不是列标题。

2个回答

5
继承ListView以捕获与点击相关的消息(WM_LBUTTON(DOWN|UP)WM_LBUTTONDBLCLK等),然后向ListView发送LVM_HITTEST消息,指定点击的客户端坐标。
根据文档,您必须将消息的wParam设置为-1以获取组信息,这意味着您必须通过直接调用SendMessage()来发送LVM_HITTEST消息,不能使用设置wParam为0的ListView_HitTest()函数。
当单击组标题时,填充的LVHITTESTINFO将启用LVHT_EX_GROUP_HEADER标志,并且iItem字段将是组索引。

我还没有测试过,但你确定当组标题被点击时,列表视图会接收到像“NM_CLICK”这样的通知吗? - Victoria
@Victoria 我还没有测试过,所以我不确定。这就是为什么我也提到了其他消息。 - Remy Lebeau
1
@Victoria 我刚测试了一下,确实在单击组标题时不会发出 NM_CLICKNM_DBCLK,但是会发出 WM_LBUTTON(DOWN|UP) - Remy Lebeau

1

这个答案基于Remy和Victoria的评论,以及Bummi在https://www.entwickler-ecke.de/topic_ListViewEigenschaften+Delphi+vs+C+SubItems+auslesen_110307,0.html上的旧答案。

对于解决方案,有几点评论:

  1. 子类化是一种选择,但也可以使用表单的ListView1MouseDown事件来实现,这样会更简单一些。
  2. tLVHitTestInfo和LVM_HITTEST在Winapi.CommCtrl中定义。

    Uses
      Winapi.CommCtrl; // For LVM_HITTEST
    
  3. LVHT_EX_GROUP_HEADER值应该手动定义。我没有在任何Delphi单元中找到它。它是组标题被点击的标识符。它应该通过LVHitTestInfo.flags进行验证。它适用于Windows Vista及以上版本。

    const
      LVHT_EX_GROUP_HEADER = $10000000;
    
  4. LVHitTestInfo.iGroup不起作用!我不知道原因。最初,我认为它应该是组索引。

这个例子有一个带有ListView的表单,样式为ViewStyle = vsReport。单击组标题将调用一个带有组索引的消息对话框。以下是详细的代码:

    Uses Winapi.CommCtrl;

    procedure TForm1.ListView1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    const
      LVHT_EX_GROUP_HEADER = $10000000; // It is Valid for Windows Vista and above.
    var
      HTI: tLVHitTestInfo; // Defined on Winapi.CommCtrl
      nGroupInx: integer;
    begin
      HTI.pt     := point(X, Y); // Add cursor position
      nGroupInx  := SendMessage(ListView1.Handle, LVM_HITTEST, -1, LPARAM(@HTI)); // Return an Item
      if nGroupInx <> -1 then // Is an Item found?
        if (HTI.flags and LVHT_EX_GROUP_HEADER) = LVHT_EX_GROUP_HEADER then // Is it a Group Header?
            ShowMessage('Clicked Group header:' + ' ' + nGroupInx.ToString);
    end;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接