Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Host extern Win32 Window in WPF

0.00/5 (No votes)
11 Apr 2015 1  

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)

C#
[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);

 

C#
    //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:
XML
<my:YourClass x:Name="host"></my:YourClass>

Execute Process:

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

History

11th April, 2015

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here