无法使用GetAsyncKeyState +消息泵,SC_MONITORPOWER不能完全正常工作

时间:2011-09-06 12:01:56

标签: c++ winapi keyboard message-queue

我正在尝试制作一个程序,可以使用组合键关闭显示器并将其重新打开。电源按钮掉了下来,所以显示器现在几乎保持不动。我注意到发送带有SC_MONITORPOWER的WPARAM的WM_SYSCOMMAND可能会做到这一点,但实际上并非如此。

首先,我尝试在我的消息泵中添加一些GetAsyncKeyState(),但每当我尝试运行它时,我的键击都没有被提取。

while (GetMessage(&Msg, NULL, 0, 0) > 0) // main message pump
{
    TranslateMessage(&Msg);
    DispatchMessage(&Msg);

    if (GetAsyncKeyState (0x31) & 0x8000) SendMessage (hwnd, WM_SYSCOMMAND, SC_MONITORPOWER, 2); // turn monitor off if '1' is pressed
    if (GetAsyncKeyState (0x32) & 0x8000) SendMessage (hwnd, WM_SYSCOMMAND, SC_MONITORPOWER, -1); // turn monitor on if '2' is pressed
    if (GetAsyncKeyState (0x33) & 0x8000) PostMessage (cmd, WM_CLOSE, 0, 0); // close console window if '3' is pressed (it even comes with the windows projects for some reason so I just hide it+deal with it
}

我尝试在消息函数之前移动GetAsyncKeyState()。我尝试使用while(true)循环并在其中包含GetMessage()。

唯一开始工作的是在循环中注释掉所有消息泵引用。这将获得击键,但是当按下'1'(0x31)时,显示器只会变暗(电源指示灯将保持稳定)几秒钟后再打开。使用值1为LPARAM进入低功耗模式也会做同样的事情。在天黑时按'2'不会做任何事情。

我的理由是,由于我禁用了消息队列,因此DefWindowProc()永远无法处理这些消息,因此会产生不正确的结果。

当我按下'1'时,我想到设置一个循环,一次关闭显示器几秒钟,直到按下'2',但我觉得我已经对代码做了很多坏事(没有消息循环的窗口)并且代码很糟糕会破坏这一点,因为我很可能在以后需要这些信息。

我窗口过程中的所有内容都是带有DestroyWindow()的WM_CLOSE,WM_DESTROY显示隐藏窗口并调用PostQuitMessage()和DefWindowProc。

所以基本上我的问题归结为“如何在我的消息泵中使用GetAsyncKeyState?”。另外,我注意到WM_POWERBROADCAST也可以实现这一点。是否更好用?

编辑:对代码进行了评论,以便您了解一些额外信息
编辑:RegisterHotKey()修复了一个问题,但显示器仍然只是黑暗几秒钟(电源指示灯亮)

1 个答案:

答案 0 :(得分:0)

正如tinman所说,使用RegisterHotKey

要解决您的问题,GetAsyncKeyState会读取当前的密钥状态。 GetMessage读取队列中的消息。它们不会同步。您应该使用与消息队列保持同步的GetKeyState

但是,RegisterHotKey