Click here to Skip to main content
12,621,923 members (34,985 online)
Click here to Skip to main content

Stats

332.4K views
17.8K downloads
160 bookmarked
Posted

Hosting EXE Applications in a WinForm project

, 21 Dec 2004
A custom control to launch and embed an EXE into a WinForm based application.
WindowsApplication1
App.ico
bin
WindowsApplication1.csproj.user
AppControl
AppControl.bmp
AppControl.csproj.user
bin
Release
AppControl.dll
using System;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace AppControl
{

	/// <summary>
	/// Application Display Control
	/// </summary>
	[
	ToolboxBitmap(typeof(ApplicationControl), "AppControl.bmp"),	
	]
	public class ApplicationControl : System.Windows.Forms.Panel
	{

		/// <summary>
		/// Track if the application has been created
		/// </summary>
		bool created = false;

		/// <summary>
		/// Handle to the application Window
		/// </summary>
		IntPtr appWin;

		/// <summary>
		/// The name of the exe to launch
		/// </summary>
		private string exeName = "";

		/// <summary>
		/// Get/Set if we draw the tick marks
		/// </summary>
		[
		Category("Data"),
		Description("Name of the executable to launch"),		
		DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)
		]
		public string ExeName
		{
			get
			{
				return exeName;
			}
			set
			{
				exeName = value;				
			}
		}

		
		/// <summary>
		/// Constructor
		/// </summary>
		public ApplicationControl()
		{			
		}


		[DllImport("user32.dll", EntryPoint="GetWindowThreadProcessId",  SetLastError=true,
			 CharSet=CharSet.Unicode, ExactSpelling=true,
			 CallingConvention=CallingConvention.StdCall)]
		private static extern long GetWindowThreadProcessId(long hWnd, long lpdwProcessId); 
			
		[DllImport("user32.dll", SetLastError=true)]
		private static extern IntPtr FindWindow (string lpClassName, string lpWindowName);

		[DllImport("user32.dll", SetLastError=true)]
		private static extern long SetParent (IntPtr hWndChild, IntPtr hWndNewParent);

		[DllImport("user32.dll", EntryPoint="GetWindowLongA", SetLastError=true)]
		private static extern long GetWindowLong (IntPtr hwnd, int nIndex);

		[DllImport("user32.dll", EntryPoint="SetWindowLongA", SetLastError=true)]
		private static extern long SetWindowLong (IntPtr hwnd, int nIndex, long dwNewLong);

		[DllImport("user32.dll", SetLastError=true)]
		private static extern long SetWindowPos(IntPtr hwnd, long hWndInsertAfter, long x, long y, long cx, long cy, long wFlags);
		
		[DllImport("user32.dll", SetLastError=true)]
		private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);
		
		[DllImport("user32.dll", EntryPoint="PostMessageA", SetLastError=true)]		
		private static extern bool PostMessage(IntPtr hwnd, uint Msg, long wParam, long lParam);
		
		private const int SWP_NOOWNERZORDER = 0x200;
		private const int SWP_NOREDRAW = 0x8;
		private const int SWP_NOZORDER = 0x4;
		private const int SWP_SHOWWINDOW = 0x0040;
		private const int WS_EX_MDICHILD = 0x40;
		private const int SWP_FRAMECHANGED = 0x20;
		private const int SWP_NOACTIVATE = 0x10;
		private const int SWP_ASYNCWINDOWPOS = 0x4000;
		private const int SWP_NOMOVE = 0x2;
		private const int SWP_NOSIZE = 0x1;
		private const int GWL_STYLE = (-16);
		private const int WS_VISIBLE = 0x10000000;
		private const int WM_CLOSE = 0x10;
		private const int WS_CHILD = 0x40000000;
		
		/// <summary>
		/// Force redraw of control when size changes
		/// </summary>
		/// <param name="e">Not used</param>
		protected override void OnSizeChanged(EventArgs e)
		{
			this.Invalidate();
			base.OnSizeChanged (e);
		}


		/// <summary>
		/// Creeate control when visibility changes
		/// </summary>
		/// <param name="e">Not used</param>
		protected override void OnVisibleChanged(EventArgs e)
		{

			// If control needs to be initialized/created
			if (created == false)
			{

				// Mark that control is created
				created = true;

				// Initialize handle value to invalid
				appWin = IntPtr.Zero;

				// Start the remote application
				Process p = null;
				try
				{

					// Start the process
					p = System.Diagnostics.Process.Start(this.exeName);

					// Wait for process to be created and enter idle condition
					p.WaitForInputIdle();

					// Get the main handle
					appWin = p.MainWindowHandle;
				}
				catch (Exception ex)
				{
					MessageBox.Show(this, ex.Message, "Error");
				}			
            
				// Put it into this form
				SetParent(appWin, this.Handle);

				// Remove border and whatnot
				SetWindowLong(appWin, GWL_STYLE, WS_VISIBLE);

				// Move the window to overlay it on this window
				MoveWindow(appWin, 0, 0, this.Width, this.Height, true);
				
			}

			base.OnVisibleChanged (e);
		}

	
		/// <summary>
		/// 
		/// </summary>
		/// <param name="e"></param>
		protected override void OnHandleDestroyed(EventArgs e)
		{
			// Stop the application
			if (appWin != IntPtr.Zero)
			{

				// Post a colse message
				PostMessage(appWin, WM_CLOSE, 0, 0);

				// Delay for it to get the message
				System.Threading.Thread.Sleep(1000);

				// Clear internal handle
				appWin = IntPtr.Zero;

			}

			base.OnHandleDestroyed (e);
		}


		/// <summary>
		/// Update display of the executable
		/// </summary>
		/// <param name="e">Not used</param>
		protected override void OnResize(EventArgs e)
		{
			if (this.appWin != IntPtr.Zero)
			{
				MoveWindow(appWin, 0, 0, this.Width, this.Height, true);
			}
			base.OnResize (e);
		}


	}


}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

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

Share

About the Author

Jay Nelson
Architect Omron Adept Technologies, Inc
United States United States
I have been developing software professionaly since 1991 writing software in automation and manufacturing environments. For 14 years I worked for companies that built custom robotic automated equipment for the semiconductor, telecommunications, and other industies. Presently, I work for a company that manufacturers industrial robots where I write high level coordination and control software.

My undergraduate degrees are in Mathematics and Philosopy. My graduate degree is in Management Information Systems. I am MCSD certified in Visual C++ 6.0 and MCSD.NET certified in C#. I am also have the PMI-ACP certification.

I enjoy karate and reading.

You may also be interested in...

Pro
Pro
| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.161128.1 | Last Updated 21 Dec 2004
Article Copyright 2004 by Jay Nelson
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid