前言
在做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 else104 {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.Height138 && _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 else159 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 else200 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 #endregion230 }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 }
运行效果:
程序下载:
附录: