Detecting Light/Dark Mode on Windows

This is a summary post bringing together information gleaned from this post and this post.

It turns out that there’s a dark mode (of sorts) on Windows that can be found in the Personalisation section of Settings. I wanted the app I’m working on to honour dark mode if the user has it enabled on their system and I wanted it to immediately switch modes when the user does so.

After several hours of messing around I came up with a solution. This solution relies on MonkeyBread Software’s MBS Win Plugin, specifically the WinNotificationMBS class. Essentially, I tell a subclass of WinNotificationMBS to listen for a specific message broadcast by Windows (WM_SETTINGCHANGE). This message is broadcast whenever the registry is altered. When my subclass receives this message it fires its GotNotification event. In this event I check the value of a specific registry key (HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize\\AppsUseLightTheme). If its value is 0 then Windows is in dark mode, if it’s 1 then it’s in light mode. I then update my UI accordingly.

Walkthrough

  1. Subclass WinNotificationMBS. Call it WindowsMessageHandler.
  2. Add a boolean property to the subclass called mDarkMode.
  3. Add an Integer constant to the subclass called WM_SETTINGCHANGE and set it to &h001A
  4. Create the following Constructor for the subclass:

[code]Public Sub Constructor()
// Calling the overridden superclass constructor.
Super.Constructor

// Listen for changes to the system registry.
Call Me.ListenForMessage(WM_SETTINGCHANGE)

// Determine if Windows is in dark mode or not.
Try
Dim reg As New _
RegistryItem(“HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize”, False)
For i As Integer = 0 To reg.KeyCount - 1
If reg.Name(i) = “AppsUseLightTheme” Then
If reg.Value(i) = 0 Then
mDarkMode = True
Else
mDarkMode = False
End If
End If
Next i
Catch e As RegistryAccessErrorException
mDarkMode = False
End Try

End Sub[/code]

  1. Add an event definition called AppearanceChanged(darkMode As Boolean) to WindowsMessageHandler. We will fire this whenever the user switches between light and dark mode and we will pass in the mode type.

  2. Add the following code to the WindowsMessageHandler.GotNotification event:

Select Case Message Case WM_SETTINGCHANGE // A system wide setting has been changed. // Has the default app mode changed (light/dark mode)? Try Dim reg As New _ RegistryItem("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize") For i As Integer = 0 To reg.KeyCount - 1 If reg.Name(i) = "AppsUseLightTheme" Then // Only update the appearance if the key has changed since the last known state. Var currentlyInDarkMode As Boolean = If(reg.Value(i) = 0, True, False) If currentlyInDarkMode <> mDarkMode Then mDarkMode = currentlyInDarkMode // Fire our custom event. AppearanceChanged(mDarkMode) End If End If Next i End Try End Select

  1. Add a new method to the App class called UpdateAppearance(sender As Object, darkMode As boolean). This is where you put the logic to handle light/dark mode changes.
  2. Add an instance of WindowsMessageHandler to your App class. We’ll call it WindowsMessages.
  3. In the App.Open event, instantiate our message handler:

#If TargetWindows // Setup our Windows message handler. This will listen for changes to the registry that // will tell us that the user has switched between light and dark mode. WindowsMessages = New WindowsMessageHandler // Intercept the `AppearanceChanged` event that the message handler fires and direct to our custom method: AddHandler WindowsMessages.AppearanceChanged, AddressOf UpdateAppearance #EndIf

Hopefully this will save a few people some time.

1 Like