MDI多文档窗体
一、MDI窗体核心概念(必考)
1. 什么是MDI窗体
MDI(Multiple Document Interface)多文档界面。
作用:一个主窗体中可以嵌套打开多个子窗体,所有子窗体只能在主窗体内活动,不会独立弹出窗口。
常见软件:Word、Excel、PS 多文档窗口模式。
2. MDI两大角色
父窗体(容器窗体) :必须设置属性 IsMdiContainer = true
子窗体(内容窗体) :通过代码指定 子窗体.MdiParent = 父窗体对象
3. MDI常用布局枚举
MdiLayout.TileVertical:垂直平铺(左右均分)
MdiLayout.TileHorizontal:水平平铺(上下均分)
MdiLayout.Cascade:层叠窗口
二、前期准备工作
1、创建窗体:Form1(主窗体)、Form2(子窗体1)、Form3(子窗体2)
2、设置 Form1 属性:IsMdiContainer = true(必须设置,否则无法嵌套子窗体)
3、给Form1添加菜单栏 MenuStrip,创建对应菜单项:
打开窗体、设置窗体、打开窗体1、打开窗体2
三、完整代码逐段拆解精讲
namespace _2MDI窗体
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
1、功能一:一次性打开多个子窗体 + 垂直平铺布局
菜单项:打开窗体
private void 打开窗体ToolStripMenuItem_Click(object sender, EventArgs e)
{
//=================打开子窗体2=================
Form2 f2 = new Form2();
//设置父容器为当前主窗体Form1
f2.MdiParent = this;
f2.Show();
//=================打开子窗体3=================
Form3 f3 = new Form3();
f3.MdiParent = this;
//单独设置窗体背景色
f3.BackColor = Color.Red;
f3.Show();
//设置所有子窗体:垂直平铺(左右排列)
LayoutMdi(MdiLayout.TileVertical);
}
核心知识点解析
f2.MdiParent = this:指定当前f2的父容器是主窗体,变成MDI子窗体
LayoutMdi():系统自带布局方法,专门用于排列所有MDI子窗体
MdiLayout.TileVertical:垂直平铺,多个子窗体左右等分屏幕显示
2、功能二:切换为水平平铺布局
菜单项:设置窗体
private void 设置窗体ToolStripMenuItem_Click(object sender, EventArgs e)
{
//水平平铺:子窗体上下等分排列
LayoutMdi(MdiLayout.TileHorizontal);
}
3、功能三:封装通用打开窗体方法(核心重点)
需求:同类窗体唯一显示,不同类窗体切换显示
逻辑:
1、如果要打开的窗体已经存在 → 隐藏所有窗体,激活显示当前同类窗体
2、如果是新窗体 → 隐藏所有旧窗体,展示新窗体
//打开窗体1菜单:打开Form2
private void 打开窗体1ToolStripMenuItem_Click(object sender, EventArgs e)
{
Open(new Form2());
}
//打开窗体2菜单:打开Form3
private void 打开窗体2ToolStripMenuItem_Click(object sender, EventArgs e)
{
Open(new Form3());
}
4、核心通用Open方法(重难点逐行解析)
/// <summary>
/// MDI窗体通用打开、去重、切换方法
/// </summary>
/// <param name="f">要打开的子窗体对象</param>
public void Open(Form f)
{
//遍历当前主窗体所有已打开的子窗体
foreach (var item in this.MdiChildren)
{
//判断:将要打开的窗体 和 已存在的窗体 类型是否一致
if (f.GetType() == item.GetType())
{
//隐藏所有子窗体
foreach (Form child in this.MdiChildren)
{
child.Hide();
}
//显示当前同类窗体
item.Show();
//激活置顶聚焦
item.Activate();
//终止方法,不再创建新窗体(实现单例)
return;
}
}
//走到这里说明:没有同类窗体,需要打开全新窗体
//先隐藏所有旧窗体
foreach (Form child in this.MdiChildren)
{
child.Hide();
}
//设置父容器
f.MdiParent = this;
//展示新窗体
f.Show();
}
四、核心属性精讲
this.MdiChildren :获取当前主窗体下所有子窗体集合
GetType():获取窗体的类型(判断是Form2还是Form3)
Hide():隐藏窗体,窗体对象还在内存,只是看不见
Show():显示隐藏的窗体
Activate():激活窗体,置顶、获取焦点
五、整体逻辑流程图解
点击菜单 → 调用Open方法 → 判断是否存在同类窗体
存在同类 → 全部隐藏 → 显示同类旧窗体 → 返回
不存在同类 → 隐藏所有旧窗体 → 创建新窗体 → 显示
六、备用极简写法(第二种写法)
注释里的极简逻辑:每次打开新窗体前隐藏全部旧窗体,始终只显示一个窗体
//第二种最简写法
//foreach (var item in this.MdiChildren)//先遍历所有子窗体 把子窗隐藏
//{
// item.Hide();
//}
//f.MdiParent = this; //设置子父关系
//f.Show(); //显示当前窗体
七、MDI核心必考知识点总结
1、主窗体必须设置 IsMdiContainer = true
2、子窗体必须赋值 MdiParent = this 才能嵌套
3、MdiChildren 获取所有子窗体
4、LayoutMdi 专门用于批量布局子窗体
5、GetType() 用于判断窗体类型,实现窗体去重
6、Hide隐藏不销毁、Show显示、Activate激活
八、易错点总结
1、忘记设置主窗体 IsMdiContainer,子窗体无法嵌套
2、不判断窗体类型,重复创建多个一模一样的窗体
3、不写return,导致重复弹窗
4、混淆Hide和Close:Hide只是隐藏,Close才是销毁窗体
FlowLayoutPanel 流式布局
一、流式布局核心知识点
1. 什么是流式布局
FlowLayoutPanel(流式布局面板)是 WinForm 自带的自动布局容器。
普通Panel:控件需要手动设置坐标固定位置,排版繁琐、适配差。
流式布局:控件自动从左到右排列,一行排满自动换行,无需手动设置Location坐标。
2. 核心特点
1、自动流式排版:左 → 右、上 → 下
2、窗口大小改变时,控件位置自动自适应
3、支持批量动态添加控件,排版整齐统一
4、通过 Margin 属性设置控件之间的边距间距
3. 必备界面控件
窗体拖拽控件:FlowLayoutPanel(命名默认 flowLayoutPanel1)
二、完整代码逐段精细拆解
namespace _3流式布局
{
public partial class Form1 : Form
{
//窗体构造方法:程序启动自动执行
public Form1()
{
InitializeComponent();
1、循环批量创建按钮
//循环10次,批量生成10个按钮
for (int i = 0; i < 10; i++)
{
//1、实例化按钮对象
Button btn = new Button()
{
//设置按钮显示文本
Text = "按钮",
};
2、设置控件间距(核心属性)
//设置按钮外边距:上、左间距10像素,右、下0
btn.Margin = new Padding(10, 10, 0, 0);
Padding参数详解(顺序固定):
new Padding(左, 上, 右, 下)
本代码效果:按钮距离左侧、上方留白10像素,按钮之间产生间距,排版不拥挤
3、将控件添加到流式布局面板
//将创建好的按钮添加到流式布局容器中
this.flowLayoutPanel1.Controls.Add(btn);
}
}
}
}
核心原理:
所有动态创建的控件,必须通过 容器.Controls.Add(控件) 添加到容器,界面才会显示。
添加后 FlowLayoutPanel 自动按照流式规则从左到右排列。
三、代码运行效果
1、程序启动,自动生成10个【按钮】
2、按钮从左向右依次排列,每个按钮左上侧留白10px间距
3、一行放不下自动换行,自适应窗体宽度
4、拖拽窗体拉大缩小,按钮排版自动适配
四、关键属性超详细解析
1. Margin 外边距
作用:控件与其他控件、容器边缘的距离
区别:Padding是控件内部留白,Margin是控件外部间距
2. Controls.Add()
动态控件显示的唯一方式,将内存中的控件对象挂载到界面容器
3. FlowLayoutPanel 自动布局规则
默认排版方向:LeftToRight 从左到右
自动换行:超出容器宽度自动换行到下一行
五、易错点总结
1、动态new控件后,不执行Add方法 → 界面看不到控件
2、不设置Margin → 所有按钮紧贴在一起,排版拥挤难看
3、普通Panel无法自动换行,必须使用FlowLayoutPanel
4、循环创建控件,无需手动命名,批量生成效率极高
六、知识点总结
1、FlowLayoutPanel 专门用于批量控件自动流式排版
2、Margin 控制控件外部间距,优化界面美观度
3、Controls.Add() 实现动态控件挂载显示
4、循环批量创建控件,是WinForm动态界面核心写法