逐步解說:在共用執行緒上顯示 Windows Form 以支援 COM Interop
您可以在 .NET Framework 訊息迴圈上顯示表單,藉此解決 COM 的互通性問題,此訊息迴圈則是使用 Application..::..Run 方法所建立。
若要使 Windows Form 能從 COM 用戶端應用程式正確運作,您就必須在 Windows Form 訊息迴圈中執行 Windows Form。 若要這麼做,請使用下列其中一種方法:
您可以使用 Form..::..ShowDialog 方法來顯示 Windows Form。 如需詳細資訊,請參閱 HOW TO:顯示 Windows Form 和 ShowDialog 方法以支援 COM Interop。
在個別的執行緒上顯示每一個 Windows Form。 如需詳細資訊,請參閱逐步解說:在自己的執行緒上顯示每個 Windows Form 以支援 COM Interop。
在 .NET Framework 元件中的新執行緒上建立共用的訊息迴圈。
下列程序示範如何在新的執行緒上使用共用訊息迴圈顯示 Windows Form。
若要將此主題中的程式碼複製為一份清單,請參閱 HOW TO:在共用執行緒上顯示 Windows Form 以支援 COM Interop。
程序
這個方法類似逐步解說:在自己的執行緒上顯示每個 Windows Form 以支援 COM Interop 中示範的方法。 然而,這個方法會建立只會在 .NET Framework 元件的一個新執行緒上執行的共用訊息迴圈,而不是在專屬執行緒上使用自己的訊息迴圈顯示每個表單。
這個方法能夠更精確地表示標準 Windows Form 應用程式的行為。 這個方法也能夠更輕鬆地在多個表單之間共用資源,因為所有的表單都在相同執行緒上執行。 逐步解說:在自己的執行緒上顯示每個 Windows Form 以支援 COM Interop 中的方案會為每個表單建立新的執行緒。 這個方案需要其他執行緒同步處理程式碼,以便在不同的表單之間共用資源。
因為這個方法更類似 Windows Form 應用程式的行為,所以將會在 .NET Framework 訊息迴圈停止時,關閉用戶端應用程式所開啟的 .NET Framework Windows Form。 當使用者關閉指派為 ApplicationContext 主要表單的表單時,就會發生這個行為。 ApplicationContext 是用來開始訊息迴圈的。
在下列程式碼範例中,ApplicationContext 的主要表單會設定為用戶端應用程式所開啟的第一個表單。 因此,當使用者關閉該表單執行個體時就會結束 .NET Framework 訊息迴圈,並且關閉所有其他的 Windows Form。
若要在新執行緒上建立讓所有表單使用的共用訊息迴圈
建立新的類別庫專案並命名為 COMWinform。
刪除預設的 Class1.vb 檔。
在 [專案] 功能表上按一下 [加入類別]。
選取 [COM 類別] 範本。
在 [名稱] 方塊中,輸入 COMForm.vb,然後按下 [加入]。
將下列程式碼陳述式貼在 COMForm 檔的頂層,就在類別定義之前。
Imports System.Windows.Forms Imports System.Runtime.InteropServices
在 COMForm 類別定義中,將下列程式碼貼在建構函式定義下。
Private WithEvents frmManager As FormManager Public Sub ShowForm1() ' Call the StartForm method by using a new instance ' of the Form1 class. StartForm(New Form1) End Sub Private Sub StartForm(ByVal frm As Form) ' This procedure is used to show all forms ' that the client application requests. When the first form ' is displayed, this code will create a new message ' loop that runs on a new thread. The new form will ' be treated as the main form. ' Later forms will be shown on the same message loop. If IsNothing(frmManager) Then frmManager = New FormManager(frm) Else frmManager.ShowForm(frm) End If End Sub Private Sub frmManager_MessageLoopExit() Handles frmManager.MessageLoopExit 'Release the reference to the frmManager object. frmManager = Nothing End Sub
在 [專案] 功能表上,按一下 [加入類別],然後選取 [類別] 範本。
在 [名稱] 方塊中輸入 FormManager.vb,然後按一下 [加入]。
以下列程式碼取代 FormManager 檔案的內容。
Imports System.Runtime.InteropServices Imports System.Threading Imports System.Windows.Forms <ComVisible(False)> _ Friend Class FormManager ' This class is used so that you can generically pass any ' form that you want to the delegate. Private WithEvents appContext As ApplicationContext Private Delegate Sub FormShowDelegate(ByVal form As Form) Event MessageLoopExit() Public Sub New(ByVal MainForm As Form) Dim t As Thread If IsNothing(appContext) Then appContext = New ApplicationContext(MainForm) t = New Thread(AddressOf StartMessageLoop) t.IsBackground = True t.SetApartmentState(ApartmentState.STA) t.Start() End If End Sub Private Sub StartMessageLoop() ' Call the Application.Run method to run the form on its own message loop. Application.Run(appContext) End Sub Public Sub ShowForm(ByVal form As Form) Dim formShow As FormShowDelegate ' Start the main form first. Otherwise, focus will stay on the ' calling form. appContext.MainForm.Activate() ' Create a new instance of the FormShowDelegate method, and ' then invoke the delegate off the MainForm object. formShow = New FormShowDelegate(AddressOf ShowFormOnMainForm_MessageLoop) appContext.MainForm.Invoke(formShow, New Object() {form}) End Sub Private Sub ShowFormOnMainForm_MessageLoop(ByVal form As Form) form.Show() End Sub Private Sub ac_ThreadExit(ByVal sender As Object, ByVal e As System.EventArgs) Handles appContext.ThreadExit appContext.MainForm.Dispose() appContext.MainForm = Nothing appContext.Dispose() appContext = Nothing RaiseEvent MessageLoopExit() End Sub End Class
在 [專案] 功能表上,按一下 [加入 Windows Form],然後按一下 [加入]。
按兩下 [Button1] 以加入 Click 事件處理常式。
將下列程式碼加入至 Click 事件處理常式:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click MessageBox.Show("Clicked button") End Sub
建置方案。
這個步驟也會在電腦上註冊 COM Interop 的專案。
若要建立示範 COM Interop 的可執行檔
啟動 Microsoft Visual Basic 6.0。
建立新的標準 EXE 專案。
在 [專案] 功能表上,按一下 [參考]。
將參考加入當建置 Visual Basic 2005 方案時產生的 COMWinform 型別程式庫。
-或-
如果在清單中看不到這個型別程式庫,請手動按一下 [瀏覽] 以尋找型別程式庫 (.tlb) 檔案。
在表單中加入一個按鈕。
在 [檢視] 功能表上按一下 [程式碼],然後將下列程式碼加入表單模組中。
Option Explicit
Private Sub Command1_Click()
Dim frm As COMWinform.COMForm
Set frm = New COMWinform.COMForm
frm.ShowForm1
End Sub
按一下 [檔案] 功能表上的 [建立執行檔],編譯專案。
執行已編譯的 Visual Basic 6.0 可執行檔。
按一下按鈕,從您稍早建立的類別庫顯示 Windows Form。
將焦點設定在 Windows Form 上的其中一個 TextBox 控制項,然後按 TAB 鍵在各個控制項之間移動。
請注意,TAB 鍵會在控制項之間移動焦點。 此外,請注意,當您按 ENTER 鍵時會引發按鈕的 Click 事件。
請參閱
工作
HOW TO:顯示 Windows Form 和 ShowDialog 方法以支援 COM Interop
逐步解說:在自己的執行緒上顯示每個 Windows Form 以支援 COM Interop