背景:
我正在开发一个从 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 键会怎样?这不会为我的控件生成任何鼠标移动或按键事件,还是我错了?嗯,所以我的问题很明显......
问题:
如果控件没有焦点并且用户不移动鼠标,如何检测修改键的更改?我正在考虑这两个选项,但我希望我错过了一些东西:
- 键盘 Hook - 可靠,但对我来说看起来有点过分
- 使用计时器定期检查修改器状态 - 我无法忍受延迟
那么,如何检测当前未聚焦的控件的修饰键更改?
最佳答案
如果你的控件没有获得焦点,它自己的按键事件将不会被触发。但是,您可以做的是让您的控件实例化一个私有(private) TApplicationEvents
内部组件,并使用其 OnMessage
event 用于检测从主消息队列检索的关键事件,然后再将其分派(dispatch)到任何控件进行处理。然后,您可以检查鼠标是否位于您的控件上方(最好使用 GetMessagePos()
而不是 GetCursorPos()
或 Screen.CursorPos
,以便您在生成消息的时间,以防消息延迟)并根据需要更新控件自己的 Cursor
属性(而不是 Screen.Cursor
属性)。
关于delphi - 如何检测没有焦点的控件中的修改键更改?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19570880/