内容简介本书是打开Windows Forms编程之门的金钥匙,它所采用的编程语言是当前最为流行、最具潜力的C#。本书内容详尽充实,共分为3个部分:初识Windows Forms、Windows Forms基础和高级Windows Forms。通过本书的学习,读者能够迅速掌握通过.NET Framework开发Windows Forms程序的所有相关技术。无论对开发桌面应用程序的Windows程序员,还是正在学习Windows Forms知识的开发人员,或者是毫无Windows开发经验的初学者,相信本书都是最佳的选择。EISBN:1-930110-28-6WINDOWS FORMS PROGRAMMING WITH C#Erik BrownCopyright © 2002 by Manning Publications Co.Original English Language Edition Published by Manning Publications Co.All Rights Reserved.本书中文简体字版由Manning Publications Co.授权清华大学出版社出版。未经出版者书面许可,不得以任何方式复制或抄袭本书的任何部分
前 言 我开始使用Microsoft的.NET Framework是在2001年初,那时我正和一个新成立的小公司合作一个项目。没料到情况发生了变化,我也因此有了比想象中更多的空闲时间。当Manning Publications问我是否有兴趣编写一本关于.Net Framework编程的书时,我欣然接受了他们的 邀请。 对于如何组织本书的内容,我强烈建议把Windows Forms应用程序的编程技巧作为介绍的重点。我一直都非常喜欢Jeff Prosise编写的Programming Windows 95 with MFC,因此在我看来,写一本利用.Net Framework编写基于Windows的应用程序的著作是一个再好不过的选择。 我的建议中还包含着一个重要问题,那就是基于本书的课程内容相应地建立一个应用程序。在介绍各个主题时,这个应用程序也相应地不断变化。这样,当读者看完这本书时,也就得到了一个功能强大的应用程序。Manning Publications也很赞同这个提议,这样,我就开始了编写本书的工作。 在写作过程中,我努力向着两个目标奋斗。第一就是尽可能全面地涵盖命名空间的各个类。我曾经读过很多类似的书—— 如果对于某个主题没有提供强有力的示例,往往使我很失望。所以,我将尽可能提供详尽的示例来说明如何在一个实际问题中正确地使用和巧妙地处理Windows Forms中的各个类。 第二个目标就是给一些高级用户介绍诸如树状视图以及拖放等有关界面功能的主题。在花很多的时间介绍一些基本的类(如菜单和按钮)的同时,对于基于Windows的编程中可能用到的一些更复杂的控件,也给出了比较详细的介绍。 这些设想、目标,再加上许多个不眠之夜,汇成了您眼前的这本书。通过创建一个基于本书的普通应用程序,对于应用程序的开发给出了一些指导,同时指出了进一步的研究工作中一些相关的类和主题。衷心希望我的工作能够提供足够的细节来说明如何在.Net Framework中组织这些基于Windows的应用程序,同时也能为您发展和扩充自己的.Net项目提供尽可能多的 帮助。 虽然本书并不是专门介绍C# 和Visual Studio .Net的,但还是尽可能地对C# 的语法、用法以及Visual Studio .Net的特征和功能做了解释,当示例中用到相关的概念和特征时,就给出对这些主题的解释和说明。在本书最后的附录A中还给出了关于C# 的一个概述。 关于本书 由于.Net Framework所涵盖的内容极其广泛,所以要在一本书里涉及所有的方面是不可能的。这一节给大家介绍一下本书的侧重点,并简单介绍书中各部分的内容。最后介绍一下所谓的“在线论坛”,关于本书的任何问题以及评论都可以在那里进行交流,并且可以通过Internet下载书中使用的一些源代码。 在讨论本书之前,我们首先介绍一下命名空间(namespaces)的概念。命名空间定义了一个组或者说一个范围,其中包含一些相关的类、结构以及其他一些类型。命名空间有点像一个家庭:它利用一个通用名称定义一组不同的成员,某些成员具有相同的功能。 .Net Framework中所有的对象,确切地讲是C#中所有的对象,组成了各个命名空间。例如,System命名空间包含了和Framework本身相关的一些对象。由.Net所定义的绝大多数命名空间都包含于System命名空间里。System.Windows命名空间定义了和Windows操作系统相关的一些类型和命名空间,而System.Web命名空间则定义了和Web页面以及服务器相关的一些类型和命名空间。 这种对应于命名空间的组织结构允许两个具有相同基本名称的对象表示两个截然不同的概念,这就像两个人可以拥有相同的姓一样。例如,在System.Web.UI.WebControls命名空间中的Button类表示网页上的一个按钮,而System.Windows.Forms命名空间中的Button类则表示应用程序窗口中的一个按钮。.Net中还有其他的命名空间,例如关于文件和目录对象的System.IO命名空间,关于图形对象的System.Drawing命名空间。在附录B中我们介绍了在.Net中常用的一些命名空间。 Windows Forms命名空间 除了对.Net Framework所支持的广大对象集合建立了一个结构之外,命名空间的概念对于如何写书也提供了一些指导。本书的重点是System.Windows.Forms命名空间,通常称之为Windows Forms。Windows Forms应用程序是被Windows操作系统执行的程序,它所使用的用户界面和随处可见的Windows用户桌面很相似。 本书希望较为系统地介绍Windows Forms命名空间,包括在这个命名空间中定义的绝大多数类型。 本书共18章,分成3个部分来介绍。 第1部分:初识WINDOWS FORMS 本书的第1部分介绍了关于C# 和Windows Forms的一些基本概念,前者比较粗略,后者比较详细。第1章利用一个文本编辑器创建了如图0-1所示的应用程序。我们将讨论如何通过.Net Framework来实现一个Windows Forms应用程序,以及如何利用C# 来进行Windows Forms编程。 图0-1 第1部分中的“Myphotos”应用程序 在第2章里,我们开始利用Microsoft的图形开发环境Visual Studio .Net在.Net Framework中创建应用程序。这一章里,我们重新创建了第1章中那个手工构建的应用程序,并将之称为“MyPhotos”。 第2部分:WINDOWS FORMS基础 在这一部分里,我们开始系统介绍Windows Forms命名空间里的各个类。这部分是前面“MyPhotos”应用程序的继承和发展,如图0-2所示(第13章中也有相同的图示)。您将会看到,这一部分将涉及创建一个Windows Forms应用程序时需要用到的主要的面向对象控件,包括菜单、状态栏、对话框、文本框以及组合框等。 “MyPhotos”应用程序将展示一个相册中的内容,它由一个或者多个图像文件或相片组成。程序将每个相册存储在一个文件里,并且允许用户逐个预览图像以及编辑相片或者相册的属性。 图0-2 第13章中的“MyPhotos”应用程序。图中给出了 主窗口和一个用于编辑选定相片属性的对话框 第3部分:高级WINDOWS FORMS 诸如图像的列表查看、拖放等更多高级主题将在本书的第3部分中介绍。这一部分利用相册的概念创建了几个不同的应用程序,包括一个类似于Windows资源管理器的用来浏览相册的应用程序,以及一个展示如何将Windows Forms控件的内容与一个从数据源中得到的数值进行绑定的“数据驱动”型应用程序。 在第18章中的“MyPhotos”应用程序的主窗口如图0-3所示。它被转换成一个多文档界面,可以显示多个相册。同时,也添加了很多新的功能,例如在不同的相册之间拖动相片以及在程序中显示本书的Web站点,等等。 本书适用读者 每个作者都希望所有的人能阅读自己的著作,我当然也不例外。在编写本书的时候,我更多的是针对以下3类读者: 对于利用.NET技术开发桌面应用程序感兴趣的Windows程序员。 图0-3 第18章中的“MyPhotos”应用程序。其中一个父窗口 中显示的正是本书第2部分中的“MyPhotos”窗口 熟悉.NET或者C# 技术,并且希望学到更多关于Windows Forms的类和编程知识的开发人员。 只有很少或者没有创建Windows应用程序经验的C++程序员。 再次说明一下:本书涉及的只是.NET Framework的一部分内容,即Systerm.Windows.Forms命名空间中包括的各个类。此外,还提供了关于C# 以及Visual Studio .NET的很多信息,尤其值得一提的是,它将会指导您一步一步地利用Visual Studio .NET创建每一个应用程序示例。同时,本书在附录C中给出了关于C# 和.NET的一个资源列表。 如果想要对.NET Framework有一个更加广泛、深入的了解,可以参考Fergal Grimes编著的Microsoft .NET for programmers,也是由Manning出版社出版的。 源代码下载 只要您购买了本书,书中出现的所有程序的源代码都可以从Manning主页上下载。您可以登录得到一些指导信息或者下载相关源代码。 作者在线 只要您购买了本书,就可以免费进入网上论坛,即“作者在线”。您可以登录主页得到关于论坛更加详尽的信息,可以注册获得进入论坛的资格,查看每一章节的代码,并可及时了解书中内容的更新和更正情况。您也可以对本书发表或褒或贬的评论,或者提一些技术问题。您可以从作者或者其他Windows Forms程序员那里获得帮助。登录就可以找到论坛的相关信息。 Manning对于读者的一个义务,就是提供一个读者与读者之间,以及读者与作者之间可以相互交流的场所。但是对于作者来讲,在这种交流中需要投入多少精力并没有具体的规定,它完全是作者自愿的(也是无偿的)。 您也可以通过eebrown@eebrown.com或者个人主页来联系Erik。 关于.NET .NET的历史既长久又短暂。虽然.NET Framework基于的编程语言以及开发环境数年前就出现了,但相对而言它还是新生事物,并且它在市场上能否成功还有待于进一步的检验。本节将简要回顾C#编程语言的历史,以及.NET Windows Forms的功能。 C语言最初是70年代早期在贝尔实验室发展起来的,当时是与UNIX操作系统联合使用的。它是从一种更早的所谓“B”语言发展而来的,而“B”语言本身是从一种被称为“BPCL”的语言派生出来的。70年代这种语言很快就流行起来,并最终在80年代中期由美国国家标准协会(ANSI)制定出了一套标准。介绍C语言的较为权威的书籍依然是Brian W. Kernighan 和Dennis M. Ritchie编写的The C Programming Language,它最早出版于1978年。 C++语言是由Bjarne Stroustrup设计出来的,他的那本著名的The C++ Programming Language最早是于1986年出版的。这个语言标准的制定仍然是由ANSI以及其他组织完成的。如今它有了更加普遍的应用。 C语言应用于Windows操作系统最早开始于Windows 1.0系统,大约是在80年代中期。Microsoft关于人机交互开发环境(IDE)的一个最早的目标是1990年左右实现的,当时推出的是Microsoft C 1.0。这个开发环境逐渐包括了C++,并且成为90年代中期的Visual C++的基础,并最终演化成为Visual Studio 6.0,它支持C++、Visual Basic以及一个算不上标准化的Java。Windows操作系统以及Win32 API构成了这些产品创建以及扩展的基础。 对于Microsoft Visual Studio的另外两个值得一提的竞争产品就是Borland C++以及Borland Delphi。它们都是非常成功的可视化开发工具,对于.NET Framework的设计以及开发都有一定的影响。实际上,Microsoft 的C#语言负责人Anders Hejlsberg就是Borland Delphi的最初设 计者。 其他贯穿于这个发展历史之中的产品还有:动态链接库、OLE和 COM的出现、诸如ODBC和ADO的数据库技术、Internet的兴起与发展,以及将基于DOS的Windows重新设计成为Windows NT和Windows XP。 “打造”.NET 和一些技术以及产品相对的是,Internet一直以来都在重新定义着程序员们设想的用户界面以及应用程序开发环境。随着诸如Netscape以及应用上取得的成功,一个产品或者一个界面越来越可能出现在一个网页浏览器上,而不再是一个传统的Windows应用程序中。Java语言已经在UNIX系统和网页服务器上获得了一些成功,就目前来讲,它是很多大型网页应用程序的设计语言。 也许是对于这种变化的响应,也许是由于现在用户桌面和Internet之间的界限正越来越模糊,Microsoft想发动一次“思想革命”—— 改变我们传统意义上对于应用程序开发的理解。其结果就是.NET Framework以及C#语言的出现1。 理解C#的最容易的方法就是设想有人将C++的所有烦人的缺点写下来,然后去除掉其中的每一项。举个例子:在C++语言中,指针的应用是件很麻烦的事情;很多代码错误并不能被编译器检测到,例如if ( x = 5 );对于字符串的操作很困难;没有一种好的方法可以安全地将一个对象“退化”成一个派生类型。C和C++语言的前身B和BPCL语言没有制定这样一个规范的类型系统—— 这种系统可以为语言中的整型、指针、字符型提供自由的空间。 在重新设计C#语言的时候,既考虑到要保留C和C++语言的灵活性,又考虑到将类型系统以及语法规则正规化。很多C++中的运行时错误在C#里都被认为是编译错误。另外,还要具有一些截然不同的特性,如内建的字符串类型,不存在全局变量,以及将评判系统和应用错误综合为通用异常模型(common exception model)。本书的附录A给出了对于C#语言的句法、关键词以及特征的概述。 尽管从设计的角度来讲,对于C#语言和.NET Framework二者的关系没有严格的要求,但两者可能将保持一段紧密的“交织”状态。.NET Framework是一个Windows操作系统的编程界面和运行环境,它本身的很大部分就是用C#编写的。 .NET Framework几乎包括了Microsoft的所有开发技术和环境—— 从COM到XML和ASP,再到Visual Studio。这些技术在同一个系统里重新被创建和发明。尽管向后兼容性没有完全丧失,.NET Framework对于这些技术以及使用这些技术的产品重新定义了类和方法。特别值得一提的是,现在的框架还包括:对Windows应用程序开发的新的支持、网址的获取和释放、异地程序之间的交互、数据库交互、安全、本地及远程安装以及其他技术。 我的目的并不是列举在.NET中可以找到的各种技术,也不是为了证明它好或是不好。有很多书籍和文章都提供了这方面的信息,如果您对其一无所知的话,也许现在就不会阅读这个介绍了。我的目的仅仅是为了说明,Microsoft正在对它的很多技术和产品进行全新的改造,并努力想把这些不同的产品放到一个框架里,即.NET Framework。 Windows Forms概述 正如我们在“关于本书”那一节所介绍的,.NET Framework中的所有对象,实际上就是C#本身的对象,是用所谓的命名空间来组织的。附录B中对于.NET Framework中比较常用的一些命名空间作了概述。 本书重点介绍其中的System.Windows.Forms命名空间,它用来创建基于Windows的应用程序。本节将概括介绍这个命名空间所定义的各个类。 在介绍各个具体的类之前,我们必须知道对于总体理解.NET Framework以及Windows Forms命名空间特殊性有所帮助的3个短语,即组件、容器以及控件。本书对于这些短语做了详尽的介绍,所以这一节中只通过几个例子进行简要介绍。 组件是允许应用程序间共享的对象。Component类就是在这种意义上封装的,它是Windows Forms命名空间大多数成员的基础。值得注意的另一点就是Icomponent接口,它定义了被所有组件支持的成员。我们将在第5章讨论这个接口,在第3章中讨论Component类。 容器是能容纳零个或者多个组件的对象。它就是一个组合机制,保证一些组件被封装在一起并被赋予相似的操作。在Windows Forms命名空间中,在需要组合一些对象时就要用到容器。Container类是基于容器这一概念封装的,Icontainer接口定义了所有容器需要的成员。 控件是一种可视化组件。在Windows Forms命名空间中,一个控件就是一个能够在Windows桌面上显示的图形化的界面组件。第4章中将要讨论的Windows Forms Control类,是所有Windows Forms控件的基础。对于我们来说,System.Web.UI命名空间中定义一个Control类来表示在网页上显示的图形对象是值得关注的。 总的来讲,您在Windows桌面上可以看到的任何一个可视化界面就是一个控件,而任何隐藏在它背后的对象就是一个组件。举个例子,一个状态栏面板是用StatusBarPanel类来表示的,这就是一个组件。而您在界面上实际看到的状态栏是StatusBar类表示的,这就是一个控件。状态栏是第4章所要介绍的主题。 控件也可以是容器,从而使得它可以容纳一系列的控件或者组件。StatusBar类就是一个容器,它容纳零个或者多个StatusBarPanel组件。另一个重要的容器控件就是Form类,它表示一个在Windows桌面上显示的应用程序窗口。我们将在第1章中介绍Form类,对它的讨论贯穿始终,第7章主要介绍“绘图和滚动”,第8章主要介绍“对话框”,而第16章主要介绍“多文档界面”。 图形界面中的大多数可视化元素,例如按钮、文本框、树以及对话框等都是用控件类表示的。一个例外就是菜单,我们将在第3章和第16章介绍这个主题。菜单对象都是组件,它是用Form类本身的一种特殊方式进行操作的。 全书始终都在讨论Windows Forms命名空间中的控件。很多普通的控件将在第9章“基本控件”、第10章“列表控件”、第11章“更多控件”、第13章“工具栏和提示”中介绍。诸如列表视图、树视图以及数据网格等高级控件将在本书第3部分中介绍。 Windows Forms命名空间里除了控件、容器以及组件外,还提供了很多其他的对象来支持基于Windows的应用程序开发。我们将在第12章“.NET分类”和第18章“.NET琐碎”中介绍其中的一些。特别值得一提的是将在第17章中介绍的关于数据绑定的概念。 如果一本关于如何创建Windows Forms应用程序的书没有讨论“可重用库”的创建问题,就显得有些欠缺了。第5章中我们将通过创建一个相册库来讨论这个概念,这个库在书中后面的部分将会用到,特别是第6章“通用对话框”将用到这个库。 致谢 在我们的生活中,一切事情看起来都是那么纷繁芜杂,众多的线索最终导致一个可以感知的结果。对于这些,我从来没有停止过感到惊奇,对于您正在读的这本书也是一样。虽然书的封面印着我的名字,但还有许许多多我认识和不认识的人为它做出了贡献。 特别感谢我的家庭:我的妻子Bridgett,她给了我耐心和爱;Katie和Sydney,谢谢他们定期的拜访和无条件的接受;Bianca,我忠实的伙伴,是他每天在办公室的另一张椅子上蜷缩着休息。 我同时感谢我的父母,David和Janet,我的老师以及其他在我的生命中支持过我的人。特别感谢Steve Cox和David Cobb,他们在很久以前令我对计算机编程产生了兴趣。 同样感谢我的朋友,他们用朋友特殊的方式支持和鼓励我,尤其是Jean Siegel,Janet Heffernan,Tony Mason和Marc Zapf。我还要感谢我的橄榄球队Haymarket Outer Limits,它让我在成稿期间获得了许多身体上的锻炼,给了我一段有趣而多产的时光。 感谢来自四面八方的校对者,他们贡献出许多的时间和精力阅读了不同章节的最初版本。没有他们的坚持和努力,这本书不能达到今天的水准。包括Marc Zapf帮我作技术校对和最终定稿;Javier Jarava竭尽全力地帮我校正每一章的代码和文本;Josh Mitts给了我深刻和鼓励性的评价;Andreas Haber为我解决许多重要的技术难点(对不起,Andreas,我最终还是没有把PropertyGrid控件放进去);Craig Fullerton仔细地校对了本书的前半部分;Mark Boulter在最初版本上进行了详尽的评价;Sam Raisanen全面地校对了第1、3和16章;还有其他人给了我许多具有远见卓识的评价和批评,包括Dharmesh Chauhan, Chris Muench, Tomas Restrepo以及Vijay Upadya。 我还要感谢看过本书最初概要的人,比如Steve Binney,Mark Boulter,Drew Marsh,Josh Mitts以及Kunle Odutola。他们的建议很重要,对于以正确的方式开始本书的编写以至最终的完成都有着很大的帮助。 最后,我要感谢在整个出版过程中与我一起工作的人,包括那些我从没见过面,但在我的写作过程中给了我很大支持的人。特别是Susan Capparelle,她在我的最初报告中认识到了本书的价值;Marjan Bace通过无数次的电话讨论给了我很多深刻的评价和建议;Ted Kennedy帮我和所有的校对者协调并收集反馈信息;Syd Brown多次为我重新编辑表格而使它们最终成形;Leslie Haimes在我已经同意了前一个封面设计后又为我重新设计了一个封面;Mary Piergies负责和工作人员沟通并替我为他们回答问题;Rebecca Pepper 和Lianna Wlasiuk鼓励我修改书中很多的结构性元素;Lois Patterson 为我详尽地检查了最终版本的文字错误;最后,Lee Fitzpatrick为我签属了版税支票。