2010-07-10 19 views
7

के निर्माण को मजबूर करना मुझे अपने कुछ WPF विंडो के Win32 विंडो हैंडल तक पहुंचने की आवश्यकता है ताकि मैं Win32 सक्रियण संदेशों को संभाल सकूं। मुझे पता है कि Win32 विंडो हैंडल प्राप्त करने के लिए मैं PresentationSource.FromVisual या WindowInteropHelper का उपयोग कर सकता हूं, लेकिन यदि WPF विंडो अभी तक नहीं बनाई गई है तो मैं समस्याओं में भाग रहा हूं।एक WPF विंडो के मूल Win32 हैंडल

यदि मैं PresentationSource.FromVisual का उपयोग करता हूं और विंडो नहीं बनाई गई है, तो लौटाया गया PresentationSource शून्य है। अगर मैं WindowInteropHelper का उपयोग करता हूं और विंडो नहीं बनाई गई है, तो Handle संपत्ति IntPtr.Zero (शून्य) है।

मैंने हैंडल तक पहुंचने का प्रयास करने से पहले विंडो पर this.Show() और this.Hide() पर कॉल करने का प्रयास किया। मैं फिर हैंडल प्राप्त कर सकता हूं, लेकिन विंडो स्क्रीन पर क्षणिक रूप से चमकती है (बदसूरत!)।

क्या कोई भी WPF विंडो बनाने के लिए मजबूर करने के तरीके के बारे में जानता है? विंडोज फॉर्म में यह Form.Handle संपत्ति तक पहुंचने जितना आसान था।

संपादित करें: मैं क्रिस टेलर के जवाब पर एक संस्करण के साथ जा रहा था। यहाँ यह है, के मामले में यह किसी और में मदद करता है:

static void InitializeWindow(Window window) 
{ 
    // Get the current values of the properties we are going to change 
    double oldWidth = window.Width; 
    double oldHeight = window.Height; 
    WindowStyle oldWindowStyle = window.WindowStyle; 
    bool oldShowInTaskbar = window.ShowInTaskbar; 
    bool oldShowActivated = window.ShowActivated; 

    // Change the properties to make the window invisible 
    window.Width = 0; 
    window.Height = 0; 
    window.WindowStyle = WindowStyle.None; 
    window.ShowInTaskbar = false; 
    window.ShowActivated = false; 

    // Make WPF create the window's handle 
    window.Show(); 
    window.Hide(); 

    // Restore the old values 
    window.Width = oldWidth; 
    window.Height = oldHeight; 
    window.WindowStyle = oldWindowStyle; 
    window.ShowInTaskbar = oldShowInTaskbar; 
    window.ShowActivated = oldShowActivated; 
} 

// Use it like this: 
InitializeWindow(myWpfWindow); 
+0

क्या आपने यह प्रश्न देखा है - http://stackoverflow.com/questions/1556182/finding-the-handle-to-a-wpf-window - यह मदद नहीं कर सकता क्योंकि यह उल्लेख नहीं करता है कि विंडो पहले से मौजूद है या नहीं या नहीं। – ChrisF

+0

@ChrisF: धन्यवाद! हाँ, मैंने इसे देखा है। दुर्भाग्यवश, खिड़की के साथ समस्या अभी तक नहीं बनाई जा रही है। –

+0

मैंने सोचा कि मैं इसका उत्तर प्राप्त करने के लिए इसका उल्लेख करूंगा ताकि यदि आपका मामला अलग हो तो इसे डुप्लिकेट के रूप में नहीं चुना जाएगा। – ChrisF

उत्तर

3

एक विकल्प को कम से कम करने के लिए खिड़की राज्य स्थापित करने के लिए और खिड़की दिखाने से पहले टास्कबार में दिखाने के लिए नहीं है। इस तरह कुछ कोशिश करो।

IntPtr hWnd; 
    WindowInteropHelper helper = new WindowInteropHelper(wnd); 

    WindowState prevState = wnd.WindowState; 
    bool prevShowInTaskBar = wnd.ShowInTaskbar; 

    wnd.ShowInTaskbar = false; 
    wnd.WindowState = WindowState.Minimized; 
    wnd.Show(); 
    hWnd = helper.Handle; 
    wnd.Hide(); 

    wnd.ShowInTaskbar = prevShowInTaskBar; 
    wnd.WindowState = prevState; 
+0

धन्यवाद! मैं इस के एक संस्करण के साथ जा रहा है (सवाल पर मेरा संपादन देखें)। –

+2

[@ डैनियलअल्बुस्चैट का जवाब] (http://stackoverflow.com/a/4826741/24874) सरल है और झटके से बचाता है। –

+0

हां, नीचे दिया गया जवाब बहुत साफ है। –

17

WindowInteropHelper.EnsureHandle का उपयोग करें, यह वही है जो आपको चाहिए।

+0

+1 ग्रेट मिल! मुझे इसे आजमा देना होगा। –

+0

मुझे एक ही समस्या मिली, और यह सबसे अच्छा जवाब है! – laishiekai

+0

फिर से, यह स्वीकार किए गए एक से बेहतर जवाब है! कृपया इसके बजाय, सबको इस्तेमाल करें! –

2

यदि विंडोइंटरोपेलपर का हैंडल नल है तो मैं समाधान ढूंढ रहा था। उम्मीद है कि यह पोस्ट कुछ अतिरिक्त जानकारी देता है कि इसे कैसे हल किया जाए।

एक समाधान का उपयोग करने के लिए है:

var window = new Window(); 
var handle = new WindowInteropHelper(window).EnsureHandle() 

यह .NET फ़्रेमवर्क 4

साथ ही काम करता है फिलहाल मैं .NET फ्रेमवर्क 3.5 का उपयोग कर रहा तो मैं एक और समाधान की जरूरत है।

#region 

using System; 
using System.Reflection; 
using System.Windows; 
using System.Windows.Interop; 

#endregion 

namespace System.Windows.Interop 
{ 
    /// <summary> 
    /// Provides NetFX 4.0 EnsureHandle method for 
    /// NetFX 3.5 WindowInteropHelper class. 
    /// </summary> 
    public static class WindowInteropHelperExtension 
    { 
     /// <summary> 
     /// Creates the HWND of the window if the HWND has not been created yet. 
     /// </summary> 
     /// <param name = "helper">An instance of WindowInteropHelper class.</param> 
     /// <returns>An IntPtr that represents the HWND.</returns> 
     /// <remarks> 
     /// Use the EnsureHandle method when you want to separate 
     /// window handle (HWND) creation from the 
     /// actual showing of the managed Window. 
     /// </remarks> 
     public static IntPtr EnsureHandle(this WindowInteropHelper helper) 
     { 
      if (helper == null) 
       throw new ArgumentNullException("helper"); 

      if (helper.Handle == IntPtr.Zero) 
      { 
       var window = (Window) typeof (WindowInteropHelper).InvokeMember(
        "_window", 
        BindingFlags.GetField | 
        BindingFlags.Instance | 
        BindingFlags.NonPublic, 
        null, helper, null); 

       typeof (Window).InvokeMember(
        "SafeCreateWindow", 
        BindingFlags.InvokeMethod | 
        BindingFlags.Instance | 
        BindingFlags.NonPublic, 
        null, window, null); 
      } 

      return helper.Handle; 
     } 
    } 
} 

WindowInteropHelper.EnsureHandle() एक खिड़की पहले से ही बनाई गई है उम्मीद नहीं है: तो फिर मैं एक WindowInteropHelper विस्तार विधि के साथ एक मंच धागा मिल गया।

संदर्भ: अलेक्जेंडर Yudakov - http://social.msdn.microsoft.com/Forums/en-MY/wpf/thread/5f89ac58-d2ef-4ac0-aefb-b2826dbef48a

0

मैं इस एक ही मुद्दे पर अटक और (क्योंकि यह मेरे लिए क्लीनर लगता है) J Pollack's answer साथ चला गया है, लेकिन कुछ है कि दोनों .NET रनटाइम पर चलाना शामिल है की जरूरत थी 2.0 और 4.0।

लेकिन जब मैं यह है कि मैं के साथ एक बदसूरत MissingMethodException क्योंकि SafeCreateWindow अब और .NET रनटाइम 4.0 में मौजूद नहीं है समाप्त हो गया था। दोनों runtimes पर कोड काम मैं MissingMethodException पकड़ने का फैसला किया बनाने के लिए और के बजाय इस तरह .NET 4.0 क्रम में बराबर आह्वान करने के लिए:

public static IntPtr EnsureHandle(this WindowInteropHelper helper) 
    { 
     if (helper == null) 
      throw new ArgumentNullException("helper"); 

     if (helper.Handle == IntPtr.Zero) 
     { 
      var window = (Window)typeof(WindowInteropHelper).InvokeMember(
       "_window", 
       BindingFlags.GetField | 
       BindingFlags.Instance | 
       BindingFlags.NonPublic, 
       null, helper, null); 

      try 
      { 
       // SafeCreateWindow only exists in the .NET 2.0 runtime. If we try to 
       // invoke this method on the .NET 4.0 runtime it will result in a 
       // MissingMethodException, see below. 
       typeof(Window).InvokeMember(
        "SafeCreateWindow", 
        BindingFlags.InvokeMethod | 
        BindingFlags.Instance | 
        BindingFlags.NonPublic, 
        null, window, null); 
      } 
      catch (MissingMethodException) 
      { 
       // If we ended up here it means we are running on the .NET 4.0 runtime, 
       // where the method we need to call for the handle was renamed/replaced 
       // with CreateSourceWindow. 
       typeof(Window).InvokeMember(
        "CreateSourceWindow", 
        BindingFlags.InvokeMethod | 
        BindingFlags.Instance | 
        BindingFlags.NonPublic, 
        null, window, new object[] { false }); 
      } 
     } 

     return helper.Handle; 
    } 

यह मैं .NET 3.5 के साथ कोड संकलन लेकिन पर चलाने की अनुमति दी .NET रनटाइम 4।उन सिस्टम पर 0 जिनमें केवल उच्च रनटाइम संस्करण स्थापित है (अर्थात् विंडोज 8 और ऊपर)।

संबंधित मुद्दे