我可以在一个控件中托管Windows窗体吗?

11

我有一个客户,他们有一个使用单例模式的Visual Basic项目,其演示逻辑比较复杂。

主要表单包含一个TabControl和多个选项卡页。如果我单击TabPageA,另一个窗体会显示在该表单前面,并调整大小以与选项卡页相同。

如果我单击TabPageB,第一个窗体将被隐藏,而另一个窗体将被显示。所以对于用户来说,看起来像是有不同选项卡页的TabControl,但实际上不是这样的。

我尝试将这些窗体转换为UserControl并将它们放入TabPage中,但由于SingleInstance应用程序,这需要进行大量重构。我尝试了一下,但由于出现了许多运行时错误,最终放弃了,并且我不想再付出更多的努力。

我的想法是,在运行时将这些窗体添加到TabPage中,并让它们像UserControl一样工作,这可能吗?


你可以尝试获取表单的控件数组的副本,并将其推入另一个控件上的新面板中。 - asawyer
你看过 MDI 吗?也许你可以用菜单项替换选项卡控件,以便主窗口能够从菜单栏打开子窗口。 - Jon Raynor
3个回答

39

您可以通过将Form类的TopLevel属性设置为False,将其转换回子控件。它基本上变成了一个带有一些未使用开销的UserControl。使它看起来类似于这样:

Public Class Form1
    Public Sub New()
        InitializeComponent()
        Dim frm As New Form2
        frm.TopLevel = False
        frm.FormBorderStyle = Windows.Forms.FormBorderStyle.None
        frm.Visible = True
        frm.Dock = DockStyle.Fill
        TabPage1.Controls.Add(frm)
    End Sub
End Class

这是一个惊人的答案。而我一直在设置所有者和处理移动... +5! - Ry-
很好,我会尝试一下,看起来很有前途。 - Jürgen Steinblock
三年过去了,这仍然是一个救命稻草!我的意思是,表单面板,你一直在哪里?!!! 上帝保佑您先生 :) - Katia

6
任何窗口都可以使用SetParent在任何其他窗口中托管(从技术上讲,控件也是窗口)。
<System.Runtime.InteropServices.DllImport("user32.dll")>
Public Function SetParent(ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr

End Function

声明和

SetParent(FormToHost.Handle, ControlToHostForm.Handle)

使用起来很方便,如果您不想再付出更多的努力,那么这也是可以的。这些表格将能够正确最大化和最小化,并且不会显示在任务栏中,同时会随着它们的容器一起关闭。


1
虽然Hans的建议对于这个问题更好,但这种方法的优点是它也适用于其他类型的窗口。 - CodesInChaos
我很久以前用过这个方法将第三方应用程序“停靠”在我的应用程序内。请注意其他应用程序中的任何“热键”(即使它没有焦点也执行功能的键)功能。您可能会破坏该功能。 - Wesley Long

-1

你可以使用面板。在每个选项卡中,不同的面板必须显示,其他面板必须隐藏。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接