I wanted to turn off my monitor in Windows 10, while listening to music, rather than wait for the Power plan “Turn off the display” timer to kick in. Hmmm, seems Windows has never improved, because I recall having this requirement back-in-the-day - haha, that was during my first project ever, when I was involved in some Win32 development...

It's so easy to trigger the monitor to sleep using the Win32 API WM_SYSCOMMAND:

  • Set wParam to 0xF170 (SC_MONITORPOWER).
  • And set the state of the display in lParam to either 1 (lower power) or 2 (shut off) - though only the latter has ever worked for me.

The New Way: PowerShell

The method is based on the idea here - running a PowerShell script from the command line (to avoid PowerShell script security). However, instead of SendMessage, use PostMessage, lest the script get stuck waiting for a reply.

Simply create a new shortcut (all entered in one line):

powershell (Add-Type '[DllImport(\"user32.dll\")]public static extern int PostMessage(int h,int m,int w,int l);' -Name a -Pas)::PostMessage(-1,0x0112,0xF170,2)

Windows Shortcut to PowerShell to turn off monitor

The shortcut can be assigned properties like a shortcut key (hotkey) too:

Windows Shortcut properties to assign hotkey to turn off monitor

The Old Way: C/C++

In fact I found my old C code, dated 2001, that does this plus locks the workstation from the command line:

#define WIN 32_LEAN_AND_MEAN
#include <windows.h>

int WINAPI WinMain(HINSTANCE hinstCurrent, HINSTANCE hinstPrevious, LPSTR lpszCmdLine, int nCmdShow)
{
  Sleep(500);
  if (lpszCmdLine[0] != 0)
  {
    HINSTANCE hinstLib = LoadLibrary("user32"); 
    if (hinstLib != NULL) {
      typedef BOOL (*PROC)();
      PROC LockWorkStation = (PROC) GetProcAddress(hinstLib, "LockWorkStation"); 
      if (LockWorkStation != NULL) (LockWorkStation)();
      FreeLibrary(hinstLib);
    }
  }
  //or return SendMessage(GetDesktopWindow(), WM_SYSCOMMAND, SC_SCREENSAVE, 0);
  return SendMessage(GetDesktopWindow(), WM_SYSCOMMAND, SC_MONITORPOWER, 2);
}

The Even Older Way: Asm

In fact, I recall writing an Assembly version that was even simpler, circa 1998. I can’t find the exact source code anymore, but it would’ve looked something like this (note this was during the Windows 32-bit days):

.586
locals
jumps
.model flat, STDCALL

include win32.inc

extern SendMessageA   :PROC

.data
.const
SC_MONITORPOWER equ 0f170h

.code
Main:
    call SendMessageA, 0ffffh, WM_SYSCOMMAND , SC_MONITORPOWER, 2
    call ExitProcess, 0
end Main