I have a WinForms application which automatically adjusts to the dark/light theme on Windows 10. My problem is that the title bar of my window always stays white, regardless which theme the user selects.
Top is current, bottom is how I want it (simulated with Photoshop)
See explorer
for example. That is not an UWP app, however it uses a dark title bar on Windows 1903 and newer (when a dark theme is selected).
How can I achieve the same thing? I do not want to use any custom titlebar as I want the application to look and behave like any native application on older Windows versions as well.
Press Win + I to open the newly added System settings panel on Windows 10. Following that, navigate through Personalization > Colors. Here you will get an option called “Show color on Start, Taskbar, action center and title bar”. Just toggle the button to enable it.
So after some long searching, I have finally found the answer for this. The trick is to use dwmapi.dll
's DwmSetWindowAttribute
and passing the undocumented constant DWMWA_USE_IMMERSIVE_DARK_MODE
into the function. In C#, the code for this looks a little something like this (works with both WinForms and WPF):
/*
using System.Runtime.InteropServices;
*/
[DllImport("dwmapi.dll")]
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
private const int DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19;
private const int DWMWA_USE_IMMERSIVE_DARK_MODE = 20;
private static bool UseImmersiveDarkMode(IntPtr handle, bool enabled)
{
if (IsWindows10OrGreater(17763))
{
var attribute = DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1;
if (IsWindows10OrGreater(18985))
{
attribute = DWMWA_USE_IMMERSIVE_DARK_MODE;
}
int useImmersiveDarkMode = enabled ? 1 : 0;
return DwmSetWindowAttribute(handle, (int)attribute, ref useImmersiveDarkMode, sizeof(int)) == 0;
}
return false;
}
private static bool IsWindows10OrGreater(int build = -1)
{
return Environment.OSVersion.Version.Major >= 10 && Environment.OSVersion.Version.Build >= build;
}
The fastest way:
[DllImport("DwmApi")] //System.Runtime.InteropServices
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, int[] attrValue, int attrSize);
protected override void OnHandleCreated(EventArgs e)
{
if (DwmSetWindowAttribute(Handle, 19, new[] { 1 }, 4) != 0)
DwmSetWindowAttribute(Handle, 20, new[] { 1 }, 4);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With