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

时间:2017-01-30 04:30:49

标签: c# winforms

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

以下是截图:

enter image description here

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

enter image description here

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

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

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

1 个答案:

答案 0 :(得分:3)

我认为MDI容器和子窗口属于不同的可执行文件(不同的项目和所有)。首先不建议这样做,但可以这样做。基本上你需要搞乱Windows API而不使用Framework管理方法。

您肯定需要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);

并在您孩子的程序中使用Main()

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

在你的情况下,这将是

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

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

Screenshot