前言
在做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的组件,关于文本编辑器就不详述了,贴下代码:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }
文件编辑器做好了,下面就是主窗体,首先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