0
votes

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)

1
Why not use RegisterHotKey()?tinman
I'll try that and see how it works out, thank you. It would still be nice to know if I can do anything except message processing in the pump though.chris
Okay, after getting that working (noticed after a bit I had if (LOWORD (lParam == MOD_CONTROL)) lol, brackets fail) it still only goes dark for a few seconds before going back to normal :/ I'm running with administrator privileges etc. Anyone else had that problem? I'm going to school soon anyways so I'll try it there too if I get a chance.chris
it turns back on automatically if I do not release the hotkey combination before the screen has turned off, i.e. the release of a key is seen as an event to wake up the computer. You might want to put in a delay or find some way to wait until all keys have been released.tinman
I imagined it wouldn't wake up when a key press or mouse movement was made, and that's where my problem lied. One line of while ((GetAsyncKeyState (0x31) & 0x8000) || (GetAsyncKeyState (0x11) & 0x8000)); did the trick, thank you very much! I'm kind of new here though, and I don't know if you can mark comments as answering your question, but since this is answered, the separate answer solves the main part so I guess it'll work to mark it.chris

1 Answers

0
votes

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 use GetKeyState which stays in sync with the message queue.

But yea, RegisterHotKey.