qt8gt0bxhw|20009F4EEE83|RyanMain|subtext_Content|Text|0xfbffb40000000000b000000001000100
There are times when you are integrating your .NET applications with other existing applications that you cannot modify and is possibly even non-.NET application. This can often result in problems integrating your .NET application's windows with the other application. However, this can be accomplished. You can easily obtain the handle (HWND) of the other application and convert it to a System.Windows.Forms.IWin32Window which can be used in your .NET application.
Discovering the handle of the running application
There are many ways to discover the running application's handle. The most common way is via p/invoke using the FindWindow Win32API. This is not a bad route, but it does require a DllImport.
[DllImport("user32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern IntPtr FindWindow(string ClassName, string WindowText);
//...
IntPtr hwnd = FindWindow("Notepad", null);
if (hwnd != IntPtr.Zero)
{
// do something with the handle
//...
}
else
MessageBox.Show("Notepad is not running.");
This returns the window handle, as an IntPtr, or an IntPtr.Zero if the window is not found. You can specify either a class name or the window text - you don't have to specify both (by setting the other one to null) or you can also specify both if you want. Like I said, there is nothing wrong with this method, I've used it many times.
Another way to discover the handle of the running application is by looking for it's process which you can then obtain it's handle from. This way does not require the use of p/invoke as you can do this completely from within the framework classes. The Process class in the System.Diagnostics namespace includes the methods to find a running process, such as the static GetProcessesByName method. This method returns an array of Processes that match the given name (my example will only use the first one).
using System.Diagnostics;
//...
Process[] procs = Process.GetProcessesByName("Notepad");
if (procs.Length != 0)
{
IntPtr hwnd = procs[0].MainWindowHandle;
// do something with the handle
//...
}
else
MessageBox.Show("Notepad is not running.");
Now with all of that, the handle itself is of little value to you in your .NET application. Many classes take a IWin32Window as the parameter when specifying the parent or owner of something. You need to wrap the handle in a class that implements IWin32Window to use it within your application and to be able to integrate with the other.
Creating the IWin32Window wrapper class
Creating the wrapper class that implements IWin32Window is simple. The IWin32Window interface contains only a single property that must be implemented to simply expose the underlying handle.
public class WindowWrapper : System.Windows.Forms.IWin32Window
{
public WindowWrapper(IntPtr handle)
{
_hwnd = handle;
}
public IntPtr Handle
{
get { return _hwnd; }
}
private IntPtr _hwnd;
}
Now to use it you just pass the handle of the external window to the constructor and then you can use it where ever you can use an IWin32Window, such as specifying the owner of a MessageBox or a Form shown using ShowDialog, etc. This example uses the IWin32Window wrapper class to display a MessageBox in front of Notepad.
Process[] procs = Process.GetProcessesByName("Notepad");
if (procs.Length != 0)
{
IntPtr hwnd = procs[0].MainWindowHandle;
MessageBox.Show(new WindowWrapper(hwnd), "Hello World!");
}
else
MessageBox.Show("Notepad is not running.");
I do this all the time when integrating with other applications that do not allow this type of integration normally. Add your own custom windows to your accounting software or to some other non-customizable application. Easy enough. Where you take this from here is up to you.