2012-12-01 18 views
18

विंडोज 8 में, मैंने रंग योजना स्वचालित रूप से सेट की है और x मिनट के बाद बदलने के लिए मेरे वॉलपेपर को कॉन्फ़िगर किया है। सक्रिय वॉलपेपर के अनुसार रंग योजना बदलती है।विंडोज 8 स्वचालित रंग थीम का सक्रिय रंग प्राप्त करें

मैं एक डब्ल्यूपीएफ एप्लीकेशन विकसित कर रहा हूं और जब मैं वर्तमान वॉलपेपर से मेल खाने के लिए रंग योजना बदलता हूं तो मेरे ग्रेडियेंट बदलना चाहते हैं।

क्या कोई तरीका वर्तमान/वास्तविक रंग योजना प्राप्त करता है और सी # में परिवर्तन की अधिसूचित किया जा सकता है?

+0

इसमें काफी इंटरऑप शामिल है और केवल कुछ * अनियंत्रित एपीआई * के साथ ही करने योग्य है। असल में, मैंने इसे विंडोज विस्टा/7 के लिए अपनी परियोजना के साथ किया है, और इसे विंडोज 8 पर सफलतापूर्वक परीक्षण किया है। मैं उस पर आधारित एक जवाब देने की कोशिश कर सकता हूं, लेकिन मुझे थोड़ी देर की आवश्यकता होगी। यह भी देखें: [Vista/7: कांच रंग प्राप्त करने के लिए कैसे?] (http://stackoverflow.com/questions/3560890/vista-7-how-to-get-glass-color) – BoltClock

+0

आप जानकारी के लिए बहुत बहुत धन्यवाद । मैंने रजिस्ट्री चाल का उपयोग किया और यह बहुत अच्छा काम करता है। – user1868880

उत्तर

15

हां, यह संभव है। हालांकि चेतावनी दी जानी चाहिए: इसमें Win32 इंटरऑप का थोड़ा सा हिस्सा शामिल है (इसका मतलब है पी/प्रबंधित कोड से देशी डीएलएल में शामिल है), और केवल कुछ अनियंत्रित एपीआई के साथ करने योग्य है। हालांकि, केवल गैर-दस्तावेजी शामिल सुविधाओं खिड़की रंग योजना प्राप्त करने के लिए कर रहे हैं (या DWM यह कहता है के रूप में, खिड़की colorization रंग) है, जो इस दूसरे प्रश्न में कवर किया जाता है:

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; 
} 

मैं इसे परीक्षण किया है और यह विंडोज 8 और उसके स्वचालित विंडो colorization की सुविधा के साथ महान काम करता है। जैसा कि ऊपर दिए गए लिंक में सुझाया गया है, आप पी/Invoke के विकल्प के रूप में रंग मानों के लिए रजिस्ट्री में देख सकते हैं, लेकिन मैंने उस विधि का परीक्षण नहीं किया है, और जैसा कि कहा गया है कि ये अनियंत्रित हैं और स्थिर होने की गारंटी नहीं है।

एक बार जब आप अपने ढाल ब्रश को चित्रित करने के लिए रंग प्राप्त कर लेते हैं, तो विंडो रंग योजना बदल जाती है, चाहे विंडोज़ द्वारा मैन्युअल रूप से या स्वचालित रूप से ब्रश अपडेट हो जाएंगे। शुक्र है, जब भी ऐसा होता है, तो विंडोज WM_DWMCOLORIZATIONCOLORCHANGED window message प्रसारित करता है, इसलिए आपको बस उस संदेश को सुनने और अपने रंगों को अपडेट होने पर अपडेट करने की आवश्यकता होती है। आप विंडो प्रक्रिया (WndProc()) पर हुक करके ऐसा करते हैं।

WM_DWMCOLORIZATIONCOLORCHANGED का मान 0x320 है; आप इसे कहीं स्थिर के रूप में परिभाषित करना चाहते हैं ताकि आप इसे कोड में उपयोग कर सकें।

इसके अलावा, WinForms के विपरीत, डब्ल्यूपीएफ विंडोज़ में वर्चुअल WndProc() विधि ओवरराइड करने की विधि नहीं है, इसलिए आपको एक प्रतिनिधि के रूप में अपने संबंधित विंडो हैंडल (एचडब्ल्यूएनडी) में एक प्रतिनिधि के रूप में बनाना और हुक करना होगा।

मेरा इन उत्तरों से कुछ उदाहरण कोड ले रहा है:

हम:

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; 
    } 
} 

विंडोज रंग बदलने के संक्रमण के दौरान, WM_DWMCOLORIZATIONCOLORCHANGED है प्रत्येक keyframe पर प्रेषित संक्रमण में, इसलिए आप रंग परिवर्तन के दौरान एक छोटे विस्फोट पर कई संदेश प्राप्त करेंगे। यह सामान्य बात है; बस अपने ग्रेडिएंट ब्रश को सामान्य रूप से अपडेट करें और आपको पता चलेगा कि जब विंडोज़ विंडो रंग योजना को बदलता है, तो आपके ग्रेडियेंट भी खिड़की के फ्रेम के साथ आसानी से संक्रमण करेंगे।

याद रखें कि आप स्थितियों में, जहां DWM उपलब्ध नहीं है, जैसे कि जब Windows XP पर चल रहा है, या Windows Vista पर चल रहा है या बाद में डेस्कटॉप संरचना के साथ अक्षम के रूप में के लिए खाते की आवश्यकता हो सकती है। आप यह भी सुनिश्चित करना चाहते हैं कि आप इसका अधिक उपयोग न करें, या आप एक महत्वपूर्ण प्रदर्शन हिट कर सकते हैं और अपने ऐप को धीमा कर सकते हैं।

+2

और यह मेरा पहला विंडोज 8 जवाब से ... Windows 8 भी जर्जर नहीं ... – BoltClock

+0

वाह तैनात है, 202k अंक: डी –

+0

ओह लड़का है, मैं सिर्फ अपनी टिप्पणी 3 साल पहले से मिल गया। : ओ –

11

यह .NET 4.5 में और बाद में पी/invokes बिना किया जा सकता। SystemParameters वर्ग अब एक StaticPropertyChanged इस ईवेंट के साथ स्थिर WindowGlassBrush और WindowGlassColor गुण है।

XAML से, आपके पास WindowGlassBrush संपत्ति के लिए बाध्य कर सकते हैं:

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

हालांकि, इस काम के साथ पृष्ठभूमि रंग अद्यतन नहीं किया जाएगा स्वचालित रूप से जब विंडोज अपना रंग बदल जाता है। दुर्भाग्य से, SystemParameters नहीं DynamicResource साथ ResourceKeys के रूप में उपयोग करने के लिए है, तो परिवर्तन सूचनाएं प्राप्त करना WindowGlassBrushKey या WindowGlassColorKey गुण प्रदान करता है 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

में SystemParameters.WindowGlassColor संपत्ति .NET 4.5 फ्रेमवर्क सिर्फ Wwps DwmGetColorizationColor –

+0

मैं इस प्रॉपर्टी का उपयोग टेम्पलेट के अंदर कर रहा हूं, क्या पुराने रंग को नए रंग के साथ बदलने के लिए टेम्पलेट को अपडेट करने का कोई तरीका है? –

+0

अफसोस की बात है, SystemParameters.WindowGlassBrush सही उच्चारण रंग वापस नहीं करेगा, कम से कम यह मेरी मशीन पर अलग है। मैं इस कोड का उपयोग करता हूं: https://gist.github.com/paulcbetts/3c6aedc9f0cd39a77c37 –