在Windows 10下,如何获得C#中“开始”菜单的确切背景颜色?

在Windows 10下,如何获得C#中“开始”菜单的确切背景颜色?,c#,wpf,windows,colors,C#,Wpf,Windows,Colors,我有一个测试项目,它使用一些未记录的函数来获得开始菜单的背景颜色: using System; using System.Windows; using System.Windows.Media; using System.Runtime.InteropServices; namespace WpfApplication1 { public static class AccentColorService { static class Interop

我有一个测试项目,它使用一些未记录的函数来获得开始菜单的背景颜色:

using System;
using System.Windows;
using System.Windows.Media;
using System.Runtime.InteropServices;

namespace WpfApplication1
{
    public static class AccentColorService
    {
        static class Interop
        {
            // Thanks, Quppa! -RR

            [DllImport("uxtheme.dll", EntryPoint = "#94", CharSet = CharSet.Unicode)]
            internal static extern int GetImmersiveColorSetCount();

            [DllImport("uxtheme.dll", EntryPoint = "#95", CharSet = CharSet.Unicode)]
            internal static extern uint GetImmersiveColorFromColorSetEx(uint dwImmersiveColorSet, uint dwImmersiveColorType, bool bIgnoreHighContrast, uint dwHighContrastCacheMode);

            [DllImport("uxtheme.dll", EntryPoint = "#96", CharSet = CharSet.Unicode)]
            internal static extern uint GetImmersiveColorTypeFromName(string name);

            [DllImport("uxtheme.dll", EntryPoint = "#98", CharSet = CharSet.Unicode)]
            internal static extern uint GetImmersiveUserColorSetPreference(bool bForceCheckRegistry, bool bSkipCheckOnFail);

            [DllImport("uxtheme.dll", EntryPoint = "#100", CharSet = CharSet.Unicode)]
            internal static extern IntPtr GetImmersiveColorNamedTypeByIndex(uint dwIndex);
        }

        public static Color GetColorByTypeName(string name)
        {
            var colorSet = Interop.GetImmersiveUserColorSetPreference(false, false);
            var colorType = Interop.GetImmersiveColorTypeFromName(name);

            var rawColor = Interop.GetImmersiveColorFromColorSetEx(colorSet, colorType, false, 0);

            return FromABGR(rawColor);
        }

        public static Color FromABGR(uint abgrValue)
        {
            var colorBytes = new byte[4];
            colorBytes[0] = (byte)((0xFF000000 & abgrValue) >> 24); // A
            colorBytes[1] = (byte)((0x00FF0000 & abgrValue) >> 16); // B
            colorBytes[2] = (byte)((0x0000FF00 & abgrValue) >> 8);  // G
            colorBytes[3] = (byte)(0x000000FF & abgrValue);         // R

            return Color.FromArgb(colorBytes[0], colorBytes[3], colorBytes[2], colorBytes[1]);
        }
    }
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Color startBackground = AccentColorService.GetColorByTypeName("ImmersiveStartBackground");
            MessageBox.Show("R: " + startBackground.R + ", G: " + startBackground.G + ", B: " + startBackground.B);
        }
    }
}
使用系统;
使用System.Windows;
使用System.Windows.Media;
使用System.Runtime.InteropServices;
命名空间WpfApplication1
{
公共静态类服务
{
静态类互操作
{
//谢谢,库帕!-RR
[DllImport(“uxtheme.dll”,EntryPoint=“#94”,CharSet=CharSet.Unicode)]
内部静态外部int GetImmersiveColorSetCount();
[DllImport(“uxtheme.dll”,EntryPoint=“#95”,CharSet=CharSet.Unicode)]
内部静态外部单元从ColorSetEx获取ImmersiveColorSet(单元dwImmersiveColorSet、单元dwImmersiveColorType、bool bIgnoreHighContrast、单元DWHighContractCacheMode);
[DllImport(“uxtheme.dll”,EntryPoint=“#96”,CharSet=CharSet.Unicode)]
内部静态外部uint GetImmersiveColorTypeFromName(字符串名称);
[DllImport(“uxtheme.dll”,EntryPoint=“#98”,CharSet=CharSet.Unicode)]
内部静态外部单元GetImmersiveUserColorSetPreference(bool bForceCheckRegistry,bool bSkipCheckOnFail);
[DllImport(“uxtheme.dll”,EntryPoint=“#100”,CharSet=CharSet.Unicode)]
内部静态外部IntPtr GetImmersiveColorNamedTypeByIndex(uint dwIndex);
}
公共静态颜色GetColorByTypeName(字符串名称)
{
var colorSet=Interop.GetImmersiveUserColorSetPreference(false,false);
var colorType=Interop.GetImmersiveColorTypeFromName(名称);
var rawColor=Interop.GetImmersiveColorFromColorSetEx(colorSet,colorType,false,0);
从ABGR(rawColor)返回;
}
来自ABGR的公共静态颜色(uint abgrValue)
{
var colorBytes=新字节[4];
colorBytes[0]=(字节)((0xFF000000&abgrValue)>>24);//A
colorBytes[1]=(byte)((0x00FF0000&abgrValue)>>16);//B
colorBytes[2]=(字节)((0x0000FF00&abgrValue)>>8);//G
colorBytes[3]=(字节)(0x000000FF&abgrValue);//R
返回Color.FromArgb(colorBytes[0],colorBytes[3],colorBytes[2],colorBytes[1]);
}
}
/// 
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
Color startBackground=AccentColorService.GetColorByTypeName(“浸入式startBackground”);
MessageBox.Show(“R:+startBackground.R+”,G:+startBackground.G+”,B:+startBackground.B);
}
}
}
据我所知,在Windows10下没有获取各种主题颜色的官方API。我几乎一字不差地使用了我找到的一个小片段

(在堆栈溢出的其他地方确实提到了这一点。)

“我的重点颜色”是“设置”下列表中出现的第一个蓝色。我已关闭“开始”菜单的透明度

带有此重音的“开始”菜单的颜色为(0、90、158)

当我运行上述代码时,显示的结果是:

R:0,G:90,B:157

这不是一个孤立的案例。对于其他强调色,与实际的“开始”菜单背景色相比,颜色通道的差异通常为+/-2

我尝试稍微提高饱和度,转换到不同的颜色空间,然后再转换回来,但我所做的一切都没有可靠地产生我在颜色通道中看到的变化


是否需要对“ImmersiveStartBackground”颜色执行额外的处理步骤,以获得开始菜单背景的确切颜色?或者,除了uxtheme.dll之外,是否还有其他资源可以查询,以获得更精确的“开始”菜单背景?

还有
SystemParameters.WindowGlassBrush
。看起来也不完全一样。你确定差异不是因为开始菜单是部分透明的吗?@Cody我不确定开始菜单是完全不透明的。我确实禁用了“开始菜单透明度”,但检查这一点是个好主意。为了验证,我在开始菜单下面放了一个黑色矩形和一个白色矩形,并测量了开始菜单在这些点上的颜色。两个区域均为(0,90158)。我认为这表明它不是99%不透明的。我的意思是,如果是这样的话,我希望黑色和白色的底层之间会有一些差异。