VB Visual Basic 2026 中文教程
第 21 课 · 多窗口程序

多窗体应用

真正的桌面应用通常不会把所有功能塞进一个 Form。主窗口可以负责导航,资料输入放在另一个窗口,About、Settings、Search 等功能也可以拥有自己的窗体。本课将学习怎样建立第二个 Form、打开与关闭窗体,以及在窗体之间传递资料。

适合:完成第 20 课的初学者建议时间:60–75 分钟实作:StudentManagementDashboard2026

本课学习目标

  • 理解为什么大型 Windows Forms 应用需要多个窗体。
  • 在项目中新增第二个 Form。
  • 使用 Show() 打开非模式窗体。
  • 使用 ShowDialog() 打开模式窗体。
  • 理解 Close()Hide() 的区别。
  • 使用构造函数把资料传给另一个窗体。
  • 通过 Public ReadOnly Property 从子窗体取回结果。
  • 使用 DialogResult.OK 判断用户是否确认。
  • 理解主窗体、子窗体和对话框的角色。
  • 完成一个带 Dashboard、学生输入窗体和 About 窗体的多窗体应用。

21.1 为什么要使用多个窗体?

当一个 Form 同时承担导航、资料输入、设置、报表和帮助功能时,界面与代码都会越来越复杂。拆成多个窗体可以让每个窗口专注于自己的任务。

MainForm

主窗口

负责 Dashboard、导航和主要状态。

StudentForm

资料输入

负责新增或编辑学生资料。

AboutForm

辅助窗口

显示应用名称、版本和说明。

21.2 在项目中新增 Form

在 Solution Explorer 中对项目按右键,选择新增项目项,然后加入一个 Windows Form。

例如新增:

StudentForm.vb

再新增:

AboutForm.vb

项目现在可能包含:

MainForm.vb
StudentForm.vb
AboutForm.vb
建议为窗体使用有意义的名称 Form1、Form2、Form3 在小练习中可以使用,但真实项目中 MainForm、StudentForm、SettingsForm 更容易维护。

21.3 使用 Show() 打开窗体

建立窗体对象:

Dim form As New AboutForm()

然后:

form.Show()

Show() 打开的是非模式(modeless)窗口。打开后,用户仍然可以回到主窗体继续操作。

MainForm点击 About
New AboutForm建立对象
Show()显示窗口
两个窗体都可操作非模式

21.4 使用 ShowDialog() 打开模式窗体

Dim form As New StudentForm()

form.ShowDialog()

ShowDialog() 打开模式(modal)窗口。在这个窗体关闭之前,用户通常不能继续操作主窗体。

Show()

适合工具窗口、About、辅助信息等允许用户同时操作其他窗体的场景。

ShowDialog()

适合新增记录、设置、确认等必须先完成当前操作才能回到主窗口的场景。

21.5 Close() 与 Hide()

Close()

Me.Close()

关闭当前窗体。通常关闭后,这个窗体对象就不再继续作为当前可见窗口使用。

Hide()

Me.Hide()

只是隐藏窗体,并没有真正关闭它。之后还可以再次 Show。

方法结果典型用途
Show()显示非模式窗体辅助窗口
ShowDialog()显示模式窗体输入、编辑、设置
Hide()隐藏但保留窗体临时隐藏
Close()关闭窗体完成操作或退出窗口

21.6 用构造函数把资料传给子窗体

假设 AboutForm 要显示当前登录用户名,可以通过构造函数传入。

AboutForm.vb

Public Class AboutForm

    Public Sub New(userName As String)

        InitializeComponent()

        lblUser.Text =
            "当前用户:" & userName

    End Sub

End Class

MainForm.vb

Dim form As New AboutForm(
    "Dr. Lee")

form.ShowDialog()
MainForm
拥有 userName
AboutForm
构造函数接收
构造函数适合传入“打开窗体时必须拥有”的资料 这样子窗体一建立就已经具备它需要的数据。

21.7 子窗体怎样把资料传回主窗体?

一种简单而清楚的方式,是让子窗体提供只读属性。

StudentForm.vb

Public ReadOnly Property StudentName As String
    Get
        Return txtStudentName.Text.Trim()
    End Get
End Property

再加入:

Public ReadOnly Property CourseName As String
    Get
        Return txtCourse.Text.Trim()
    End Get
End Property

成绩:

Public ReadOnly Property Score As Double

21.8 使用 DialogResult.OK 表示用户确认

在 StudentForm 放两个按钮:

btnOK
btnCancel

可以在 Designer 设置:

btnOK.DialogResult = OK
btnCancel.DialogResult = Cancel

或者在代码中设置:

Me.DialogResult =
    DialogResult.OK

Me.Close()

MainForm 就可以判断:

Dim form As New StudentForm()

If form.ShowDialog() =
    DialogResult.OK Then

    ' 用户确认了输入

End If

21.9 StudentForm:验证后返回资料

Public Class StudentForm

    Public ReadOnly Property StudentName As String
        Get
            Return txtStudentName.Text.Trim()
        End Get
    End Property

    Public ReadOnly Property CourseName As String
        Get
            Return txtCourse.Text.Trim()
        End Get
    End Property

    Public ReadOnly Property Score As Double

    Private Sub btnOK_Click(
        sender As Object,
        e As EventArgs) Handles btnOK.Click

        If String.IsNullOrWhiteSpace(
            txtStudentName.Text) Then

            MessageBox.Show(
                "请输入学生姓名。")

            txtStudentName.Focus()
            Exit Sub

        End If

        If String.IsNullOrWhiteSpace(
            txtCourse.Text) Then

            MessageBox.Show(
                "请输入课程名称。")

            txtCourse.Focus()
            Exit Sub

        End If

        Dim scoreValue As Double

        If Not Double.TryParse(
            txtScore.Text,
            scoreValue) Then

            MessageBox.Show(
                "请输入有效成绩。")

            txtScore.Focus()
            Exit Sub

        End If

        If scoreValue < 0 OrElse
           scoreValue > 100 Then

            MessageBox.Show(
                "成绩必须介于 0 与 100。")

            txtScore.Focus()
            Exit Sub

        End If

        _Score = scoreValue

        Me.DialogResult =
            DialogResult.OK

        Me.Close()

    End Sub

    Private Sub btnCancel_Click(
        sender As Object,
        e As EventArgs) Handles btnCancel.Click

        Me.DialogResult =
            DialogResult.Cancel

        Me.Close()

    End Sub

End Class
为什么 Score 属性看起来和前两个不同? 姓名和课程可以直接从 TextBox 读取 String;成绩必须先通过 TryParse,因此使用成功解析后的数值保存到只读属性的隐藏字段中。

21.10 使用 Using 管理模式窗体

对于临时建立、显示、关闭后就不再使用的模式窗体,可以写:

Using form As New StudentForm()

    If form.ShowDialog() =
        DialogResult.OK Then

        lblStudent.Text =
            form.StudentName

    End If

End Using

离开 Using 后,窗体会被释放。

21.11 Owner:指定父窗口

ShowDialog 可以指定拥有者:

form.ShowDialog(Me)

这里的 Me 是当前主窗体。这样可以让对话框在主窗体的上下文中显示,并维持更合理的窗口关系。

21.12 实作:学生管理 Dashboard

建立新的 Windows Forms 项目:

StudentManagementDashboard2026

建立三个窗体:

MainForm.vb
StudentForm.vb
AboutForm.vb
Student Management Dashboard 2026
功能 新增学生 查看当前学生 About

Dashboard

学生人数:2

最近加入:李明

新增学生
李明
Visual Basic 2026
88
CancelOK

MainForm 加入:

控件Name用途
ButtonbtnAddStudent打开 StudentForm
ButtonbtnAbout打开 AboutForm
TextBoxtxtStudentsMultiline = True;ReadOnly = True
LabellblCount显示学生人数

MainForm 保存学生列表

Private ReadOnly students As New List(Of Student)()

新增学生按钮

Private Sub btnAddStudent_Click(
    sender As Object,
    e As EventArgs) Handles btnAddStudent.Click

    Using form As New StudentForm()

        If form.ShowDialog(Me) <>
            DialogResult.OK Then

            Exit Sub

        End If

        Dim student As New Student(
            form.StudentName,
            form.CourseName,
            form.Score)

        students.Add(student)

    End Using

    DisplayStudents()

End Sub

显示学生

Private Sub DisplayStudents()

    txtStudents.Clear()

    For Each student As Student In students

        txtStudents.Text &=
            student.GetSummary() &
            Environment.NewLine &
            "--------------------" &
            Environment.NewLine

    Next

    lblCount.Text =
        $"学生人数:{students.Count}"

End Sub

About 按钮

Private Sub btnAbout_Click(
    sender As Object,
    e As EventArgs) Handles btnAbout.Click

    Using form As New AboutForm(
        "Student Management Dashboard 2026")

        form.ShowDialog(Me)

    End Using

End Sub

AboutForm 构造函数

Public Class AboutForm

    Public Sub New(
        applicationName As String)

        InitializeComponent()

        lblTitle.Text =
            applicationName

        lblDescription.Text =
            "Visual Basic 2026 多窗体应用示例"

    End Sub

    Private Sub btnClose_Click(
        sender As Object,
        e As EventArgs) Handles btnClose.Click

        Me.Close()

    End Sub

End Class

21.13 程序执行流程

1
MainForm 负责导航

用户点击“新增学生”。

2
建立 StudentForm

使用 ShowDialog(Me) 打开模式输入窗体。

3
StudentForm 验证输入

只有资料有效时才设置 DialogResult.OK。

4
MainForm 读取属性

从 StudentName、CourseName、Score 取得结果。

5
建立 Student 对象

加入 List(Of Student),再刷新 Dashboard。

21.14 什么时候使用 Show,什么时候使用 ShowDialog?

窗口建议原因
新增学生ShowDialog主窗体需要等待输入结果。
设置窗口ShowDialog通常希望完成或取消设置后再继续。
工具窗口Show用户可以同时操作主窗口。
About两者皆可通常 ShowDialog 更简单,也很常见。

21.15 初学者常见错误

错误 1

每次都直接使用默认窗体实例

教学中更建议明确 Dim form As New StudentForm(),对象生命周期更清楚。

错误 2

ShowDialog 后不检查结果

用户可能按 Cancel。只有 DialogResult.OK 才应读取并保存输入。

错误 3

Hide 代替 Close 后不断累积窗体

不再需要的窗口应关闭或释放,避免无意义地长期保留。

错误 4

子窗体直接大量操作 MainForm 控件

更清楚的做法是通过属性、构造函数或返回结果传递资料,减少窗体之间过度耦合。

21.16 小练习

  1. 新增 SettingsForm,用 ShowDialog 打开。
  2. 让 SettingsForm 返回一个 Boolean,例如是否启用深色模式。
  3. 为 StudentForm 加入 StudentId,并传回 MainForm。
  4. 建立一个只使用 Show() 的 HelpForm,观察主窗体是否仍可操作。
  5. 在 AboutForm 显示通过构造函数传入的版本文字。
  6. 尝试把 StudentForm 的取消按钮设置为 DialogResult.Cancel。
  7. 新增“编辑学生”窗口,并让构造函数接收现有 Student 对象的资料作为初始值。

本课复习

  1. 为什么大型应用通常使用多个 Form?
  2. Show()ShowDialog() 最大的区别是什么?
  3. Close()Hide() 有什么不同?
  4. 构造函数适合把哪一类资料传给子窗体?
  5. 怎样让 StudentForm 把输入结果传回 MainForm?
  6. DialogResult.OK 有什么用途?
  7. 为什么 MainForm 应该检查 ShowDialog 的返回值?
  8. ShowDialog(Me) 中的 Me 是什么?
  9. Using 区块对临时模式窗体有什么好处?
  10. 为什么应避免让两个窗体直接互相操作大量控件?