2009-09-09 22 views
45

मैं PInvoking RegisterHotKey() द्वारा विंडो दिखाने के लिए एक वैश्विक हॉट कुंजी बनाते हैं। लेकिन ऐसा करने के लिए मुझे उस विंडो की HWND की आवश्यकता है, जो विंडो लोड होने तक मौजूद नहीं है, इसका मतलब है कि पहली बार दिखाया गया है। लेकिन मैं हॉट कुंजी सेट करने से पहले खिड़की दिखाना नहीं चाहता हूं। क्या उस विंडो के लिए HWND बनाने का कोई तरीका है जो उपयोगकर्ता के लिए अदृश्य है?इसे दिखाए बिना एक WPF विंडो लोड हो रहा है

उत्तर

56

आप .NET 4.0 लक्षित कर रहे हैं आप WindowInteropHelper पर उपलब्ध नए EnsureHandle विधि का उपयोग कर सकते:

public void InitHwnd() 
{ 
    var helper = new WindowInteropHelper(this); 
    helper.EnsureHandle(); 
} 

(pointing this out. के लिए थॉमस लेवेस्क करने के लिए धन्यवाद)

आप .नेट फ्रेमवर्क के एक पुराने संस्करण को लक्षित कर रहे हैं, तो सबसे आसान तरीका कुछ गुण स्थापित सुनिश्चित करने के लिए है, जबकि HWND को पाने के लिए खिड़की दिखाने के लिए है कि खिड़की अदृश्य है और ध्यान चोरी नहीं करता है:

var window = new Window() //make sure the window is invisible 
{ 
    Width = 0, 
    Height = 0, 
    WindowStyle = WindowStyle.None, 
    ShowInTaskbar = false, 
    ShowActivated = false 
}; 
window.Show(); 

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

+2

में बदल गया है, यह काम करता है, धन्यवाद। विंडोस्टेट को सेट करना भी जरूरी नहीं है। साथ ही, मैंने एक्सएएमएल में विंडो की सामग्री सेट की है, लेकिन यह महत्वपूर्ण नहीं है। एक और बात यह है कि WindowStartupLocation = CentreScreen इस तरह से सही तरीके से काम नहीं करता है, लेकिन इसे ठीक करना आसान है। – svick

+0

ने विंडोस्टेट सेटर हटा दिया ... मुझे बताने के लिए धन्यवाद। –

+1

मैं 'ResizeMode = ResizeMode.NoResize' भी जोड़ूंगा, क्योंकि यह आकार बदलने के लिए विंडो सीमा को हटा देता है। – schnaader

0

विंडोइंटरोपेलर क्लास आपको WPF विंडो के लिए HWND प्राप्त करने की अनुमति देनी चाहिए।

MyWindow win = new MyWindow(); 
WindowInteropHelper helper = new WindowInteropHelper(win); 

IntPtr hwnd = helper.Handle; 

MSDN Documentation

+1

मैं यही कर रहा हूं, लेकिन इस तरह, विंडो में अभी तक कोई HWND नहीं है, इसलिए सहायक। हैंडल 0 है, जो मुझे चाहिए। – svick

5

मैं तुम क्या कर रहे करने की कोशिश की कभी नहीं किया है, लेकिन अगर आप HWND पाने के लिए विंडो दिखाने की जरूरत है, लेकिन नहीं करना चाहती दिखाने यह, सेट खिड़की की अस्पष्टता 0 तक। यह किसी हिट परीक्षण को होने से भी रोक देगा। जब आप इसे दृश्यमान बनाना चाहते हैं तो अस्पष्टता को बदलने के लिए विंडो पर एक सार्वजनिक विधि हो सकती है।

+0

यह एक गंदे हैक की तरह है, लेकिन यह निश्चित रूप से काम करेगा। –

+0

दुर्भाग्य से, अस्पष्टता सेटिंग प्रभावी होने के लिए, अनुमति ट्रांस्पेरेंसी को सत्य पर सेट किया जाना चाहिए और इससे बदले में विंडो स्टाइल को विंडो स्टाइल में मजबूर कर दिया जाएगा। कोई नहीं, जो मैं चाहता हूं। इसके अलावा, विंडो दिखाए जाने के बाद अनुमति ट्रांस्पेरेंसी को बदला नहीं जा सकता है, इसलिए मैं इसे बाद में सेट नहीं कर सकता। – svick

0

अस्पष्टता 0 को सेट करने के लिए एक समान नस में एक और विकल्प, आकार को 0 पर सेट करना और स्थिति को स्क्रीन से बाहर सेट करना है। इसके लिए AllowTransparency = True की आवश्यकता नहीं होगी।

यह भी याद रखें कि एक बार जब आप इसे दिखाएंगे तो एक बार जब आप इसे छुपा सकते हैं और अभी भी एचडब्ल्यूएन प्राप्त कर सकते हैं।

16

यह एक गंदा हैक है, लेकिन यह काम करना चाहिए, और अस्पष्टता को बदलने की कमियां नहीं है:

  • सेट WindowStartupLocationManual-
  • कहीं बाहर करने के लिए Top और Left गुण सेट स्क्रीन
  • गलत पर ShowInTaskbar सेट इतना है कि उपयोगकर्ता का एहसास नहीं है वहाँ एक नई विंडो
  • Show और Hide वें है ई खिड़की

अब आप HWND

संपादित पुनः प्राप्त करने में सक्षम होना चाहिए:, एक और विकल्प शायद बेहतर: सेट गलत पर ShowInTaskBar और Minimized को WindowState, तो यह दिखाने: यह बिल्कुल नहीं दिखाई देंगे

+2

+1 ShowInTaskBar = झूठी और विंडोस्टेट = न्यूनतम कार्य। –

+2

आपके दूसरे विकल्प के साथ, मैं स्क्रीन के निचले बाएं कोने में विंडो को कम से कम देख सकता हूं। लेकिन पहला वादा करता है। – svick

+0

@ एसविक: आप किस ओएस का उपयोग कर रहे हैं? विंडोज 7 पर कम से कम विंडो –

0

विंडो 0 x 0 पीएक्स का आकार बनाएं, ShowInTaskBar को झूठी पर रखें, इसे दिखाएं, फिर आवश्यक होने पर इसका आकार बदलें।

3

मुझे WPF के बारे में बिल्कुल कुछ नहीं पता है, लेकिन क्या आप WM_HOTKEY संदेश प्राप्त करने के लिए अन्य माध्यमों (उदाहरण के लिए PInvoke) का उपयोग करके message only window बना सकते हैं? यदि हां, तो एक बार जब आप WM_HOTKEY प्राप्त करते हैं, तो आप वहां से WPF विंडो लॉन्च कर सकते हैं।

+0

+1, यदि आप ऐसा करना चाहते हैं तो आप केवल एक अन्य थ्रेड पर Winforms विंडो का उपयोग कर सकते हैं। –

15

आप विंडो को एक तथाकथित संदेश-केवल विंडो में भी बदल सकते हैं। चूंकि यह विंडो प्रकार ग्राफ़िकल तत्वों का समर्थन नहीं करता है, यह कभी नहीं दिखाया जाएगा। मूल रूप से यह बुला करने के लिए नीचे आता है:

SetParent(hwnd, (IntPtr)HWND_MESSAGE); 

या तो एक समर्पित संदेश विंडो जो हमेशा छुपा होगा बना सकते हैं या असली जीयूआई विंडो का उपयोग और इसे वापस एक सामान्य विंडो के लिए बदल जब आप इसे प्रदर्शित करना चाहते हैं। अधिक पूर्ण उदाहरण के लिए नीचे दिए गए कोड को देखें।

[DllImport("user32.dll")] 
    static extern IntPtr SetParent(IntPtr hwnd, IntPtr hwndNewParent); 

    private const int HWND_MESSAGE = -3; 

    private IntPtr hwnd; 
    private IntPtr oldParent; 

    protected override void OnSourceInitialized(EventArgs e) 
    { 
     base.OnSourceInitialized(e); 
     HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource; 

     if (hwndSource != null) 
     { 
      hwnd = hwndSource.Handle; 
      oldParent = SetParent(hwnd, (IntPtr)HWND_MESSAGE); 
      Visibility = Visibility.Hidden; 
     } 
    } 

    private void OpenWindowMenuItem_Click(object sender, RoutedEventArgs e) 
    { 
     SetParent(hwnd, oldParent); 
     Show(); 
     Activate(); 
    } 

मेरे लिए क्या लगता है की एक कष्टप्रद छाया के साथ, शून्य और किसी से शैली के लिए चौड़ाई, ऊँचाई की स्थापना ऐसा नहीं हो पाया के रूप में यह अभी भी एक छोटे से खिड़की से पता चला है, का समाधान एक के चारों ओर बॉर्डर होना करने के लिए 0x0 विंडो (विंडोज 7 पर परीक्षण)। इसलिए मैं यह वैकल्पिक विकल्प प्रदान कर रहा हूं।

+1

यह केवल 100% समाधान प्रतीत होता है। –

+0

इस महान टिप के लिए धन्यवाद।यह वास्तव में मेरी मदद करता है, क्योंकि यहां अन्य सभी समाधानों ने कुछ दुष्प्रभाव पैदा किए जो कि सुंदर नहीं थे। लेकिन दुख की बात है, लेकिन आपका भी करता है। मुझे मेट्रोविंडो मिला (फ्लुएंट रिबन सूट का उपयोग करके)। इसके बाद खिड़की में एक सामान्य खिड़की सीमा होती है, जो आमतौर पर उन मेट्रोविंडोज़ के लिए दृश्यमान नहीं होती है ... कोई विचार यह कैसे हल करें? – SharpShade

+0

बिल्कुल सही। यह सिर्फ जरूरत है: ShowActivated = झूठा; दृश्यता के बाद, क्योंकि इसके बिना यह चमकती है। – blez

10

मैंने पहले से ही उस प्रश्न का उत्तर पोस्ट कर दिया था, लेकिन मुझे अभी एक बेहतर समाधान मिला है।

आप सिर्फ इतना है कि HWND बनाई गई है सुनिश्चित करने की आवश्यकता है, तो वास्तव में खिड़की बिना दिखाए, तो आप ऐसा कर सकते हैं:

public void InitHwnd() 
    { 
     var helper = new WindowInteropHelper(this); 
     helper.EnsureHandle(); 
    } 

(वास्तव में EnsureHandle विधि उपलब्ध नहीं था जब प्रश्न पोस्ट किया गया था, इसे .NET 4.0 में पेश किया गया था)

+0

अच्छी तरह से किया गया थॉमस – tofutim

+0

यह शायद अब स्वीकार्य उत्तर होना चाहिए, या मुझे यह भी शामिल करने के लिए अपना उत्तर अपडेट करना चाहिए? निश्चित रूप से फ्रेमवर्क संस्करण मतभेदों के लिए सम्मानित अभ्यास क्या है। –

+0

@ पैट्रिकक्लॉग, मुझे या तो पता नहीं है ... आप या तो इसे अपने उत्तर में शामिल कर सकते हैं, या सिर्फ मेरे उत्तर का संदर्भ दे सकते हैं, जो भी आपको लगता है वह सबसे अच्छा है। –

0

मैंने अदृश्य विंडो दिखाने के लिए विस्तार विधि बनाई है, अगले Show कॉल ठीक व्यवहार करेंगे।

public static class WindowHelper 
{ 
    public static void ShowInvisible(this Window window) 
    { 
     // saving original settings 
     bool needToShowInTaskbar = window.ShowInTaskbar; 
     WindowState initialWindowState = window.WindowState; 

     // making window invisible 
     window.ShowInTaskbar = false; 
     window.WindowState = WindowState.Minimized; 

     // showing and hiding window 
     window.Show(); 
     window.Hide(); 

     // restoring original settings 
     window.ShowInTaskbar = needToShowInTaskbar; 
     window.WindowState = initialWindowState; 
    } 
} 
संबंधित मुद्दे