【发布时间】:2013-11-03 10:51:36
【问题描述】:
背景:
我正在开发一个从TCustomControl 类派生的控件,它可以获取焦点并且里面有一些内部元素。如果用户将光标悬停在这些内部元素上,它们就会突出显示,您可以选择它们、移动它们等等。现在问题来了……
问题:
如果用户持有 CTRL、ALT 或 SHIFT 修饰符,我将使用(假设)聚焦元素执行不同的操作。如果用户悬停元素并按住例如 CTRL 键,我想要更改鼠标光标。非常简单,您只需覆盖KeyDown 和KeyUp 方法并检查它们的Key 参数是否等于VK_CONTROL。在这样的代码中:
procedure TMyCustomControl.KeyDown(var Key: Word; Shift: TShiftState);
begin
inherited;
if Key = VK_CONTROL then
Screen.Cursor := crSizeAll;
end;
procedure TMyCustomControl.KeyUp(var Key: Word; Shift: TShiftState);
begin
inherited;
if Key = VK_CONTROL then
Screen.Cursor := crDefault;
end;
即使这不是检查 CTRL 键是否被按下和释放的最佳方法(例如,由于现有的 Shift 状态参数),它仍按预期工作有焦点,甚至可以得到,但是……
我的目标是在用户将鼠标悬停在控件(或者准确地说,是其中的某个元素)并按住时更改鼠标光标。即使我的控件没有焦点,该 CTRL 键也是如此。可以说,所以只需覆盖MouseMove 方法并在那里请求修饰符状态。本来就是这样,但是……
如果用户将鼠标光标停留在我的控件上并按下并释放 CTRL 键会怎样?这不会为我的控件生成任何鼠标移动或按键事件,还是我错了?好吧,所以我的问题很明显......
问题:
如果控件没有焦点并且用户没有用鼠标移动,我如何检测修饰键的变化?我正在考虑这两个选项,但我希望我错过了一些东西:
- 键盘挂钩 - 可靠,但对我来说看起来有点矫枉过正
- 使用计时器定期检查修饰符状态 - 我无法忍受延迟
那么,您将如何检测当前未聚焦的控件的修饰键更改?
【问题讨论】:
-
很明显你的子控件是windowed的。您可以让您的控件的子级通知其父级键盘事件。
-
@Andreas,对不起,也许我没有正确理解您的评论...如果您的意思是我提到的那些元素,不。它们只是虚拟的。只有一个窗口控件,需要知道鼠标悬停时修改键的变化。但现在我在想。甚至父表单也不需要处于活动状态,因此可能没有比键盘钩子“更好”的解决方案。
-
似乎您已经知道 2 个解决方案,而且很可能没有更好的解决方案。如果您将通过计时器检查修饰符的状态(仅在鼠标进入/离开事件之间需要计时器)假设每秒 50 次,用户将无法感受到延迟,所以我想它比系统更简单和更稳定-宽键盘挂钩。
-
@Andrei,你是对的。 20ms 的间隔不会有人注意到。而且我可以在鼠标进入控件并且控件没有聚焦时启用它。键盘钩子真的是矫枉过正。当我写这个问题时,我只是忘记了应用程序不活跃的情况。谢谢大家!
标签: delphi winapi delphi-xe3