Dark-Mode-Forms icon indicating copy to clipboard operation
Dark-Mode-Forms copied to clipboard

Handle Dark/Light change of Windows?

Open MagicAndre1981 opened this issue 1 year ago • 8 comments

How can I handle Dark/Light change of Windows for displayed window? After changing the Dark/Light setting for apps in Windows settings, opening a new window follows the new theme, but the old main window is still in old theme.

MagicAndre1981 avatar Jun 10 '24 09:06 MagicAndre1981

To me, this seems too complicated to implement and there is IMHO not much demand and use for such a feature...

It would require to keep a list of weak references to all the controls and then loop through it, setting the colors and perhaps handling potential "special needs" of some of them. While I recently added a static ConditionalWeakTable to track already processed controls, this cannot be directly used as it does not expose its Keys and Values collections.

kachnitata avatar Jun 10 '24 10:06 kachnitata

And adding support for switching back to the light theme would add one more level of complexity

kachnitata avatar Jun 10 '24 10:06 kachnitata

Hi, all windows get themed when they are created and if Windows theme changes when your program is still running you will have to find a way to re-launch your main window for the colors to be applied.

BlueMystical avatar Jun 10 '24 15:06 BlueMystical

Now that you have code to force a theme can you please add an option to handle theme change? I tried to override WndProc and handle WM_THEMECHANGED but the code is never executed. Is changing dark/light mode raising a different message?

MagicAndre1981 avatar Aug 12 '24 06:08 MagicAndre1981

ok, the message is called WM_SETTINGSCHANGE and here you need to check the LParam var stringLParam = Marshal.PtrToStringAuto(m.LParam); if this is set to ImmersiveColorSet (if (stringLParam == "ImmersiveColorSet")) the theme changed via settings app.

Here you also need to update your public bool IsDarkMode as it is currently only assigned at constructor and return wrong values after dark /light change.

Best would be to have an enum with FollowSystemTheme (handle the WM_SETTINGSCHANGE message and change colors), ForceLightTheme, ForceDarkTheme to force a color no matter what is set in windows.

MagicAndre1981 avatar Aug 12 '24 06:08 MagicAndre1981

ok, I had to create a new base Form class and later inherit my forms from this base form class. In the base form class I added the overriding of WndProc and a protected variable protected DarkModeCS dm; which I assign in each constructor base.dm = new DarkModeCS(this); and depending on the return of GetWindowsColorMode() I call dm.ApplyTheme(true); or dm.ApplyTheme(false); and also update the IsDarkMode property.

This works fine so far and the window get redrawn in the now correct colors.

MagicAndre1981 avatar Aug 12 '24 07:08 MagicAndre1981

@MagicAndre1981 ..an option to handle theme change.. What do you mean by that? an event? Ohh yes, i forgot to update the IsDarkMode prop, thanks for the remind.

BlueMystical avatar Aug 12 '24 15:08 BlueMystical

This was one of the things that my Pull Request addressed. In the form you needed to reapply the theme to you could simply call the reference to a DarkModeCS instance and run the ApplyTheme() method. This would refetch the IsDarkMode property and reapply the theme. Sorry I didn't elaborate more on what I was using the Pull Request code for at the time.
Ref: https://github.com/BlueMystical/Dark-Mode-Forms/pull/40

IAmHappyCatDev avatar Aug 14 '24 02:08 IAmHappyCatDev

@BlueMystical I've added a PR for this in #59 Hopefully I haven't missed anything.

MagicAndre1981 avatar Oct 17 '24 11:10 MagicAndre1981

Thank you!

BlueMystical avatar Oct 17 '24 15:10 BlueMystical

ok, update the doc, to include the changes and add the hint to inherit from the new base class.

MagicAndre1981 avatar Oct 17 '24 15:10 MagicAndre1981