Search code examples
c#wpfhwndhost

Proper way of hosting an external window inside WPF using HwndHost


I'd like to host a window of an external process inside my WPF application. I'm deriving HwndHost like this:

    class HwndHostEx : HwndHost
    {
        [DllImport("user32.dll")]
        static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

        private IntPtr ChildHandle = IntPtr.Zero;

        public HwndHostEx(IntPtr handle)
        {
            this.ChildHandle = handle;
        }

        protected override System.Runtime.InteropServices.HandleRef BuildWindowCore(System.Runtime.InteropServices.HandleRef hwndParent)
        {
            HandleRef href = new HandleRef();

            if (ChildHandle != IntPtr.Zero)
            {
                SetParent(this.ChildHandle, hwndParent.Handle);
                href = new HandleRef(this, this.ChildHandle);
            }

            return href;
        }

        protected override void DestroyWindowCore(System.Runtime.InteropServices.HandleRef hwnd)
        {

        }
    }

and using it like this:

 HwndHostEx host = new HwndHostEx(handle);
 this.PART_Host.Child = host;

where handle is a handle for an external window I'd like to host and PART_Host is a border inside my WPF window:

<StackPanel UseLayoutRounding="True"
        SnapsToDevicePixels="True"
        Background="Transparent">
        <Border Name="PART_Host" />
...

This gives me an exception:

Hosted HWND must be a child window.

Sorry for my lack of knowledge but what is the proper way of hosting an external window inside WPF application?


Solution

  • Right before calling 'SetParent' do this:

    public const int GWL_STYLE = (-16);
    public const int WS_CHILD = 0x40000000;
    
    SetWindowLong(this.ChildHandle, GWL_STYLE, WS_CHILD);