チュートリアル : Windows フォームを別個のスレッドに表示することによって COM 相互運用をサポートする
更新 : 2007 年 11 月
COM 相互運用機能に関する問題は、フォームを .NET Framework メッセージ ループに表示することで解決できます。このメッセージ ループは、Application.Run メソッドを使って作成します。
COM クライアント アプリケーションから Windows フォームを正しく動作させるには、フォームを Windows フォーム メッセージ ループで実行する必要があります。この場合、次のいずれかの方法を使用します。
Form.ShowDialog メソッドを使って、Windows フォームを表示する。詳細については、「方法 : ShowDialog メソッドで Windows フォームを表示して COM 相互運用機能をサポートする」を参照してください。
各 Windows フォームを別個のスレッドに表示する。
共有メッセージ ループを .NET Framework コンポーネントの新しいスレッドに作成する。詳細については、「チュートリアル : Windows フォームを共有スレッドに表示することによって COM 相互運用をサポートする」を参照してください。
次のプロシージャは、Windows フォームを別個のスレッドに表示する方法を示しています。
このトピックのコードを単一のリストとしてコピーするには、「方法 : 独自のスレッドで各 Windows フォームを表示して COM 相互運用機能をサポートする」を参照してください。
手順
フォームを別個のスレッドに配置し、Application.Run メソッドを呼び出すと、Windows フォーム メッセージ ポンプがそのスレッドで開始されます。この方法を使うには、Invoke メソッドを使って、アンマネージ アプリケーションからフォームへのすべての呼び出しをマーシャリングする必要があります。
この方法を使う場合、フォームの各インスタンスが個別のメッセージ ループを使って個別のスレッドで動作する必要があります。1 つのスレッドで複数のメッセージ ループを使うことはできません。したがって、クライアント アプリケーションのメッセージ ループは変更できません。ただし、.NET Framework コンポーネントを変更して、別個のメッセージ ループを使う新しいスレッドを開始することはできます。
Windows フォームの各インスタンスを新しいスレッドに作成するには
新しいクラス ライブラリ プロジェクトを作成して、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 フォームの追加] をクリックします。次に、[追加] をクリックします。
[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 相互運用機能に登録します。
COM 相互運用機能を使用する実行可能ファイルを作成するには
Microsoft Visual Basic 6.0 を起動します。
新しい標準 EXE プロジェクトを作成します。
[プロジェクト] メニューの [参照設定] をクリックします。
Visual Basic 2005 ソリューションの生成時に作成された COMWinform タイプ ライブラリへの参照を追加します。
または
このタイプ ライブラリが一覧に表示されていない場合は、[参照] をクリックしてタイプ ライブラリ (.tlb) ファイルを手動で見つけます。
フォームにボタンを追加します。
[表示] メニューの [コード] をクリックし、以下のコードをフォーム モジュールに追加します。
[Visual Basic]
Option Explicit
Private Sub Command1_Click()
Dim frm As COMWinform.COMForm
Set frm = New COMWinform.COMForm
frm.ShowForm1
End Sub
参照
処理手順
方法 : ShowDialog メソッドで Windows フォームを表示して COM 相互運用機能をサポートする
チュートリアル : Windows フォームを共有スレッドに表示することによって COM 相互運用をサポートする