作为 MDI 子窗口的程序

发布于 2024-08-06 02:49:11 字数 89 浏览 2 评论 0原文

有没有办法将程序用作 MDI 子窗口。我正在考虑拥有一个主 MDI 父窗口,它可以有多个子窗口,其中一些子窗口本身就是程序(.exe 文件)。

蒂姆

Is there a way to use a program as a MDI child window. 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

海的爱人是光 2024-08-13 02:49:11

实际上有一个非常简单的方法可以做到这一点。

首先,您需要向表单添加一个面板。该面板将用于“托管”应用程序。

接下来,您需要将“System.Runtime.InteropServices”和“System.Diagnostics”命名空间添加到您的命名空间中:
csharp

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

现在,我们需要设置 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);

现在,在按钮单击事件内,启动进程,并将其父级设置为面板。在此示例中,我将使用记事本:

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

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);
赢得她心 2024-08-13 02:49:11

几年前我已经实现了类似的事情(基于 .NET Framework 1.1,如果我没记错的话)。该实现的关键要素是:

  • 我们创建了一个扩展的 Form 类,它公开了一些特定的功能,例如用于提取将调用 UI 的用户命令的接口。
  • 主应用程序将扫描应用程序目录中的 dll 并检查它们(使用 Reflection)来查找基于我们特殊 Form 类的任何类,并从中提取信息以构建将调用命令的菜单结构。
  • 当用户调用导致显示表单的命令时,就会创建该表单(使用 Activator.CreateInstance),从表单边框中剥离并嵌入到容器中(在我们的例子中是 TabControl 中的 TabPage,在您的情况下,您的应用程序中很可能是“空”MDI 子表单)。

我认为这一切都进展得相当好(实际上我认为该框架仍在其创建的公司内维护和使用)。

您可能需要关注内存管理。例如,由于无法卸载程序集,因此如果有此要求,您将需要将外部程序集加载到单独的 AppDomain 中。还要注意加载子窗口 UI 时动态附加的任何事件处理程序,以便在卸载 UI 时正确分离它们。

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 a TabPage in a TabControl, 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.

梦里梦着梦中梦 2024-08-13 02:49:11

导入 InteropServicesThreading 命名空间

using System.Runtime.InteropServices;
using System.Threading;

user32.dll 导入 SetParent

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

创建一个新进程并使其成为 MDI 子进程使用 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);

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文