Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 作为MDI子窗口的程序_C#_Windows_Winforms_Mdi - Fatal编程技术网

C# 作为MDI子窗口的程序

C# 作为MDI子窗口的程序,c#,windows,winforms,mdi,C#,Windows,Winforms,Mdi,是否有办法将程序用作MDI子窗口。我正在考虑使用一个主MDI父窗口,它可以有多个子窗口,其中一些窗口本身就是程序(.exe文件) Tim几年前我实现了一个类似的东西(.NET Framework 1.1为基础,如果我没记错的话)。这项执行的关键要素是: 我们创建了一个扩展的表单类,该类公开了一些特定的功能,例如用于提取调用UI的用户命令的界面 主应用程序将扫描应用程序目录中的dll并检查它们(使用),以根据我们的特殊表单类查找任何类,并从中提取信息以构建调用命令的菜单结构 当用户调用将导致显示

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


Tim

几年前我实现了一个类似的东西(.NET Framework 1.1为基础,如果我没记错的话)。这项执行的关键要素是:

  • 我们创建了一个扩展的
    表单
    类,该类公开了一些特定的功能,例如用于提取调用UI的用户命令的界面
  • 主应用程序将扫描应用程序目录中的dll并检查它们(使用),以根据我们的特殊表单类查找任何类,并从中提取信息以构建调用命令的菜单结构
  • 当用户调用将导致显示表单的命令时,它被创建(使用)、从表单边框中剥离并嵌入到容器中(在我们的示例中是
    TabControl
    中的
    TabPage
    ,在您的示例中很可能是应用程序中的“空”MDI子表单)
我认为这一切都进行得相当顺利(实际上,我认为该框架仍在为其创建的公司内部进行维护和使用)


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

几年前我实现了类似的事情(.NET Framework 1.1,如果我没记错的话)。这项执行的关键要素是:

  • 我们创建了一个扩展的
    表单
    类,该类公开了一些特定的功能,例如用于提取调用UI的用户命令的界面
  • 主应用程序将扫描应用程序目录中的dll并检查它们(使用),以根据我们的特殊表单类查找任何类,并从中提取信息以构建调用命令的菜单结构
  • 当用户调用将导致显示表单的命令时,它被创建(使用)、从表单边框中剥离并嵌入到容器中(在我们的示例中是
    TabControl
    中的
    TabPage
    ,在您的示例中很可能是应用程序中的“空”MDI子表单)
我认为这一切都进行得相当顺利(实际上,我认为该框架仍在为其创建的公司内部进行维护和使用)


您可能需要关注内存管理。例如,由于无法卸载程序集,如果这是一项要求,则需要将外部程序集加载到单独的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);