18

I turn my monitors on and off by using the following code:

[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

private const int WM_SYSCOMMAND = 0x0112;
private const int SC_MONITORPOWER = 0xF170;
private const int MonitorTurnOn = -1;
private const int MonitorShutoff = 2;

//Turn them off
SendMessage(f.Handle, WM_SYSCOMMAND, (IntPtr)SC_MONITORPOWER, (IntPtr)MonitorShutoff);

//Turn them on
SendMessage(f.Handle, WM_SYSCOMMAND, (IntPtr)SC_MONITORPOWER, (IntPtr)MonitorTurnOn);

This used to work as intended, but after installing Windows 8 (I assume this is the reason, since I see others have the same issue) turning the screen on won't work. I can still turn it off, but no matter how many times I run SendMessage() with MonitorTurnOn, I still have to move the mouse or press a key to get the monitors back on.

Any suggestions on how to make this work on Windows 8?

Erlend D.
  • 3,013
  • 6
  • 37
  • 59

4 Answers4

16

I had the same problem, the solution I found is to move the mouse :

mouse_event(MOUSEEVENTF_MOVE, 0, 1, 0, NULL);
Sleep(40);
mouse_event(MOUSEEVENTF_MOVE, 0, -1, 0, NULL);

It will wake the monitor on. Earlypearl

earlypearl
  • 596
  • 6
  • 10
  • 1
    Thank you, even though it isn't a perfect solution, it seems to work. I wasn't allowed to edit your answer to include the DllImport and constant, so I added one myself below. – Erlend D. Jan 05 '13 at 12:24
  • 10
    No need for any `Sleep` here. A single move with delta 0, 0 will suffice. – David Heffernan Jul 29 '14 at 08:44
  • Why do you use a delay between the two movements? I tried it without and it worked fine. And why exactly 40 ms? – Martin Aug 15 '20 at 10:19
8

Here's Earlypearl's answer with the needed includes:

[DllImport("user32.dll")]
static extern void mouse_event(Int32 dwFlags, Int32 dx, Int32 dy, Int32 dwData, UIntPtr dwExtraInfo);

private const int MOUSEEVENTF_MOVE = 0x0001;

private void Wake(){
    mouse_event(MOUSEEVENTF_MOVE, 0, 1, 0, UIntPtr.Zero);
    Sleep(40);
    mouse_event(MOUSEEVENTF_MOVE, 0, -1, 0, UIntPtr.Zero);
}
Erlend D.
  • 3,013
  • 6
  • 37
  • 59
  • Though this question is tagged C#, some people might also be looking for a way to do this in a .bat file, or powershell script or from a Task Scheduler action, in which case this answer https://superuser.com/a/1371383 suggests a solution. In a .bat file this line will move the mouse 40 pixels right: `powershell (Add-Type '[DllImport(\"user32.dll\")]^public static extern void mouse_event(uint dwFlags, int dx, int dy, uint dwData, int dwExtraInfo);' -Name user32 -PassThru)::mouse_event(1,40,0,0,0)` – Doin Jan 20 '19 at 09:43
2

I had the same idea for this issue Just Changed the dear earlypearl's solution a wee bit and tested it on windows XP, 7, 8, Server 2008 and all worked perfectly.

mouse_event(MOUSEEVENTF_MOVE, 0, 1, 0, UIntPtr.Zero);

it does not need to be called twice.

Omid S.
  • 731
  • 7
  • 15
  • While a single move suffices to turn the monitor on, it should be undone by a movement in the other direction because the user may have positioned the cursor on a specific GUI element before and a blind click on a different position may lead to unwanted actions. This is especially true if there’s any chance the movement is triggered multiple times. – Martin Aug 28 '20 at 20:43
0

I have found out this trick to work on windows 8.1

Turn them off

SendMessage(f.Handle, WM_SYSCOMMAND, (IntPtr)SC_MONITORPOWER, (IntPtr)MonitorShutoff);

Turn them on

SendMessage(f.Handle, WM_SYSCOMMAND, (IntPtr)SC_MONITORPOWER, (IntPtr)1);

According to MSN, "1" is to switch monitor to "Low Power" but it does the trick. The screen will not turn off anymore.

Prafulla Kumar Sahu
  • 9,321
  • 11
  • 68
  • 105
Ben Mar
  • 13
  • 2