繁体   English   中英

Windows 10 上的 WinForms Dark 标题栏

[英]WinForms Dark title bar on Windows 10

我有一个 WinForms 应用程序,它会自动调整到 Windows 上的深色/浅色主题 10。我的问题是我的 window 的标题栏始终保持白色,无论用户选择哪个主题。

在此处输入图像描述
顶部是当前的,底部是我想要的(用 Photoshop 模拟)

例如,请参见explorer管理器。 这不是 UWP 应用程序,但它在 Windows 1903 及更新版本(选择深色主题时)上使用深色标题栏。

我怎样才能达到同样的目的? 我不想使用任何自定义标题栏,因为我希望应用程序的外观和行为也像旧 Windows 版本上的任何本机应用程序一样。

所以经过长时间的搜索,我终于找到了答案。 诀窍是使用dwmapi.dllDwmSetWindowAttribute并将未记录的常量DWMWA_USE_IMMERSIVE_DARK_MODE传递给函数。 在 C# 中,这个代码看起来有点像这样(适用于 WinForms 和 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;
}

最快的方法:

[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);
}

对于 Jonas Kohl 的解决方案,请记住,对于 .net fw 4.8.1 及之前的版本,返回的版本不正确,已在 .Net6 中修复,这里是一个片段(.Net 5 不受管理):

    private static bool IsWindows10OrGreater(int build = -1)
    {
        return WindowsVersion() >= 10 && WindowsBuildNumber() >= build;
    }

    public static int WindowsVersion()
    {
     //for .Net4.8 and Minor
     #if NETFRAMEWORK
        int result = 10;
        var reg = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
        string[] productName = reg.GetValue("ProductName").ToString().Split((char)32);
        int.TryParse(productName[1], out result);
        return result;
     #else
        //fixed in .Net6
        return System.Environment.OSVersion.Version.Major;
     #endif
    }

    public static int WindowsBuildNumber()
    {
        //for .Net4.8 and Minor
    #if NETFRAMEWORK
        int result = 22000;
        var reg = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
        string buildNumber = reg.GetValue("CurrentBuildNumber").ToString();
        int.TryParse(buildNumber, out result);
        return result;
    #endif

    #if NET
        //fixed in .Net6
        return System.Environment.OSVersion.Version.Build;
    #endif
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM