如何使用 GetAsyncKeyState 查看按键被按下了 x 秒

Posted

技术标签:

【中文标题】如何使用 GetAsyncKeyState 查看按键被按下了 x 秒【英文标题】:How to use GetAsyncKeyState to see key was pressed for x seconds 【发布时间】:2017-01-31 11:04:44 【问题描述】:

我正在尝试创建一个代码来检测鼠标按钮是否被按下。到目前为止,我有一个代码可以检测按钮是否被按下一次。但它并没有让我检查按钮是否被连续按下。例如按下鼠标左键,这将启动一个计时器,0.5 秒后它会再次检查,如果它仍然向下输出一些东西。

我想这样设置

while (true)


    if (GetAsyncKeyState(VK_LBUTTON) & (0x8000 != 0))
    

        cout << ("left button pressed") << endl;
        Sleep(500);
        if (GetAsyncKeyState(VK_LBUTTON) & (0x8000 != 0))
        

            cout << ("Left button held down") << endl;
        

    

但是,它不起作用,如果我快速连续双击它只会输出第二条语句。

确定在调用函数时某个键是向上还是向下,以及在上一次调用 GetAsyncKeyState 之后是否按下了该键。

msdn 网站是这么说的。这是否意味着我应该在得到我想要的结果之后检查它是否是 UP。

【问题讨论】:

0x8000 始终不等于 0,正确放置括号。最简单的测试方法是使用if (GetAsyncKeyState(VK_LBUTTON) &lt; 0)。现在您知道为什么 GetAsyncKeyState() 具有非常不寻常的 SHORT 返回类型。 【参考方案1】:

GetAsyncKeyState 只是告诉你现在的状态,它不应该用来监控随着时间的推移可能发生的变化!

如果您想跟踪鼠标,无论哪个应用程序接收输入,那么您应该使用SetWindowsHookEx 安装low-level mouse hook。

如果您只关心自己窗口中的鼠标事件,那么最好按照其他答案中的建议跟踪 WM_LBUTTON* 鼠标消息。

作为对 WM_LBUTTONDOWN 的响应,您将全局标志设置为 true 并启动计时器。作为对 WM_LBUTTONUP 的响应,您将其设置为 false 并停止计时器。如果计时器触发并且标志为真,则执行您想要的任务。

【讨论】:

【参考方案2】:

如果您尝试在 WINAPI GUI 应用程序中实现这一点,here 是您的答案 - 在 WM_LBUTTONDOWN 上写入第一个时间戳,在 WM_LBUTTONUP 上写入第二个时间戳,然后计算您需要的经过时间。实际上更好的是 - 它只会捕获将进入您的应用程序窗口的消息,并且不会像使用 GetAsyncKeyState 那样捕获其他应用程序的按键。

更新:无论如何,使用标准的 Windows 消息处理(因为它是基于事件的,对程序员来说更自然)而不是检查一段时间内对象的状态 - 您可能会完全错过所需的事件。您似乎正在尝试解决 XY 问题。

UPDATE2:Here 是一个很好的教程,教你如何正确操作。

【讨论】:

处理 WM_LBUTTONDOWNWM_LBUTTONUP 不允许您在超时时响应。您必须实现timer 才能确定何时按下按钮达到预定义的时间间隔。此外,问题是询问物理密钥状态。建议使用每线程虚拟化输入并不能满足此要求。 你得问问选民,但我想原因与我评论中概述的类似。 @IInspectable 当然这里需要定时器。例如 QueryPerformanceFrequency/QueryPerformanceCounter 函数可以做到这一点。另一方面,单击按钮 2 次,间隔时间很短,会破解 OP 提供的解决方案。此外,恕我直言,睡眠()几乎在任何情况下都不好使用:它挂起处理线程,使其无法接收任何其他事件。我什至不会提到它的可靠性......我还想补充一点,按下和释放按钮是两个不同的事件,它们应该作为两个不同的事件处理。 @IInspectable 这保证了您不会遇到在所需时间内多次按下按钮的问题 - KEY_UP 始终跟随 KEY_DOWN。此外,我发现很难确定 OP 需要 物理键状态。您试图帮助尝试的解决方案,而不是问题 本身。如果 OP 能描述他真正想要做什么,那将会更有帮助。 我不是说你错了,而是你在回答一个不同的问题。无论如何,我不能代表任何对你提议的答案投票的人,我解释了为什么我没有投票。

以上是关于如何使用 GetAsyncKeyState 查看按键被按下了 x 秒的主要内容,如果未能解决你的问题,请参考以下文章

使用 GetAsyncKeyState() 的键监听器/记录器

GetRawInputData 与 GetAsyncKeyState()

检查窗口是不是处于活动状态

GetAsyncKeyState 使用 cin 创建问题

如何检测 C++ 中是不是按下了任何键?

杂文虚拟键码表(供函数GetAsyncKeyState()使用)