c# - 检测 WPF 中的系统主题更改

标签 c# .net wpf winapi dwm

对于我的 WPF 应用程序,我需要检测 DWM 何时打开/关闭或系统主题何时更改。
WinForms 中有这样的事件,但我在 WPF 中看不到。

最佳答案

我还没有听说过当 WinForms 窗口从系统接收消息时触发的 WinForms 事件,但是它有自己的 WndProc() 方法你可以覆盖。您可能混淆了窗体事件的窗口消息。 啊,所以在 WinForms 窗口中调用的是 StyleChanged 事件。不过,我的其余回答仍然有效。

WPF 与 Windows API 没有紧密联系,因为它是一种高级技术,在内部进行了大量抽象。首先,它自己在窗口中绘制一切,并且不要求系统为其绘制(编辑:,这就是为什么 WPF 缺少这样一个 StyleChanged 事件)。也就是说,当切换 DWM 和主题更改时,Windows 会向所有窗口发送消息,您仍然可以从 WPF 层深入到低级别以访问这些消息并相应地操作您的 WPF 控件。

将窗口过程作为窗口的 SourceInitialized 事件的一部分附加到 WPF 窗口的 HWND(窗口句柄)。在您的窗口过程中,处理 WM_DWMCOMPOSITIONCHANGEDWM_THEMECHANGED分别显示窗口消息。

这是一个简单的例子(样板代码改编自 this question of mine ):

private IntPtr hwnd;
private HwndSource hsource;

private const int WM_DWMCOMPOSITIONCHANGED= 0x31E;
private const int WM_THEMECHANGED = 0x31A;

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: 
        case WM_THEMECHANGED:         

            // Respond to DWM being enabled/disabled or system theme being changed

            return IntPtr.Zero;

        default:
            return IntPtr.Zero;
    }
}

关于c# - 检测 WPF 中的系统主题更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6360671/

相关文章:

c# - .Net 控制台应用程序调用一个 Web API,调用另一个 Web API

c# - 将 C# ExtNet DirectMethod 实现转换为 VB.NET

c# - 向后播放动画( Storyboard)

c# - WPF 应用程序中的复合 ViewModel

wpf - 如何更新绑定(bind)的自定义依赖属性的源?

c# - 目前仅支持HTTP/1.0和HTTP/1.1版本请求

c# - 三星 6S 上 C# .NET 4.5.1 MVC 5.2.2 中的 MP3 流式传输

.net - 在 HSM 上使用私钥的 SSL

c# - 期间无限循环

.net - 如何将我的 IServiceLocator 实现设置为 ServiceLocator.Current?