views:

103

answers:

2

I need to access the Win32 window handles of some of my WPF windows so I can handle Win32 activation messages. I know I can use PresentationSource.FromVisual or WindowInteropHelper to get the Win32 window handle, but I am running into problems if the WPF window has not been created yet.

If I use PresentationSource.FromVisual and the window has not been created, the returned PresentationSource is null. If I use WindowInteropHelper and the window has not been created, the Handle property is IntPtr.Zero (null).

I tried calling this.Show() and this.Hide() on the window before I tried to access the handle. I can then get the handle, but the window flashes momentarily on the screen (ugly!).

Does anyone know of a way to force a WPF window to be created? In Windows Forms this was as easy as accessing the Form.Handle property.

Edit: I ended up going with a variant on Chris Taylor's answer. Here it is, in case it helps someone else:

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);
+3  A: 

One option is to set window state to minimized and not to show in the taskbar before Showing the window. Try something like this.

  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;
Chris Taylor
Thanks! I ended up going with a variant of this (see my edit on the question).
Zach Johnson
+1  A: 

I've just found an answer to this question

Top-level Window classes do [have handles], and they can be obtained by the method in your code, but not until the handle is actually created. Once the SourceInitialized event has fired you can assume the handle has been created and you won't get a zero pointer back.

From this it looks like you can't "pre-create" the window to get the handle.

ChrisF