我有一个
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;
如何解决这个问题并获得正确的项目,鼠标悬停?
这里重要的是,鼠标的屏幕坐标 (x, y) 右键单击列表项时 通常与单击时的鼠标屏幕坐标 (x', y') 不同(或以其他方式调用)菜单项。我的意思是,您经常将鼠标移动到菜单项以单击它。所以你需要在鼠标按下时保存坐标。
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
我还编写了代码,以便双击某个项目可以切换其复选框。