Programs as MDI Child windows
Is there a way to use a program as a MDI child window开发者_如何学Python. I am thinking of having one main MDI parent window which can have multipe child windows, some of which will be programs(.exe files) in there own right.
Tim
There is actually a pretty easy way to do this.
First, you need to add a panel to your form. This panel will be used to "host" the application.
Next, you need to the "System.Runtime.InteropServices" and the "System.Diagnostics" namespace to your namespaces: csharp
using System.Diagnostics;
using System.Runtime.InteropServices;
Now, we need setup our WinAPI functions:
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hwndChild, IntPtr hwndNewParent);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, Int32 wParam, Int32 lParam);
Now, inside a button click event, start the process, and set it's parent to the panel. In this example, I will be using notepad:
// Create a new process
Process proc;
// Start the process
proc = Process.Start("notepad.exe");
proc.WaitForInputIdle();
// Set the panel control as the application's parent
SetParent(proc.MainWindowHandle, this.panel1.Handle);
// Maximize application
SendMessage(proc.MainWindowHandle, 274, 61488, 0);
I have implemented a similar thing a few years ago (.NET Framework 1.1 based, if I recall correctly). Key elements of that implementation were:
- We created an extended
Form
class that exposed some specific functionality, such as an interface for extracting user commands that would invoke the UI. - The main application would scan the dll's in the application directory and inspect them (using Reflection) to find any classes based on our special Form class, and extract information out of them to build menu structures that would invoke the commands.
- When a user invoked a command that would lead to a form being displayed, it was created (using
Activator.CreateInstance
), stripped from form borders and embedded into a container (in our case aTabPage
in aTabControl
, in your case most likely an "empty" MDI Child form in your application).
This all worked out fairly well I think (I actually think that the framework is still being maintained and used within the company it was created for).
You may want to keep an eye at memory management. For instance, since an assembly cannot be unloaded, if that is a requirement you will need to load external assemblies into separate AppDomains. Also pay attention to any event handlers that are attached dynamically when child window UI's are loaded, so that they are properly detached when the UI's are unloaded.
Import the InteropServices
and Threading
namespaces
using System.Runtime.InteropServices;
using System.Threading;
Import SetParent
from user32.dll
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr child,IntPtr parent);
Create a new process and make it an MDI child of our form using SetParent
Process proc;
// Start the process
proc = Process.Start("calc.exe");
proc.WaitForInputIdle();
Thread.Sleep(500);
// Set the panel control as the application's parent
SetParent(proc.MainWindowHandle, this.panel1.Handle);
精彩评论