delphi - 如何检测没有焦点的控件中的修改键更改?

标签 delphi winapi delphi-xe3

背景:

我正在开发一个从 TCustomControl 类派生的控件,它可以获得焦点并且内部有一些内部元素。如果用户将光标悬停在这些内部元素上,这些内部元素就会突出显示,您可以选择它们、移动它们等等。现在来解决问题...

问题:

如果用户按住 CTRLALTSHIFT 修饰符,我将对(比方说)聚焦元素执行不同的操作。我想要的是,如果用户将鼠标悬停在元素上并按住 CTRL 键,则更改鼠标光标。非常简单,您只需重写 KeyDownKeyUp 方法并检查它们的 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/

相关文章:

winapi - FindWindow 错误 183

Delphi XE3 - 无法连接字符串

winapi - 检测前景窗口何时发生变化

c - 用户模式钩子(Hook)的检测

delphi - Delphi key 'Known Packages' 中的 key 顺序重要吗?

Delphi Statictext字体颜色变化无样式

mysql - 从 Delphi XE3 连接到嵌入式 MySQL

delphi - 在运行时创建自定义标题栏和边框,TMainMenu 起作用

delphi - 我如何知道使用了哪种 SASL 机制?

delphi - IDE 期望文件位于不同位置