第9章 Windows窗体应用程序设计 9.1 窗体设计 9.2 常用的控件设计 9.3 多个窗体之间的数据传递 9.4 多文档窗体 9.1 窗体设计 9.2 常用的控件设计 9.3 多个窗体之间的数据传递 9.4 多文档窗体 9.5 窗体设计的事件机制
9.1 窗体设计 窗体(Form)是一个窗口或对话框,是存放各种控件(包括标签、文本框、命令按钮等)的容器,可用来向用户显示信息。
9.1.1 创建Windows窗体应用程序的过程 添加一个窗体的操作步骤是:选择“项目”|“添加Windows窗体”菜单命令,在出现的 “添加新项”对话框中,选中“Windows窗体”,输入相应的名称(这里为Form2.cs),单击“添加”按钮。 一个Windows应用程序可以包含多个窗体。
标题栏 属性 窗口 属性含 义说明 工具箱 工具栏 窗体 窗体设计器窗口 菜单栏 解决方案 资源管理 器
9.1.2 窗体类型 在C#中,窗体分为如下两种类型: 9.1.2 窗体类型 在C#中,窗体分为如下两种类型: (1)普通窗体,也称为单文档窗体(SDI),前面所有创建的窗体均为普通窗体。普通窗体又分为如下两种: 模式窗体。这类窗体在屏幕上显示后用户必须响应,只有在它关闭后才能操作其他窗体或程序。 无模式窗体。这类窗体在屏幕上显示后用户可以不必响应,可以随意切换到其他窗体或程序进行操作。通常情况下,当建立新的窗体时,都默认设置为无模式窗体。 (2)MDI父窗体,即多文档窗体,其中可以放置普通子窗体。
9.1.3 窗体的常用属性 布局属性 窗口样式属性 外观样式属性 行为属性 9.1.4 窗体的常用事件 9.1.5 窗体的常用方法
9.1.6 多个窗体之间的调用 使用以下代码可以打开另外一个窗体: 新窗体类 窗体实例名 = new 新窗体类(); 当然,只是实例化一个窗体类的对象是不能让窗体“显示”出来的,还要调用该对象的方法才能显示出窗体,窗体对象有两个方法可以完成该功能: 窗体实例名.Show();
Show()方法以无模式对话框方式显示该窗体,即新窗体显示后,主窗体(调用窗体)和子窗体(被调用窗体)之间可以任意切换,互不影响。 窗体实例名.ShowDialog(); ShowDialog()方法以模式对话框方式显示该窗体,即新窗体显示后,必须操作完子窗体,关闭子窗体后才能再操作主窗体。
【例9.1】 1. Form1窗体: (1)设计界面 (2)事件过程: private void button1_Click(object sender, EventArgs e) { Form myform = new Form1_1(); //定义Form1_1类对象 myform.ShowDialog(); //以模式窗体方式调用 } private void button2_Click(object sender, EventArgs e) { Form myform = new Form1_2(); //定义Form1_2类对象 myform.Show(); //以无模式窗体方式调用
2. Form1_1窗体: (1)设计界面 (2)事件过程:无 3. Form1_1窗体: (1)设计界面 (2)事件过程:无
Program.cs文件 : using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; namespace proj9_1 { static class Program { /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); }
按F5键或单击工具栏中的按钮运行本项目。 上机调试运行结果。
9.1.7 窗体上各事件的引发顺序 当一个窗体启动时,执行事件过程的次序如下: 一个窗体被卸载时,执行事件过程的次序如下: 9.1.7 窗体上各事件的引发顺序 当一个窗体启动时,执行事件过程的次序如下: (1)本窗体上的Load事件过程。 (2)本窗体上的Activated事件过程。 (3)本窗体上的其他Form级事件过程。 (4)本窗体上包含对象的相应事件过程。 一个窗体被卸载时,执行事件过程的次序如下: (1)本窗体上的Closing事件过程。 (2)本窗体上的FormClosing事件过程。 (3)本窗体上的Closed事件过程。 (4)本窗体上的FormClosed事件过程。
9.1.8 焦点与Tab键次序 焦点(Focus)是指当前处于活动状态的窗体或控件。 要将焦点移到当前窗体中的textBox1文本框,可以使用以下命令: textBox1.Focus();
9.2 常用的控件设计 9.2.1 控件概述 控件是包含在窗体上的对象,是构成用户界面的基本元素,也是C#可视化编程的重要工具。 工具箱中包含了建立应用程序的各种控件,根据控件的不同用途分为若干个选项卡,可根据用途单击相应的选项卡,将其展开,选择需要的控件。
大多数控件共有的基本属性如下 : 1)Name属性 2)Text属性 3)尺寸大小(Size)和位置(Location)属性 4)字体属性(Font) 5)颜色属性(BackColor和ForeColor) 6)Cursor属性 7)可见(Visible)和有效(Enabled)属性
9.2.2 富文本框控件 提供类似Microsoft Word能够输入、显示或处理具有格式的文本。 9.2.2 富文本框控件 提供类似Microsoft Word能够输入、显示或处理具有格式的文本。 【例9.2】 设计一个窗体,说明富文本框的使用方法。 Form2窗体: (1)设计界面 (2)事件过程: private void Form2_Load(object sender, EventArgs e) { richtextBox1.LoadFile("D:\\C#程序\\ch9\\file.RTF", RichtextBoxStreamType.RichText); } @"D:\C#程序\ch9\file.RTF",
将本窗体设计为启动窗体,运行本项目,在富文本框RichtextBox1中显示D:\\C#程序\\ch9\\file.RTF文件的内容。
9.2.3 分组框控件 9.2.4 面板控件 这两类控件十分简单,用作界面美观的作用,不作介绍。
9.2.5 复选框控件 属于选择类控件,用来设置需要或不需要某一选项功能。在运行时,如果用户用鼠标单击复选框左边的方框,方框中就会出现一个“√”符号,表示已选取这个功能了。 复选框的功能是独立的,如果在同一窗体上有多个复选框,用户可根据需要选取一个或几个。
主要属性: Checked:获取或设置一个布尔值,该值指示是否已选中控件。如果为True,则指示选中状态;否则为False(默认值)。 主要事件: Click:单击事件。
【例9.3】 设计一个窗体,说明复选框的应用。 Form3窗体: (1)设计界面 (2)事件过程: 【例9.3】 设计一个窗体,说明复选框的应用。 Form3窗体: (1)设计界面 (2)事件过程: private void button1_Click(object sender, EventArgs e) { if (checkBox1.Checked && checkBox3.Checked && !checkBox2.Checked && !checkBox4.Checked) MessageBox.Show("您答对了,真的很棒!!!", "信息提示", MessageBoxButtons.OK); else MessageBox.Show("您答错了,继续努力吧!!!", "信息提示", MessageBoxButtons.OK); }
运行界面
9.2.6 单选按钮控件 单选按钮是多选一,只能从多个选项中选择一个,各选项间的关系是互斥的。 9.2.6 单选按钮控件 单选按钮是多选一,只能从多个选项中选择一个,各选项间的关系是互斥的。 单选按钮使用时经常用多个控件构成一个组,同一时刻只能选择同一组中的一个单选按钮。 其设计方法是,将多个单选按钮放在一个分组框中,同一分组框中的所有单选按钮构成一个选项组。
【例9.4】 设计一个窗体,说明单选按钮的使用方法。 【例9.4】 设计一个窗体,说明单选按钮的使用方法。 Form4窗体: (1)设计界面 (2)事件过程: private void button1_Click(object sender, EventArgs e) { if (radiobutton3.Checked) MessageBox.Show("您选对了,这是微软公司开发的操作系统", "信息提示", MessageBoxButtons.OK); else if (radiobutton1.Checked || radiobutton4.Checked) MessageBox.Show("您选错了,这是程序设计语言", else MessageBox.Show("您选错了,这是数据库管理系统", }
运行界面
9.2.7 图片框控件 用于在窗体的特殊位置上放置图形信息,也可以在其上放置多个控件,因此它可作为其他控件的容器 。 主要属性: 9.2.7 图片框控件 用于在窗体的特殊位置上放置图形信息,也可以在其上放置多个控件,因此它可作为其他控件的容器 。 主要属性: Image:获取或设置图片框中显示的图像。在运行时再使用Image.FromFile函数加载图像。
【例9.5】 设计一个窗体,以选择命令按钮方式显示春、夏、秋、冬4个季节的图片。 【例9.5】 设计一个窗体,以选择命令按钮方式显示春、夏、秋、冬4个季节的图片。 Form5窗体: (1)设计界面 (2)事件过程: private void button1_Click(object sender, EventArgs e) { pictureBox1.Image = Image.FromFile("D:\\C#程序\\ch9\\spring.jpg"); } private void button2_Click(object sender, EventArgs e) { pictureBox1.Image = Image.FromFile("D:\\C#程序\\ch9\\summer.jpg"); private void button3_Click(object sender, EventArgs e) { pictureBox1.Image = Image.FromFile("D:\\C#程序\\ch9\\fall.jpg"); private void button4_Click(object sender, EventArgs e) { pictureBox1.Image = Image.FromFile("D:\\C#程序\\ch9\\winter.jpg");
运行界面
9.2.8 组合框控件 从一个列表中一次只能选取或输入一个选项,其主要特点是具有带向下箭头的方框。 9.2.8 组合框控件 从一个列表中一次只能选取或输入一个选项,其主要特点是具有带向下箭头的方框。 在程序运行时,按下此按钮就会下拉出一个列表框供用户选择项目。另外,还可以在组合框上方的框中输入数据。
组合框的属性 说明 DropDownStyle 获取或设置指定组合框样式的值。可取以下值之一: DropDown(默认值):文本部分可编辑。用户必须单击箭头按钮来显示列表部分。 DropDownList:用户不能直接编辑文本部分。用户必须单击箭头按钮来显示列表部分。 Simple:文本部分可编辑。列表部分总可见。 上述3种样式的组合框如图9.19所示。 DropDownWidth 获取或设置组合框下拉部分的宽度(以像素为单位)。 DropDownHeight 获取或设置组合框下拉部分的高度(以像素为单位)。 Items 表示该组合框中所包含项的集合。 SelectedItem 获取或设置当前组合框中选定项的索引。 SelectedText 获取或设置当前组合框中选定项的文本。 Sorted 指示是否对组合框中的项进行排序。
DropDownStyle=Simple DropDownStyle=DropDown DropDownStyle=DropDownList
组合框的Items属性是最重要的属性,它是存放组合框中所有项的集合,对组合框的操作实际上就是对该属性即项集合的操作。 说明 Count 组合框的项集合中项个数。 Items的方法 说明 Add 向ComboBox项集合中添加一个项。 AddRange 向ComboBox项集合中添加一个项的数组。 Clear 移除ComboBox项集合中的所有项。 Contains 确定指定项是否在ComboBox项集合中。 Equqls 判断是否等于当前对象。 GetType 获取当前实例的Type。 Insert 将一个项插入到ComboBox项集合中指定的索引处。 IndexOf 检索指定的项在ComboBox项集合中的索引。 Remove 从ComboBox项集合中移除指定的项。 RemoveAt 移除ComboBox项集合中指定索引处的项
组合框的事件 组合框的事件 说明 Click 在单击控件时发生。 TextChanged 在 Text 属性值更改时发生。 SelectedIndexChanged 在SelectedIndex属性值改变时发生。 KeyPress 在控件有焦点的情况下按下键时发生。
【例9.6】 设计一个窗体,通过一个文本框向合框中添加项。 【例9.6】 设计一个窗体,通过一个文本框向合框中添加项。 Form6窗体: (1)设计界面 (2)事件过程: private void button1_Click(object sender, EventArgs e) { if (textBox1.Text != "") if (!comboBox1.Items.Contains(textBox1.Text)) comboBox1.Items.Add(textBox1.Text); //不添加重复项 }
运行界面
9.2.9 列表框控件 是一个为用户提供选择的列表,用户可从列表框列出的一组选项中用鼠标选取一个或多个所需的选项。 9.2.9 列表框控件 是一个为用户提供选择的列表,用户可从列表框列出的一组选项中用鼠标选取一个或多个所需的选项。 如果有较多的选择项,超出规定的区域而不能一次全部显示时,C#会自动加上滚动条。 与组合框类似。
列表框的属性 说明 MultiColumn 获取或设置列表框控件是否支持多列。设置为True,则支持多列,设置为False(默认值),则不支持多列 SelectedIndex 获取或设置列表框控件中当前选定项从0开始的索引。 SelectedIndices 获取一个集合,它包含所有当前选定项的从0开始的索引。 SelectedItem 获取或设置列表框控件中当前选定项。 SelectedItems 获取一个集合,它包含所有当前选定项。 Items 获取列表控件项的集合。 SelectionMode 获取或设置列表框控件的选择模式。可选以下值之一: one:表示只能选择一项。 none:表示无法选择。 MultiSimple:表示可以选择多项。 MultiExtended:表示可以选择多项。并且按下Shift键的同时单击鼠标或者同时按下Shift键和箭头键,会将选定内容从前一选定项扩展到当前项,按下Ctrl键的同时单击鼠标将选择或撤销选择列表中的某项。 Text 当前选取的选项文本。
【例9.7】 设计一个窗体,其功能是在两个列表框中移动数据项。 【例9.7】 设计一个窗体,其功能是在两个列表框中移动数据项。 Form7窗体: (1)设计界面 (2)事件过程: private void Form7_Load(object sender, EventArgs e) { listBox1.Items.Add("清华大学"); listBox1.Items.Add("北京大学"); listBox1.Items.Add("浙江大学"); listBox1.Items.Add("南京大学"); listBox1.Items.Add("武汉大学"); listBox1.Items.Add("中国科技大学"); listBox1.Items.Add("中国人民大学"); listBox1.Items.Add("华中科技大学"); listBox1.Items.Add("复旦大学"); enbutton(); //调用enbutton()方法 }
private void enbutton() //自定义方法 { if (listBox1.Items.Count == 0) //当左列表框为空时右移命令按钮不可用 { button1.Enabled = false; button2.Enabled = false; } else //当左列表框不为空时右移命令按钮可用 { button1.Enabled = true; button2.Enabled = true; if (listBox2.Items.Count == 0) //当右列表框为空时左移命令按钮不可用 { button3.Enabled = false; button4.Enabled = false; else //当右列表框不为空时左移命令按钮可用 { button3.Enabled = true; button4.Enabled = true;
private void button1_Click(object sender, EventArgs e) { if (listBox1.SelectedIndex >= 0) //将左列表框中选中项移到右列表框中 { listBox2.Items.Add(listBox1.SelectedItem); listBox1.Items.RemoveAt(listBox1.SelectedIndex); } enbutton(); //调用enbutton()方法 private void button2_Click(object sender, EventArgs e) { foreach (object item in listBox1.Items)//将左列表框中所有项移到右列表框中 listBox2.Items.Add(item); listBox1.Items.Clear();
private void button3_Click(object sender, EventArgs e) { if (listBox2.SelectedIndex >= 0) //将右列表框中选中项移到左列表框中 { listBox1.Items.Add(listBox2.SelectedItem); listBox2.Items.RemoveAt(listBox2.SelectedIndex); } enbutton(); //调用enbutton()方法 private void button4_Click(object sender, EventArgs e) { foreach (object item in listBox2.Items)//将右列表框中所有项移到左列表框中 listBox1.Items.Add(item); listBox2.Items.Clear();
运行界面
9.2.10 带复选框的列表框控件 用来显示一系列列表项的,不过每个列表项前面都有一个复选项。这样,是否选中了某个列表项就可以很清楚地表现出来。
9.2.11 定时器控件 特点是每隔一定的时间间隔就会自动运行一次定时器事件。所谓时间间隔,指的是定时器事件两次调用之间的时间间隔,一般以毫秒(ms)为基本单位。
定时器的属性 说明 Enabled 设置是否起用定时器控件。若设置为True(默认值),表示启动定时器开始计时;否则,表示暂停定时器的使用。 Interval 设置两个定时器事件之间的时间间隔。设置时以毫秒为单位,设置的范围是0~65535ms。 定时器的方法 说明 Start 启动定时器,也可以将Enabled属性设置为True来启动定时器。 Stop 停止定时器,也可以将Enabled属性设置为False来停止定时器。
【例9.9】 设计一个窗体说明定时器的使用方法。 【例9.9】 设计一个窗体说明定时器的使用方法。 Form9窗体: (1)设计界面 (2)事件过程: private void Form9_Load(object sender, EventArgs e) { textBox1.Text = DateTime.Now.ToString("h:mm:ss"); timer1.Enabled = true; //启到定时器timer1 timer1.Interval = 100; } private void timer1_Tick(object sender, EventArgs e) { textBox1.Text = DateTime.Now.ToString("h:mm:ss");
运行界面
9.2.12 滚动条控件 滚动条的结构为两端各有一个滚动箭头,两个滚动箭头中间是滚动条部分,在滚动条上有一个能够移动的小方块,叫做滚动框。 9.2.12 滚动条控件 滚动条的结构为两端各有一个滚动箭头,两个滚动箭头中间是滚动条部分,在滚动条上有一个能够移动的小方块,叫做滚动框。 水平滚动条和垂直滚动条
滚动条的属性 说明 Maximum 表示滚动条的最大值。 Minimum 表示滚动条的最小值。 Value 表示目前滚动条所在位置对应的值。 LargeChange 设置滚动条的最大变动值。 SmallChange 设置滚动条的最小变动值。 滚动条的事件 说明 Scroll 当用鼠标压住滚动条上的滑块进行移动时,滑块被重新定位时发生。 Change 当改变Value属性值时发生。
【例9.10】 设计一个窗体说明滚动条的使用方法。 【例9.10】 设计一个窗体说明滚动条的使用方法。 Form10窗体: (1)设计界面 (2)事件过程: private void Form10_Load(object sender, EventArgs e) { hScrollBar1.Maximum = 100; hScrollBar1.Minimum = 0; hScrollBar1.SmallChange = 2; hScrollBar1.LargeChange = 5; vScrollBar1.Maximum = 100; vScrollBar1.Minimum = 0; vScrollBar1.SmallChange = 2; vScrollBar1.LargeChange = 5; hScrollBar1.Value = 0; vScrollBar1.Value = 0; textBox1.Text = "0"; }
private void hScrollBar1_Scroll(object sender, ScrollEventArgs e) { textBox1.Text = hScrollBar1.Value.ToString("d"); //将hScrollBar1.Value整数将实际宽度转换成字符串在textBox1中显示 vScrollBar1.Value = hScrollBar1.Value; } private void vScrollBar1_Scroll(object sender, ScrollEventArgs e) { textBox1.Text = vScrollBar1.Value.ToString("d"); hScrollBar1.Value = vScrollBar1.Value;
运行界面 private void button1_Click(object sender, EventArgs e) { if (Convert.ToInt16(textBox1.Text)>= 0 && Convert.ToInt16(textBox1.Text) <= 100) { hScrollBar1.Value = Convert.ToInt16(textBox1.Text); vScrollBar1.Value = Convert.ToInt16(textBox1.Text); } 运行界面
9.2.13 月历控件 9.2.14 日期/时间控件 9.2.15 超链接标签控件 这三种控件使用简单,不作介绍。
9.3 多个窗体之间的数据传递 9.3.1 通过静态字段传递数据 9.3 多个窗体之间的数据传递 9.3.1 通过静态字段传递数据 其原理是将类的静态字段充当全局变量使用,在调用SForm窗体前将MForm中要传递的数据保存在类静态字段中,在执行SForm窗体时,从该类静态字段中读出数据并处理。
【例9.13】采用通过静态字段传递数据的方法,在两个窗体之间传递一个整数和一个字符串。 新建一个proj9-2的Windows应用程序项目,在项目中新建一个类文件class1.cs(选择“项目|添加类”命令,在出现的“添加新项”对话框中单击“添加”按钮即可),其中设计一个类TempDate,该类中含有需要在窗体间传递数据的静态字段: public class TempData { public static int mynum; public static string mystr; }
在该项目中添加一个MForm窗体,包含两个标签、两个文本框(textBox1和textBox2)和一个命令按钮button1,其设计界面如图9.36所示。在button1上设计如下单击事件过程: private void button1_Click(object sender, EventArgs e) { TempData.mynum = int.Parse(textBox1.Text); //将文本框textBox1的值转换为整数后保存在静态字段mynum中 TempData.mystr = textBox2.Text; //将文本框textBox2的值保存在静态字段mystr中 Form myform = new SForm(); myform.ShowDialog(); }
再在该项目中添加一个SForm窗体,包含一个分组框,分组框中有两个标签、两个文本框(textBox1和textBox2)和一个命令按钮button1,其设计界面如图9.37所示。在该窗体上设计如下事件过程: private void SForm_Load(object sender, EventArgs e) { textBox1.Text = TempData.mynum.ToString(); //读出静态字段mynum中的数据 textBox2.Text = TempData.mystr; //读出静态字段mystr中的数据 } private void button1_Click(object sender, EventArgs e) { this.Close(); //关闭本窗体
执行MForm窗体,首先显示MForm窗体,在两个文本框中分别输入“125”和“China”,然后单击“调用SForm”命令按钮,此时显示SForm窗体,如图9.38所示,从中看到SForm窗体中的文本框显示出从MForm窗体传递过来的数据。
9.3.2 通过构造函数传递数据 若要将MForm窗体的数据传递到SForm窗体。其原理是修改SForm窗体的构造函数,将要接收的数据作为该窗体构造函数的形参,在MForm窗体中调用SForm窗体时,将要传递的数据作为实参,从而达到窗体间传递数据的目的。
【例9.14】采用通过构造函数传递数据的方法,在两个窗体之间传递一个整数和一个字符串。 MForm1 SForm1
在MForm1窗体上设计如下事件过程: private void button1_Click(object sender, EventArgs e) { int num = int.Parse(textBox1.Text); string str = textBox2.Text; Form myform = new SForm1(num,str); //带传递数据调用SForm1的构造函数 myform.ShowDialog(); }
在SForm1窗体上设计两个private字段mynum和mystr,并设计SForm_Load等事件过程和修改SForm1的构造函数,对应的代码如下: public partial class SForm1 : Form { private int mynum; //类私有字段,接收传递过来的数据 private string mystr; //类私有字段,接收传递过来的数据 public SForm1(int num, string str) { InitializeComponent(); mynum=num; mystr=str; }
private void SForm1_Load(object sender, EventArgs e) { textBox1.Text = mynum.ToString(); //显示传递过来的数据 textBox2.Text = mystr; //显示传递过来的数据 } private void button1_Click(object sender, EventArgs e) { this.Close();
运行界面
9.4 多文档窗体 多文档界面应用程序由一个应用程序(MDI父窗体)中包含多个文档(MDI子窗体)组成,父窗体作为子窗体的容器,子窗体显示各自文档,而且不能将其移动到父窗体的区域之外。 多文档界面应用程序有如下特性: (1)所有子窗体均显示在MDI窗体的工作区内,用户可改变、移动子窗体的大小,但被限制在MDI窗体中。 (2)当最小化子窗体时,它的图标将显示在MDI窗体上而不是在任务栏中。 (3)当最大化子窗体时,它的标题与MDI窗体的标题一起显示在MDI窗体的标题栏上。 (4)MDI窗体和子窗体都可以有各自的菜单,当子窗体加载时覆盖MDI窗体的菜单。
MDI父窗体属性 说明 ActiveMdiChild 表示当前活动的MDI子窗口,如没有子窗口则返回NULL IsMdiContainer 指示窗体是否为MDI父窗体,值为True时表示是父窗体,值为False时表示是普通窗体 MdiChildren 以窗体数组形式返回所有MDI子窗体
一般只使用父窗体的LayoutMdi方法,其使用格式为: MDI父窗体名.LayoutMdi(value) 其功能是在MDI父窗体中排列MDI子窗体,参数value决定排列方式,有以下4种取值: LayoutMdi.ArrangeIcons:所有MDI子窗体以图标形式排列在MDI父窗体中。 LayoutMdi.TileHorizontal:所有MDI子窗体均垂直平铺在MDI父窗体中。 LayoutMdi.TileVertical:所有MDI子窗体均水平平铺在MDI父窗体中。 LayoutMdi.Cascade:所有MDI子窗体均层叠在MDI父窗体中。
MDI子窗体属性 说明 IsMdiChild 指示窗体是否为MDI子窗体,值为True时表示是子窗体,值为False时表示是一般窗体 MdiParent 用来指定该子窗体的MDI父窗体
【例9.15】 设计一个Windows应用程序,说明多文档窗体的使用方法。 Form1窗体,将其IsMdiContainer属性设为True : 设计界面
事件过程: private void button1_Click(object sender, EventArgs e) { Form2 child = new Form2(); child.MdiParent = this; child.Show(); n++; child.Text = "第" + n + "个子窗体"; } private void button2_Click(object sender, EventArgs e) { this.LayoutMdi(System.Windows.Forms. MdiLayout.ArrangeIcons); private void button3_Click(object sender, EventArgs e) MdiLayout.Cascade); private void button4_Click(object sender, EventArgs e) MdiLayout.TileVertical);
运行界面 private void button5_Click(object sender, EventArgs e) { this.LayoutMdi(System.Windows.Forms. MdiLayout.TileHorizontal); } 运行界面
9.5 窗体设计的事件机制 9.5.1 窗体事件处理原理 1. 创建窗体 9.5 窗体设计的事件机制 9.5.1 窗体事件处理原理 1. 创建窗体 创建一个名称为proj9-4的Windows应用程序项目,添加一个窗体Form1,将窗体的Text属性改为“我的窗体”,向其中拖放一个命令按钮button1,将其Text属性改为“确定”,字体设置为5号黑体,前景色设置为红色,窗体的设计界面如图9.43所示。
再在button1上设计一个Click事件过程: private void button1_Click(object sender, EventArgs e) { MessageBox.Show("您单击了button1", "信息提示", MessageBoxButtons.OK); } 运行界面
2. 代码分析 (1)Form1.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;
namespace proj9_4 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { MessageBox.Show("您单击了button1", "信息提示", MessageBoxButtons.OK); }
(2)Form1.Designer.cs namespace proj9_4 { partial class Form1 { /// <summary> /// 必需的设计器变量。 /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// 清理所有正在使用的资源。 /// <param name="disposing">如果应释放托管资源,为true;否则为false。</param>
protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); #region Windows 窗体设计器生成的代码 /// <summary> /// 设计器支持所需的方法 - 不要 /// 使用代码编辑器修改此方法的内容。 /// </summary>
private void InitializeComponent() { this.button1 = new System.Windows.Forms.Button(); this.SuspendLayout(); // // button1 this.button1.Font = new System.Drawing.Font("黑体", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.button1.ForeColor = System.Drawing.Color.Red; this.button1.Location = new System.Drawing.Point(60, 39); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(77, 26); this.button1.TabIndex = 0; this.button1.Text = "确定"; this.button1.UseVisualStyleBackColor = true; this.button1.Click += new System.EventHandler(this.button1_Click);
// // Form1 this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(206, 114); this.Controls.Add(this.button1); this.Name = "Form1"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "我的窗体"; this.ResumeLayout(false); } #endregion private System.Windows.Forms.Button button1;
事件过程的代码由程序员定制,这里的button1_Click功能是弹出一个消息框。其方法头部如下: private void button1_Click(object sender, EventArgs e) object参数是引发事件的对象,本例中是button1。把一个引用发送给引发事件的对象,就可以把同一个事件过程赋予多个对象。 EventArgs参数是包含有关事件的其他有用信息的对象。这个参数可以是任意类型,只要它派生自EventArgs即可。不同的事件该参数可以不同。
Form1的事件处理机制
在理解窗体事件处理原理后,开发Windows应用程序的重要任务是设计事件过程。设计事件过程主要有以下两种方法:
9.5.2 在Windows窗体中创建事件过程 在Windows窗体设计器上创建事件处理程序的过程如下: (1)单击要为其创建事件处理程序的窗体或控件。 (2)在属性窗口中单击“事件”按钮 。 (3)在可用事件的列表中,单击要为其创建事件处理程序的事件。
④ 在事件名称右侧的框中,键入处理程序的名称,然后按Enter键。如图9 ④ 在事件名称右侧的框中,键入处理程序的名称,然后按Enter键。如图9.46所示是为button1命令按钮选择button1_Click事件处理程序,这样C#系统会在对应窗体的.Designer.cs文件中自动添加订阅事件的语句。 ⑤ 开发人员将适当的代码添加到该事件过程中。
9.5.3 在运行时为Windows窗体创建事件处理程序 在运行时创建事件处理程序的过程如下: (1)在代码编辑器中打开要向其添加事件处理程序的窗体。 (2)对于要处理的事件,将带有其方法签名的方法添加到窗体上。 例如,如果要处理命令按钮button1的Click事件,则需创建如下的一个方法: private void button1_Click(object sender, System.EventArgs e) { //输入相应的代码 }
(3)将适合应用程序的代码添加到事件处理程序中。 (4)确定要创建事件处理程序的窗体或控件。 (3)将适合应用程序的代码添加到事件处理程序中。 (4)确定要创建事件处理程序的窗体或控件。 (5)打开对应窗体的.Designer.cs文件,添加指定事件处理程序的代码处理事件。例如,以下代码指定事件处理程序button1_Click处理命令按钮控件的Click事件: button1.Click += new System.EventHandler(button1_Click);
9.5.4 将多个事件连接到Windows窗体中的单个事件处理程序 在应用程序设计中,可能需要将单个事件处理程序用于多个事件或让多个事件执行同一过程,这样便于简化代码。在C#中将多个事件连接到单个事件处理程序的过程如下: (1)选择要将事件处理程序连接到的控件。 (2)在“属性”窗口中,单击“事件”按钮。 (3)单击要处理的事件的名称。 (4)在事件名称旁边的值区域中,单击下拉按钮显示现有事件处理过程列表,这些事件处理程序会与要处理的事件的方法签名相匹配。 (5)从该列表中选择适当的事件处理过程。 代码将添加到该窗体中,以便将该事件绑定到现有事件过程。
【例9.16】 设计一个Windows应用程序,用于模拟简单计算器的功能。 Form1窗体,将其IsMdiContainer属性设为True : 设计界面 运 算 符 组 数 字 组 buttond_Click buttonp_Click
private void Form1_Load(object sender, EventArgs e) { textBox1.Text = ""; label1.Text = ""; } private void buttond_Click(object sender, EventArgs e) //单击数字命令按钮的事件处理程序 { btn = (Button)sender; textBox1.Text = textBox1.Text + btn.Text;
private void buttonop_Click(object sender, EventArgs e) //单击运算符命令按钮的事件处理程序 { btn = (Button)sender; if (btn.Name!="button12") //用户不是单击“=”命令按钮 { x = Convert.ToDouble(textBox1.Text); textBox1.Text = ""; s = btn.Name; //保存用户按键 label1.Text = x.ToString(); } else //用户单击“=”命令按钮 { if (label1.Text == "") MessageBox.Show("输入不正确!!!", "信息提示", MessageBoxButtons.OK); else
{ y = Convert.ToDouble(textBox1.Text); switch(s) { case "button13": //用户刚前面单击“+”命令按钮 textBox1.Text = (x + y).ToString(); break; case "button14": //用户刚前面单击“-”命令按钮 textBox1.Text = (x - y).ToString(); case "button15": //用户刚前面单击“×”命令按钮 textBox1.Text = (x * y).ToString(); case "button16": //用户刚前面单击“÷”命令按钮 if (y == 0) MessageBox.Show("除零错误!!!", "信息提示", MessageBoxButtons.OK); else textBox1.Text = (x / y).ToString(); } label1.Text = textBox1.Text; }}}
运行界面(通过单击命令按钮在文本框中输入15.2,单击“+”命令按钮,再输入63.7,最后单击“=”命令按钮)
━━本章完━━