分享(C高级编程第6版)第31章Windows窗体

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

第31章Windows窗体基于Web的应用程序在过去几年非常流行。从管理员的角度来看,把所有的应用程序逻辑放在一个中央服务器上是非常吸引人的。但部署基于客户的软件会非常困难,特别是部署基于COM的客户软件。基于Web的应用程序的缺点是它们不能提供丰富的用户体验。.NETFramework允许开发人员创建丰富、智能的客户应用程序,而且不再有部署问题和以前的DLLHell。无论选择Windows窗体还是WPF(参见第34章),客户应用程序都不再难以开发或部署。Windows窗体已经对Windows开发产生了影响。当应用程序处于初始设计阶段时,是建立基于Web的应用程序还是建立客户应用程序已经很难抉择了。Windows客户应用程序开发起来非常快速和高效,它们可以为用户提供丰富的体验。VisualBasic开发人员对Windows窗体应比较熟悉。创建新窗体(也称为窗口或对话框)也采用把控件从工具箱拖放到窗体设计器上的方式。但是,如果您在创建消息泵和监视消息时使用的是C样式的传统Windows编程,或者您是一位MFC程序员,就会发现现在可以获得需要的低级内部功能了。现在可以重写wndproc,捕获这些消息,但常常并不是真需要它们。本章将主要介绍Windows窗体的如下方面:●Form类●Windows窗体的类层次结构●System.Windows.Forms命名空间中的控件和组件●菜单和工具栏●创建控件●创建用户控件31.1创建Windows窗体应用程序首先需要创建一个Windows窗体应用程序。下面的示例创建了一个空白窗体,并把它显示在屏幕上。这个示例没有使用VisualStudio2008,而是在文本编辑器中输入代码,使用命令行编译器进行编译。下面是代码清单:usingSystem;usingSystem.Windows.Forms;namespaceNotepadForms{publiccalssMyForm:System.Windows.Forms.Form{publicMyForm(){}[STAThread]staticvoidMain(){Application.Run(newMyForm());}}}在编译和运行这个示例时,会得到一个没有标题的小空白窗体。该窗体没有什么实际功能,但它却是一个Windows窗体。代码中有两个地方需要注意。第一个是使用继承功能来创建MyForm类。下面的代码声明MyForm派生于System.Windows.Forms。publiccalssMyForm:System.Windows.Forms.FormForm类是System.Windows.Forms命名空间的一个主要类。代码的其他部分如下:[STAThread]staticvoidMain(){Application.Run(newMyForm());}Main是C#客户应用程序的默认入口。一般在大型应用程序中,Main()方法不位于窗体中,而是位于类中,它负责完成需要的启动处理。在本例中,我们在项目属性对话框中设置启动的类名。注意属性[STAThread],它把COM线程模型设置为单线程单元(Single-ThreadedApartment,STA)。COM交互操作需要STA线程模型,默认为添加到Windows窗体项目中。Application.Run()方法负责启动标准的应用程序消息循环。它有3个重载版本:第一个重载版本不带参数,第二个重载版本把ApplicationContext对象作为其参数,本例中的第三个重载版本把窗体对象作为其参数。在这个示例中,MyForm对象是应用程序的主窗体,这表示在关闭这个窗体时,应用程序就结束了。使用ApplicationContext类,可以对主消息循环何时结束和应用程序何时退出有更多的控制权。Application类包含一些非常有用的功能。它提供了一些静态方法和属性,用于控制应用程序的启动和停止过程,访问由应用程序处理的Windows消息。表31-1列出了其中一些比较有用的方法和属性。表31-1方法/属性说明CommonAppDataPath对应用程序的所有用户都通用的数据路径。一般是BasePath\CompanyName\ProductName\Version,其中BasePath是C:\DocumentsandSettings\username\ApplicationData。如果该路径不存在,就创建一个ExecutablePath这是启动应用程序的可执行文件的路径和文件名(续表)方法/属性说明LocalUserAppDataPath类似于CommonAppDataPath,但这个属性支持漫游MessageLoop如果在当前线程上存在消息循环,就返回True,否则返回falseStartupPath类似于ExecutablePath,但不返回文件名AddMessageFilter用于预处理消息。在基于IMessagerFilter的对象上执行,消息可以从消息循环中过滤出来,或者在消息发送到循环中之前进行特殊的处理DoEvents类似于VisualBasic的DoEvents语句,允许处理队列中的消息EnableVisualStyles允许对应用程序的各种可视化元素使用XP可视化样式。它有两个重载版本,接收清单信息。一个重载版本的参数是清单流,另一个重载版本的参数是清单所在的完整名称和路径Exit和ExitThreadExit结束所有当前运行的消息循环,并退出应用程序。ExitThread只结束消息循环,关闭当前线程上的所有窗口在VisualStudio2008中生成这个示例时,它会是什么样子?首先要注意,创建了两个文件,其原因是VisualStudio2008利用了Framework的部分类特性,把设计器生成的代码放在一个独立的文件中。使用默认名称Form1,这两个文件就是Form1.cs和Form1.Designer.cs。除非选择了Project菜单中的ShowAllFiles选项,否则在SolutionExplorer中看不到Form1.Designer.cs。下面是VisualStudio2008为两个文件生成的代码。第一个文件是Form1.cs:usingSystem;usingSystem.Collections.Generic;usingSystem.ComponentModel;usingSystem.Data;usingSystem.Drawing;usingSystem.Linq;usingSystem.Text;usingSystem.Windows.Forms;namespaceVisualStudioForm{publicpartialclassForm1:Form{publicForm1(){InitializeComponent();}}}这很简单,其中包含一些using语句和一个简单的构造函数。接着是Form1.Designer.cs的代码:namespaceVisualStudioForm{partialclassForm1{///summary///Requireddesignervariable.////summaryprivateSystem.ComponentModel.IContainercomponents=null;///summary///Cleanupanyresourcesbeingused.////summary///paramname=disposingtrueifmanagedresourcesshouldbedisposed;otherwise,false./paramprotectedoverridevoidDispose(booldisposing){if(disposing&&(components!=null)){components.Dispose();}base.Dispose(disposing);}#regionWindowsFormDesignergeneratedcode///summary///RequiredmethodforDesignersupport-donotmodify///thecontentsofthismethodwiththecodeeditor.////summaryprivatevoidInitializeComponent(){this.components=newSystem.ComponentModel.Container();this.AutoScaleMode=System.Windows.Forms.AutoScaleMode.Font;this.Text=Form1;}#endregion}}窗体的设计器文件一般不应直接编辑。唯一的例外是要在Dispose方法中进行特殊的处理。InitializeComponent方法详见本章后面的内容。首先,这个示例应用程序的代码比简单的命令行示例长。在类的开头有好几个using语句,在本例中大多数是不必要的。但保留它们并无大碍。类Form1派生于System.Windows.Forms,与前面的Notepad示例一样,但代码从一开始就不同。Form1.Designer文件的第一行代码如下:privateSystem.ComponentModel.Containercomponents=null;在这个示例中,这行代码并没有做什么工作。当给窗体添加组件时,也就把该组件添加给了组件对象,该组件对象是一个容器。添加到这个容器中的原因与窗体的释放有关。窗体类支持IDisposable接口,因为它是在Component类中执行的。在组件添加到组件容器中时,容器将确保组件被正确地跟踪,并在释放窗体时释放它。如果查看代码中的Dispose方法,就可以看到它:protectedoverridevoidDispose(booldisposing){if(disposing&&(components!=null)){components.Dispose();}base.Dispose(disposing);}在此可以看到,在调用Dispose方法时,也会调用组件对象的Dispose方法,因为组件对象包含其他组件,所以它们也会被释放。Form1类的构造函数在Form1.cs中,如下所示:publicForm1(){InitializeComponent();}注意对InitializeComponent()的调用。InitializeComponent()在Form1.Designer.cs中,顾名思义,InitializeComponent()初始化了添加到窗体上的所有控件,还初始化了窗体的属性。在本示例中,InitializeComponent()如下所示:privatevoidInitializeComponent(){this.components=newSystem.ComponentModel.Container();this.AutoScaleMode=System.Windows.Forms.AutoScaleMode.Font;this.Text=Form1;}这是很基本的初始化代码。该方法与VisualStudio的设计器相关联。使用设计器修改窗体时,这些改动会在InitializeComponent()中反映出来。如果在InitializeComponent()中修改了任意类型的代码,下次在设计器中进行修改时,这些改动就会丢失。每次在设计器中进行修改后,InitializeComponent()都会重新生成。如果需要为窗体或窗体上的控件和组件添加其他初始化代码,就应在调用InitializeComponent()后添加。InitializeComponent()还负责实例化控件,这样在InitializeComponent()之前所有引用控件的调用都会失败,并生成一个空引用异常。要

1 / 47
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功