【发布时间】:2020-03-15 15:43:19
【问题描述】:
【问题讨论】:
-
从您的图形中,您看起来像是从“颜色”设置页面中选择了 Accent 颜色,而不是从“背景设置”页面中选择了背景颜色。获取背景颜色很容易,而获取强调色则更复杂。
-
是的,我需要强调色
【问题讨论】:
您需要致电UISettings.GetColorValue(UIColorType.Background),如记录的here。
【讨论】:
WinForms 是一项旧技术,尚未进行太多更新以支持新的操作系统功能。没有使用基本 .Net 库获取 Accent 颜色的好方法(尽管有一个基于注册表的黑客使用未记录的键来检索值)。幸运的是,您可以通过添加 NUGET 包 Microsoft.Windows.SDK.Contracts 来访问某些 Windows 运行时 API。
添加此包后,您可以创建Windows.UI.ViewManagement.UISettings Class 的实例,然后使用UISettings.GetColorValue(UIColorType) Method 检索值。
要收到值更改的通知,您可以订阅SystemEvents.UserPreferenceChanged Event。此事件将更改归类为 UserPreferenceCategory.General 类型更改,这是旧逻辑不知道发生了什么更改时的默认值(同样旧代码未针对新功能更新)。您可以通过listenimg 检测WM_SETTINGCHANGE message 的更改并检查WParam 何时为空并且LParam 指向一个字符串(“ImmersiveColorSet”),但这依赖于字符串值永远不会改变并且并不比对所有响应好多少UserPreferenceCategory.General 更改。
综上所述,一个简单的实现如下:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
UserPreferenceChangedEventHandler UserPerferenceChanged = (s, e) =>
{ if (e.Category == UserPreferenceCategory.General || e.Category == UserPreferenceCategory.VisualStyle) BackColor = GetAccentColor(); };
SystemEvents.UserPreferenceChanged += UserPerferenceChanged;
Disposed += (object s, EventArgs e) => { SystemEvents.UserPreferenceChanged -= UserPerferenceChanged; };
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
BackColor = GetAccentColor();
}
static Windows.UI.ViewManagement.UISettings uiSettings = new Windows.UI.ViewManagement.UISettings();
private static System.Drawing.Color GetAccentColor()
{
Windows.UI.Color c = uiSettings.GetColorValue(Windows.UI.ViewManagement.UIColorType.Accent);
return Color.FromArgb(c.A, c.R, c.G, c.B);
}
}
【讨论】:
您可以覆盖WndProc 来处理WM_SETTINGCHANGE 消息。
收到此消息后,您可以通过检查消息WParam 来确定设置更改是否与桌面更改有关:如果是SPI_SETDESKWALLPAPER,则桌面设置已更改。
背景颜色的变化是这样通知的。
当您收到消息时,颜色值已更改,因此您可以使用 SystemColors 类检索它:SystemColors.Desktop 返回桌面的当前颜色。
private const int WM_SETTINGCHANGE = 0x001A;
private const int SPI_SETDESKWALLPAPER = 0x0014;
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
switch (m.Msg) {
case WM_SETTINGCHANGE:
if (m.WParam.ToInt32() == SPI_SETDESKWALLPAPER) {
this.BackColor = SystemColors.Desktop;
}
m.Result = IntPtr.Zero;
break;
// other case switches
}
【讨论】: