Download presentation
Presentation is loading. Please wait.
Published byIda Budiaman Modified 6年之前
1
第三章 常用控件和类的使用 微软Visual C#2005 Express Edition(以后简称VS2005)是微软推出的免费版本,适合初学者学习用C#语言编写Windows应用程序,VS2005使用控件(组件)设计Windows应用程序。将VS2005工具箱窗口中的控件放到窗体中,使用属性窗口或在程序中用语句修改控件属性,设计应用程序界面,为控件增加事件处理函数,完成指定的功能。
2
3.1 控件通用属性 大部分控件,例如Label、Button、TextBox等,都是Control类的派生类。Control类定义了这些派生类控件通用的一组属性和方法,以下是Control类的一些常用属性: Name: Location: Left和Top: Size: BackColor: Enabled: Visible: Modifier: Cursor:
3
3.2 Form类 Form类是对Windows应用程序窗体的封装,属于System.Windows.Forms命名空间。Form类对象具有Windows应用程序窗体的最基本功能。它可以是对话框、单文档或多文档应用程序窗口的基类。Form类对象还是一个容器,在Form窗体中可以放置其他控件,例如菜单控件、工具条控件等等,还可以放置子窗体。Form类常用属性、方法和事件如下:
4
3.2 Form类 续) 属性AutoScroll: 方法Close(): 属性Text: 方法Hide():
属性AcceptButton和CancelButton: 属性MaxiMizeBox: 属性MiniMizeBox: 方法Close(): 方法Hide(): 方法Show(): 事件Load:
5
3.3 标签(Label)控件 Label控件常用属性如下: Text: AutoSize: ForeColor: Font:
6
3.4 按钮(Button)控件 Button控件常用属性和事件如下: 属性Text: 事件Click:
7
3.4 按钮(Button)控件(续) private void button1_Click(object sender, EventArgs e) { //此行语句为程序员增加的代码,其余是自动增加的代码 label1.ForeColor=Color.Red; }//label1是控件名字(label的Name属性),用来区分不同控件。 private void button2_Click(object sender, EventArgs e) { label1.ForeColor=Color.Black; }//运行阶段修改属性,Black为Color结构的静态属性 private void button3_Click(object sender, EventArgs e) { Close(); } //调用窗体Form1类的方法Close()
8
3.5 事件处理函数的参数 事件处理函数一般有两个参数,第一个参数(object sender)引用产生该事件的对象。事件处理函数第二个参数(EventArgs e)代表事件的一些附加信息,事件不同,所代表的信息也不相同。 private void button1_Click(object sender, EventArgs e) { if(sender==button1)//判断是否是button1产生的事件 label1.ForeColor=Color.Red; else label1.ForeColor=Color.Black; } button2 选用button1_Click为事件处理函数
9
3.5 文本框(TextBox)控件 常用属性和事件如下: 属性Text: 属性MaxLength: 属性SelectionLength:
属性ReadOnly: 属性PasswordChar: 属性MultiLine: 属性ScrollBars: 属性SelectionLength: 属性SelectionStart: 属性SelectedText: 属性AcceptsReturn: 事件TextChanged:
10
3.5 文本框(TextBox)控件(续)
11
3.5 文本框(TextBox)控件(续) //标题为"求积"的按钮的单击事件处理函数如下:
private void button1_Click(object sender,EventArgs e) { float ss,ee; ss=Convert.ToSingle(textBox1.Text); ee=Convert.ToSingle(textBox2.Text); textBox3.Text=Convert.ToString(ss*ee); } //标题为“清空”的按钮的单击事件处理函数如下: private void button2_Click(object sender, EventArgs e) { textBox1.Text=""; textBox2.Text=""; textBox3.Text="";
12
3.7 Convert类 Convert类中提供了一些静态方法,用来把一种类型数据转换为另一种类型数据。例如:Convert.ToSingle(textBox1.Text)把字符串textBox1.Text转换为单浮点数。Convert.ToString(3.14)把单浮点数3.14转换为字符串。其他转换函数还有:ToInt16(string)、ToInt32(string)、ToByte(char)、ToChar(Byte)、ToChar(int16)、ToDecimal(string)、ToDouble(string)、ToSByte(string)、ToUInt16(string)等。
13
3.8 RadioButton和GroupBox控件
RadioButton是单选按钮控件,多个RadioButton控件可以为一组,这一组内的RadioButton控件只能有一个被选中。GroupBox控件是一个容器类控件,在其内部可放置其他控件,表示其内部的所有控件为一组。一般把RadioButton控件放到GroupBox控件中,表示这些RadioButton控件是一组。有一些特性是互斥的,例如性别,选择这类特性可用RadioButton和GroupBox控件。GroupBox控件常用属性属性只有一个,属性Text,指定GroupBox控件顶部的标题。RadioButton控件常用属性和事件如下: 属性Text: 属性Checked: 事件CheckedChanged: 事件Click:
14
3.8 RadioButton和GroupBox控件 (续)
15
3.8 RadioButton和GroupBox控件 (续)
private void radioButton1_CheckedChanged( object sender, EventArgs e) { if(radioButton1.Checked) label1.Font=new Font("宋体",label1.Font.Size); }//label1显示的字体变为宋体,字体大小不变 private void radioButton2_CheckedChanged( { if(radioButton2.Checked) label1.Font=new Font("黑体",label1.Font.Size); } private void radioButton3_CheckedChanged( { if(radioButton3.Checked) label1.Font=new Font("楷体_GB2312",label1.Font.Size);}
16
3.9 Font类 Font类有两个构造函数:第一个是Font(字体名称,字号),例如,label1.Font=new Font("黑体",9),用法还可参考例3.4。第二个是Font(字体名称,字号,字体风格),其中第三个参数是枚举类型,具体定义如下: enum FontStyle{ Regular=0, //正常字体 Bold=1, //黑体 Italic=2, //斜体 BoldItalic=3, //黑斜体 Underline=4, //下划线,5=黑体下划线,6=斜体下划线,7=黑斜体下划线 Strikeout=8 }//删除线,9=黑体删除线,10=斜体删除线,依此类推。
17
3.9 Font类(续) 修改标签控件字体为斜体的两种方法代码如下: label1.Font=new Font(“黑体”,9,
label1.Font.Style|FontStyle.Italic);//方法1 label1.Font.Style|(FontStyle)2); //方法2 修改标签控件字体不为斜体的两种方法代码如下:: label1.Font.Style&~FontStyle.Italic);//方法1 label1.Font=new Font(“黑体”, 9,label1.Font.Style&(FontStyle)(~2));//方法2 修改其他字体风格的代码类似,请读者自己实现。
18
3.10 多选框(CheckBox)控件 CheckBox控件常用属性和事件如下: l 属性Text:多选框控件旁边的标题。
l 属性Checked:布尔变量,为true表示多选框被选中,为false不被选中。 l 事件Click:单击多选框控件时产生的事件。 l 事件CheckedChanged:多选框控件有被选中和不 被选中两种状态,该事件是多选框状态改变时产 生的事件。
19
3.10 多选框(CheckBox)控件 (续)
20
3.10 多选框(CheckBox)控件 (续) 例子1: private void checkBox1_CheckedChanged(
object sender,EventArgs e) { String text1=“你的爱好是:”; //checkBox1是标题为"音乐"的多选框控件 if(checkBox1.Checked) text1=text1+checkBox1.Text; //checkBox2是标题为"文学"的多选框控件 if(checkBox2.Checked) text1+=checkBox2.Text; label1.Text=text1; }
21
3.10 多选框(CheckBox)控件 (续) 例子2(界面同例子1)
标题为“音乐”的多选框控件CheckBox1的CheckedChanged事件处理函数如下: private void checkBox1_CheckedChanged( object sender, EventArgs e) { int n=s.IndexOf(“音乐”); if(n==-1) s+="音乐"; else s=s.Remove(n,2); label1.Text=s; }
22
3.10 多选框(CheckBox)控件 (续) 标题为"文学"多选框控件CheckBox2的CheckedChanged事件处理函数如下:
private void checkBox2_CheckedChanged( object sender, EventArgs e) { int n=s.IndexOf("文学"); if(n==-1) s+="文学"; else s=s.Remove(n,2); label1.Text=s; }
23
3.11 列表选择控件(ListBox) 列表选择控件的常用属性、事件和方法如下: 属性Items: 属性SelectedIndex:
属性SelectedIndices: 属性SelectedItem: 属性SelectedItems: 属性SelectionMode : 属性Sorted: 方法GetSelected(): 事件SelectedIndexChanged: 在属性窗口中,单击Items属性右侧标题为"…"的按钮,打开"字符串集合编辑器"对话框,在其中输入四项:粗体、斜体、下划线、删除线,注意每一项要换行。
24
3.11 列表选择控件(ListBox)(续)
25
3.11 列表选择控件(ListBox)(续)
26
3.11 列表选择控件(ListBox)(续) void listBox1_SelectedIndexChanged(object sender, EventArgs e) { int Style=0,k=1;//Style=0正常字体,1=黑体,2=斜体,3=黑斜体等,参见3.9节 for(int i=0;i<listBox1.Items.Count;i++)//此例Count=4 { if(listBox1.GetSelected(i))//例如此例GetSelected(0)=true表示粗体选中 Style=Style|k; //增加指定风格 else Style=Style&(~k); //取消指定风格 k=k*2; } FontStyle m=new FontStyle(); m=(FontStyle)Style; label1.Font=new Font(label1.Font.Name,label1.Font.Size,m);
27
3.12下拉列表组合框(ComboBox)控件 常用属性、事件和方法如下: 属性DropDownStyle: 属性Items:
属性MaxDropDownItems: 属性Sorted: 属性SelectedItem: 属性SelectedIndex: 事件SelectedIndexChanged:
28
3.12下拉列表组合框(ComboBox)控件
29
3.12下拉列表组合框(ComboBox)控件 private void Form1_Load(object sender,EventArgs e) {//Families是类FontFamily的一个静态属性,得到操作系统中所使用的所有字体名 FontFamily[] families=FontFamily.Families; foreach (FontFamily family in families) comboBox1.Items.Add(family.Name);//注意Add方法的使用 } private void comboBox1_SelectedIndexChanged( object sender, EventArgs e) { label1.Font=new Font(comboBox1.Text,label1.Font.Size);
30
3.13 ToolTip控件
31
3.13 ToolTip控件 (续) 放ToolTip控件到窗体,属性Name=toolTip1,修改textBox1属性toolTip1的ToolTip=“这是编辑框”,这是当鼠标在textBox1上停留一段时间后,出现的提示。在Form1的构造函数中,增加语句如下: toolTip1.SetToolTip(button1,“这是按钮”); //参数1是要显示提示的控件,参数2是提示
32
3.14 超级链接(LinkLable)控件 常用的属性、方法和事件如下: 属性LinkArea: 属性LinkColor:
属性VisitedLinkColor: 属性LinkVisited: 属性LinkArea: 事件LinkClicked:
33
3.14 超级链接(LinkLable)控件 (续)
修改LinkLabel控件属性LinkArea.Length=2,LinkArea.Start=2。也可在构造函数用语句修改:linkLabel1.LinkArea=new LinkArea(2,2); private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { linkLabel1.LinkVisited=true; System.Diagnostics.Process.Start( " } System.Diagnostics.Process.Start("C:/"); System.Diagnostics.Process.Start("notepad");
34
3.15 定时(Timer)组件 属性Interval: 方法Start()和Stop(): 属性Enabled: 事件Tick:
定时组件常用的属性、方法和事件如下: 属性Interval: 属性Enabled: 方法Start()和Stop(): 事件Tick:
35
3.15 定时(Timer)组件 (续) void Form1_Load(object sender, EventArgs e)
{ this.timer1.Interval=100; this.timer1.Enabled=true; label1.Text=DateTime.Now.ToString(); } void timer1_Tick(object sender, EventArgs e) { label1.Text=DateTime.Now.ToString();
36
3.16 DateTime类 String s=DateTime.Now.ToString(); //DateTime.Today.ToString() int y=DateTime.Now.Year; //得到年 int m=DateTime.Now.Month; //得到月 int d=DateTime.Now.Day; //得到日期 String s=DateTime.Now.DayOfWeek.ToString(); //英文表示的星期 int h=DateTime.Now.Hour; //得到小时 int m=DateTime.Now.Minute; //得到分 int s=DateTime.Now.Second; //得到秒 //定义一个DateTime类对象,表示1999年1月13日3时57分32.11秒 System.DateTime moment=new System.DateTime(1999,1,13,3,57,32,11); System.DateTime dTime=new System.DateTime(1980,8,5);//1980年8月5日 //定义时间间隔:17天4小时2分1秒 System.TimeSpan tSpan=new System.TimeSpan(17,4,2,1); System.DateTime result=dTime+tSpan; //结果是:1980年8月22日4:2:1 AM.
37
3.17 菜单 菜单术语:顶级菜单项 、弹出菜单 、菜单项 、子菜单 快捷键 、加速键
可以建立多个MenuStrip类对象,指定主窗口的菜单是menuStrip1: this. MainMenuStrip = this.menuStrip1; 菜单项常用的属性和事件如下: 属性Checked: 属性ShortCutKeys: 属性ShowShortCutKeys: 属性Text:菜单项标题。如为字符-,为分隔线。打开文件(&0)增加快捷键。 事件Click:单击菜单项事件。 设计界面:
38
3.17 菜单 (续)
39
3.17 菜单 (续) 运行效果:
40
3.17 菜单 (续) private void 红色ToolStripMenuItem_Click(object sender,EventArgs e) { label1.ForeColor=Color.Red; } private void 黑色ToolStripMenuItem_Click(object sender,EventArgs e) { label1.ForeColor=Color.Black; } private void 退出ToolStripMenuItem_Click(object sender,EventArgs e) { Close(); }
41
3.18 工具条 在工具条中可以放置Button、Label、TextBox、ComboBox、ProGressBar等控件 ,控件ToolStrip常用的属性如下: 属性Items:单击属性窗口中该属性后边标题为“…”的按钮,打开“项集合编辑器”对话框 属性Dock: 工具条中的按钮都是独立的控件,选中工具条中的按钮,属性窗体将显示该控件的属性和事件。可为按钮增加事件处理函数。
42
3.18 工具条 (续)
43
3.19 状态栏控件 在状态栏中可以放置SplitButton、StatusLabel、DropDownButton、ProGressBar等控件。单击属性窗口中状态栏控件属性Items后边标题为“…”的按钮,打开“项集合编辑器”对话框 ,从图中ComboBox控件的下拉列表中可以选择放到状态栏中的控件,单击"添加"按钮,可以为状态栏添加控件。选中左侧列表框中显示的已添加到状态栏中的控件,可以在右侧属性列表中修改其属性。为使状态栏长度保持一定,可修改属性AutoSize=false,修改属性Size为指定值。StatusLabel用来在状态栏显示字符,只要修改其Text属性即可修改显示的字符。
44
3.19 状态栏控件 (续)
45
3.19 状态栏控件 (续)
46
3.19 状态栏控件 (续) 放Timer组件到窗体,Name=timer1,属性Interval=1000,Enabled=true。
private void timer1_Tick( object sender,EventArgs e) { toolStripStatusLabel1.Text = DateTime.Now.ToString(); }//第一栏显示时间 private void Form1_MouseMove( object sender, MouseEventArgs e) {toolStripStatusLabel2.Text="X:"+e.X.ToString()+ ",Y:"+e.Y.ToString(); }
47
3.20鼠标事件和Panel控件 从类System.Windows.Forms.Control派生的控件都有鼠标事件,控件的Click事件本质上也是鼠标事件。一些窗体控件还有单独的鼠标事件,鼠标事件处理函数一般有两个参数,第一个参数(object sender)引用产生该事件的对象,例如为Form1的鼠标事件增加事件处理函数,它的第一个参数sender引用Form1对象。(System.Windows.Forms.MouseEventArgs e)是事件处理函数第二个参数,代表事件的一些信息,事件不同,所代表的信息也不相同,鼠标按下事件处理函数中,e.X和e.Y为发生事件时鼠标位置的x和y坐标,e.Button为MouseButtons.Left,表示单击了鼠标左键,为Right和Middle则分别表示单击了右键和中间键。e.Clicks为鼠标单击的次数,如果为1次,为单击,大于1次,则为双击。窗体控件包括以下鼠标事件:
48
3.20鼠标事件和Panel控件(续) MouseDown: MouseUp: MouseMove: MouseEnter:
MouseLeave:
49
3.20鼠标事件和Panel控件 (续) Panel是一个可以包含其他控件的控件,例如包含一组RadioButton控件。如果Panel控件的Enabled属性设置为false,则也会禁用包含在Panel中的所有控件。默认情况下,Panel控件在显示时没有任何边框。可以用BorderStyle属性提供标准或三维的边框,将窗体分为不同区域。因为Panel控件派生于ScrollableControl类,所以可以用AutoScroll属性来启用Panel控件中的滚动条。当AutoScroll属性设置为true时,使用所提供的滚动条可以滚动显示在Panel中,但不在其可视区域内的所有控件。
50
3.21 快捷菜单 快捷菜单和菜单的属性、事件和方法基本一致,只是快捷菜单没有顶级菜单项,因此这里就不多介绍了。
51
3.22 综合例子:计算器
52
3.22 综合例子:计算器 (续) Button1-Button9单击事件处理函数如下:
private void button0_Click(object sender,EventArgs e) { Button b1=(Button)sender; if(textBox1.Text!="0")//如果前边已输入非零数字例如12 textBox1.Text+= b1.Text;//此次如键入0应为:120 else//如果已输入的数字为零,显示的数字应为:0,而不应为:00 textBox1.Text= b1.Text; }
53
3.22 综合例子:计算器 (续) 标题为“.”按钮事件处理函数如下: private void btn_dot_Click(
object sender, EventArgs e) { int n=textBox1.Text.IndexOf("."); if(n==-1)//如果没有小数点,增加小数点,否则不增加 textBox1.Text=textBox1.Text+"."; } 编译,运行,单击标题为“0”到"9"以及"."的按钮,在控件textBox1中可以看到输入的数字,也可以输入小数。
54
3.22 综合例子:计算器 (续) 实现加法。增加一个变量double sum = 0,记录部分和。输入了第一个加数,然后输入任一运算符(+、-、*、\或=),在输入第二个加数前,应先清除编辑框中显示的第一个加数。为实现此功能,为Form1类增加一个布尔变量blnClear,初始值为false,表示输入数字或小数点前不清除编辑框中显示,输入运算符(+、-、*、\或=)后,blnClear=true,表示如果再输入数字或小数点,先清除编辑框中的显示的前一个加数。修改前边程序,输入数字或小数点前,要判断变量blnClear,如为true,清除编辑框中显示的内容后,再显示新输入的数字或小数点,同时修改blnClear=false。为此修改Button0单击事件处理函数如下:
55
3.22 综合例子:计算器 (续) private void button0_Click(object sender,EventArgs e) { if(blnClear)//如为真,输入下一个加数前,应先清除textBox1显示内容 { textBox1.Text="0"; //新增语句 blnClear=false; } Button b1=(Button)sender;//以下为原来已有语句 if(textBox1.Text!="0") textBox1.Text+= b1.Text; else textBox1.Text= b1.Text;
56
3.22 综合例子:计算器 (续) 修改btn_dot_Click方法如下:
private void btn_dot_Click(object sender, EventArgs e) { if(blnClear)//如为真,输入下一个加数前应先清除textBox1 { textBox1.Text="0"; //新增语句 blnClear=false; } int n=textBox1.Text.IndexOf("."); if(n==-1)//如果没有小数点,增加小数点,防止多次输入小数点 textBox1.Text=textBox1.Text+".";
57
3.22 综合例子:计算器 (续) 如果要计算1+2-3,先单击标题为"1"的按钮(简称按钮1),编辑框中显示1,再单击按钮+,执行运算sum=sum+1(注意此时sum=0),显示sum到编辑框中(实际显示不变),记住此次输入的运算符,这里为+号。单击按钮2,编辑框中显示2,再单击按钮-,按记录的运算符(这里是+)计算sum=sum+2,显示sum到编辑框中,记住此次输入的运算符,这里为-号,依此类推。为实现此功能,必须定义一个字符串变量strOper,记录输入的运算符,初始值为"+",保证输入第一个运算符后,执行运算sum=sum+第一个加数,由于初始sum=0,也就是sum=第一个加数。标题为"+"的按钮的单击事件处理函数如下:
58
3.22 综合例子:计算器 (续) private void btn_add_Click(object sender, EventArgs e) { double dbSecond=Convert.ToDouble(textBox1.Text); if(!blnClear)//如果未输入第二个操作数,不运算, //例如连续键入+、-、*、\或= switch(strOper) //按上次记录的运算符号运算 { case "+": sum+=dbSecond; break; //在此语句后边增加其他运算符-、*、\的处理代码 } if(sender==btn_add) //记录此次键入的运算符 strOper="+";//在此语句后边可增加运算符-、*、\、=的处理代码 textBox1.Text=Convert.ToString(sum);//显示部分和 blnClear=true;//设置标记使键入另1个加数前,要先清除显示的前个加数
59
3.22 综合例子:计算器 (续) 等号(=)处理语句和+号处理基本一致,修改标题为“+”按钮的事件函数如下:
private void btn_add_Click(object sender, EventArgs e) { double dbSecond=Convert.ToDouble(textBox1.Text); if(!blnClear)//如果未输入第二个操作数,不运算 switch(strOper) //按记录的运算符号运算 { case "+": sum+=dbSecond; break; //在此语句后边增加其他运算符-、*、\的处理代码 } if(sender==btn_add) strOper="+"; if(sender==btn_equ) //为=号处理增加的语句 strOper="="; textBox1.Text=Convert.ToString(sum); blnClear=true; }
60
3.22 综合例子:计算器 (续) 为标题为“C”按钮增加事件处理函数如下:
private void btn_C_Click(object sender, EventArgs e) { textBox1.Text="0"; sum=0; blnClear=false; strOper="+"; }
61
3.23 类库、组件和控件 类库 在软件开发行业,软件开发者为了简化和加快程序设计,都希望利用他人已经实现的代码。这些可复用代码可以用类库的形式提供给软件开发者。类库是一个扩展名为dll的文件,也称动态连接库,在文件中定义了一些类,使用类库的软件开发者可以从这些类创建类的对象,使用类的方法,或者生成这些类的派生类。使用VS2005可以很容易的创建和使用类库。 见例子【例3.18】 和【例3.19】
62
3.23 类库、组件和控件 (续) 组件 在 .NET Framework 中,组件是实现 System.ComponentModel.IComponent 接口的一个类,或者是实现该接口类的直接或间接派生类。System.ComponentModel.Component类实现了IComponent接口,是所有组件类的基类。组件也以类库的形式提供给使用者,因此使用VS2005设计组件的方法和例3.18相同,只是组件类应是System.ComponentModel.Component类的派生类。可以在组件类中定义属性、事件和方法,由于Component类的支持,在VS2005的工具箱中可以看到组件,在属性和事件窗口可以看到自定义组件的属性和事件。VS2005工具箱中的Timer定时器就是一个组件。组件和控件增加属性和事件的方法完全一致,这里就不介绍创建组件的具体步骤了,MSDN中也有相应的例子。
63
3.23 类库、组件和控件 (续) 控件 控件也是类,和组件不同,控件实现了用户界面,创建Windows 控件有三种常见方案: 复合控件:
扩展控件: 自定义控件: 【例3.21】仿真软件中有许多元器件,例如逻辑电路仿真软件中包括与门、或门、反向器等元件。用自定义控件来描述这些元器件是很方便的。本例通过实现反向器的简单逻辑仿真,说明了用自定义控件设计仿真软件的一些基本技术。
64
3.23 类库、组件和控件 (续) GateBase类是所有门电路的基类,完整定义如下: using System;
using System.Collections.Generic; using System.Text; using System.Windows.Forms;//Control类所在命名空间 using System.Drawing;//输出图形必须引入的命名空间, //参见第5章 namespace GateLibrary { public delegate void ChangedEvent(object sender,EventArgs e);//代表类声明见1.18节 //自定义控件的基类必须为Control
65
3.23 类库、组件和控件 (续) public abstract class GateBase:Control//抽象类,所有门电路的基类
{ //每个门电路都有若干输入引脚,一个输出引脚。用索引指示器记录输入引脚值 protected List<int> PinInput=null;//PinInput[i]表示第i个输入引脚值 public int this[int nIndex] //索引指示器,见1.20节 { get{ return PinInput[nIndex]; } //如果修改值和已有输入值相同不修改 set{ if(PinInput[nIndex] != value) { PinInput[nIndex] = value; OnInputChanged(EventArgs.Empty); } }//每当门输入引脚值改变,调用OnInputChanged事件方法
66
3.23 类库、组件和控件 (续) int PinOutput = 0; //门的输出引脚值
public int GateOutput //用定义属性GateOutput得到及修改输出引脚值 { get{ return PinOutput; } set{ PinOutput = value; } }//每个输出引脚可能连接其它门电路输入引脚,LinkGate和LinkGateNum记录这些连接 public List<GateBase> LinkGate=null;//输出引脚连接的其它门 public List<int> LinkGateNum=null;//连接的其它门的输入引脚编号 public event ChangedEvent InputChanged; //声明一个事件 public virtual void OnInputChanged(EventArgs e) { int m=GateLogic();//根据输入进行逻辑计算,返回计算的输出引脚值 if(PinOutput==m) //如果输出值没有改变,退出 return;
67
3.23 类库、组件和控件 (续) PinOutput=m; //修改输出值
base.Invalidate();//门输出=0为红色,否则为黑色,重画门电路外观图,见5.9.6节 GateBase gate;//修改本输出连接的其它门的输入值为PinOutput int k;//其它门的输入发生变化,也将产生输入变化事件 for (int i=0; i < LinkGate.Count; i++) { gate = (GateBase)LinkGate[i]; k = (int)LinkGateNum[i]; gate[k] = PinOutput; } if (InputChanged != null)//如果Changed代表了事件处理函数 InputChanged(this, e);//执行Changed代表的函数 }//每当门的输入发生变化,调用这个方法
68
3.23 类库、组件和控件 (续) public GateBase() //构造函数
{ PinInput=new List<int>(); LinkGate = new List<GateBase>(); LinkGateNum = new List<int>(); }//抽象方法GateLogic()定义,返回计算逻辑值 public abstract int GateLogic(); }//GateLogic()是实现门逻辑关系的抽象方法,无实现代码,不同门的逻辑关系不同 }
69
3.23 类库、组件和控件 (续) 从GateBase派生一个反向器类,NotGate,定义如下:
public class NotGate : GateBase { public NotGate():base() //构造函数 { PinInput.Add(1);//增加一个引脚,门电路的输入初始值=1 GateOutput = 0; //输出初始值=0 base.Width=41; //自定义控件宽 base.Height=31; //自定义控件高 } protected override void OnPaint(PaintEventArgs e) //覆盖Control类的OnPaint方法 { Graphics g = e.Graphics; //以下画出控件的外观 Pen pen1 = new Pen(Color.Black);//定义黑色的笔
70
3.23 类库、组件和控件 (续) if (GateOutput == 1) //反向器输出为1,其外观图形的颜色为红色,否则为黑色
pen1.Color = Color.Red; g.DrawEllipse(pen1, 30, 10, 10, 10); /画园,见5.6.3节 Point[] point ={ new Point(0, 15), new Point(15, 15), new Point(15, 0), new Point(30, 15), new Point(15, 30), new Point(15, 15) }; g.DrawLines(pen1, point); //画多条线段,见5.6.1节 //本方法显示自定义控件的外观(图3.18),Paint事件参见5.2.2节 public override int GateLogic()//抽象方法GateLogic()实现,返回计算逻辑值 { if (base[0] == 0) //反向器的逻辑关系,输出等于输入的反相 return 1; else return 0; }
71
3.23 类库、组件和控件 (续)
72
3.23 类库、组件和控件 (续) public Form1() { InitializeComponent();
//记录notGate1的输出连到 notGate2的输入引脚0 notGate1.LinkGate.Add(notGate2); notGate1.LinkGateNum.Add(0); notGate2[0] = 0; notGate2.GateOutput = 1; } private void timer1_Tick(object sender, EventArgs e) { if (notGate1[0] == 0) notGate1[0] = 1; else notGate1[0] = 0; }
Similar presentations