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) >= 0)
然后退出;
@user1580348 显式函数如何调用隐式解决方案?
我认为 OP 关心的不是隐式与显式,而是GetKeyState(VK_CONTROL) < 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:仅检测带有修饰键的键?的主要内容,如果未能解决你的问题,请参考以下文章