Intention
Using the following code, I managed to load some applications in my windows form.
Code
What this function does is…
- stating a process
- embedding the process into a panel of my form
- maximizing the embedded process
- adding a resize event handler to the panel to update the size of the embedded process on panel resize
- adding a closed event handler to the form to terminate the embedded process on form close
Usings
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
Constants
const int GWL_STYLE = -16;
const long WS_VISIBLE = 0x10000000,
WS_MAXIMIZE = 0x01000000,
WS_BORDER = 0x00800000,
WS_CHILD = 0x40000000;
Function
IntPtr LoadExtern(Control Panel, string Path)
{
try
{
Process Process = Process.Start(Path);
Process.WaitForInputIdle();
IntPtr Handle = Process.MainWindowHandle;
SetParent(Handle, Panel.Handle);
SetWindowLong(Handle, GWL_STYLE, (int)(WS_VISIBLE+(WS_MAXIMIZE|WS_BORDER)));
MoveWindow(Handle, 0, 0, Panel.Width, Panel.Height, true);
Panel.Resize += new EventHandler(
delegate(object sender, EventArgs e)
{
MoveWindow(Handle, 0, 0, Panel.Width, Panel.Height, true);
}
);
this.FormClosed += new FormClosedEventHandler(
delegate(object sender, FormClosedEventArgs e) {
SendMessage(Handle, 83, 0, 0);
Thread.Sleep(1000);
Handle = IntPtr.Zero;
}
);
return Handle;
}
catch (Exception e) { MessageBox.Show(this, e.Message, "Error"); }
return new IntPtr();
}
DLL Imports
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll")]
static extern bool MoveWindow(IntPtr Handle, int x, int y, int w, int h, bool repaint);
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr Handle, int Msg, int wParam, int lParam);
Result
This code works nice with some applications, like the windows notepad. Notepad is started and included in the panel of my form. There is no caption and the are no borders, as it should be.
LoadExtern(panel1, "notepad.exe");
After closing the form the embedded process gets terminated like expected.
Problem
Unfortunately my code doesn’t work for some other (bigger) applications like firefox or sublimetext.
LoadExtern(panel2, @"C:\Program Files (x86)\Mozilla Firefox\firefox.exe");
What happens is that my form starts and firefox starts, but in its own window. Could you help me to include sublimetext or firefox in my applications?
Part of the solution
Thanks to Sheng Jiang’s answers, I got it working for some more applications. What I did is to wait for a main window handle.
Process.WaitForInputIdle();
IntPtr Handle = new IntPtr();
for (int i = 0; Handle == IntPtr.Zero && i < 300; i++)
{
Handle = Process.MainWindowHandle;
Thread.Sleep(10);
}
But I still can’t embed applications like the windows explorer.
This code works for most applcations. I embedded the file explorer simply using a webbrowser control on my form and set its url to a file location. The internet explorer control magically turns into a file explorer then.
This is my final code, feel free to use this for you own projects.
I somebody is interested in the hole C# classes for embedding window processes and console processes into your form, check out this github repository.