WINAPI GetKeyboardState behavior modified by GetKeyState when application is out of focus?
从WPF应用程序(假定还有其他应用程序)调用WINAPI命令GetKeyboardState(aByteArray)时,只有在应用程序具有焦点时,才能正确检测到按住SHIFT键的情况。当应用程序没有焦点时,方法调用后aByteArray[VK_SHIFT]为0。
但是,如果对于任何aVKCode值,在GetKeyboardState(aByteArray),之前紧接GetKeyState(aVKCode)调用,即使返回值被丢弃,则GetKeyboardState(aByteArray)将在以下情况下提供保持的SHIFT键的正确非零状态:该应用程序不是重点。
这种行为是违反直觉的,并且似乎引起了许多程序员的悲伤。我相信GetKeyboardState文档中有相关信息,内容为:
The status changes as a thread removes keyboard messages from its message queue. The status does not change as keyboard messages are posted to the thread's message queue, nor does it change as keyboard messages are posted to or retrieved from message queues of other threads.
可能,GetKeyState()与消息队列进行交互,因此必须在GetKeyboardState()之前调用它,以使GetKeyboardState()发挥所需的作用。但是,我不熟悉消息队列的概念以及Windows如何添加和删除项目,因此我想在这里问一下。谁能解释为什么仅对GetKeyboardState()的调用无法捕获没有集中应用程序的情况下按住的SHIFT键?
-
(键盘)输入是按线程(或一组连接输入的线程)虚拟化的。 每个线程都维护自己的键盘状态信息。 在线程拥有的窗口具有输入焦点的同时按下键将不会更新任何其他线程中的键盘状态(与该线程连接的那些窗口除外)。 快速介绍了异步输入与同步输入的更多详细信息。
GetKeyState始终与线程的最后处理的消息关联。 因此,当您在消息处理程序中使用GetKeyState时,会将该消息放入消息队列时获得键状态。
如果消息处理被延迟,则可以保证程序员可以处理每条消息,并且他可以在那一刻检测到键状态。 I.E .:"发生鼠标单击时,是否按下Shift键?"
如果在其他消息之间进行了处理,则仅使用GetKeyState可能会跳过状态或消息。
要检测当前键状态,必须使用GetAsyncKeyState
这些功能都有详细记录。
最后:GetKeyState和GetAsyncKeyState都不是检测是否在程序内部按下了Shift键的好方法。 处理消息并检测WM_KEYDOWN。
-
谢谢你提供的详情。 我正在查看的代码使用WM_KEYDOWN来检测按键,并且如果该消息中的键是字母数字,那么我将使用GetKeyState查找shift或capslock是否按下,以便将由WM_KEYDOWN指示的键转换为ASCII。 因此,我确实希望您的前两段中描述的行为。 我选择使用GetKeyState的原因是,在我开始处理WM_KEYDOWN消息之前,可能已经按下了shift和/或大写锁定键,而我仍然希望能够检测到这些情况。 在这种情况下,您将使用哪种方法?