top
Loading...
深入淺出VB.NetWindowsForm

在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

明白這個后,我們就可以著手準備創建一個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

當你用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

所有的控件都來源于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

事件響應

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

實現繼承

現在我們進入本文最重要的一部分,我們在這部分將討論繼承的強大作用,當創建一個新表單時,就擴展了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

注意除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的強大功能。比如,掌握繼承,能使你最大限度的利用代碼重用技術。


作者:http://www.zhujiangroad.com
來源:http://www.zhujiangroad.com
北斗有巢氏 有巢氏北斗