我没有听说过WinForms窗口从系统接收消息时触发的WinForms事件,但是它有自己的啊,所以这是WndProc()方法可以覆盖.您可能会混淆表单事件的窗口消息.StyleChanged在WinForms窗口中调用的事件.我的其余部分仍然有效.
WPF与Windows API没有密切联系,因为它是一种高级技术,可以从内部投入大量抽象.首先,它会在窗口中自行绘制所有内容,并且不会要求系统为其绘制(编辑:这就是WPF缺少此类StyleChanged事件的原因).也就是说,当切换DWM时以及主题发生变化时,Windows会向所有窗口发送消息,您仍然可以从WPF层深入到低级别来访问这些消息并相应地操作WPF控件.
将窗口过程附加到WPF窗口的HWND(窗口句柄),作为窗口SourceInitialized事件的一部分.在窗口过程中,分别处理WM_DWMCOMPOSITIONCHANGED和WM_THEMECHANGED窗口消息.
这是一个简单的例子(从我的这个问题改编的样板代码):
private IntPtr hwnd;
private HwndSource hsource;
private void Window_SourceInitialized(object sender, EventArgs e)
{
if ((hwnd = new WindowInteropHelper(this).Handle) == IntPtr.Zero)
{
throw new InvalidOperationException("Could not get window handle.");
}
hsource = HwndSource.FromHwnd(hwnd);
hsource.AddHook(WndProc);
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case WM_DWMCOMPOSITIONCHANGED: // Define this as 0x31A
case WM_THEMECHANGED: // Define this as 0x31E
// Respond to DWM being enabled/disabled or system theme being changed
return IntPtr.Zero;
default:
return IntPtr.Zero;
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,接受的解决方案不适用于 Aero 颜色主题更改,并且 WM 消息十六进制数字混合在一起 - 但我同意如果您想在 WPF 中捕获 WM 消息,它非常有用。一段时间以来,我一直在尝试寻找这个问题的解决方案,并且我认为我已经解决了所有可能的情况(对于航空和经典主题)。
Aero 颜色变化会触发 WM_DWMCOLORIZATIONCOLORCHANGED 消息。
要检测颜色主题何时发生变化,您必须使用多种方法。Form.StyleChanged 事件将检测除Aero 颜色更改之外的所有主题更改。这是 StyleChanged 的替代解决方案。(好吧,我知道这是 WinForms,但您已经明白了。无论如何,WPF 等效项已在接受的答案中。)
private const int WM_DWMCOLORIZATIONCOLORCHANGED = 0x320;
private const int WM_DWMCOMPOSITIONCHANGED = 0x31E;
private const int WM_THEMECHANGED = 0x031A;
protected override void WndProc(ref Message m)
{
switch(m.Msg)
{
case WM_DWMCOLORIZATIONCOLORCHANGED:
case WM_DWMCOMPOSITIONCHANGED:
case WM_THEMECHANGED:
// you code here
break;
default:
break;
}
base.WndProc(ref m);
}
Run Code Online (Sandbox Code Playgroud)
对于 Aero 颜色主题,SystemEvents.UserPreferenceChanged 事件也适用(谢谢您!):
Microsoft.Win32.SystemEvents.UserPreferenceChanged += SystemEvents_UserPreferenceChanged;
private void SystemEvents_UserPreferenceChanged(object sender, Microsoft.Win32.UserPreferenceChangedEventArgs e)
{
if (e.Category == Microsoft.Win32.UserPreferenceCategory.General)
{
// your code here, compare saved theme color with current one
}
}
Run Code Online (Sandbox Code Playgroud)
正如您在上面所看到的,它远非直观。Aero 颜色更改会触发“常规”首选项更改事件,尽管有许多更合适的事件,例如“VisualStyle”等...
如果想要彻底,您应该将保存的 DWM 颜色与当前的 DWM 颜色进行比较,以确保它确实是触发此事件的 Aero 颜色主题(使用 DwmGetColorizationParameters API 调用),而不是其他颜色。有关如何检索 Aero 颜色的信息,请参阅以下答案: 获取 Windows 8 自动颜色主题的活动颜色
| 归档时间: |
|
| 查看次数: |
3700 次 |
| 最近记录: |