次の方法で共有


チュートリアル : Windows フォームを別個のスレッドに表示することによって COM 相互運用をサポートする

COM 相互運用機能に関する問題は、Application.Run メソッドを使って作成される .NET Framework メッセージ ループにフォームを表示することで解決できます。

COM クライアント アプリケーションから Windows フォームを正しく動作させるには、フォームを Windows フォーム メッセージ ループで実行する必要があります。 この場合、次のいずれかの方法を使用します。

次のプロシージャは、Windows フォームを別個のスレッドに表示する方法を示しています。

このトピックのコードを単一のリストとしてコピーするには、「方法 : 独自のスレッドで各 Windows フォームを表示して COM 相互運用機能をサポートする」を参照してください。

手順

フォームを別個のスレッドに配置し、Application.Run メソッドを呼び出すと、Windows フォーム メッセージ ポンプがそのスレッドで開始されます。 この方法を使うには、Invoke メソッドを使って、アンマネージ アプリケーションからフォームへのすべての呼び出しをマーシャリングする必要があります。

この方法を使う場合、フォームの各インスタンスが個別のメッセージ ループを使って個別のスレッドで動作する必要があります。 1 つのスレッドで複数のメッセージ ループを使うことはできません。 したがって、クライアント アプリケーションのメッセージ ループは変更できません。 ただし、.NET Framework コンポーネントを変更して、別個のメッセージ ループを使う新しいスレッドを開始することはできます。

Windows フォームの各インスタンスを新しいスレッドに作成するには

  1. 新しいクラス ライブラリ プロジェクトを作成して、COMWinform と命名します。

  2. 既定の Class1.vb ファイルを削除します。

  3. [プロジェクト] メニューの [クラスの追加] を選択します。

  4. [COM クラス] テンプレートをクリックします。

  5. [ファイル名] ボックスに「COMForm.vb」と入力し、[追加] をクリックします。

  6. 次のコード ステートメントを、COMForm ファイルの先頭部分にあるクラス定義の前に貼り付けます。

    Imports System.Windows.Forms
    Imports System.Runtime.InteropServices
    
  7. 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
    
  8. [プロジェクト] メニューの [クラスの追加] をクリックします。次に、[クラス] テンプレートをクリックします。

  9. [ファイル名] ボックスに「FormManager.vb」と入力し、[追加] をクリックします。

  10. 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
    
  11. [プロジェクト] メニューの [Windows フォームの追加] をクリックします。次に、[追加] をクリックします。

  12. フォームに TextBox コントロールおよび Button コントロールを追加します。

  13. [Button1] をダブルクリックして Click イベント ハンドラーを追加します。

  14. Click イベント ハンドラーに次のコードを追加します。

    Private Sub Button1_Click( _
    ByVal sender As System.Object, _
    ByVal e As System.EventArgs) _
    Handles Button1.Click
        MessageBox.Show("Clicked button")
    End Sub
    
  15. ソリューションをビルドします。

    また、このステップでは、プロジェクトをこのコンピューターの COM 相互運用機能に登録します。

COM 相互運用機能を使用する実行可能ファイルを作成するには

  1. Microsoft Visual Basic 6.0 を起動します。

  2. 新しい標準 EXE プロジェクトを作成します。

  3. [プロジェクト] メニューの [参照設定] をクリックします。

  4. Visual Basic 2005 ソリューションのビルド時に生成された COMWinform タイプ ライブラリへの参照を追加します。

    または

    このタイプ ライブラリが一覧に表示されていない場合は、[参照] をクリックしてタイプ ライブラリ (.tlb) ファイルを手動で見つけます。

  5. フォームにボタンを追加します。

  6. [表示] メニューの [コード] をクリックし、以下のコードをフォーム モジュールに追加します。

[Visual Basic]

Option Explicit

Private Sub Command1_Click()
    Dim frm As COMWinform.COMForm
    Set frm = New COMWinform.COMForm
    frm.ShowForm1
End Sub
  1. [ファイル] メニューの [EXE の作成] をクリックしてプロジェクトをコンパイルします。

  2. コンパイルされた Visual Basic 6.0 実行可能ファイルを実行します。

  3. ボタンをクリックして、前に作成したクラス ライブラリから Windows フォームを表示します。

  4. Windows フォームの TextBox コントロールの 1 つにフォーカスを設定してから、Tab キーを押してコントロール間を移動します。

    Tab キーを使用してフォーカスを別のコントロールに移動できることを確認します。 また、Enter キーを押すとボタンの Click イベントが発生することも確認します。

参照

処理手順

方法 : ShowDialog メソッドで Windows フォームを表示して COM 相互運用機能をサポートする

概念

COM への .NET Framework コンポーネントの公開

COM 用のアセンブリのパッケージ化

COM へのアセンブリの登録

Windows フォームおよびアンマネージ アプリケーションの概要