65.9K
CodeProject is changing. Read more.
Home

Host extern Win32 Window in WPF

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (2 votes)

Apr 11, 2015

CPOL
viewsIcon

18254

Introduction

I used this code snippet in early 2008 as I was working in a WPF Project that had to support/integrate

a navigation system (which was written with WinForms). 

The task was to host this Win32 Window into the WPF Application.

Using the code

Create a new classed derived from System.Windows.Controls.ContentControl

P/Invoke(s)

[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X,
int Y, int cx, int cy, uint uFlags);

[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

[DllImport("user32.dll", SetLastError = true)]
static extern int GetWindowLong(IntPtr hWnd, int nIndex);

 

    //Recalculate the size and position of the windows client area.
    const UInt32 SWP_FRAMECHANGED = 0x0020;  /* The frame changed: send WM_NCCALCSIZE */ 
    //set a new Window Style (Border, has horizontal/vertical scrollbar, please see MSDN)
    static readonly int GWL_STYLE = (-16);
    //the specified window has a title bar
    public const uint WS_CAPTION = 0x00C00000;
    //Creates a window with a resizable frame.
    public const uint WS_THICKFRAME = 0x00040000;
    //If the parent window is redrawn,the area which is covered by the "child" windows will be excluded.
    public const uint WS_CLIPCHILDREN = 0x02000000;
    //Create a new overlapped window,take care that it has a titlebar and border per default.
    public const uint WS_OVERLAPPED = 0x00000000; 
 
    private WindowsFormsHost host = new WindowsFormsHost();
    private System.Windows.Forms.Panel panel = new System.Windows.Forms.Panel();
    private IntPtr windowHandle;

    public System.Diagnostics.Process Process
    {
        set
        {
            try
            {
                value.Start();
                
                if (!value.WaitForInputIdle(3000))
                {
                    throw new ArgumentException();   
                }
                //For correct responding, it's important to let sleep our thread for a while.
                System.Threading.Thread.Sleep(1000);
                this.windowHandle = value.MainWindowHandle;
                int dwStyle = GetWindowLong(this.windowHandle, GWL_STYLE);
                SetWindowLong(this.windowHandle, GWL_STYLE, new IntPtr(dwStyle &
                ~WS_CAPTION & ~WS_THICKFRAME));
                SetWindowPos(this.windowHandle, IntPtr.Zero, 0, 0,
                Convert.ToInt32(Math.Floor(this.ActualWidth)),
                Convert.ToInt32(Math.Floor(this.ActualHeight)), SWP_FRAMECHANGED);
                SetParent(this.windowHandle, panel.Handle);        
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message.ToString());
            }
        }
    }

    public Window_Host_Helper()
    {
        this.Content = host;
        this.panel.CreateControl();
        host.Child = this.panel;
    }

    protected override void OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs e)
    {
        base.OnPropertyChanged(e);
    }

    protected override System.Windows.Size ArrangeOverride(System.Windows.Size arrangeBounds)
    {
        base.ArrangeOverride(arrangeBounds);
        SetWindowPos(this.windowHandle, IntPtr.Zero, 0, 0,
        Convert.ToInt32(Math.Floor(arrangeBounds.Width)),
        Convert.ToInt32(Math.Floor(arrangeBounds.Height)), 0);

        return arrangeBounds;
    }

    protected override void OnContentChanged(object oldContent, object newContent)
    {
        this.Content = this.host;
    }  
}
XAML:
<my:YourClass x:Name="host"></my:YourClass>

Execute Process:

Process p = new Process();
p.StartInfo = new ProcessStartInfo(@"c:\process.exe");
host.Process = p;
Kill Process:
private void Page_Unloaded(object sender, RoutedEventArgs e)
{
    try
    {
         p.Kill();
    }
    catch (Exception ex)
    {
         Console.WriteLine(ex.Message.ToString());
    }
}

History

11th April, 2015