深入浅出VB.Net Windows Form

来源:岁月联盟 编辑:zhu 时间:2007-01-31
   

  在VB.Net中,Windows form完全变了,在.Net Framework中Windows Form代表了System.Windows.Forms.Form类。本文通过详细描写写一个Windows应用程序要做的基本工作,来介绍新的底层技术,这包括创建表单,添加控件,事件响应。也给出了Winform的面向对象的分析,包括能够使代码重用的最有力的新特征:继承。

  新版的VB增加了一个新的可以被称为面向对象的程序设计语言的标志性特征:继承。现在没有人在对VB是不是真正的面向对象的语言进行争论了。但这一切对所有VB程序员意味作什么呢?是不是以为做每个VB程序员都必须学习oop呢?答案没有那么简单。原来版本的VB以易于使用闻名,我们每个人都记得拖动控件是那样的容易,你根本用不着明白什么是面向对象就可以创建Windows应用程序。对大多数使用以前版本的VB程序员来说一多半的面向对象的特征没有用。Visual Basic.Net保留了VB早先的易用性,用VB.Net创建一个Windows应用程序还是那样容易,但现在我要告诉你精通oop对充分利用VB.Net的强大功能的帮助。

  简介

  一切都是对象,面向对象有三个主要特征:封装,继承和多态,这是任何一本oop的书里讲到的。这是一个很广泛的话题,要说清楚需要写厚厚的一本书。因此在这里我只一点讲述关于继承的内容,那些对于oop很熟悉的人可以不看这部分。

  现在开始

  如果你有一个叫classA的类,它包含很多方法。你可以将classA扩展成另外一个类,这个新类是classA的子类,他继承了classA的方法和变量,在这个子类中可以使用父类的方法和变量,也可以创建属于自己的方法。这样做的好处就很明显了:如果你自己要写一个软件,但同时其他人已经有一个相似的软件,这时你就借用或者买他的程序,然后扩展它,这样你就用不着写全部应用程序的代码,你只需要写其中的20%就行了,这样你算算要节约多少时间和金钱。

  list1显示了三个VB.Net类:classA,classB,classC,classA继承于classA,classC继承于classB,代码显示classB可以使用classA的SendMessage 方法和他自己的SendPersonalMessage方法,classC可以使用classA的SendMessage 方法和classB的SendPersonalMessage方法,以及自身的SendPrivateMessage方法。

  list1 关于VB.Net继承的例子

  Imports System
Class ClassA
  Public Sub SendMessage()
   Console.WriteLine("From SendMessage in ClassA")
  End Sub
End Class
Class ClassB
  Inherits ClassA
  Public Sub SendPersonalMessage()
   Console.WriteLine("From SendPersonalMessage in ClassB")
  End Sub
End Class
Class ClassC
  Inherits ClassB
  Public Sub SendPrivateMessage()
   Console.WriteLine("From SendPrivateMessage in ClassC")
  End Sub
End Class
Module Module1
  Sub Main()
   Dim a As ClassA = New ClassA()
   Dim b As ClassB = New ClassB()
   Dim c As ClassC = New ClassC()
   a.SendMessage()
   b.SendMessage()
   b.SendPersonalMessage()
   c.SendMessage()
   c.SendPersonalMessage()
   c.SendPrivateMessage()
  End Sub
End Module

[责任编辑:editor]

   

  明白这个后,我们就可以着手准备创建一个Windows 表单

创建VB.Net表单

  VB.Net可以利用.Net framework基类库快速创建一个Windows应用程序,System.Windows.Forms名称空间提供你需要的Windows表单,创建表单只需要创建一个继承于System.WinForms.Form的新类,下面的代码创建了一个新类form1,该类继承于System.Windows.Forms.Form。

  Public Class Form1 : Inherits System.Windows.Forms.Form
End Class

  注意如果 Inherits在一个独立的行,那么就不需要用分号分隔类名。

  Public Class Form1
  Inherits System.Windows.Forms.Form
End Class

  当表单工作时就要使用来自System.Windows.Forms 名称空间的类,那么就要引入名称空间。

  Imports System.Windows.Forms
Public Class Form1
  Inherits System.WinForms.Form
End Class

  如果使用visual studio.Net那么就要写一些初始化代码。这也许让你有点糊涂了。我们来做点实验,创建一个新的Windows应用程序,打开代码窗,删除上面的所有代码,然后按F5运行这个程序,你将看到一个空白的窗体。很容易,是不是?但这怎么可能?这是因为FORM1继承于System.Windows.Forms.Form。System.Windows.Forms.Form 包含了很多类,窗体类自身是在第7层,他继承于ContainerControl,ContainerControl 继承于ScrollableControl,我们看下图就明白了:

  Object
  MarshalByRefObject
   Component
    Control
     ScrollableControl
      ContainerControl
       Form
         图一1: System.Windows.Forms.Form类的继承关系

  然而你还是怀疑,没有任何代码,他是怎样显示窗体的,Visual Studio.Net 实际上只作了一点事情,首先是.VBproj文件指定一个首先运行的类,这有点象隐藏起来的 sub main,在缺省状态下,第一个表单(就象例子中的form1)应该是被创建的第一个类,VB.Net假定是一个无争议的构造器,就象:

  Public Sub New()
End Sub

  所以,第一个表单有一个构造器,显式的创建这个构造器不是件好事。

  Imports System.Windows.Forms
Public Class Form1
  Inherits System.Windows.Forms.Form
  Public Sub New()
  End Sub
End Class

[责任编辑:editor]

   

  当你用new关键字实例化一个新对象时,一个类构造器将被调用,通常你只需要写一些初始化代码就行了。在初始化时有大量代码,你可以建一个private sub来装载这些代码,初始化时只需要调用这个子程序

  把下面的代码添加进前面的程序中

  Imports System.Windows.Forms
Public Class Form1
  Inherits System.Windows.Forms.Form
  Public Sub New()
   InitializeComponent
  End Sub
  
  Private Sub InitializeComponent()
   '
   ' write your initialization code here
   '
  End Sub
End Class

  初始化代码一般包括:设置表单的标题或者定义表单的大小,在VB.Net的表单中表示表单标题的是text属性,这个属性由System.Windows.Forms.Control继承而来,对于大小,表单由Width 和 Height 属性决定,同样是继承于System.Windows.Forms.Control .

  引用现在使用的类的实例时可以使用关键字:Me,在下面的InitializeComponent 子程序中确定表单的标题和大小。

  Private Sub InitializeComponent()
  Me.Text = "Developer Form"
  Me.Width = 400
  Me.Height = 300
End Sub

  按下F5,运行,可以看见一个宽400高300pixels的空白表单,只是他的标题变成"Developer Form."

  *****图1*****

  向窗体添加控件

  没有控件的窗体没有丝毫用处,.Net基类提供了大量控件,有button, checkbox, textbox, label等等,对于.Net Framework新手,你一定想知道这些对象的层次结构。举例而言button控件就如下:

  Object
  MarshalByRefObject
   Component
    Control
     ButtonBase
      Button

[责任编辑:editor]

   

  所有的控件都来源于Control类,将一个控件添加进表单需要三个步骤:

  1、宣布控件变量

  2、实例化控件

  3、将控件增加入表单。

  由于VB.Net变量范围不一样,若变量在函数内被宣布,那么函数对他是可见的,如果想让控件对整个类都时可见的,那么就要在类一级宣布他。

  实例化控件就象实例化其他对象一样,使用new关键字,一旦你有了控件的实例,你就可以将他添加进表单中。不能将控件直接添加到表单中,因为表单没有Add(Control)方法。无论如何,form类从control类中继承了control属性,在表单类中,使用这个属性可以获得表单的System.Windows.Forms.Form.ControlCollection中的对象。Form.ControlCollection代表了表单中的控件集合,可以使用add方法向表单增加一个控件,remove方法从表单中删除一个控件。

  明白了这三个步骤,下面的例程演示向表单添加控件的过程

  'Declare the button
Dim Button1 As System.Windows.Forms.Button
'Instantiate the button
Button1 = New System.Windows.Forms.Button()
'Add the button to the form
Me.Controls.Add(Button1)

  当然,你可以按照你的想法设置控件的众多属性,而且可以在添加进表单之前或者之后设置他们的值,但在实例化之前就不能进行设置。控件有诸如left,right,width,height这样的属性表示他的大小,button控件也有象button对象那样的text属性。

  下面是添加两个控件到表单中的例子。

  Listing 2: Adding controls to a form.

  Imports System.Windows.Forms
Public Class Form1
  Inherits Form
  ' Control declaration: a Button and a TextBox
  Private Button1 As Button
  Private TextBox1 As TextBox
  Public Sub New()
   InitializeComponent()
  End Sub
  Private Sub InitializeComponent()
   Me.Text = "Developer Form"
   Me.Width = 400
   Me.Height = 300
   Button1 = New Button()
   TextBox1 = New TextBox()
   Button1.Left = 200
   Button1.Top = 200
   Button1.Width = 100
   Button1.Height = 40
   Button1.TabIndex = 0
   Button1.Text = "Click Me"
   TextBox1.Left = 200
   TextBox1.Top = 30
   TextBox1.Width = 150
   TextBox1.Height = 40
   Me.Controls.Add(Button1)
   Me.Controls.Add(TextBox1)
  End Sub
End Class

[责任编辑:editor]

   

  事件响应

  VB6及其以前的版本都是事件驱动,可以很容易写出响应事件的代码,举例而言,有一个叫button1的button控件,你希望他响应用户点击事件,你所需要做的是建立一个button1_click子程序(实际上VB_ide已经帮你做了),在VB.Net中也一样,一旦你将控件加入设计模式,就可以点击它,告诉VB.Net你想写一个事件响应程序,在这里将显示怎样手工写事件响应程序。

  如果你希望对象响应一个事件,那么在你宣布变量时要使用关键字WithEvents,例如,你想使你的按钮响应一个事件,原来的方式是:

  Private Button1 As Button

  现在要在变量名前加上关键字WithEvents,就像下面这段代码

  Private WithEvents Button1 As Button

  然后你需要为每个事件创建一个处理过程,这样你的控件才会响应它。对于button1响应click事件需要写一个button1_click子程序,代码如下:

  Private Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Button1.Click
  '响应代码
End Sub

  form类和所有控件类都继承control类的事件,在.Net Framework 索引中列出了System.Windows.Forms.Control类全部58个事件,包括继承自componentde 事件。常用的事件有:Click, DoubleClick, GotFocus, LostFocus, KeyUp, KeyDown等等。

  在list3的代码中创建了一个窗体并添加了两个控件:button控件和textbox控件,对button1控件在宣布变量时使用关键字WithEvents,创建两个事件处理程序:Button1_Click 和 Button1_GotFocus

  Listing 3:
Imports System.Windows.Forms
Public Class Form1
  Inherits Form
  Private WithEvents Button1 As Button
  Private TextBox1 As TextBox
  Public Sub New()
   InitializeComponent()
  End Sub
  Private Sub InitializeComponent()
   Me.Text = "Developer Form"
   Me.Width = 400
   Me.Height = 300
   Button1 = New Button()
   TextBox1 = New TextBox()
  
   Button1.Left = 200
   Button1.Top = 200
   Button1.Width = 100
   Button1.Height = 40
   Button1.TabIndex = 0
   Button1.Text = "Click Me"
   TextBox1.Left = 200
   TextBox1.Top = 30
   TextBox1.Width = 150
   TextBox1.Height = 40
   Me.Controls.Add(Button1)
   Me.Controls.Add(TextBox1)
  End Sub
  Private Sub Button1_Click(ByVal sender As Object, _
    ByVal e As System.EventArgs) Handles Button1.Click
   TextBox1.Text = "Ooops.... you clicked me."
  End Sub
  Private Sub Button1_GotFocus(ByVal sender As Object, _
      ByVal e As System.EventArgs) Handles Button1.GotFocus
   TextBox1.Text = "Button got focus."
  End Sub
End Class

[责任编辑:editor]

   

  实现继承

  现在我们进入本文最重要的一部分,我们在这部分将讨论继承的强大作用,当创建一个新表单时,就扩展了System.WinForms.Form 类,VB.Net支持继承,你就可以扩展你自己的表单,通过这种方法,当需要创建一个和以前的表单相似的表单时,可以通过扩展以前的表单来实现,这样可以节约大量时间。就像下面这个表单。

  Public Class NewForm
  Inherits WindowsApplication1.ExistingForm

  下面的例子显示了表单的继承性。我们创建了一个Employee表单,Employee表单中有两个标签,两个文本框,两个按钮。如图4:

  *******图4*********

  现在我们需要为公司的承包人创建一个表单,承包人就像公司的其他雇员一样,唯一不同的是他们不拿公司的薪水,公司只为他们的服务而向其它公司付费。现在,我们扩展已经存在的Employee表单肯定要比创建一个新表单要强。承包人有FIRST NAME,LAST NAME,另外还有一个外公司域。

  list4列出了employee表单的代码

  Listing 4: The Employee Form
Imports System.Drawing
Imports System.Windows.Forms
Imports System.ComponentModel
Public Class Form2
  Inherits Form
  Public Sub New()
   MyBase.New()
   'This call is required by the Win Form Designer.
   InitializeComponent()
  End Sub
  #Region " Windows Form Designer generated code "
  'Required by the Windows Form Designer
  Private components As System.ComponentModel.Container
  Protected cancel As System.Windows.Forms.Button
  Private LastName As System.Windows.Forms.TextBox
  Private FirstName As System.Windows.Forms.TextBox
  Private Label2 As System.Windows.Forms.Label
  Private Label1 As System.Windows.Forms.Label
  Protected ok As System.Windows.Forms.Button
  Dim Form2 As System.Windows.Forms.Form
  Private Sub InitializeComponent()
   Me.Label1 = New System.Windows.Forms.Label()
   Me.FirstName = New System.Windows.Forms.TextBox()
   Me.ok = New System.Windows.Forms.Button()
   Me.Label2 = New System.Windows.Forms.Label()
   Me.LastName = New System.Windows.Forms.TextBox()
   Me.cancel = New System.Windows.Forms.Button()
   Me.SuspendLayout()
   '
   'Label1
   '
   Me.Label1.Location = New System.Drawing.Point(8, 24)
   Me.Label1.Name = "Label1"
   Me.Label1.TabIndex = 1
   Me.Label1.Text = "First Name"
   '
   'FirstName
   '
   Me.FirstName.Location = New System.Drawing.Point(120, 16)
   Me.FirstName.Name = "FirstName"
   Me.FirstName.Size = New System.Drawing.Size(136, 20)
   Me.FirstName.TabIndex = 3
   Me.FirstName.Text = ""
   '
   'ok
   '
   Me.ok.Location = New System.Drawing.Point(8, 128)
   Me.ok.Name = "ok"
   Me.ok.Size = New System.Drawing.Size(112, 32)
   Me.ok.TabIndex = 0
   Me.ok.Text = "OK"
   '
   'Label2
   '
   Me.Label2.Location = New System.Drawing.Point(8, 48)
   Me.Label2.Name = "Label2"
   Me.Label2.Size = New System.Drawing.Size(88, 16)
   Me.Label2.TabIndex = 2
   Me.Label2.Text = "Last Name"
   '
   'LastName
   '
   Me.LastName.Location = New System.Drawing.Point(120, 40)
   Me.LastName.Name = "LastName"
   Me.LastName.Size = New System.Drawing.Size(136, 20)
   Me.LastName.TabIndex = 4
   Me.LastName.Text = ""
   '
   'cancel
   '
   Me.cancel.Location = New System.Drawing.Point(144, 128)
   Me.cancel.Name = "cancel"
   Me.cancel.Size = New System.Drawing.Size(112, 32)
   Me.cancel.TabIndex = 5
   Me.cancel.Text = "Cancel"
   '
   'Form2
   '
   Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
   Me.ClientSize = New System.Drawing.Size(272, 181)
   Me.Controls.AddRange(New System.Windows.Forms.Control()
    {Me.cancel, Me.LastName, Me.FirstName, Me.Label2, Me.Label1,
    Me.ok})
   Me.Name = "Form2"
   Me.Text = "Employee Form"
   Me.ResumeLayout(False)
  
  End Sub
  #End Region
End Class

[责任编辑:editor]

   

  注意除ok和cancel按钮外,其他所有控件都被宣布为私有变量,ok和cancel控件被宣布为protect类型,由继承得来的类可以访问protect类型的控件。

  list5列出了employee表单的扩展表单Contractor。注意我们添加了两个控件并且改变ok按钮的位置。

  Listing 5: The Contractor form
Imports System.Windows.Forms
Public Class Form1
  Inherits WindowsApplication1.Form2
  Private Label3 As Label
  Private ExternalCompany As TextBox
  Public Sub New()
   InitializeComponent()
  End Sub
  Private Sub InitializeComponent()
   Label3 = New Label()
   ExternalCompany = New TextBox()
   Label3.Location = New System.Drawing.Point(8, 72)
   Label3.Size = New System.Drawing.Size(88, 16)
   Label3.Text = "Ext Company"
   ExternalCompany.Location = New System.Drawing.Point(120, 62)
   ExternalCompany.Size = New System.Drawing.Size(136, 20)
   ' Change the ok button position
   ok.Location = New System.Drawing.Point(8, 140)
   Me.Text = "Contractor Form"
   Me.Controls.Add(Label3)
   Me.Controls.Add(ExternalCompany)
  End Sub
End Class

  ****************图5*************

  总结

  现在我们完全明白了VB.Net中窗体表单,他和VB6中的表单一样容易,但它是完全面向对象的,理解面向对象编程使你能够充分利用VB.Net的强大功能。比如,掌握继承,能使你最大限度的利用代码重用技术。

[责任编辑:editor]