【发布时间】:2011-09-06 12:01:56
【问题描述】:
我正在尝试制作一个程序,该程序可以使用组合键关闭显示器并使用另一个组合键将其重新打开。电源按钮掉了,所以显示器现在几乎保持开启状态。我注意到发送 WPARAM 为 SC_MONITORPOWER 的 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)时,显示器只会在打开之前变暗(电源灯会保持稳定)几秒钟。使用 LPARAM 的值 1 进入低功耗模式会做同样的事情。在天黑时按“2”不会做任何事情。
我的理由是,由于我禁用了消息队列,DefWindowProc() 永远无法处理这些消息,因此它们会产生不正确的结果。
我曾想过在按下“1”时设置一个循环,以便一次关闭显示器几秒钟,直到按下“2”,但我认为我已经对代码做了足够多的坏事(没有消息循环的窗口)并且有这么糟糕的代码会破坏我以后很可能需要这些信息的点。
我的窗口过程中的所有内容都是带有 DestroyWindow() 的 WM_CLOSE、显示隐藏窗口并调用 PostQuitMessage() 和 DefWindowProc 的 WM_DESTROY。
所以基本上我的问题归结为“如何将 GetAsyncKeyState 与我的消息泵一起使用?”。另外,我注意到 WM_POWERBROADCAST 也可以做到这一点。哪个更好用?
编辑:对代码进行了注释,让您了解更多
编辑:RegisterHotKey() 修复了一个问题,但显示器仍然只变暗几秒钟(电源灯常亮)
【问题讨论】:
-
为什么不使用 RegisterHotKey()?
-
我会试试看效果如何,谢谢。很高兴知道我是否可以做任何事情,除了在泵中处理消息。
-
好的,在开始工作后(我注意到了一点 if (LOWORD (lParam == MOD_CONTROL)) 大声笑,括号失败)它仍然只变暗几秒钟,然后恢复正常:/我正在以管理员权限等运行。其他人有这个问题吗?反正我马上就要上学了,有机会我也去那里试试。
-
如果我在屏幕关闭之前没有释放热键组合,它会自动重新打开,即释放键被视为唤醒计算机的事件。您可能需要延迟或想办法等到所有键都被释放。
-
我想当按键或鼠标移动时它不会唤醒,这就是我的问题所在。一行 while ((GetAsyncKeyState (0x31) & 0x8000) || (GetAsyncKeyState (0x11) & 0x8000));成功了,非常感谢!不过,我在这里有点新,我不知道您是否可以将 cmets 标记为回答您的问题,但是由于已回答,因此单独的答案解决了主要部分,因此我想标记它会起作用。
标签: c++ winapi keyboard message-queue