介绍
由当前关于互联网的许多讨论来看,似乎微软的Visual Studio开发系统已经完全不再支持开发传统的基于Windows操作系统的应用程序了。而实际情况是,微软依然非常重视对基于Windows的应用程序的开发。
Win Forms是一种全新的窗体形式,开发人员可以利用它创建充分利用微软的Windows操作系统中丰富的用户接口的应用程序。Win Forms是微软的.NET平台的一部分,采用了许多新的技术,包括一个公共应用程序框架、可管理的执行环境、集成的安全性和面向对象的设计原则。此外,Win Forms还提供了对方便迅速连接到互联网服务和创建基于ADO+数据模型的应用程序的支持。有了Visual Studio中全新的共享开发环境,开发人员就能够使用包括Visual Basic和C#在内的任何支持.NET平台的编程语言开发基于Win Forms的应用程序。
Win Forms是什么?
就象在上面提到的那样,Win Forms是.NET Framework中专指Windows客户端UI编程的名字空间,它与被称作Web Forms的ASP+ UI的设计原理相同,但其中的类和具体的实现是完全不同的,Win32 API和Web组件之间的类是不能够互相转换的。然而,象.NET框架中的其他部分一样,一致性是其最优先考虑的部分,目的是让一个Win Forms开发人员能够迅速地适应Web Forms的编程方式,反之亦然。例如,二个名字空间都有Button类,其中都有文本域、OnClick事件和ForeColor、BackColor、Font等属性。
Win Forms控制是完全基于System.WinForms.Control类的,Control类有基本的HWND功能,处理大部分常见的WM_xxxx消息。从Control类派生出的是RichControl控制,它添加了输出逻辑和绘制代码,System.WinForms名字空间中的大部分控制都是由继承RichControl得来的。ScrollableControl添加了对窗口用户区滚动的支持。一般情况下,滚动支持是通过ContainerControl控制获得的,ContainerControl控制是由继承
ScrollableControl控制而得来的,其中添加了对子控制、焦点和标签进行管理的支持。由继承ContainerControl而生成的是Form,它是Win Form的最高层的控制,它有控制标题条、系统菜单、不规则窗口和缺省控制的属性。另一个由继承ContainterControl而生成的是UserControl,它就是开发人员可以创建的控制的基本类。UserControl是用来管理其他子控制的。微软的Visual Studio .NET中有可视化的UserControl和Form设计器,我们可以发现用来添加和设计由继承它们生成的类的工程条目。
我们已经讨论了有关Win Forms的最基本的知识,下面我们就来讨论Win Forms的一些深层次的特性。
较短的学习周期
Win Forms的首要目的是能够尽可能地提高开发人员在开发Win32平台应用程序的编程效率。无论是GDI还是窗口状态管理,在Win32中编程者相当困难的。例如,象WS_BORDER或WS_CAPTION等窗口风格只能在创建窗口时设定或修改,当然了,象WS_VISIBLE或WS_CHILD等窗口风格可以在已经创建的窗口上进行修改。Win Forms就能够消除这种不统一性,确保操作可以在所有时间以同一种方式进行,可以在任何时候以任何顺序修改Win Forms控制的属性,并产生希望的效果。在改变这些属性时需要创建新的HWND,Win Forms会自动地创建窗口,并对它进行合理的设置。
使用Win Forms,获得控制的通知或事件也更加简单。所有的Win Forms事件都是基于一种被称作Delegates的通用语言运行库功能的。Delegates是一种安全函数的指针,可以为任何控制的任何事件添加Delegate事件自理程序,我们也无需通过重载创建一个处理所有事件的类,创建一个事件图,或者为一个类中的所有事件实现一个接口而只会执行其中的一个。事件也可以通过重载继承类进行处理,但一般情况下只有控制的创建者和在高级的应用程序设计中才会这样作。接收一个按钮的Click事件是相当简单的:
public class ButtonClickForm: System.WinForms.Form {
private System.WinForms.Button button1;
public ButtonClickForm() {
// 创建按钮
button1 = new System.WinForms.Button();
// 添加事件处理程序
button1.AddOnClick(new System.EventHandler(button1_Click));
// 在窗体上添加按钮
this.Controls.Add(button1);
}
private void button1_Click(object sender, EventArgs e) {
MessageBox.Show("button1 clicked!");
}
}
在上面的代码中,我们已经创建了一个按钮并添加了一个事件处理程序方法button1_Click,当该按钮被点击时,其中的几行代码就会开始执行。
着手开发Win Forms工程也是相当简单的。在Visual Studio .NET中创建Win Forms工程只会生成一个被编译的文件Form1.cs,而不会生成头文件、接口定义文件、引导应用程序文件、资源文件和库文件,工程所需要的所有信息都包含在窗体的代码中,其结果是工程可以很方便地由一个单一窗体组成的应用被扩充为包括有多个代码文件、复杂的由多窗体构成的应用程序。其中没有需要连接的临时对象文件,只有代码文件和已经建立的DLL文件。随着慢慢熟悉这种方法,创建.NET框架应用程序和C/C++应用程序在复杂性方面的判别就会越来越明显。由于信息只包含在代码文件中,在Visual Studio .NET环境之外创建工程也是相当简单的,而无论是Visual Basic代码、C#代码或是其他任何支持.NET框架的语言写成的。
由于Win Forms是建立在通用语言运行库的,因此开发人员可以选择任何一种支持通用语言运行库的编程语言开发Win32应用程序。开发人员可以使用从C#到COBOL、Eiffel、Perl在内的17种编程语言开发Win Forms应用程序(或者Web Forms应用程序和Data应用程序),这使得掌握多种编程语言的开发人员可以高效地使用Win Forms建立应用程序。
输出布局
如果你曾经尝试着创建一个能够正确地改变大小的窗体,就会发现这是多么困难了/MFC和以前的Visual Basic没有对此提供任何内置的支持。但在Visual Studio .NET中仅仅需要几行的代码(甚至这些代码不需要你动手编写,因为在设计窗体时的Property Browser(属性浏览器)中就能实现这样的功能。),就能创建一个能够正确地改变大小的对话框。
基本的输出布局是由二部分组成的:Anchoring和Docking。RichControl类有一个Anchor属性,这是一个枚举型变量的值通过或运算来描述一个控制与其父控制边缘的距离。例如,如果在一个窗体上创建了一个按钮,并且将其Anchor属性设置为AnchorStyles.BottomRight,则在改变大小时,按钮将与窗体的下、右边缘保持相同的距离。如果将Anchor属性设置为AnchorStyles.All,按钮将与窗体的四周保持固定的距离,按钮就会改变自己的大小来符合这一要求。
Docking是Anchoring的一种特殊情况。RichControl的Dock属性定义控制与父控制的哪个边相接触,它的值可以是Top、Left、Right、Bottom或Fill。当父控制的大小变化时,它将仍然维持与特定边缘的距离。将一个控制移动到移动到父控制的底部,并将Anchor设置为AnchorStyle.BottomLeftRight,等同于将Dock属性设置为Bottom。在本例中,列表框与窗体的左边缘相接触,按钮与窗体的顶、左和右边保持一定的距离,因此,它们能够维持相对的位置和大小。下面例子中对话框(图2)是使用Visual Studio .NET中的Win Forms Designer设计的。在创建它时我用了2分钟的时间,而没有编写一行代码:
// ResizableSample.cs
namespace ResizableSampleNamespace {
using System;
using System.Drawing;
using System.ComponentModel;
using System.WinForms;
///
/// Summary description for ResizableSample.
///
public class ResizableSample : System.WinForms.Form {
///
/// Required by the Win Forms designer
///
private System.ComponentModel.Container components;
private System.WinForms.Button button3;
private System.WinForms.Button button2;
private System.WinForms.Button button1;
private System.WinForms.ListBox listBox1;
public ResizableSample() {
// Win Form Designer要求下面的初始化函数
InitializeComponent();
}
///
/// 清除所使用的资源文件
///
public override void Dispose() {
base.Dispose();
components.Dispose();
}
///