2012-12-01 84 views
18

在Windows 8中,我已將顏色方案設置爲自動並將配置我的牆紙在x分鐘後更改。配色方案根據活動壁紙而變化。獲取Windows 8自動顏色主題的活動顏色

我正在開發一個WPF應用程序,並希望在Windows更改顏色方案以匹配當前壁紙時更改我的漸變。

有沒有辦法獲取當前/實際的配色方案並通知C#中的更改?

+0

這包含了相當多的互操作性,只適用於某些*未公開的API *。事實上,我已經使用我自己的Windows Vista/7項目完成了這個任務,並在Windows 8上成功地進行了測試。我可以嘗試根據這個答案提出一個答案,但我需要一段時間。另請參閱:[Vista/7:如何獲取玻璃顏色?](http://stackoverflow.com/questions/3560890/vista-7-how-to-get-glass-color) – BoltClock

+0

非常感謝您的信息。我使用了註冊表技巧,效果很好。 – user1868880

回答

15

是的,這是可能的。但是需要注意的是:這包含了很多Win32互操作(這意味着P /從託管代碼調用本地DLL),並且僅適用於某些未公開的API。雖然涉及的只是無證特點是獲得窗口顏色方案(或爲DWM調用它,窗口上色的顏色),這是覆蓋在這個其他問題:

Vista/7: How to get glass color?

在我自己的項目,我使用的調用來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 window message,所以只需要聽取該消息並在發送時更新顏色。您可以通過掛鉤窗口程序(WndProc())來完成此操作。

WM_DWMCOLORIZATIONCOLORCHANGED的值是0x320;你會想把它定義爲常量,所以你可以在代碼中使用它。另外,與WinForms不同,WPF窗口沒有虛擬的WndProc()方法來覆蓋,因此您必須創建一個代理並將其掛接到其關聯的窗口句柄(HWND)。

以一些示例代碼從我的這些問題的答案:

我們:

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或更高版本上運行並禁用桌面合成時。您還需要確保不會過度使用此功能,否則可能會導致嚴重的性能下降並拖慢您的應用程序。

+2

這是我第一次發佈Windows 8的答案... Windows 8.不是太破舊... – BoltClock

+0

哇,202k點:D –

+0

哦,男孩,我剛剛從3年前發現我的評論。 :O –

11

這可以在.NET 4.5及更高版本中完成,無需P/Invokes。 SystemParameters類現在具有靜態WindowGlassBrushWindowGlassColor屬性以及StaticPropertyChanged事件。

從XAML,您可以綁定到WindowGlassBrush屬性,如:

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

然而,這項任務的背景顏色不會得到更新時自動的Windows改變它的顏色。不幸的是,SystemParameters不提供WindowGlassBrushKeyWindowGlassColorKey性能與DynamicResource ResourceKeys使用,因此讓變更通知要求後面的代碼來處理StaticPropertyChanged事件。

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(); 
     } 
    } 
} 
+0

System.Data.Services.WindowGlassColor屬性中的SystemParameters.WindowGlassColor屬性.NET 4.5框架只是包裝DwmGetColorizationColor –

+0

我在模板內使用此屬性,有沒有什麼辦法更新模板來替換舊的顏色與新的? –

+0

不幸的是,SystemParameters.WindowGlassBrush將不會返回正確的重音顏色,至少它在我的機器上是不同的。我使用這個代碼:https://gist.github.com/paulcbetts/3c6aedc9f0cd39a77c37 –