VB.NET中的變化
簡介
在本篇文章中,我們將介紹Windows Forms,它與我們以前所熟知的窗體是有所不同的。此外,我們還會說明在VB.NET中編程與在以前的VB版本中有何不同之處。
Windows Forms
Windows Forms是目前我們所知道的最高級的窗體,其中有許多很酷的功能,使開發人員能夠設計出更精彩的屏幕顯示。
在這里我們不會再敘述冗長的理論,我們將直接說明有關Windows Forms的問題:
·啟動VB.NET。
·在VB.NET的開始頁上,點擊Create New Project(創建新工程)。
·在Visual Basic Projects標簽下選擇Windows Application。
·如果有必要,改變Name和Location。
·點擊OK按鈕。
哈哈!現在屏幕上出現一個Windows Form了吧。
![]() 圖:Big Changes1 |
現在點擊Form1,就會出現Properties窗口,與以前的版本相比,這里有了一些小小的變化,原來的Caption屬性如今變成了Text,Font屬性被分解成了Name、Size等屬性,此外,還新添加了為創建MDI應用程序而設置的IsMDIContainer屬性。
現在我們再來看看屏幕左側的Toolbox,點擊Win Forms框,然后看一下屏幕,馬上就會發現,在VB.NET中的控制都是全新的。
使用Toolbox底部附近向下的方向鍵瀏覽該表,就會發現其中的控制比以往的版本中多了許多。
在Form1中添加一個Label控制,方法與在VB6中添加Label控制相同。試著改變Font和在以往的版本中被稱作Caption的Text屬性。
VB.NET中也包含有許多常見的控制:Button(以往的CommandButton)、RadioButton(以往的OptionButton)、GroupBox(以往的Frame),另外象TextBox、CheckBox、 PictureBox、ListBox和ComboBox等控制都進行了適當的擴展。試著在窗體上添加上述的各種控制,并研究其關健的屬性。
提示:或許你已經注意到了,Shape控制已經不見了,但我們仍然可以通過被稱作System.Drawing.Graphics的名字空間在窗體上添加圖像。
在這個列表中,我們還會發現許多在VB6中不經常使用的控制,例如,DateTimePicker、ProgressBar和ListView等控制,這些控制必須使用Components菜單才能添加進應用程序中。
現在你已經可以來親自試一下在以前的版本中沒有出現過的控制了。
提示:如果想看看你添加的控制在運行時是個什么模樣,可以按下F5鍵,這樣就可以編譯你的應用,并運行應用程序了,這一點與在VB6中完全一樣。
除此之外,還有一些在以前的VB版本中沒有出現過的控制,我們來看看這些控制的用法。首先是MainMenu控制,它就是以前的Menu Builder,下面我們來試試它的功能:
·在窗體上添加MainMenu控制。
·點擊窗體上標有Type Here的方框。
·輸入&File。
·現在在新的File菜單中添加一個子項。
·在File菜單項的右側點擊標有Type Here的方框,擴充菜單系統,添加菜單項。
·按下F5鍵,運行應用程序,并測試新設計的菜單系統。
提示:輸入一個破折號可以在菜單中添加一個分隔符。
![]() 圖:Big Changes2 |
我們可以象在VB6中那樣給菜單項添加代碼。雙擊相應的菜單項,就可以在出現的代碼窗口中添加該菜單項對應的代碼。我們將后面詳細地說明這一問題。
下面讓我們來看看LinkLabel,這是一種看起來與互聯網網頁上的超文本鏈接類似的控制。缺省情況下,它是藍色的,并標有下劃線,當鼠標經過它時就會變成一只手,如果被點擊,顏色就會隨之發生變化。但在缺省情況下它并不指向一個互聯網網頁,點擊它時,它的Click事件的代碼就會運行。
在窗體上添加一個LinkLabel控制,然后按下F5鍵運行程序,測試新添加的LinkLabel控制。
提示:試著改變LinkBehavior屬性,看看更多的LinkLabel的效果。
另外,我個人認為ErrorProvider是一個特別有用的控制,如果有確認錯誤發生,它將用一個圖標高亮度地顯示出錯的控制。下面是它的用途的一個例子:
![]() 圖:Big Changes3 |
此外,以往版本中的ToolTips在VB.NET中成為了ToolTip控制,原來的Windows Open 和Save對話框也成了控制。TrayIcon控制允許開發人員輕而易舉地在系統托盤中添加圖標和菜單,HelpProvider控制使你能夠簡單地實現幫助文件的訪問。
類似的控制還有許多,但在本篇文章中我們不可能都一一涉及,如果讀者希望得到更多的有關這些方面的資料,請參閱VB.NET系統中的幫助。
提示:點擊Properties窗口下的Dynamic Help按鈕就可以得到相關的幫助。
控制的定位
長期以來,VB中的Resize命令一直是困擾編程人員的一個因素,雖然有許多人提出了解決方案,但效果并不理想。這也是大多數的VB.NET控制包含有Anchor和Dock屬性的原因,這二個屬性將有助于解決對象的大小和位置問題。
我們先來看看Anchor屬性,它能夠使一個或多個控制邊緣與窗體的邊緣保持固定的距離。我們來看看下面的例子:
·創建一個新的Windows Application類型的應用程序。
假設你正在創建一個Web應用軟件,并希望在窗體的底部放置一個TextBox控制,我們希望它的長度與窗體相適應。
·在窗體中添加一個TextBox控制,如下圖所示:
![]() 圖:Big Changes4 |
·點擊TextBox1,并察看其Anchor屬性。
缺省情況下,控制的anchor屬性為TopLeft(即窗體的左上角)。換一句話說,它與窗體的左側和上部保持著一定的距離。
![]() 圖:Big Changes5 |
下面我們來改變TextBox1的Anchor屬性:
·改變Anchor的屬性,不選擇Top,而選擇Left、Right和Bottom。
Anchor屬性將變化為BottomLeftRight,意味著TextBox1將與窗體的底部、左側和右側保持著同樣的距離。
·按F5鍵,運行你的應用程序。
·改變窗體的大小。
Dock屬性也相當地重要,但它畢竟不是革命性的,它與VB6中控制所擁有的Align屬性類似,它使得特定的控制一直在窗體的一邊,或者使用Fill選項,覆蓋整個窗體。
·在Form1中添加一個新的TextBox控制。
·試驗其Dock屬性。
繼承
在VB.NET中也有繼承的概念。在以后的文章中,我還將對真正的代碼繼承進行專門的討論。在本篇文章中,我們討論的是Visual Inheritance(視覺繼承),也即一個窗體從主窗體那兒得到了輸出布局(甚至是其代碼。)。
假設我們有許多通用的控制,例如可能是一個OK按鈕、互聯網網址鏈接、窗體背景、用于數據輸入的TextBox控制和向導的輸出布局等,不論需要使用任何窗體元素,我們都可以通過視覺繼承共享它們及其相關的邏輯。
·創建一個新的Windows Application類型的應用程序。
·在Form1中添加一些公共元素。
我添加的公共元素包括anchor屬性為BottomRight的LinkLabel、anchor屬性為BottomLeft的OK按鈕和一個提示我的應用程序名字的Label。添加控制后的窗體應該如下圖所示:
![]() 圖:Big Changes6 |
在能夠繼承一個窗體前,必須“建立”它(一種微編譯)。
·在Build菜單中選擇Build菜單項。
下面我們來繼承這一窗體。
·依次點擊Project->Add Inherited Form(添加被繼承窗體)。
·確保已經選擇了Inherited Form(被繼承窗體),然后點擊OK鍵。
·在出現的列表中選擇Form1并點擊OK按鈕。
![]() 圖:Big Changes7 |
·如果Form2沒有自動出現,則在Solution Explorer中雙擊它。Form2擁有Form1所擁有的所有控制。
·在Form2中添加一些TextBox控制。
![]() 圖:Big Changes8 |
下面我們來看看運行時的Form2,不過這樣需要改變Project Properties(工程屬性):
·在Solution Explorer(方案瀏覽器)中右擊你創建的Windows Application類應用程序。
·從彈出式菜單中選擇Properties(屬性)。
此時,屏幕上應該顯示如下所示的畫面。如果不是這樣,那可能是你在Solution Explorer中選錯了項目。
![]() 圖:Big Changes9 |
我們可以在這里改變Assembly名(以前補稱作Project名)、版本號、應用程序圖標和Startup對象,這才是我們感興趣的目標。
·將Startup Object改為Form2,點擊OK按鈕。
現在我們來測試一下繼承得到的窗體:
·點擊F5鍵,對應用程序進行測試。
注意觀察它們是如何協同作用的。試著改變Form2的大小━━如果已經使用過Form1的Anchor屬性,它們對Form2也起同樣的作用。如果為Form1編寫了代碼,這些代碼也將自動地被Form2所繼承。甚至可以讓Form2覆蓋掉Form1的一部分功能。例如,盡管其外觀是由Form1繼承得到的,但OK按鈕可以被Form2識別。
編程方面的變化
有一點是毫無疑問的,VB.NET在編程方面也有巨大的變化。
有許多讀者對VB.NET在編程方面的變化不理解,但一旦他們開始理解為什么會發生這樣的變化,并能夠正確地使用這些變化時,就會感受到這些變化的重大意義。
下面我們就通過對VB.NET的代碼窗口進行研究,來領會VB.NET在編程方面的變化。
·創建一個新的Windows Application類型的應用程序。
·在Form1上添加一個新的Button控制。
·右擊Form1。
·選擇View Code菜單項。
此時屏幕上應該顯示如圖所示的Code Window(代碼窗口):
![]() 圖:Big Changes10 |
你一定會感到驚奇,代碼窗口中怎么會有這么多代碼呢?然而更令人驚奇的是其答案,這些代碼都是你添加上去的。這些代碼都是你在創建新的Windows Form時添加的,那么這些代碼的作用是什么呢?這些代碼看起來有點奇怪,但其核心的作用就是定義創建的窗體。
還記得我曾經說過VB.NET中的所有文件都有一個.vb擴展名嗎?VB.NET之所以知道它是窗體,正是由于其代碼的原因,這些代碼定義了窗體的從窗體名到其坐標,再到其中所包含的控制等方方面面。
提示:如果仔細瀏覽該窗體后的代碼,就會發現,Form1實際上是個類。從VB4開始,我們就能夠將窗體當作類來處理了,但實際上,它們從來都不是真正的類。但在VB.NET中,窗體成了真正的類,擁有Constructors和Dispose方法等VB.NET中類的所有特性。
這就是其他多余的代碼的作用了。好了,我們現在先不理這些代碼,首先來看看如何添加自己的代碼。
提示:我們可以通過在代碼的左側使用+或-號擴展或消去自己的代碼,還可以使用#Region命令定義自己的“不可見區域”。
名字空間━━最大的變化
要添加自己的代碼,需要首先回到Design視圖中。
·依次點擊View->Designer。
我們再次回到了代碼窗口,你可以發現,在VB.NET中編寫Button的代碼象在VB6中一樣地簡單,如果它有Button控制的話。呵呵,VB6中是沒有Button控制的。
·雙擊Button1。
光標應該在代碼窗口中的
| Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) |
和
| End Sub |
之間閃爍。
Button1按鈕被點擊時,在上面有二行內容之間的任何代碼都會被執行。
提示:為了能夠對Button控制或窗體的其他事件響應,應該使用代碼窗口正上方的組合框選擇類和方法的名字。當然也可以自己編寫一個單獨的子程序響應一個事件。
下面我們為Button1添加自己的代碼:
·在Button1的Click事件中添加下面的代碼:
MessageBox.Show("Hey... hehe... you clicked me and it tickles!")
·按F5鍵,對代碼進行測試。
提示:象我們以前曾提到的那樣,MessageBox.Show是VB.NET中用來顯示信息框的新方法,它取代以以前的MsgBox命令。
你可能已經聽說過VB.NET中的“名字空間”這個術語了。“名字空間”是組織函數的一種很有用的途徑。它從本質上說就是嵌入在整個.NET框架中的一組類,每種.NET編程語言都可以使用它。例如,VisualBasic名字空間中就包含有我們使用的數十個函數。
為了搞清楚我上面所說的意思,可以轉到代碼窗口,輸入Microsoft后再輸入一個.號,就會出現二種選擇:Win32和VisualBasic。如果輸入VisualBasic后再按一個.號,就會顯示出許多編輯器所知道的功能來。
因此,如果想使用象我們在VB中使用的StrReverse函數那樣的功能,則可以通過下面的代碼實現:
| MessageBox.Show(Microsoft.VisualBasic.StrReverse("Karl Moore")) |
呵,不要驚叫,它就是比我們以前使用的語句還要長,我也沒有什么辦法。下面我們來解釋一下這種結構所具有的優點,首先,它具有很好的組織性,這樣可以避免名字沖突,為使用所有的編程語言打下了良好的基礎。缺省情況下,Microsoft.VisualBasic名字空間中的所有命令都缺省導入的,這意味著我們無需再在命令前添加Microsoft.VisualBasic前綴。
提示之一:名字空間是通過在窗體或組件中指定“Imports 什么.什么”或指定工程屬性中的Imports屬性而指定的。
提示之二:不要對Imports感到迷惑。它只是使你無需輸入冗長前綴的一種方法,事實上,它與我們早已熟悉的With語句非常相似。
一定會有讀者提出來,我們不使用Microsoft.VisualBasic名字空間不就行了,這初聽起來確實是個好主意,因為沒有Microsoft.VisualBasic名字空間,我們照樣可以實現所需要的功能。但你不要忘記,名字空間不只有Microsoft.VisualBasic這一個,還有System等許多名字空間,其中包含的功能非常多。也許你會需要用到一個沒有缺省導入的名字空間的功能,這時就需要導入它或者使用一個名字空間的全路徑名。
我們什么時候需要這樣作呢?也許你在編寫圖形軟件,可能會用對System.Drawing.Graphics名字空間有興趣;如果正在處理數據庫,則可能會用到System.Data.ADO名字空間;如果你還希望使用以前版本的Visual Basic代碼,那就研究研究Microsoft.VisualBasic.Compatibility.VB6這個名字空間吧。
![]() 圖: Big Changes11 |
下面我們書歸正傳。名字空間是一種有助于在應用程序中合理安排各種類變量名字的命名方案,我們可以在程序中使用已經被缺省導入的名字空間中的命令,而無需輸入其整個前綴。
好了,我們已經講述了名字空間。照我的看法,名字空間是VB.NET與以前VB之間的最大的不同之處。名字空間是一個很奇怪的概念,有點不大好理解,我們需要在實踐中慢慢領會。
核心的變化
在編程方面,與以前的VB6相比,VB.NET有哪些變化我們需要掌握呢?
除了名字空間外,下面的變化也會對你的編程產生影響:
Long,Integer━━以前的Long型變量成了VB.NET中的Integer,而Integer則成了VB.NET中的Short,新的Long型變量的長度成了64位。
Byte,Char━━新的Byte型數據的值可以是0-255之間的一個數,新的Char類型數據占用2個字節的空間,可以是一個Unicode編碼的字符。
不再有數組━━在VB.NET中已經不再有數組了,而代之以Object數據類型,可以包含任何內容。
Currency數據類型被取代━━VB.NET中沒有了Currency數據類型,取而代之的是128位的Decimal數據類型。
變量定義━━在VB6中,Dim X, Y, Z As Integer這個語句將生成2個數組和1個整型數;而在VB.NET中,將生成三個Integer類型的數組。
0基數組━━VB.NET中的數組是從0開始的,意味著其下標將從0開始。因此,Dim MyArray(10) As Integer語句將會生成11個Integer類型的數組變量━━從0到10。
UDT的變化━━用戶自定義數據類型非常有用,在VB.NET中定義這種類型的變量時,需要使用象API那樣的關健詞結構,而不能再使用Type。下面是一個如何定義UDT類型變量的例子:
| Structure MyStructure Public Name As String Public Age As Byte End Structure |
不再支持Collection對象━━VB.NET不再支持Collection對象,它在System.Collections名字空間中提供了幾種新的集合類型━━最相近的是HashTable和ObjectList,當然了,你也可以象在下面那樣通過Compatibility名字空間使用原來的Collection對象。
| Dim MyCol As Microsoft.VisualBasic.Compatibility.VB6.Collection MyCol.Add("My Information") |
新的運算符━━VB.NET新增加了一些新的有助于減少代碼長度的算術運算符。例如,X += 4與X = X + 4是等效的。
簡化流程━━VB.NET簡化了If...Then語句中的流程。因此,如果If...Then語句有二部分,第一部分返回了“假”值,VB.NET就不會再去檢查第二部分的值了。
不再使用Set語句━━在VB6中,我們經常使用Set語句,它可以用來建立除一般的數據類型之外的對象。由于在VB.NET中,所有的數據都是對象,因此已經不再需求它了,如果你輸入了它,VB.NET會自動地把它刪除掉。
屬性定義━━VB.NET中的屬性定義已經不再需要Set和Get語句了。下面是一個新的Property過程的例子,需要注意的是Value是一個關健字,它的值就是傳遞給這一屬性的值。
| Public Property MachinePart() As String Set mstrName = Value End Set Get MachinePart = mstrName End Get End Property |
錯誤處理━━ VB.NET中,我們使用Try,Catch和Finally結構進行錯誤處理。Try模塊中的代碼是正在運行的代碼,如果有錯誤發生,Catch模塊中的代碼就會執行,Finally模塊中的代碼則一直在運行。VB編程人員會感到有點不適應,熟悉C或Java的編程人員也是如此。我建議你使用VB.NET幫助中的索引找到Error Handling(錯誤處理)部分中的Introduction to Exception Handling(意外處理介紹),找到其中的Try...Catch...Finally statement小節,測試一下其中的例子。
采用傳值方式傳遞參數━━ 缺省情況下,所有的參數的傳遞都是按值進行的。
不再支持.Show方法━━VB.NET已經不再支持簡單的Form.Show方法。由于VB.NET中的所有數據都是對象,因此,需要在首先執行Dim FormName As New Form1語句后,再執行FormName.Show。
碎片收集━━盡管碎片收集并不是編程方面的變化,但如果操作系統認為認為需要清理對象地址等時,碎片收集過程就會開始運行。因此在VB6中,如果把一個對象的值設置為Nothing,它就會立即在內存中消失。在VB.NET中就不是這樣了,在你的對象被碎片收集程序清除前,它仍然會在內存中保留一段時間。因此在類終止代碼運行后,不能認為對象已經從內存中消失了。這樣有個好處,能夠自動糾正循環調用問題。
Return關健字━━在一個函數內部,無須再把函數名設置為返回值或一個對象,可以簡單地通過Return MyData在不改變實際代碼的情況下改變函數的名字。
提示:在這里我不能一一寫出所有語法的變化,只能揀最重要的寫出來,希望能起到拋磚引玉的作用。
提示之二:值得一提的是,VB6中的許多功能在VB.NET中仍然有效,只要通過Microsoft.VisualBasic.Compatibility.VB6名字空間調用就可以了。但如果能夠使用新的方法、更一般的功能,那是最好不過的了。










