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_SETTINGCHANGEand 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.GotNotificationevent:
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
Appclass calledUpdateAppearance(sender As Object, darkMode As boolean).This is where you put the logic to handle light/dark mode changes. - Add an instance of
WindowsMessageHandlerto yourAppclass. We’ll call itWindowsMessages. - In the
App.Openevent, 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.