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
- Subclass
WinNotificationMBS
. Call itWindowsMessageHandler
. - Add a boolean property to the subclass called
mDarkMode
. - Add an Integer constant to the subclass called
WM_SETTINGCHANGE
and set it to&h001A
- 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]
-
Add an event definition called
AppearanceChanged(darkMode As Boolean)
toWindowsMessageHandler
. We will fire this whenever the user switches between light and dark mode and we will pass in the mode type. -
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
- Add a new method to the
App
class calledUpdateAppearance(sender As Object, darkMode As boolean).
This is where you put the logic to handle light/dark mode changes. - Add an instance of
WindowsMessageHandler
to yourApp
class. We’ll call itWindowsMessages
. - 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.