如何正确获取系统边框的实际颜色?
问题
WinAPI中的GetSysColor(COLOR_ACTIVEBORDER)函数本应返回系统活动窗口的边框颜色,但在部分自定义了Windows颜色的系统中,实际显示的边框颜色与标准色不同,可GetSysColor()始终返回标准灰色。请问如何获取系统实际使用的边框颜色?
已尝试的方法
我试过以下几种方式,但部分结果不符合预期:
var color = SystemColors.Desktop; // 正确获取桌面颜色 var color1 = SystemColors.ControlText; // 错误:无论启用何种Windows主题,始终返回黑色 var color = GetThemeSysColor(HTHEME.NULL, SystemColorIndex.COLOR_DESKTOP); // 正确获取桌面颜色 var color1 = GetThemeSysColor(HTHEME.NULL, SystemColorIndex.COLOR_BTNTEXT); // 错误 var theme = OpenThemeData(HWND.NULL, "BUTTON"); var color = GetThemeSysColor(theme, COLOR_BTNTEXT); // 错误 var theme = OpenThemeData(_button.Handle, "BUTTON"); var color = GetThemeSysColor(theme, COLOR_BTNTEXT); // 错误
解决方案
要获取系统实际使用的活动窗口边框颜色,需区分系统是否启用主题和DWM(桌面窗口管理器),使用对应的API处理:
1. 针对启用主题的系统
当系统启用主题时,GetSysColor无法获取自定义主题颜色,需通过主题API获取窗口边框的实际颜色:
- 调用
OpenThemeData打开"Window"主题类(对应窗口相关主题样式) - 使用
GetThemeColor获取活动窗口边框对应的颜色属性,元素ID为WP_ACTIVEBORDER,状态ID为CBS_NORMAL
示例代码:
[DllImport("uxtheme.dll", CharSet = CharSet.Unicode)] private static extern IntPtr OpenThemeData(IntPtr hwnd, string pszClassList); [DllImport("uxtheme.dll")] private static extern int GetThemeColor(IntPtr hTheme, int iPartId, int iStateId, int iPropId, out COLORREF pColor); [DllImport("uxtheme.dll")] private static extern int CloseThemeData(IntPtr hTheme); public enum WindowParts { WP_ACTIVEBORDER = 2 } public enum CommonStates { CBS_NORMAL = 1 } public enum ThemeColorProps { TMT_FILLCOLOR = 310 } public struct COLORREF { public uint ColorDWORD; public COLORREF(uint dwColor) { ColorDWORD = dwColor; } public Color ToColor() { return Color.FromArgb( (byte)((ColorDWORD >> 16) & 0xFF), (byte)((ColorDWORD >> 8) & 0xFF), (byte)(ColorDWORD & 0xFF) ); } } public Color GetActiveBorderColor() { IntPtr themeHandle = OpenThemeData(IntPtr.Zero, "Window"); if (themeHandle != IntPtr.Zero) { COLORREF colorRef; if (GetThemeColor(themeHandle, (int)WindowParts.WP_ACTIVEBORDER, (int)CommonStates.CBS_NORMAL, (int)ThemeColorProps.TMT_FILLCOLOR, out colorRef) == 0) { CloseThemeData(themeHandle); return colorRef.ToColor(); } CloseThemeData(themeHandle); } // 降级使用GetSysColor return ColorTranslator.FromWin32(GetSysColor((int)SystemColorIndex.COLOR_ACTIVEBORDER)); }
2. 针对启用DWM的系统(Windows Vista及以上)
如果系统启用了DWM颜色着色功能,窗口边框颜色可能与DWM全局着色颜色一致,可使用DwmGetColorizationColor获取:
[DllImport("dwmapi.dll")] private static extern int DwmGetColorizationColor(out uint pcrColorization, out bool pfOpaqueBlend); public Color GetDwmBorderColor() { uint color; bool opaque; if (DwmGetColorizationColor(out color, out opaque) == 0) { // DWM颜色包含alpha通道,提取RGB部分 return Color.FromArgb( (byte)((color >> 16) & 0xFF), (byte)((color >> 8) & 0xFF), (byte)(color & 0xFF) ); } // 降级使用主题API或GetSysColor return GetActiveBorderColor(); }
注意事项
- 调用主题API前,需用
IsAppThemed判断系统是否支持主题 - 不同Windows版本的主题元素、属性可能存在差异,需做好兼容性处理
- 自定义主题可能覆盖默认边框颜色逻辑,优先使用主题API获取
内容的提问来源于stack exchange,提问作者user626528
相关产品推荐
相关产品推荐

