无法使用 GetAsyncKeyState +消息泵,SC_MONITORPOWER 未完全工作
我正在尝试制作一个程序,可以使用组合键关闭显示器并使用另一个组合键将其重新打开。电源按钮脱落,所以显示器现在几乎保持打开状态。我注意到发送带有 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)时,显示器只会在打开之前变暗(电源灯将保持稳定)几秒钟。使用 LPARAM 的值 1 进入低功耗模式会起到同样的作用。天黑时按“2”不会有任何反应。
我的理由是,由于我禁用了消息队列,DefWindowProc() 永远无法处理这些消息,因此它们会产生不正确的结果。
我考虑过在按下“1”时设置一个循环,以一次关闭显示器几秒钟,直到按下“2”为止,但我想我已经对代码做了足够多的坏事了(带有没有消息循环)并且拥有如此糟糕的代码会破坏我以后很可能需要此信息的点。
我的窗口过程中的所有内容都是带有 DestroyWindow() 的 WM_CLOSE、显示隐藏窗口并调用 PostQuitMessage() 的 WM_DESTROY 和 DefWindowProc。
所以基本上我的问题归结为“如何将 GetAsyncKeyState 与我的消息泵一起使用?”。另外,我注意到 WM_POWERBROADCAST 也可以实现这一点。有一个更好用吗?
编辑:评论代码,以便您了解更多信息
编辑:RegisterHotKey() 修复了一个问题,但显示器仍然只变暗几秒钟(电源灯常亮)
I'm trying to make a program that can turn off the monitor with a key combination and turn it back on with another. The power button fell off, so the monitor pretty much stays on now. I noticed sending a WM_SYSCOMMAND with a WPARAM of SC_MONITORPOWER would probably do the trick, but in reality it wasn't.
First, I tried putting a few GetAsyncKeyState()s in my message pump, but whenever I tried to run it, my keystrokes were not picked up.
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
}
I tried moving the GetAsyncKeyState()s before the message functions. I tried using a while (true) loop and including GetMessage() in it.
The only thing that started to work was commenting out all message pump references in the loop. This would pick up the keystrokes, but when pressing '1' (0x31), the monitor would only go dark (the power light would stay solid) for a few seconds before turning on. Using a value of 1 for LPARAM to go into low-power mode would do the same thing. Pressing '2' while it was dark would not do anything.
My reasoning for this is that since I disabled the message queue, DefWindowProc() was never able to handle these messages and thus they would produce incorrect results.
I thought about setting up a loop when '1' is pressed to keep turning the monitor off for a few seconds at a time until '2' is pressed, but I figured I've done enough bad things to the code already (window with no message loop) and having code this bad would kind of ruin the point when I'll most likely need this information later anyways.
All that's in my window procedure is a WM_CLOSE with DestroyWindow(), WM_DESTROY which shows the hidden window and calls PostQuitMessage(), and DefWindowProc.
So basically my question comes down to "How can I use GetAsyncKeyState with my message pump?". Also, I noticed WM_POWERBROADCAST can achieve this too. Is one better to use?
EDIT: commented the code so you know a bit extra
EDIT: RegisterHotKey() fixed one problem, but the monitor still only goes dark for a few seconds (power light solid)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
正如tinman所说,使用RegisterHotKey。
为了解决您的问题,
GetAsyncKeyState
读取当前的按键状态。GetMessage
读取队列中的消息。它们不会同步。您应该使用GetKeyState
来与消息队列保持同步。但是,是的,
RegisterHotKey
。As tinman said, use
RegisterHotKey
.To address your question,
GetAsyncKeyState
reads the current key state.GetMessage
reads messages in a queue. They won't be synchronized. You should instead useGetKeyState
which stays in sync with the message queue.But yea,
RegisterHotKey
.