简体   繁体   English

程序作为MDI子窗口

[英]Programs as MDI Child windows

Is there a way to use a program as a MDI child window. 有没有办法将程序用作MDI子窗口。 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. 我想有一个主MDI父窗口,它可以有多窗口子窗口,其中一些是自己的程序(.exe文件)。

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 接下来,您需要将“System.Runtime.InteropServices”和“System.Diagnostics”命名空间添加到命名空间:csharp

using System.Diagnostics;
using System.Runtime.InteropServices;

Now, we need setup our WinAPI functions: 现在,我们需要设置我们的WinAPI函数:

[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). 几年前我已经实现了类似的东西(基于.NET Framework 1.1,如果我没记错的话)。 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. 我们创建了一个扩展的Form类,它暴露了一些特定的功能,例如用于提取将调用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. 主应用程序将扫描应用程序目录中的dll并检查它们(使用Reflection )以基于我们的特殊Form类查找任何类,并从中提取信息以构建将调用命令的菜单结构。
  • 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 a TabPage in a TabControl , in your case most likely an "empty" MDI Child form in your application). 当用户调用一个导致表单显示的命令时,它就会被创建(使用Activator.CreateInstance ),从表单边框中剥离并嵌入到容器中(在我们的例子中, TabControlTabPage ,在你的情况下很可能是一个您的应用程序中的“空”MDI子表单)。

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. 例如,由于无法卸载程序集,因此如果需要,则需要将外部程序集加载到单独的AppDomain中。 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. 还要注意在加载子窗口UI时动态附加的任何事件处理程序,以便在卸载UI时正确分离它们。

 // using
using System.Runtime.InteropServices;<br>
using System.Threading;

//out at the class code //在课堂代码处

 [DllImport("user32.dll")]<br>
    static extern IntPtr SetParent(IntPtr child,IntPtr parent);

// Create a new process //创建一个新流程

 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM