首頁>Program>source

在windows 8中,我已將配色方案設置為自動,並將墙纸配置為在x分钟後更改.配色方案根据活動壁纸而變化.

我正在開發wPF應用程式,並希望在windows更改配色方案以匹配当前墙纸時更改渐變。

有没有办法获取当前/實際的配色方案並通知C#更改?

最新回復
  • 5月前
    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或更高版本(禁用桌面合成)上執行時.您還需要確保自己不要過度使用它,否則可能会匯致效能嚴重下降並降低應用程式的速度。

  • 5月前
    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中的总和