Search code examples
c#.netwpfwinapihandle

Forcing the creation of a WPF Window's native Win32 handle


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

Solution

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