




已阅读5页,还剩9页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
我的学习计划本节介绍一下Windows窗体设计中的一些概念和原则。控件的名称 当开发人员在窗体中新增一个控件时,系统会给这个控件设置默认名称,比如对于Label控件,其默认名称可能为lable1、label2等,对于TextBox控件其默认名称可能为textBox1、textBox2等等。 如下图所示,笔者设计了一个“用户信息”窗体,在默认情况下,各个控件的名称如下图所示。这是一种非常糟糕的窗体设计结果。在编写该窗体的C#代码时,由于无法同时看到窗体设计界面,因此很难记下各种控件的名称及其功能。当窗体控件比较多时,此时的程序代码的编写和维护时相当困难的。袁永福版权所有 因此开发人员应当养成在窗体上新建控件就立即修改控件名称的习惯。这样能有效的改进软件的用户界面的设计质量,也是窗体后台代码高质量的基础。对于Label控件,由于基本上不参与编程,只是在用户界面上显示一段不可改变的静态文本,因此可以不设置Label控件的名称,但当在少数情况下,当窗体后台代码需要操作Label控件的文本等属性值时,为了提高代码的质量也应当修改Label控件的名称。比如对于下面这个窗体,各个数据输入控件的名称设置如下。跟代码变量命名规则类型,窗体控件也有命名规则,业界主流的控件命名规则可能有多种,各种规则之间差别不大,笔者采用的命名规则大致如下袁永福版权所有 控件名称一般为表示控件类型的前缀加上表示控件作用的字符组成。常用控件类型和前缀对应关系如下表所示控件类型 前缀 Button 按钮 btn CheckBox 复选框 chk ColumnHeader 视图列表头 col ComboBox 组合框 cbo ContextMenu 快捷菜单 ctm DataGrid 数据网格控件 dg DataGridView 数据网格视图控件 dgv DateTimePicker 时间输入框 dtp DomainUpDown 数值框 dud Form 窗体 frm GroupBox 组合框 grp HscrollBar 水平滚动条 hsb ImageList 图标列表 img Label 文本标签 lbl LinkLabel 带链接的文本标签 lbl ListBox 列表框 lst ListView 视图列表 lvw Menu 菜单 menu MenuItem 菜单项 menu NumericUpDown 数值框 nud Panel 面板 pnl PictureBox 图片框 pic ProgressBar 进度条 prg RadioButton 单选框按钮 rdo Spliter 拆分条 spl StatusBar 状态栏 stu StatusBarPanel 状态栏区域 pnl StatusStrip 状态栏 stu TabControl 分页控件 tab TabPage 分页标签页面 page TextBox 文本框 txt Timer 定时器 tmr ToolBar 工具条 tbr ToolStrip 工具栏 tsp ToolStripButton 工具栏按钮 btn ToolStripComboBox 工具栏下拉组合框 cbo ToolStripDropDownButton 工具栏下拉列表 btn ToolStripDropDownMenu 工具栏菜单项目 menu ToolStripLabel 工具栏静态文本 lbl ToolStripProgressBar 工具栏进度条 prg ToolStripTextBox 工具栏文本框 txt TreeView 树状视图列表 tvw VScrollBar 垂直滚动条 vsb WebBrowser 浏览器控件 wb 对于其他非常用的控件类型的前缀读者可以自己琢磨或者请教他人,控件名称前缀只是一个比较小的细节问题,即使有误也无伤大雅。袁永福版权所有 笔者一般使用英文或者缩写来表示控件的作用,若没有合适的英文则采用汉语全拼音或者干脆用中文汉字,但绝不会用中文汉语拼音首字母,因为汉语拼音首字母很难仅仅从字母上猜出其表示的汉字,而猜测英文缩写相对容易得多。 如下图所示,可能有些人使用汉语拼音首字母来设置控件的名称,比如“姓名”文本框取名“txtXM”,这是一种不好的控件命名方式,因为很多时候是实在是难于从拼音首字母中猜测控件的作用,控件名称的低可读性降低了程序代码的可读性。因此按照比较合理的命名方式,“姓名”文本框的名称就采用TextBox控件的前缀“txt”和表示姓名的英文“Name”组合而成为“txtName”。 一般来说商业软件不是“一次开发,长期使用”,而是“一次开发,长期修改,长期使用”,因此开发商业软件需要考虑到未来的修改和升级换代,此时程序代码不但要耐用,还需要耐看耐改,程序代码需要具备良好的可读性,而给控件设置合适的名称就是一个基础工作。其实除了控件的名称,其他的诸如数据库表名字段名,窗体名称,程序模块名称等等都需要遵守一定的命名规范。袁永福版权所有TabIndex属性 首先的设置好控件的TabIndex属性值。在程序运行显示窗体时,用户可以按下Tab键来切换输入焦点,而切换顺序就依照各个控件的TabIndex属性。一般的输入焦点切换顺序按照从左到右,从上到下。因此需要设置左上方位的控件的TabIndex属性值为小,右下方为的控件的TabIndex属性值为大。但实际开发中还是按照具体功能需求来安排输入焦点切换顺序。 在设置各个控件的TabIndex属性值时不应设置为连续的值,比如设置第一个控件的TabIndex属性值为1,第二个控件为2,第三个控件为3,等等等。采用这种设置时,当未来在输入焦点顺序中插入新的控件,则会需要修改大量的控件的TabIndex属性值。为此笔者建议输入的各个控件的TabIndex属性值不联系,比如有10的间隔,此时可以设置第一个控件的TabIndex属性值为10,第二个控件为20,第三个控件为30,等等等。这样就为未来插入新的控件留下TabIndex顺序的空间。如下图所示在这个“用户信息”窗体设计的例袁永福版权所有子中,当该窗体运行显示后,用户可以按下Tab键从左到右从上到下的切换焦点。 有些控件并不能接受输入焦点,比如Label控件,但仍然需要为这类控件设置合适的TabIndex属性值。因为Label控件虽然不能接受输入焦点,但仍然能接受快捷键,比如在“用户信息”的窗体设计中,笔者设置第一个Label控件的文本为“姓名 (&N):”,则程序运行后显示该窗体时,用户按下“Alt+N”组合键时,Label控件就感应到快捷键并试图设置输入焦点到自己,由于Label控件不能接受输入焦点,因此系统就会将输入焦点自动切换到Label控件的下一个焦点顺序的控件上。也就是TabIndex值为20的文本框上。这样用户就使用快捷键“Alt+U”就能快速切换焦点到“姓名”文本框了。 当用户界面上数据输入域很多时,这种快速切换输入焦点的功能是很人性化的,方便用户使用纯键盘操作来高速输入和修改数据,显得用户界面做的很专业。若没有这种功能,则用户需要频繁的切换鼠标和键盘来输入数据,大大拖累的操作速度。 商业程序的用户界面要求比较高,因为使用者可能好几年天天面对相同的用户界面,累计下来会重复进行几万次操作,此时用户界面需要耐看耐用,这需要在很多细节上做好功夫,其中设置各袁永福版权所有个控件的TabIndex属性值就是一个基础工作,必须花点心思做好。Z-Index 在WinForm窗体设计中有一个Z-Index的概念。窗体布局是采用绝对坐标方式的,每一个控件都有Left和Right属性用于确定控件的左上角在窗体中的X-Y坐标。 当窗体有多个控件时,控件之间可能存在相互重叠的现象,这类似图像处理中层的概念。也就是说一个控件单独的占有一个控件布局层,多个控件就会有多个布局层的叠加,而越靠近窗体的控件就越容易被覆盖,于是从窗体开始计算,每个控件布局层都有一个从0开始计算的序号,这个序号就是Z-Index。 从另外一种方式理解,窗体上的控件布局是不仅仅是X-Y坐标系那种二维的,而是三维的,第三维就是Z坐标轴,它是从窗体向用户延伸的,控件是分布在窗体和用户之间。此时可以说用户是俯看用户界面,若不注意是不会感觉到第三维的存在。而且控件在第三维中的坐标值就是Z-Index,这个值是从0开始的,不会重复;Z-Index值大的控件可以覆盖掉值小的控件。 我们还可以从第三种方式看Z-Index值,窗体对象有一个Controls的属性,该属性值可以看做一个控件数组,窗体上所有的控件都在这个数组中。系统创建窗体时,是从这个数组逆向遍历获得控件对象,然后依次放置在窗体上,很显然在数组中靠前的控件可以覆盖掉靠后的控件,于是控件在这个数组中的逆向序号也可以看做Z-Index值。 实际上其他软件开发技术中也有Z-Index属性,比如VB,还有Web开发中才CSS样式也支持Z-Index属性值。 Z-Index与其他控件相关,因此控件本身不会有Z-Index属性,而且根据控件在窗体中的布局动态的计算出来的。 在VS.NET的窗体设计器中,不能直接设置控件的Z-Index值,但可以使用布局工具条上的“置于顶层”和“置于低层”按钮来将控件沿着Z坐标轴置于最大值或最小值,也就是沿着Z坐标轴移动控件,使其最靠近用户或者最靠近窗体。看了书上和百度的 还是看不懂 请通俗的讲一下 枚举是什么意思 干什么用的 不要像一个星期的举例 谢谢2009-3-25 23:39 最佳答案 是一种复合值类型,使用关键字enum来定义,主要表示一组逻辑上相关联的项的集合。就像你所说的一个星期,星期一到星期天是一组相关联的项。枚举,把这些都举例出来一样。赞同2| 评论 向TA求助 回答者: angelawill6108 | 四级 擅长领域: 江西 软件 文学 华语流行乐 VC+ 参加的活动: 暂时没有参加的活动 其他回答 共4条 2009-3-25 23:47 zwu | 六级 在.net里一切皆对象,enum在.net和C里虽然关键字一样,但不是同一个东西了,这里叫枚举,C里叫联合,你可以把枚举理解成一种简化的类,里边的成员都是静态的,常量,值一定是整数的一种东西,只是为了语法上的方便而已,就是把一组常量列举出来方便使用 赞同0| 评论 2009-3-25 23:57 zhang5760338 | 五级 使用关键字enum来定义,枚举没有方法和属性但可以赋值,一般是定义在类外面,主要好处是可以避免不合理的赋值。public enum Genders /定义一个枚举Male,Femaleprivate Genders gender;public Genders gender get return gender; set gender=value;/使用枚举赋值student.Gender=Genders.Male;/也可以这样写student.Gender=ssss;/但是赋值是不能通过的编译的。因为只有枚举Genders只有两个属性Male,Female,没有别的。VS组件-Timer组件的使用2008-05-14 14:54Timer 组件Timer 组件是基于服务器的计时器,它使您能够指定在应用程序中引发 Elapsed 事件的周期性间隔。然后可以操控此事件以提供定期处理。例如,假设您有一台关键性服务器,必须每周 7 天、每天 24 小时都保持运行。可以创建一个使用 Timer 的服务,以定期检查服务器并确保系统开启并在运行。如果系统不响应,则该服务可以尝试重新启动服务器或通知管理员。基于服务器的 Timer 是为在多线程环境中用于辅助线程而设计的。服务器计时器可以在线程间移动来处理引发的 Elapsed 事件,这样就可以比 Windows 计时器更精确地按时引发事件。有关基于服务器的计时器的更多信息,请参见“基于服务器的计时器介绍”。基于 Interval 属性的值,Timer 组件引发 Elapsed 事件。可以处理该事件以执行所需的处理。例如,假设您有一个联机销售应用程序,它不断向数据库发送销售订单。编译发货指令的服务分批处理订单,而不是分别处理每个订单。可以使用 Timer 每 30 分钟启动一次批处理。当 AutoReset 设置为 false 时,Timer 只在第一个 Interval 过后引发一次 Elapsed 事件。若要保持以 Interval 时间间隔引发 Elapsed 事件,请将 AutoReset 设置为 true。Elapsed 事件在 ThreadPool 线程上引发。如果 Elapsed 事件的处理时间比 Interval 长,在另一个 ThreadPool 线程上将会再次引发此事件。因此,事件处理程序应当是可重入的。下面的示例创建一个 Timer,它每隔五秒钟在控制台上显示一次“Hello World!”。using System;using System.Timers;public class Timer1public static void Main() / Normally, the timer is declared at the class level, so/ that it doesnt go out of scope when the method ends./ In this example, the timer is needed only while Main / is executing. However, KeepAlive must be used at the/ end of Main, to prevent the JIT compiler from allowing / aggressive garbage collection to occur before Main / ends. System.Timers.Timer aTimer = new System.Timers.Timer();/ Hook up the Elapsed event for the timer. aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);/ Set the Interval to 2 seconds (2000 milliseconds). aTimer.Interval = 2000; aTimer.Enabled = true; Console.WriteLine(Press the Enter key to exit the program.); Console.ReadLine();/ Keep the timer alive until the end of Main. GC.KeepAlive(aTimer); / Specify what you want to happen when the Elapsed event is / raised.private static void OnTimedEvent(object source, ElapsedEventArgs e) Console.WriteLine(Hello World!); /在应用里的timer和组件里的timer有什么不同? 服务器计时器、Windows计时器和线程计时器 在 Visual Studio.NET 和 .NET Framework 中有三种计时器控件: 基于服务器的计时器,位于“工具箱”的“组件”选项卡上; 基于Windows的标准计时器,位于“工具箱”的“Windows 窗体”选项卡上,以及仅可在编程时使用的线程计时器。 基于 Windows 的计时器从 Visual Basic 的1.0 版起就存在于该产品中并且基本上保持不变。该计时器已经为在 Windows 窗体应用程序中使用而进行了优化。基于服务器的计时器是传统的计时器为了在服务器环境上运行而优化后的更新版本。线程计时器是一种简单的、轻量级计时器,使用回调方法而不是事件,并由线程池线程提供。 在 Win32 体系结构中有两种类型的线程:UI 线程和辅助线程。UI 线程绝大多数时间处于空闲状态,等待消息循环中的消息到来。一旦接收到消息,它们就进行处理并等待下一个消息到来。另外,辅助线程用来执行后台处理而且不使用消息循环。Windows 计时器和基于服务器的计时器在运行时都使用 Interval 属性。线程计时器的时间间隔在 Timer 构造函数中设置。计时器的设计目的各不相同,它们的线程处理明确地指出了这一点: Windows 计时器是为单线程环境设计的,其中UI 线程用于执行处理。Windows 计时器的精度限定为 55 毫秒。这些传统计时器要求用户代码有一个可用的 UI 消息泵,而且总是在同一个线程中操作,或者将调用封送到另一个线程。对于COM 组件来说,这样会降低性能。 基于服务器的计时器是为在多线程环境下与辅助线程一起使用而设计的。由于它们使用不同的体系结构,因此基于服务器的计时器可能比 Windows 计时器精确得多。服务器计时器可以在线程之间移动来处理引发的事件。 对消息不在线程上发送的方案中,线程计时器是非常有用的。例如,基于 Windows 的计时器依赖于操作系统计时器的支持,如果不在线程上发送消息,与计时器相关的事件将不会发生。在这种情况下,线程计时器就非常有用。 Windows 计时器位于System.Windows.Forms 命名空间中,服务器计时器位于System.Timers 命名空间中,而线程计时器位于 System.Threading 命名空间中。/C中Timer组件用法关于C#中timer类 在C#里关于定时器类就有3个1.定义在System.Windows.Forms里 2.定义在System.Threading.Timer类里 3.定义在System.Timers.Timer类里System.Windows.Forms.Timer是应用于WinForm中的,它是通过Windows消息机制实现的,类似于VB或 Delphi中的Timer控件,内部使用API SetTimer实现的。它的主要缺点是计时不精确,而且必须有消息循环,Console Application(控制台应用程序)无法使用。 System.Timers.Timer 和System.Threading.Timer非常类似,它们是通过.NET Thread Pool实现的,轻量,计时精确,对应用程序、消息没有特别的要求。System.Timers.Timer还可以应用于WinForm,完全取代上面的 Timer控件。它们的缺点是不支持直接的拖放,需要手工编码。例: 使用System.Timers.Timer类 System.Timers.Timer t = new System.Timers.Timer(10000);/实例化Timer类,设置间隔时间为10000毫秒; t.Elapsed += new System.Timers.ElapsedEventHandler(theout);/到达时间的时候执行事件; t.AutoReset = true;/设置是执行一次(false)还是一直执行(true); t.Enabled = true;/是否执行System.Timers.Timer.Elapsed事件;public void theout(object source, System.Timers.ElapsedEventArgs e) MessageBox.Show(OK!); private void button1_Click(object sender, System.EventArgs e) System.Timers.Timer t = new System.Timers.Timer(1 * 60 * 60 * 1000); t.Elapsed += new System.Timers.ElapsedEventHandler(Timer_TimesUp); t.Enabled = true;private void Timer_TimesUp(object sender, System.Timers.ElapsedEventArgs e)MessageBox.Show(hello);/如果非要button 触发的话:private void Form1_Load(object sender, System.EventArgs e) System.Timers.Timer t = new System.Timers.Timer(1 * 60 * 60 * 1000); t.Elapsed += new System.Timers.ElapsedEventHandler(Timer_TimesUp); t.Enabled = true;private void button1_Click(object sender, System.EventArgs e) MessageBox.Show(hello);private void Timer_TimesUp(object sender, System.Timers.ElapsedEventArgs e) this.button1.PerformClick();/C#通过事件委托使用Timerprivate System.Timers.Timer timerClock = new System.Timers.Timer(); timerClock.Elapsed += new ElapsedEventHandler(OnTimer); timerClock.Interval = 1000; timerClock.Enabled = true; public void OnTimer( Object source, ElapsedEventArgs e ) /Your code here /c#windows服务中timer的使用方法Timer组件是也是一个WinForm组件了,和其他的WinForm组件的最大区别是:Timer组件是不可见的,而其他大部分的组件都是都是可见的,可以设计的。Timer组件也被封装在名称空间System.Windows.Forms中,其主要作用是当Timer组件启动后,每隔一个固定时间段,触发相同的事件。Timer组件在程序设计中是一个比较常用的组件,虽然属性、事件都很少,但在有些地方使用它会产生意想不到的效果。一 本文程序设计和运行的软件环境(1).微软公司视窗2000服务器版(2).Net FrameWork SDK Beta 2二 程序设计的思路以及关键步骤的解决方法其实要使得程序的窗体飘动起来,其实思路是比较简单的。首先是当加载窗体的时候,给窗体设定一个显示的初始位置。然后通过在窗体中定义的二个Timer组件,其中一个叫Timer1,其作用是控制窗体从左往右飘动(当然如果你愿意,你也可以改为从上往下飘动,或者其他的飘动方式),另外一个Timer2是控制窗体从右往左飘动(同样你也可以改为其他飘动方式)。当然这二个Timer组件不能同时启动,在本文的程序中,是先设定Timer1组件启动的,当此Timer1启动后,每隔0.01秒,都会在触发的事件中给窗体的左上角的横坐标都加上1,这时我们看到的结果是窗体从左往右不断移动,当移动到一定的位置后,Timer1停止。Timer2启动,每隔0.01秒,在触发定义的事件中给窗体的左上角的横坐标都减去1,这时我们看到的结果是窗体从右往左不断移动。当移动到一定位置后,Timer1启动,Timer2停止,如此反覆,这样窗体也就飘动起来了。要实现上述思路,必须解决好以下问题。(1).如何设定窗体的初始位置:设定窗体的初始位置,是在事件Form1_Load()中进行的。此事件是当窗体加载的时候触发的。Form有一个DesktopLocation属性,这个属性是设定窗体的左上角的二维位置。在程序中是通过Point结构变量来设定此属性的值,具体如下:/设定窗体起初飘动的位置,位置为屏幕的坐标的(0,240)private void Form1_Load ( object sender , System.EventArgs e )Point p = new Point ( 0 , 240 ) ;this.DesktopLocation = p ;(2). 如何实现窗体从左往右飘动:设定Timer1的Interval值为10,就是当Timer1启动后,每隔0.01秒触发的事件是Timer1_Tick(),在这个事件中编写给窗体左上角的横坐标不断加1的代码,就可以了,具体如下:private void timer1_Tick(object sender, System.EventArgs e) /窗体的左上角横坐标随着timer1不断加一 Point p = new Point ( this.DesktopLocation.X + 1 , this.DesktopLocation.Y ) ; this.DesktopLocation = p ; if ( p.X = 550 ) timer1.Enabled = false ; timer2.Enabled = true ; (3). 如何实现窗体从右往左飘动:代码设计和从左往右飘动差不多,主要的区别是减1而不是加1了,具体如下:/当窗体左上角位置的横坐标为-150时,timer2停止,timer1启动private void timer2_Tick(object sender, System.EventArgs e) file:/窗体的左上角横坐标随着timer2不断减一Point p = new Point ( this.DesktopLocation.X - 1 , this.DesktopLocation.Y ) ;this.DesktopLocation = p ;if ( p.X = - 150 ) timer1.Enabled = true ; timer2.Enabled = false ; 三 用Visual C编写窗体飘动程序的源代码通过上面的介绍,不难写出窗体飘动的程序源代码。如下:using System ;using System.Drawing ;using System.Collections ;using System.ComponentModel ;using System.Windows.Forms ;using System.Data ; namespace floatingFormpublic class Form1 : Formprivate Timer timer1 ;private Timer timer2 ;private Label label1 ;private Button button1 ;private System.ComponentModel.IContainer components ;public Form1 ( )file:/初始化窗体中的各个组件InitializeComponent ( ) ;file:/清除在程序中使用过的资源protected override void Dispose ( bool disposing )if ( disposing )if ( components != null ) components.Dispose ( ) ;base.Dispose( disposing ) ;private void InitializeComponent ( )ponents = new System.ComponentModel.Container ( ) ;this.timer1 = new Timer ( ponents ) ;this.timer2 = new Timer ( ponents ) ;this.label1 = new Label ( ) ;this.button1 = new Button ( ) ;this.SuspendLayout ( ) ;this.timer1.Enabled = true ;this.timer1.Interval = 10 ;this.timer1.Tick += new System.EventHandler ( this.timer1_Tick ) ;this.timer2.Enabled = false ;this.timer2.Interval = 10 ;this.timer2.Tick += new System.EventHandler ( this.timer2_Tick ) ;this.button1.Font = new Font ( 宋体 , 10 ) ;this.button1.Location = new Point ( 1 , 8 ) ;this.button1.Name = button1 ;this.button1.Size = new Size ( 80 , 25 ) ;this.button1.TabIndex = 0 ;this.button1.Text = 停止飘动 ;this.button1.Click += new System.EventHandler ( this.button1_Click ) ;this.label1.Font = new Font ( 宋体 , 22F , FontStyle.Bold , GraphicsUnit.Point , ( ( System.Byte ) ( 0 ) ) ) ;this.label1.Location = new Point ( 8 , 38 ) ;this.label1.Name = label1 ;this.label1.Size = new Size ( 344 , 40 ) ;this.label1.TabIndex = 1 ;this.label1.Text = 用
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论