C# 作为MDI子窗口的程序
是否有办法将程序用作MDI子窗口。我正在考虑使用一个主MDI父窗口,它可以有多个子窗口,其中一些窗口本身就是程序(.exe文件)C# 作为MDI子窗口的程序,c#,windows,winforms,mdi,C#,Windows,Winforms,Mdi,是否有办法将程序用作MDI子窗口。我正在考虑使用一个主MDI父窗口,它可以有多个子窗口,其中一些窗口本身就是程序(.exe文件) Tim几年前我实现了一个类似的东西(.NET Framework 1.1为基础,如果我没记错的话)。这项执行的关键要素是: 我们创建了一个扩展的表单类,该类公开了一些特定的功能,例如用于提取调用UI的用户命令的界面 主应用程序将扫描应用程序目录中的dll并检查它们(使用),以根据我们的特殊表单类查找任何类,并从中提取信息以构建调用命令的菜单结构 当用户调用将导致显示
Tim几年前我实现了一个类似的东西(.NET Framework 1.1为基础,如果我没记错的话)。这项执行的关键要素是:
- 我们创建了一个扩展的
类,该类公开了一些特定的功能,例如用于提取调用UI的用户命令的界面表单
- 主应用程序将扫描应用程序目录中的dll并检查它们(使用),以根据我们的特殊表单类查找任何类,并从中提取信息以构建调用命令的菜单结构
- 当用户调用将导致显示表单的命令时,它被创建(使用)、从表单边框中剥离并嵌入到容器中(在我们的示例中是
中的TabControl
,在您的示例中很可能是应用程序中的“空”MDI子表单)李>TabPage
您可能需要关注内存管理。例如,由于无法卸载程序集,如果这是一项要求,则需要将外部程序集加载到单独的AppDomain中。还要注意在加载子窗口UI时动态附加的任何事件处理程序,以便在卸载UI时正确分离它们。几年前我实现了类似的事情(.NET Framework 1.1,如果我没记错的话)。这项执行的关键要素是:
- 我们创建了一个扩展的
类,该类公开了一些特定的功能,例如用于提取调用UI的用户命令的界面表单
- 主应用程序将扫描应用程序目录中的dll并检查它们(使用),以根据我们的特殊表单类查找任何类,并从中提取信息以构建调用命令的菜单结构
- 当用户调用将导致显示表单的命令时,它被创建(使用)、从表单边框中剥离并嵌入到容器中(在我们的示例中是
中的TabControl
,在您的示例中很可能是应用程序中的“空”MDI子表单)李>TabPage
您可能需要关注内存管理。例如,由于无法卸载程序集,如果这是一项要求,则需要将外部程序集加载到单独的AppDomain中。还要注意在加载子窗口UI时动态附加的任何事件处理程序,以便在卸载UI时正确分离它们。实际上有一种非常简单的方法可以做到这一点 首先,您需要在表单中添加一个面板。此面板将用于“托管”应用程序 接下来,需要将“System.Runtime.InteropServices”和“System.Diagnostics”命名空间添加到命名空间中: csharp 现在,我们需要设置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);
实际上有一个非常简单的方法可以做到这一点 首先,您需要在表单中添加一个面板。此面板将用于“托管”应用程序 接下来,需要将“System.Runtime.InteropServices”和“System.Diagnostics”命名空间添加到命名空间中: csharp 现在,我们需要设置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);
这似乎不起作用。记事本窗口已创建,但未连接到mdi应用程序。@Tim-如果您创建一个新的mdi子窗口,并将新进程窗口的父窗口设置为mdi子窗口的窗口句柄,则记事本窗口可以正常工作。对我有效,但没有任何更改。此操作似乎不起作用。记事本窗口已创建,但未连接到mdi应用程序。@Tim-如果您创建一个新的mdi子窗口,并将新进程窗口的父窗口设置为mdi子窗口的窗口句柄,则记事本窗口可以正常工作。对我来说,该窗口没有任何更改。谢谢,我怀疑我必须这样做。我要演一出戏。谢谢,我想我得演这样的戏。我要去看戏。
[DllImport("user32.dll")]<br>
static extern IntPtr SetParent(IntPtr child,IntPtr parent);
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);