TApplicationEvents.OnShortCut:仅检测带有修饰键的键?

Posted

技术标签:

【中文标题】TApplicationEvents.OnShortCut:仅检测带有修饰键的键?【英文标题】:TApplicationEvents.OnShortCut: Detect only Keys with modifier-key? 【发布时间】:2021-12-22 02:57:11 【问题描述】:

我将 Delphi 11 Alexandria 中的 TApplicationEvents.OnShortCut 事件与 Windows 10 中的 Delphi VCL 应用程序一起使用,例如:

procedure TformMain.ApplicationEvents1ShortCut(var Msg: TWMKey; var Handled: Boolean);
begin
  CodeSite.Send('TformMain.ApplicationEvents1ShortCut: Msg.CharCode', Msg.CharCode);
end;

不幸的是,即使没有按下修饰键也会触发此事件,例如单独使用“V”键或“B”键。当没有按下修饰键时如何退出此事件处理程序,例如:

procedure TformMain.ApplicationEvents1ShortCut(var Msg: TWMKey; var Handled: Boolean);
begin
  if NoModifierKeyPressed then EXIT;
  ...
end;

【问题讨论】:

【参考方案1】:

您可以使用单元 Winapi.Windows 中的 GetKeyState 函数,以及 VK_CONTROL 或 VK_SHIFT 等虚拟键代码。例如:

procedure TformMain.ApplicationEvents1ShortCut(var Msg: TWMKey; var Handled: Boolean);
begin
  if (Msg.CharCode = Ord('V')) and (GetKeyState(VK_CONTROL) < 0) then
    ShowMessage('Ctrl+V was pressed');
end;

【讨论】:

谢谢。这是一个隐含的解决方案。如何明确检测未按下任何修饰键 - 即仅按下没有修饰键的 V 键? If GetKeyState(VK_CONTROL) &gt;= 0) 然后退出; @user1580348 显式函数如何调用隐式解决方案? 我认为 OP 关心的不是隐式与显式,而是GetKeyState(VK_CONTROL) &lt; 0 只测试 一个特定的修饰符,而不是所有可能的修饰符。但是,当然,您可以轻松地将这些单修饰符测试组合起来,使自己成为一个任意修饰符测试。 有趣的细微差别...如何找到所有可能修饰符的详尽列表?我可以列出我知道的修饰符(SHIFT、CTRL,也许还有更多),但我怎么知道不存在更多呢?也许明年,带有更多修饰键的新键盘将可用,Windows 会增加对它的支持,包括新的修饰符常量。确实,这个问题很有趣……我不知道答案。【参考方案2】:

考虑到@RemyLebeau 和@Andreas Rejbrand 的好心人:

这对我有用:

function NoModifierKeyPressed: Boolean;
var
  keys: TKeyboardState;
begin
  GetKeyboardState(keys);
  Result := (keys[VK_SHIFT] and $80 = 0) and (keys[VK_CONTROL] and $80 = 0) and (keys[VK_MENU] and $80 = 0);
end;

【讨论】:

您应该在这种情况下使用GetKeyState(),因为您在活动键处理程序中调用此代码,因此请查看调用线程的消息队列已处理的最新键状态.但是,当一次检查多个键时,您应该使用单个 GetKeyboardState() 调用而不是多个 GetKeyState() 调用,例如:function NoModifierKeyPressed: Boolean; var keys: array[0..255] of Byte; begin GetKeyboardState(keys); Result := (keys[VK_SHIFT] and $80 = 0) and (keys[VK_CONTROL] and $80 = 0) and (keys[VK_MENU] and $80 = 0); end; @RemyLebeau 谢谢,但编译器说:实际和正式 var 参数的类型必须相同:i.imgur.com/VrQQNj3.png @user1580348:写keys: TKeyboardState而不是keys: array[0..255] of Byte @user1580348 抱歉,我没有查看 Delphi 对GetKeyboardState() 的实际声明:type ...; TKeyboardState = array[0..255] of Byte; ... function GetKeyboardState(var KeyState: TKeyboardState): BOOL; stdcall; 所以 Andreas 是正确的。实际的 Win32 函数采用 PBYTE 谢谢大家。这似乎现在有效:i.imgur.com/F16V3eZ.png 这是正确的吗?

以上是关于TApplicationEvents.OnShortCut:仅检测带有修饰键的键?的主要内容,如果未能解决你的问题,请参考以下文章