チュートリアル : Windows フォームを別個のスレッドに表示することによって COM 相互運用をサポートする
COM 相互運用機能に関する問題は、Application.Run メソッドを使って作成される .NET Framework メッセージ ループにフォームを表示することで解決できます。
COM クライアント アプリケーションから Windows フォームを正しく動作させるには、フォームを Windows フォーム メッセージ ループで実行する必要があります。 この場合、次のいずれかの方法を使用します。
Form.ShowDialog メソッドを使って、Windows フォームを表示する。 詳細については、「方法 : ShowDialog メソッドで Windows フォームを表示して COM 相互運用機能をサポートする」を参照してください。
各 Windows フォームを別個のスレッドに表示する。
次のプロシージャは、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
[ファイル] メニューの [EXE の作成] をクリックしてプロジェクトをコンパイルします。
コンパイルされた Visual Basic 6.0 実行可能ファイルを実行します。
ボタンをクリックして、前に作成したクラス ライブラリから Windows フォームを表示します。
Windows フォームの TextBox コントロールの 1 つにフォーカスを設定してから、Tab キーを押してコントロール間を移動します。
Tab キーを使用してフォーカスを別のコントロールに移動できることを確認します。 また、Enter キーを押すとボタンの Click イベントが発生することも確認します。
参照
処理手順
方法 : ShowDialog メソッドで Windows フォームを表示して COM 相互運用機能をサポートする