首页>Program>source

在windows 8中,我已将配色方案设置为自动,并将墙纸配置为在x分钟后更改.配色方案根据活动壁纸而变化.

我正在开发wPF应用程序,并希望在windows更改配色方案以匹配当前墙纸时更改渐变。

有没有办法获取当前/实际的配色方案并通知C#更改?

最新回答
  • 2021-1-12
    1 #

    是的,有可能.但是要警告:这包含了很多win32互操作(这意味着P /从托管代码调用到本机DLL),并且是 only doable with certain undocumented APIs .虽然,唯一涉及的未记录功能是用于获取窗口配色方案(或DwM称之为窗口配色),这在另一个问题中涉及:

    Vista / 7:如何获得玻璃色?

    在我自己的项目中,我使用了对 DwmGetColorizationParameters()的调用 :

    internal static class NativeMethods
    {
        [DllImport("dwmapi.dll", EntryPoint="#127")]
        internal static extern void DwmGetColorizationParameters(ref DWMCOLORIZATIONPARAMS params);
    }
    public struct DWMCOLORIZATIONPARAMS
    {
        public uint ColorizationColor, 
            ColorizationAfterglow, 
            ColorizationColorBalance, 
            ColorizationAfterglowBalance, 
            ColorizationBlurBalance, 
            ColorizationGlassReflectionIntensity, 
            ColorizationOpaqueBlend;
    }
    

    我已经对其进行了测试,它在windows 8及其自动窗口着色功能中都可以很好地工作.正如上面链接中所建议的那样,您可以在注册表中查找颜色值,以替代P / Invoke,但我尚未测试该方法,并且如上所述,这些方法没有记录,因此不能保证稳定。

    一旦获得用于绘制渐变笔刷的颜色,则当窗口配色方案更改时,无论是手动还是由windows自动更改,这些画笔都不会更新.值得庆幸的是,windows广播了 WM_DWMCOLORIZATIONCOLORCHANGED 只要发生这种情况,您就只需要侦听该消息并在发送消息时更新颜色即可.您可以通过挂钩窗口过程( WndProc() )。

    WM_DWMCOLORIZATIONCOLORCHANGED的value 是 0x320 ; 您需要将其定义为某个常量,以便可以在代码中使用它。

    此外,与winForms不同,wPF窗口没有虚拟的 WndProc() 重写方法,因此您必须创建一个并将其作为与其关联的窗口句柄(HwND)的委托挂钩。

    从我的以下答案中获取一些示例代码:

      How do I make a WPF window movable by dragging the extended window frame?

      Detect system theme change in WPF

    我们有:

    const int WM_DWMCOLORIZATIONCOLORCHANGED = 0x320;
    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 static Color GetWindowColorizationColor(bool opaque)
    {
        var params = NativeMethods.DwmGetColorizationParameters();
        return Color.FromArgb(
            (byte)(opaque ? 255 : params.ColorizationColor >> 24), 
            (byte)(params.ColorizationColor >> 16), 
            (byte)(params.ColorizationColor >> 8), 
            (byte) params.ColorizationColor
        );
    }
    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        switch (msg)
        {
            case WM_DWMCOLORIZATIONCOLORCHANGED:
                /* 
                 * Update gradient brushes with new color information from
                 * NativeMethods.DwmGetColorizationParams() or the registry.
                 */
                return IntPtr.Zero;
            default:
                return IntPtr.Zero;
        }
    }
    

    当windows转换颜色更改时, WM_DWMCOLORIZATIONCOLORCHANGED 会在过渡过程中的每个关键帧处分派,因此在颜色更改期间,您会在短时间内收到大量消息.这很正常; 只需像往常一样更新渐变笔刷,您会注意到,当windows转换窗口配色方案时,您的渐变也会与其余窗口框架一起平滑过渡。

    请记住,您可能需要考虑DwM不可用的情况,例如在windows XP上运行,或者在windows Vista或更高版本(禁用桌面合成)上运行时.您还需要确保自己不要过度使用它,否则可能会导致性能严重下降并降低应用程序的速度。

  • 2021-1-12
    2 #

    这可以在.NET 4.5及更高版本中完成,而无需P / Invokes .现在,SystemParameters类具有静态windowGlassBrush和windowGlassColor属性以及StaticPropertyChanged事件。

    从XAML,您可以像这样绑定到windowGlassBrush属性:

    <Grid Background="{x:Static SystemParameters.WindowGlassBrush}">
    

    但是,使用此分配,windows更改颜色时,背景颜色将不会自动更新.不幸的是,SystemParameters不会 提供windowGlassBrushKeywindowGlassColorKey属性以与DynamicResource一起用作ResourceKeys,因此获取更改通知需要后面的代码来处理StaticPropertyChanged事件。

    not
    
    public partial class MainWindow : Window { public MainWindow() { this.InitializeComponent(); SystemParameters.StaticPropertyChanged += this.SystemParameters_StaticPropertyChanged; // Call this if you haven't set Background in XAML. this.SetBackgroundColor(); } protected override void OnClosed(EventArgs e) { SystemParameters.StaticPropertyChanged -= this.SystemParameters_StaticPropertyChanged; base.OnClosed(e); } private void SetBackgroundColor() { this.Background = SystemParameters.WindowGlassBrush; } private void SystemParameters_StaticPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (e.PropertyName == "WindowGlassBrush") { this.SetBackgroundColor(); } } }

  • Matlab旋转图像而不使用旋转
  • foreach循环php中的总和