Easily toggle between Windows light/dark mode
- 2 minutes read - 404 wordsTips & tricks …
… and sometimes “things I always have to look up how to do”
As winter and the weather darken the days, the lights in my home office start to come on earlier and earlier. It also means that my monitor setup gets brighter and brighter against the background light. This tends to give me eye strain, so I found myself playing around with light/dark themes in both Windows and different applications.
Having applications automatically follow the Windows theme setting is the easiest and more and more applications offer that option these days. But I wanted a quick and simple way to toggle Windows between light and dark mode without hunting through the settings.
With a bit of Googling I developed a Powershell script to do this a few years ago so I’ll share it here for all to use:
$regKeyPath = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize"
$currentUseLightTheme = Get-ItemPropertyValue -Path $regKeyPath -Name SystemUsesLightTheme
$newUseLightTheme = (1 - $currentUseLightTheme)
Set-ItemProperty -Path $regKeyPath -Name SystemUsesLightTheme -Value $newUseLightTheme -Type Dword -Force
Set-ItemProperty -Path $regKeyPath -Name AppsUseLightTheme -Value $newUseLightTheme -Type Dword -Force
Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
public class NativeMethods
{
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(
IntPtr hWnd,
uint Msg,
UIntPtr wParam,
string lParam,
uint fuFlags,
uint uTimeout,
out UIntPtr lpdwResult);
}
"@
$HWND_BROADCAST = [IntPtr] 0xffff
$WM_SETTINGCHANGE = 0x1a
$SMTO_ABORTIFHUNG = 0x2
$result = [UIntPtr]::Zero
[void] ([Nativemethods]::SendMessageTimeout(
$HWND_BROADCAST,
$WM_SETTINGCHANGE,
[UIntPtr]::Zero,
'ImmersiveColorSet',
$SMTO_ABORTIFHUNG,
5000,
[ref] $result))
This does a few things, so let’s walk through it:
- read the current theme setting from the
SystemUsesLightTheme
registry key - toggle it’s value and store in a variable
- set the
SystemUsesLightTheme
andAppsUseLightTheme
registry keys to the new value - broadcast a
WM_SETTINGCHANGE
message to notify all applications of the change
NOTE: Just changing the registry doesn’t reliably change all windows/apps, possibly because they are only listening for
RegNotifyChangeKeyValue
.For example, the Windows taskbar and the system tray font are unreliable.
The “proper” way to detect system changes like this is to listen for a
WM_SETTINGCHANGE
message withlParam
ofImmersiveColorSet
. Therefore we broadcast this to all top-level windows viaSendMessageTimeout()
.
You can find this script and a C# version that does the same thing in this repo.
For me, my simple script does the job. But if you want to have much more control over this and other related settings then I suggest taking a look at the Windows Auto Night Mode app.