是否可以在 MDI 容器内运行另一个 WinForm 并使用其 Program.cs?

Wil*_* Jr -2 c# winforms

为了解释我的问题,我将尝试截图,以便我可以将我的信息传达给所有人。在图片上,我有主项目,即 MainWinForm 和解决方案文件夹,其中包含两个 Windows 项目,即 FirstWinFormApp 和 SecondWinFormApp。

这是屏幕截图:

在此处输入图片说明

MainWinForm 项目包含一个 Form1.cs,它是一个设置为 true 的 MDI 容器。我正在尝试使用按钮单击事件处理程序从 FirstWinFormApp 项目启动表单 (First.cs)。

在此处输入图片说明

一切都应该正常工作。我可以在 Form1 的 MDI Container 中启动 First.cs 表单。

现在这里是棘手的部分,我想运行 FirstWinFormApp 的 Program.cs 而不是 MainWinForm 的 Program.cs。这背后的原因是我对我的项目(组件、连接等)的要求。

当我启动应用程序时,MainWinForm 项目的 Program.cs 被触发。当我调用子应用程序时,不再调用它的 Program.cs。即使 MainWinForm 项目的 Program.cs 已经被调用,我是否可以调用子应用程序 (FirstWinFormApp) 的 Program.cs?

luu*_*005 5

我想 MDI 容器和子窗口将属于不同的可执行文件(不同的项目和所有)。一开始不建议这样做,但可以这样做。基本上,您需要弄乱 Windows API,而不是使用框架托管方法。

您肯定需要SetParent API - 即使父窗口不是 MDI 容器,它也可以将您的窗口放在另一个窗口中。但是,您需要某种方式来传达父窗口的 Handle 属性,并且这些方法要么不稳定(将指针写在两个进程都可以访问的地方)或不必要地复杂(需要进程间通信)。

最简单的方法是,您可以使用 FindWindow 通过标题从子窗口中找到主窗口。如果另一个程序与您的 MDI 窗口具有相同的标题,这将失败。

下面的代码未经测试,但您需要在子窗口的 Program.cs 中使用它:

[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
private static extern IntPtr FindWindow(IntPtr className, string lpWindowName);
Run Code Online (Sandbox Code Playgroud)

并在您的子程序的 Main()

var hwnd = FindWindow(IntPtr.Zero, "My MDI Title");
SetParent(childWindow.Handle, hwnd);
Run Code Online (Sandbox Code Playgroud)

在您的情况下,这将类似于

[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
private static extern IntPtr FindWindow(IntPtr className, string lpWindowName);

static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    var formObj = new First();

    var hwnd = FindWindow(IntPtr.Zero, "My MDI Title");
    SetParent(formObj.Handle, hwnd);

    Application.Run(formObj);
}
Run Code Online (Sandbox Code Playgroud)

请务必将 MDI 表单的标题也更改为“我的 MDI 标题”。在下面的测试应用程序中,我是相反的- 在 Form1 中放置一个记事本窗口,但您可以按照自己喜欢的方式进行操作。

截屏