前言
在做winfrom项目的时候我们可能会用到嵌套窗体,就是说一个容器中有多个窗体,可以分别管理和应用这些窗体,.net中提供了一种机制就是MDI,可能大家都会用,这边就简单的介绍下。
简单应用
winfrom中怎么用MDI呢,其实只要设置窗体的一个属性就可以了:
IsMdiContainer属性设置为true就表示该窗体为MDI窗体,很简单,那我们可以在窗体加载的时候这些写:
1 private void Form1_Load(object sender, EventArgs e)
2 {
3 Form childForm1 = new Form();
4 childForm1.Text = "窗口1";
5 childForm1.MdiParent = this;
6 childForm1.Show();
7
8 Form childForm2 = new Form();
9 childForm2.Text = "窗口2";
10 childForm2.MdiParent = this;
11 childForm2.Show();
12 }
childForm1.MdiParent = this;这句代码的意思就是设置子窗体的MDI父窗体为本窗体,看下运行效果:
基本方法
关于MDI相关的方法主要是窗体的布局方法LayoutMdi(),参数是MdiLayout枚举:
成员名称 | 说明 |
---|---|
ArrangeIcons | 所有 MDI 子图标均排列在 MDI 父窗体的工作区内。 |
Cascade | 所有 MDI 子窗口均层叠在 MDI 父窗体的工作区内。 |
TileHorizontal | 所有 MDI 子窗口均水平平铺在 MDI 父窗体的工作区内。 |
TileVertical | 所有 MDI 子窗口均垂直平铺在 MDI 父窗体的工作区内。 |
LayoutMdi(MdiLayout.Cascade);效果:
LayoutMdi(MdiLayout.TileHorizontal);效果:
仿Notepad小程序
我们在办公的时候可能都用过Notepad++,很方便,其实Notepad++里面的窗体就有点MDI的感觉:
我们也可以利用MDI做出类似的感效果,Notepad++是文本编辑器,里面每个窗体其实就是单独的Notepad,首先我们需要先建一个文件编辑器的窗体,其实就是一个RichTextBox控件,因为RichTextBox控件是富文本编辑器,所以我们可以进行字体和颜色的调整,调整字体和颜色用的是winfrom的组件,关于文本编辑器就不详述了,贴下代码:

1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Text;
7 using System.Windows.Forms;
8
9 namespace MDINotepad
10 {
11 public partial class NotepadForm : Form
12 {
13 private int _currentCharIndex;
14
15 #region Code segment for constructors.
16
17 public NotepadForm()
18 {
19 InitializeComponent();
20 }
21
22 public NotepadForm(string filePath): this()
23 {
24 //判断文件的后缀名,不同的文件类型使用不同的参数打开。
25
26 if (filePath.EndsWith(".rtf", true, null))
27 rtbEditor.LoadFile(filePath,
28 RichTextBoxStreamType.RichText);
29 else
30 rtbEditor.LoadFile(filePath,
31 RichTextBoxStreamType.PlainText);
32
33 Text = filePath;
34 }
35
36 #endregion
37
38 #region Code segment for private operations.
39
40 private void Save(string filePath)
41 {
42 try
43 {
44 //判断文件的后缀名,不同的文件类型使用不同的参数保存。
45
46 if (filePath.EndsWith(".rtf", true, null))
47 rtbEditor.SaveFile(filePath,
48 RichTextBoxStreamType.RichText);
49 else
50 rtbEditor.SaveFile(filePath,
51 RichTextBoxStreamType.PlainText);
52 }
53 catch (Exception ex)
54 {
55 MessageBox.Show(ex.ToString());
56 }
57 }
58
59 private void SaveAs()
60 {
61 sfdDemo.FilterIndex = Text.EndsWith(".rtf", true, null) ? 1 : 2;
62
63 if (sfdDemo.ShowDialog() == DialogResult.OK)
64 {
65 Save(sfdDemo.FileName);
66 Text = sfdDemo.FileName;
67 }
68 }
69
70 #endregion
71
72 #region Code segment for event handlers.
73
74 private void tsmiSaveFile_Click(object sender, EventArgs e)
75 {
76 if (!System.IO.File.Exists(Text))
77 SaveAs();
78 else
79 Save(Text);
80 }
81
82 private void tsmiSaveAs_Click(object sender, EventArgs e)
83 {
84 SaveAs();
85 }
86
87 private void tsmiBackColor_Click(object sender, EventArgs e)
88 {
89 cdDemo.Color = rtbEditor.SelectionBackColor;
90 if (cdDemo.ShowDialog() == DialogResult.OK)
91 {
92 rtbEditor.SelectionBackColor = cdDemo.Color;
93 }
94 }
95
96 private void rtbEditor_SelectionChanged(object sender, EventArgs e)
97 {
98 if (rtbEditor.SelectionLength == 0)
99 {
100 tsmiBackColor.Enabled = false;
101 tsmiFont.Enabled = false;
102 }
103 else
104 {
105 tsmiBackColor.Enabled = true;
106 tsmiFont.Enabled = true;
107 }
108 }
109
110 private void tsmiFont_Click(object sender, EventArgs e)
111 {
112 fdDemo.Color = rtbEditor.SelectionColor;
113 fdDemo.Font = rtbEditor.SelectionFont;
114 if (fdDemo.ShowDialog() == DialogResult.OK)
115 {
116 rtbEditor.SelectionColor = fdDemo.Color;
117 rtbEditor.SelectionFont = fdDemo.Font;
118 }
119 }
120
121 private void pdEditor_PrintPage(object sender,
122 System.Drawing.Printing.PrintPageEventArgs e)
123 {
124 //存放当前已经处理的高度
125
126 float allHeight = 0;
127 //存放当前已经处理的宽度
128
129 float allWidth = 0;
130 //存放当前行的高度
131 float lineHeight = 0;
132 //存放当前行的宽度
133 float lineWidth = e.MarginBounds.Right - e.MarginBounds.Left;
134
135 //当前页没有显示满且文件没有打印完,进行循环
136
137 while (allHeight < e.MarginBounds.Height
138 && _currentCharIndex < rtbEditor.Text.Length)
139 {
140 //选择一个字符
141
142 rtbEditor.Select(_currentCharIndex, 1);
143 //获取选中的字体
144
145 Font currentFont = rtbEditor.SelectionFont;
146 //获取文字的尺寸
147
148 SizeF currentTextSize =
149 e.Graphics.MeasureString(rtbEditor.SelectedText, currentFont);
150
151 //获取的文字宽度,对于字母间隙可以小一些,
152 //对于空格间隙可以大些,对于汉字间隙适当调整。
153
154 if (rtbEditor.SelectedText[0] == ' ')
155 currentTextSize.Width = currentTextSize.Width * 1.5f;
156 else if (rtbEditor.SelectedText[0] < 255)
157 currentTextSize.Width = currentTextSize.Width * 0.6f;
158 else
159 currentTextSize.Width = currentTextSize.Width * 0.75f;
160
161 //初始位置修正2个像素,进行背景色填充
162
163 e.Graphics.FillRectangle(new SolidBrush(rtbEditor.SelectionBackColor),
164 e.MarginBounds.Left + allWidth + 2, e.MarginBounds.Top + allHeight,
165 currentTextSize.Width, currentTextSize.Height);
166
167 //使用指定颜色和字体画出当前字符
168
169 e.Graphics.DrawString(rtbEditor.SelectedText, currentFont,
170 new SolidBrush(rtbEditor.SelectionColor),
171 e.MarginBounds.Left + allWidth, e.MarginBounds.Top + allHeight);
172
173 allWidth += currentTextSize.Width;
174
175 //获取最大字体高度作为行高
176
177 if (lineHeight < currentFont.Height)
178 lineHeight = currentFont.Height;
179
180 //是换行符或当前行已满,allHeight加上当前行高度,
181 //allWidth和lineHeight都设为0。
182
183 if (rtbEditor.SelectedText == "\n"
184 || e.MarginBounds.Right - e.MarginBounds.Left < allWidth)
185 {
186 allHeight += lineHeight;
187 allWidth = 0;
188 lineHeight = 0;
189 }
190 //继续下一个字符
191
192 _currentCharIndex++;
193 }
194
195 //后面还有内容,则还有下一页
196
197 if (_currentCharIndex < rtbEditor.Text.Length)
198 e.HasMorePages = true;
199 else
200 e.HasMorePages = false;
201 }
202
203 private void tsmiPrint_Click(object sender, EventArgs e)
204 {
205 if (pdDemo.ShowDialog() == DialogResult.OK)
206 {
207 //用户确定了打印机和设置后,进行打印。
208
209 pdEditor.Print();
210 }
211 }
212
213 private void tsmiPageSetup_Click(object sender, EventArgs e)
214 {
215 psdDemo.ShowDialog();
216 }
217
218 private void tsmiPrintPreview_Click(object sender, EventArgs e)
219 {
220 ppdDemo.ShowDialog();
221 }
222
223 private void pdEditor_BeginPrint(object sender,
224 System.Drawing.Printing.PrintEventArgs e)
225 {
226 _currentCharIndex = 0;
227 }
228
229 #endregion
230 }
231 }
View Code
文件编辑器做好了,下面就是主窗体,首先IsMdiContainer属性设置为true,在上面我们加下菜单:
新建Notepad的代码:
1 private void tsmiNewTxt_Click(object sender, EventArgs e)
2 {
3 NotepadForm childForm = new NotepadForm();
4 childForm.Text = "新建文本文档.txt";
5 childForm.MdiParent = this;
6 childForm.Show();
7 }
运行效果:
程序下载:MDI窗体.rar
附录:小菜学习编程-Winform系列(初学者)
作者:田园里的蟋蟀
微信公众号:你好架构
出处:http://www.cnblogs.com/xishuai/
公众号会不定时的分享有关架构的方方面面,包含并不局限于:Microservices(微服务)、Service Mesh(服务网格)、DDD/TDD、Spring Cloud、Dubbo、Service Fabric、Linkerd、Envoy、Istio、Conduit、Kubernetes、Docker、MacOS/Linux、Java、.NET Core/ASP.NET Core、Redis、RabbitMQ、MongoDB、GitLab、CI/CD(持续集成/持续部署)、DevOps等等。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
分享到:
QQ空间
新浪微博
腾讯微博
微信
更多