如何获取控件内鼠标指针的坐标

问题描述 投票:0回答:1

我有一个

TPopupMenu
,其中一个项目应该(在执行其他操作之后)选择鼠标光标所在的
TChecklistBox
(类别过滤器)的项目。目前我使用以下代码执行此操作,但这不准确,因为它选择下一个 or 2ndnext 项目!

var
  ClickedItem: Integer;
  CategoryFilter: TChecklistBox;
begin
  CategoryFilter.CheckAll(cbUnchecked, FALSE, FALSE);
  ClickedItem := CategoryFilter.ItemAtPos(Mouse.CursorPos.Subtract(CategoryFilter.ClientOrigin), TRUE);
  if ClickedItem > -1 then
    CategoryFilter.Checked[ClickedItem] := TRUE;
end;

如何解决这个问题并获得正确的项目,鼠标悬停?

delphi mouse cursor-position delphi-10.4-sydney
1个回答
0
投票

这里重要的是,鼠标的屏幕坐标 (x, y) 右键单击列表项时 通常与单击时的鼠标屏幕坐标 (x', y') 不同(或以其他方式调用)菜单项。我的意思是,您经常将鼠标移动到菜单项以单击它。所以你需要在鼠标按下时保存坐标。

幸运的是,VCL 可以为您做到这一点。弹出菜单的

PopupPoint
属性包含这些坐标。

所以你可以做

procedure TForm1.MenuItem1Click(Sender: TObject);
begin
  var LIdx := CheckListBox1.ItemAtPos
    (
      CheckListBox1.ScreenToClient(PopupMenu1.PopupPoint),
      True
    );
  if LIdx <> -1 then
    CheckListBox1.Checked[LIdx] := True;
end;

实际上,我自己基本上就是这么做的:

请注意,您还应该确保右键单击某个项目也会选择(而不是选中)它。否则用户体验很差。

这样您就可以简单地使用

ItemIndex
属性来查找单击的项目,因此您根本不需要
PopupPoint

for var i := 0 to Count - 1 do
  Checked[i] := i = ItemIndex; // check only this one

我还编写了代码,以便双击某个项目可以切换其复选框。

© www.soinside.com 2019 - 2024. All rights reserved.