如何检测鼠标点击 TListView 组 header?
How to detect a mouse click on a TListView Group header?
我正在使用 Delphi 10.1 和 VCL。如何检测 TListView
中组 header 上的点击或 double-click?不在列 header.
子类化 ListView 以捕获与点击相关的消息(WM_LBUTTON(DOWN|UP)
、WM_LBUTTONDBLCLK
等),然后向 ListView 发送一条 LVM_HITTEST
消息,指定点击的客户端坐标。
根据文档,您必须将消息的 wParam
设置为 -1 才能获取组信息,这意味着您必须通过直接调用 SendMessage()
来发送 LVM_HITTEST
消息,您不能使用 ListView_HitTest()
函数,它将 wParam
设置为 0.
单击组 header 时,填充的 LVHITTESTINFO
将启用 LVHT_EX_GROUP_HEADER
标志,iItem
字段将成为组索引。
答案基于 Remy 和 Victoria 的评论,以及 Bummi 在 https://www.entwickler-ecke.de/topic_ListViewEigenschaften+Delphi+vs+C+SubItems+auslesen_110307,0.html 的旧答案。
对解决方案的评论很少:
- 子类是一个选项,但也可以使用 Form 的 ListView1MouseDown 事件来实现,这会稍微简单一些。
tLVHitTestInfo & LVM_HITTEST 定义在 Winapi.CommCtrl.
Uses
Winapi.CommCtrl; // For LVM_HITTEST
LVHT_EX_GROUP_HEADER 值应手动定义。我没有在任何 Delphi 单元中找到它。它是单击组 header 的标识符。应使用 LVHitTestInfo.flags 进行验证。它适用于 Windows Vista 及更高版本。
const
LVHT_EX_GROUP_HEADER = 000000;
LVHitTestInfo.iGroup 不行!我不知道原因。本来我以为应该是Group索引
例子中有一个窗体,上面有ListView,样式为ViewStyle = vsReport。鼠标单击组 header 将调用带有组索引的消息对话框。详细代码如下:
Uses Winapi.CommCtrl;
procedure TForm1.ListView1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
const
LVHT_EX_GROUP_HEADER = 000000; // 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;
我正在使用 Delphi 10.1 和 VCL。如何检测 TListView
中组 header 上的点击或 double-click?不在列 header.
子类化 ListView 以捕获与点击相关的消息(WM_LBUTTON(DOWN|UP)
、WM_LBUTTONDBLCLK
等),然后向 ListView 发送一条 LVM_HITTEST
消息,指定点击的客户端坐标。
根据文档,您必须将消息的 wParam
设置为 -1 才能获取组信息,这意味着您必须通过直接调用 SendMessage()
来发送 LVM_HITTEST
消息,您不能使用 ListView_HitTest()
函数,它将 wParam
设置为 0.
单击组 header 时,填充的 LVHITTESTINFO
将启用 LVHT_EX_GROUP_HEADER
标志,iItem
字段将成为组索引。
答案基于 Remy 和 Victoria 的评论,以及 Bummi 在 https://www.entwickler-ecke.de/topic_ListViewEigenschaften+Delphi+vs+C+SubItems+auslesen_110307,0.html 的旧答案。
对解决方案的评论很少:
- 子类是一个选项,但也可以使用 Form 的 ListView1MouseDown 事件来实现,这会稍微简单一些。
tLVHitTestInfo & LVM_HITTEST 定义在 Winapi.CommCtrl.
Uses Winapi.CommCtrl; // For LVM_HITTEST
LVHT_EX_GROUP_HEADER 值应手动定义。我没有在任何 Delphi 单元中找到它。它是单击组 header 的标识符。应使用 LVHitTestInfo.flags 进行验证。它适用于 Windows Vista 及更高版本。
const LVHT_EX_GROUP_HEADER = 000000;
LVHitTestInfo.iGroup 不行!我不知道原因。本来我以为应该是Group索引
例子中有一个窗体,上面有ListView,样式为ViewStyle = vsReport。鼠标单击组 header 将调用带有组索引的消息对话框。详细代码如下:
Uses Winapi.CommCtrl;
procedure TForm1.ListView1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
const
LVHT_EX_GROUP_HEADER = 000000; // 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;