<address id="xpjh9"><listing id="xpjh9"><meter id="xpjh9"></meter></listing></address>

<address id="xpjh9"><address id="xpjh9"><listing id="xpjh9"></listing></address></address>
<noframes id="xpjh9">
<noframes id="xpjh9">

<address id="xpjh9"><address id="xpjh9"><listing id="xpjh9"></listing></address></address>
    <form id="xpjh9"></form><address id="xpjh9"><listing id="xpjh9"><menuitem id="xpjh9"></menuitem></listing></address>

      <noframes id="xpjh9">
      VB.net 2010 視頻教程 VB.net 2010 視頻教程 VB.net 2010 視頻教程
      SQL Server 2008 視頻教程 c#入門經典教程 Visual Basic從門到精通視頻教程
      當前位置:
      首頁 > 編程開發 > VBnet >
      • vb.net教程之VB.NET中的多窗體編程:升級到 .NET

      • 2017-06-07 13:35 來源:未知
      王凌峰 編譯 

      前言 
      在微軟 Visual Basic 6.0 中,一條簡單的 “Form2.Show” 語句就能顯示項目中的第二窗體 (Form2)。然而,它在 Visaul Basic .NET 中卻行不通了,因為 .NET 版在窗體處理機制上有了很大的變化。剛剛轉向 .NET 版的 Visaul Basic 程序員實在難以接受這么大的變化,因為現在連“顯示第二窗體”這么簡單的任務都無從下手。我希望能夠通過本文向大家介紹 Visaul Basic .NET 與早期的 Visual Basic 在窗體處理機制上有哪些不同之處,以及如何按照 .NET 的模式進行多窗體編程。 
      Visual Basic 6.0 對 Visual Basic .NET 
      窗體(窗體類)正如其它類一樣,無論在哪個版本的 Visual Basic 中都是必不可少的。窗體也有屬性、方法和事件,且在同一個項目中也允許創建多個窗體實例 (參見 http://msdn.microsoft.com/library/en-us/off2000/html/defInstance.asp)。例如:假設你在 Visual Basic 6.0 項目中定義了一個窗體 Form2 ,則你可以創建它的 3 個實例并同時顯示出來。代碼如下: 
      Dim myFirstForm As Form2 
      Dim mySecondForm As Form2 
      Dim myThirdForm As Form2 

      Set myFirstForm = New Form2 
      Set mySecondForm = New Form2 
      Set myThirdForm = New Form2 

      myFirstForm.Show 
      mySecondForm.Show 
      myThirdForm.Show 
      以上代碼用 3 條 Set 語句生成了 3 個 Form2 實例。你可以把它原封不動地搬到 Visual Basic .NET 中運行,它照樣能夠正確顯示 3 個 Form2 窗體。在這里,“Form2” 其實相當于一個普通的類。Visual Basic 6.0 允許代碼直接訪問尚未實例化的窗體類;然而Visual Basic .NET 卻規定在訪問任何類之前都要進行實例化,而且必須借助實例來訪問類。這種變化當然有可能造成許多疑惑。Visual Basic 6.0 等早期版本能自動生成每個窗體的默認實例,從而允許直接通過窗體名稱來訪問窗體。例如:在 Visual Basic 6.0 項目中,可以直接用代碼 “Form2.Show” 顯示 Form2 的默認實例;然而在 Visual Basic .NET 中,這么做只會引發錯誤,因為 Visual Basic .NET 既不會創建默認的窗體實例,也不允許直接訪問尚未實例化的窗體類。 
      這就是 Visual Basic .NET 與早期 Visual Basic 在窗體處理機制上的關鍵區別——你只有先創建窗體實例,然后才可以顯示窗體外觀、訪問窗體屬性及其控件。它們還有另一個區別:Visual Basic 6.0 項目自動創建的默認窗體實例都能被當成全局變量使用,也就是說,項目中的任何代碼都能直接引用窗體,并且每次被引用的都是該窗體的同一個實例。例如:你可以在窗體中 button 控件的 Click 事件處理程序里用代碼 “Form2.Show” 顯示 Form2 窗體,然后用下列代碼改變 Form2 中某個 textbox 控件 (TextBox1)的內容: 
      Form2.TextBox1.Text = "Fred" 
      可是,你在 Visual Basic .NET 中運行它卻會得到一條錯誤消息:“Reference to a Non-Shared Member Requires an Object Reference”(引用非共享類成員必須使用對象指針)。這是在提醒你:你正在訪問的類尚未進行實例化。有一個簡便的解決方案:當你在調試過程中得到上述錯誤消息時,就把相應的語句: 
      Form2.Show() 
      改成: 
      Dim myForm2 As New Form2() 
      myForm2.Show() 
      此方案適用于大多數場合。然而,當項目中還有其它代碼訪問同一個 Form2 實例 (比如改變其中 TextBox1 的文本) 時,你可能會考慮把下列語句: 
      Form2.TextBox1.Text = "Fred" 
      改成: 
      Dim myForm2 As New Form2() 
      myForm2.TextBox1.Text = "Fred" 
      不幸的是,這段代碼創建了一個新的 Form2 實例,結果你所訪問的窗體不再是原先的 Form2 ,這豈不麻煩了!更壞的是,你不會因此而得到任何錯誤消息提示,同時你先前調用 Show() 顯示的 Form2 窗體也不會發生任何變化。 
      升級向導如何解決它 
      如果你用升級向導 (Upgrade Wizard) 把 Visual Basic 6.0 項目升級為 Visual Basic .NET 版,則它會在每個窗體中自動添加一段特殊代碼,通過顯式創建窗體實例來模擬早期 Visual Basic 版本中的默認實例化機制。此段代碼被包裹于標號為 “Upgrade Support”的代碼區塊內,借助一個新增的 Shared 屬性來生成當前窗體的實例: 
      Private Shared m_vb6FormDefInstance As Form1 
      Private Shared m_InitializingDefInstance As Boolean 
      Public Shared Property DefInstance() As Form1 
      Get 
      If m_vb6FormDefInstance Is Nothing _ 
      OrElse m_vb6FormDefInstance.IsDisposed Then 
      m_InitializingDefInstance = True 
      m_vb6FormDefInstance = New Form1() 
      m_InitializingDefInstance = False 
      End If 
      DefInstance = m_vb6FormDefInstance 
      End Get 
      Set(ByVal Value As Form1) 
      m_vb6FormDefInstance = Value 
      End Set 
      End Property 
      代碼中的 DefInstance 是一個 Shared 屬性,它能以 “窗體名.DefInstance” 的形式直接訪問。它所在項目中的任何代碼訪問它都將得到同一個窗體實例。這樣,你就能模擬 Visual Basic 6.0 項目對窗體的直接引用了,只不過在代碼中以 “Form2.DefInstance” 代替 “Form2” 而已。
      這時,你只需用 Form2.DefInstance.Show() 和Form2.DefInstance.TextBox1.Text = "Fred" 分別替換原先對 Form2 相應的直接引用就大功告成了。假如你不用升級向導,而是在 Visual Basic .NET 窗體中手工插入上述代碼 (以及升級向導在窗體的 New過程中自動添加的代碼),也行。當然了,你并不一定非要修改窗體代碼,因為有一種編程模式可以在 .NET 項目中模擬默認窗體實例的創建。本文將用余下的篇幅來介紹這種編程模式。 
      .NET 窗體之間的交互 
      在 Visual Basic 6.0 等早期版本中,多個窗體之間的交互通常需要借助默認窗體實例來完成。下面我將結合某些具體的編程任務來講解如何在 .NET 下實現多窗體交互,希望它能對你的開發任務有所幫助。 
      保持窗體引用的全局性 
      前面提到,進行 .NET 窗體編程時應該牢牢把握下列原則:在訪問窗體之前,你必須進行窗體實例化;如果在項目中有多處代碼訪問同一窗體,則你必須把它的同一實例指針傳遞給這些代碼。對于早已習慣了直接把默認窗體實例當成全局變量來使用的 Visual Basic 6.0 程序員來說,這可是個嚴重的挑戰。好在 .NET 為你提供了兩條出路:其一,把窗體實例指針保存在全局變量中;其二,把窗體實例指針傳遞給任何需要訪問它的窗體、類、模塊或者過程。 
      .NET 中的數值全局化 
      我以前曾經指出,Visual Basic .NET 不支持全局變量,現在我又要說,在 .NET 中可以在某種程度上實現數值全局化。這算不算此一時,彼一時?不,我不是那種人。Visual Basic .NET 確實不支持全局變量,然而它借助 Shared (相當于 C# 中的 static) 變量卻能模擬全局變量。事實上,前面介紹的 Visual Basic 升級向導自動添加到窗體代碼中的 DefInstance 屬性就是 Shared 類成員。無論容納 DefInstance 屬性的窗體類是否已經實例化,它都能被項目中的任何代碼所引用。象這樣的 Shared 屬性不就相當于全局變量嗎?因此,你可以創建這樣的類: 
      Public Class myForms 
      Private Shared m_CustomerForm As CustomerForm 
      Public Shared Property CustomerForm() As CustomerForm 
      Get 
      Return m_CustomerForm 
      End Get 
      Set(ByVal Value As CustomerForm) 
      m_CustomerForm = Value 
      End Set 
      End Property 
      End Class 
      你需要在首次實例化一個窗體時,把該窗體的實例保存到一個類中: 
      Dim myNewCust As New CustomerForm() 
      myNewCust.Show() 
      myForms.CustomerForm = myNewCust 
      這里的 CustomerForm 屬性值就是你的窗體實例。于是,其它代碼就能從項目的任何地方通過它來間接訪問你的窗體了: 
      Module DoingStuffWithForms 
      Sub DoExcitingThings() 
      myForms.CustomerForm.Text = _ 
      DateTime.Now().ToLongTimeString 
      End Sub 
      End Module 
      象這樣把窗體實例保存為屬性值就能按照你的要求模擬 Visual Basic 6.0 中的全局變量。如此模擬的“全局變量”其作用域比類域 (class scope) 高一個層次。所謂類域,是指變量僅僅在定義它的類(確切地說,應該包括模塊、類或窗體)中有效。比類域還低一層次的是過程域 (procedure scope),即變量僅僅在定義它的例程中有效。 
      窗體指針在項目中的傳遞 
      除了把窗體實例全局化以外,你還可以把窗體類指針保存在變量中傳遞給需要訪問該窗體的例程。假設你有一個窗體 Form1,并希望在點擊 Form1 中某個按鈕 (Button1) 時打開另第二窗體 Form2 ,然后在點擊第二窗體 Form2 中的另一個按鈕 (Button2) 時進行某項計算。你可以把整個代碼都寫在 Form1 中,即: 
      Public Class Form1 
      Inherits System.Windows.Forms.Form 
      Dim myForm2 As Form2 

      Private Sub Button1_Click(ByVal sender As System.Object, _ 
      ByVal e As System.EventArgs) Handles Button1.Click 
      myForm2 = New Form2() 
      myForm2.Show() 
      End Sub 

      Private Sub Button2_Click(ByVal sender As System.Object, _ 
      ByVal e As System.EventArgs) Handles Button2.Click 
      Calculations.CompoundInterestCalc(myForm2) 
      End Sub 
      End Class 
      無論是把窗體指針全局化,還是把它以參數的形式傳遞,都是可行的。然而,你必須根據項目的需要選擇最佳方案。當 .NET 項目中只有少數幾個過程需要訪問特定窗體時,我建議你給這些過程增加一個參數,以在必要時接受窗體指針。當你的項目有太多過程需要訪問該窗體時,你就應該考慮設置一個全局窗體指針變量。當然了,你最好還是考慮調整項目代碼結構,使得真正訪問該窗體的類或者過程只有一個。如果你希望用窗體來顯示登錄信息,則你可以先創建一個類,把窗體實例保存為它的 Shared 類成員,然后添加一個 Shared 方法 WriteToLogWindow 來完成實際的窗體訪問。于是,項目中的任何代碼只需調用此 WriteToLogWindow 方法就能間接訪問顯示登錄信息的窗體了: 
      Public Class Log 
      Private Shared m_LogForm As Form2 
      Public Shared Property LogForm() As Form2 
      Get 
      Return m_LogForm 
      End Get 
      Set(ByVal Value As Form2) 
      m_LogForm = Value 
      End Set 
      End Property 

      Public Shared Sub WriteToLogWindow(ByVal Message As String) 
      Dim sb As New _ 
      StringBuilder(m_LogForm.txtLogInfo.Text) 
      sb.Append(Environment.NewLine) 
      sb.Append(Message) 
      m_LogForm.txtLogInfo.Text = sb.ToString() 
      End Sub 
      End Class 
      讀取和改變窗體內的信息 
      到現在為止,我們討論的只是如何創建和訪問窗體實例,而沒有涉及如何讀取或改變窗體內的信息。如果你的窗體已經按照前述方法實例化,并且訪問窗體的代碼都位于窗體所在的項目中,則你可以直接操作窗體中的任何控件來讀取和改變窗體內的信息。但我覺得這樣并不理想。與其直接訪問窗體中的文本框、按鈕等控件,還不如增加一個 Public 屬性,通過它來控制窗體中的控件。如果你有意嘗試這種特殊的窗體訪問方式,請跟我來: 
      在 Visual Basic .NET 中新建一個 Windows 應用程序項目。 
      此時項目中已經自動生成了一個窗體 Form1 。現在添加另一個窗體 Form2 :在“解決方案資源管理器”中按右鍵單擊項目名稱 -> “添加” -> “添加 Windows 窗體” -> 點擊“打開”以接受默認名稱 Form2.vb 。 
      在 Form1 中添加兩個按鈕,分別按照默認值命名為 Button1 和 Button2 ,并且調整它們在窗體中的位置以免重疊。 
      在 Form2 中添加一個簡單文本框,按照默認值命名為 TextBox1 
      把下列代碼添加到 Form2 的“End Class”前面 (在“解決方案資源管理器”中按右鍵單擊 “Form2”-> “查看代碼”,再粘貼下列代碼): 
      Public Property CustomerName() As String 
      Get 
      Return TextBox1.Text 
      End Get 
      Set(ByVal Value As String) 
      TextBox1.Text = Value 
      End Set 
      End Property 
      接下來要做的是: 
      a. 切換到 Form1 的代碼,在 “Inherits System.Windows.Forms.Form” 后面增加一行: 
      Dim myForm2 As New Form2() 
      b. 在 Form1 中雙擊Button1 按鈕,在它的 Click 事件處理程序代碼中輸入下列代碼: 
      myForm2.CustomerName = "Fred" 
      myForm2.Show() 
      c. 在 Form1 中雙擊Button2 按鈕,在它的 Click 事件處理程序代碼中輸入下列代碼: 
      MessageBox.Show(myForm2.CustomerName) 
      myForm2.CustomerName = "Joe" 
      d. 按 F5 運行項目,并點擊窗體中的 Button1 和 Button2 按鈕,以觀察代碼運行情況。 
      表面看來,通過 CustomerName 屬性來訪問 Form2 與直接訪問 Form2 非常相似。然而,這種間接的窗體訪問方式能夠帶來很多好處,其中最重要的一點就在于它實現了更高的抽象性。換言之,哪怕你不知道 Form2 中控件的任何細節 (比如:窗體中是否包含 textbox 控件) ,也能與 Form2 交換數據;你所要做的只是讀取或設置 CustomerName 屬性值而已。有了這種抽象,你就能在修改 Form2 的實現時不影響項目中的其它代碼,因而大大簡化了整個項目代碼的維護。單從本文的例子來看,這種基于屬性的窗體編程模式似乎并不比常規方式簡單。然而,它以屬性的形式隱藏了窗體的全部細節,故能用簡潔、一致的代碼來訪問窗體。所以,它在一些相當復雜的用戶界面編程中能夠大顯身手。總而言之,通過屬性值來訪問窗體及其控件的編程模式雖然不太直觀,卻對程序員很有價值:它不但比直接訪問窗體的編程模式來得更專業,而且讓整個項目的代碼清晰易讀。 
      結論 
      Visual Basic .NET 取消了早期版本中的“默認窗體實例”,卻引起了不少 .NET 編程新手的困惑。Visual Basic .NET 規定,只有通過引用窗體實例,才能訪問窗體的屬性、方法及其控件。你所保存的窗體實例指針應該盡量讓整個項目都能直接訪問到它。Visual Basic .NET 的窗體處理機制已經變得更合理、更強大,可對于剛接觸 .NET 的程序員來說,它的改進偏偏是造成許多困惑的根源。

      本欄文章均來自于互聯網,版權歸原作者和各發布網站所有,本站收集這些文章僅供學習參考之用。任何人都不能將這些文章用于商業或者其他目的。

      相關教程
      江苏快3 玉树 | 南阳 | 内蒙古呼和浩特 | 揭阳 | 扬中 | 龙口 | 宝应县 | 开封 | 澄迈 | 固原 | 肇庆 | 濮阳 | 瓦房店 | 安康 | 如东 | 黔西南 | 莱州 | 北海 | 宁国 | 喀什 | 海西 | 迪庆 | 临猗 | 鸡西 | 陵水 | 白沙 | 泰兴 | 建湖 | 临汾 | 白沙 | 大理 | 莆田 | 仙桃 | 庆阳 | 南充 | 定州 | 石河子 | 柳州 | 临沧 | 莱芜 | 玉环 | 安岳 | 大连 | 吴忠 | 牡丹江 | 潍坊 | 青海西宁 | 广州 | 石河子 | 六安 | 丽江 | 郴州 | 鞍山 | 高密 | 平顶山 | 伊犁 | 寿光 | 河北石家庄 | 诸城 | 福建福州 | 泰安 | 台南 | 泰安 | 阳春 | 黑龙江哈尔滨 | 永康 | 南京 | 武威 | 广汉 | 宝应县 | 巴彦淖尔市 | 张家口 | 塔城 | 任丘 | 抚顺 | 汉中 | 果洛 | 铜川 | 黑河 | 南充 | 昭通 | 萍乡 | 保山 | 海西 | 安康 | 资阳 | 酒泉 | 莆田 | 辽源 | 黔南 | 阿克苏 | 信阳 | 泗洪 | 青海西宁 | 洛阳 | 东海 | 东营 | 河南郑州 | 莒县 | 毕节 | 新乡 | 义乌 | 毕节 | 哈密 | 宿州 | 陕西西安 | 单县 | 河源 | 南京 | 金华 | 昆山 | 姜堰 | 黄石 |