【问题标题】:Programs as MDI Child windows作为 MDI 子窗口的程序
【发布时间】:2009-10-03 20:09:06
【问题描述】:

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

提姆

【问题讨论】:

    标签: c# windows winforms mdi


    【解决方案1】:

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

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

    接下来,您需要将“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);
    

    【讨论】:

    • 这似乎不起作用。记事本窗口已创建,但未连接到 mdi 应用程序。
    • @Tim - 如果您创建一个新的 MDI 子窗口并将新进程窗口的父级设置为 MDI 子窗口的窗口句柄,它确实有效。
    • 为我工作,无需任何更改
    【解决方案2】:

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

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

    我认为这一切都很顺利(我实际上认为该框架仍在为其创建的公司内维护和使用)。

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

    【讨论】:

    • 谢谢,我怀疑我必须做这样的事情。我会玩的。
    【解决方案3】:

    导入 InteropServicesThreading 命名空间

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

    user32.dll 导入SetParent

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

    使用SetParent创建一个新进程并使其成为我们表单的 MDI 子进程

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

    【讨论】:

      猜你喜欢
      • 2018-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-29
      相关资源
      最近更新 更多