4

I found this on google:

Version 1:

SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, 2); //turn off
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, -1);  //turn on

Version 2:

HWND h = FindWindow(0, 0);
SendMessage(h, WM_SYSCOMMAND, SC_MONITORPOWER, 2);
SendMessage(h, WM_SYSCOMMAND, SC_MONITORPOWER, -1);

On my laptop(Win8.1+Visual Studio 2010): For both versions, turnoff works but turnon doesn't. When turnon code is executed, the screen is on and then off again immediately.

Another interesting thing: on my desktop(Win8.1+VS2013), the program will stuck on either line of version 1. But, it can go through version 2. Turn off works, but turn on is totally ineffective.

user2864740
  • 60,010
  • 15
  • 145
  • 220
Hanchen Li
  • 43
  • 1
  • 5
  • You should not be broadcasting this message. Send it to a valid window. Either create one yourself, or send it to the desktop window. – David Heffernan Jul 29 '14 at 08:48

1 Answers1

5

WM_SYSCOMMAND with SC_MONITOR appears to be broken to wake up the monitor since Windows 8's more advanced energy saving features, whilst sleep works fine.

You could alternatively trigger a small mouse move at the core system level to trigger waking up correctly, example code in C# but should be easily ported to C++:

void Main( object )
{
  int MOUSEEVENTF_MOVE = 0x0001;

  mouse_event(MOUSEEVENTF_MOVE, 0, 1, 0, UIntPtr.Zero);
  System.Threading.Thread.Sleep( 40 );
  mouse_event(MOUSEEVENTF_MOVE, 0, -1, 0, UIntPtr.Zero);
}

Documentation. Formally you should use SendInput, but mouse_event isn't going anywhere soon (it's been semi-deprecated since Vista).

Niels Keurentjes
  • 41,402
  • 9
  • 98
  • 136
  • Thank you very much! It works for me. Does anyone know why SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, 2); acts different computers. Both computer runs Win 8.1 x64 2014 Update. I am afraid my code will stuck on other computers. – Hanchen Li Jul 29 '14 at 08:44
  • @HanchenLi I covered that in my comment to your question. For what it is worth, the code in this answer is very bad. Niels posted it by copying from some other source without really understanding it. But you should not use this code. The Sleep is crazy. A single call to `SendInput` suffices. – David Heffernan Jul 29 '14 at 08:52
  • No, the sleep makes no sense at all. SendInput places a message in the queue of the thread of the active window. In fact, the correct way to do this in C++ is with this code: `INPUT input = { INPUT_MOUSE }; input.mi.dwFlags = MOUSEEVENTF_MOVE; SendInput(1, &input, sizeof(INPUT));` – David Heffernan Jul 29 '14 at 08:58
  • No, `SendInput` most certainly doesn't work like that. It operates on the system level, not on any window level. The system itself processes the input queues - either fed by drivers from mouse and keyboard, or `SendInput`, or older functions like `mouse_event`. After parsing these and looking into the Z-order of the available windows, it then uses `PostMessage` to notify the relevant windows with higher-level messages like `WM_MOUSEMOVE`, in their GUI thread's message queue. – Niels Keurentjes Jul 29 '14 at 09:03
  • SendInput does indeed work as I describe. It does not receive a window handle as input. The system however, knows which window is active, and which thread owns that window. It then places the input event onto that thread's queue. Z-order is utterly irrelevant. The code in my comment above is the correct way to do this. A single input event with a null mouse move. No sleep. – David Heffernan Jul 29 '14 at 09:11