You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测Delphi 10.1 VCL中TListView组标题的点击事件?

在Delphi 10.1 VCL中检测TListView组标题的单击/双击操作

在Delphi 10.1的VCL环境里,TListView默认并没有直接提供组标题的点击事件,不过我们可以通过两种可靠的方式来实现检测:

方法一:拦截原生Windows消息(最精准)

TListView本质是封装了Windows的SysListView32控件,我们可以通过重写它的WndProc来拦截WM_NOTIFY消息,判断点击是否发生在组标题上。

实现步骤:

  1. 在你的窗体类中,重写目标ListView的WndProc方法(或者创建自定义TListView子类)。
  2. 检测NM_CLICK(单击)和NM_DBLCLK(双击)通知,判断点击对象是否为组标题。

代码示例:

procedure TForm1.ListView1WndProc(var Message: TMessage);
var
  pNMItemActivate: PNMITEMACTIVATE;
  pHdr: PNMHDR;
begin
  inherited; // 先让默认消息处理执行

  if Message.Msg = WM_NOTIFY then
  begin
    pHdr := PNMHDR(Message.LParam);
    // 处理单击事件
    if pHdr.code = NM_CLICK then
    begin
      pNMItemActivate := PNMITEMACTIVATE(Message.LParam);
      // 组标题被点击时,iItem会是-1,iGroupId对应组的ID
      if pNMItemActivate.iItem = -1 then
      begin
        if pNMItemActivate.iGroupId >= 0 and pNMItemActivate.iGroupId < ListView1.Groups.Count then
        begin
          ShowMessage(Format('单击了组:%s', [ListView1.Groups[pNMItemActivate.iGroupId].Header]));
          // 这里添加你要执行的逻辑
        end;
      end;
    end
    // 处理双击事件
    else if pHdr.code = NM_DBLCLK then
    begin
      pNMItemActivate := PNMITEMACTIVATE(Message.LParam);
      if pNMItemActivate.iItem = -1 then
      begin
        if pNMItemActivate.iGroupId >= 0 and pNMItemActivate.iGroupId < ListView1.Groups.Count then
        begin
          ShowMessage(Format('双击了组:%s', [ListView1.Groups[pNMItemActivate.iGroupId].Header]));
          // 这里添加你要执行的逻辑
        end;
      end;
    end;
  end;
end;

方法二:利用VCL的HitTest方法(更直观)

VCL提供了HitTest方法可以检测鼠标点击的区域,我们可以结合OnMouseUp和OnDblClick事件来判断是否点击了组标题。

实现步骤:

  1. 给ListView绑定OnMouseUp(检测单击)和OnDblClick(检测双击)事件。
  2. 在事件中获取鼠标位置,调用HitTest判断是否命中组标题,再通过GetGroupAtPos获取对应组。

代码示例:

// 检测单击
procedure TForm1.ListView1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  HitInfo: THitTests;
  GroupIdx: Integer;
begin
  if Button = mbLeft then
  begin
    HitInfo := ListView1.HitTest(Point(X, Y));
    if htGroupHeader in HitInfo then
    begin
      GroupIdx := ListView1.GetGroupAtPos(Point(X, Y));
      if GroupIdx <> -1 then
      begin
        ShowMessage(Format('单击了组:%s', [ListView1.Groups[GroupIdx].Header]));
        // 添加自定义逻辑
      end;
    end;
  end;
end;

// 检测双击
procedure TForm1.ListView1DblClick(Sender: TObject);
var
  MousePos: TPoint;
  HitInfo: THitTests;
  GroupIdx: Integer;
begin
  MousePos := ListView1.ScreenToClient(Mouse.CursorPos);
  HitInfo := ListView1.HitTest(MousePos);
  if htGroupHeader in HitInfo then
  begin
    GroupIdx := ListView1.GetGroupAtPos(MousePos);
    if GroupIdx <> -1 then
    begin
      ShowMessage(Format('双击了组:%s', [ListView1.Groups[GroupIdx].Header]));
      // 添加自定义逻辑
    end;
  end;
end;

注意事项

  • 确保你的ListView的ViewStyle设置为支持分组的样式(比如vsReport、vsList等),并且已经正确添加了TListViewGroup。
  • 方法一的消息拦截方式更可靠,不会受鼠标事件的其他干扰;方法二代码更简洁直观,适合快速实现。

内容的提问来源于stack exchange,提问作者Reron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:41:22