Exemplarische Vorgehensweise: Unterstützen von COM-Interop durch das Anzeigen jedes Windows Forms in einem eigenen Thread

Sie können Probleme mit der COM-Interoperabilität beheben, indem Sie das Formular in einer .NET Framework-Meldungsschleife anzeigen, die mit der Application.Run-Methode erstellt wird.

Damit ein Windows Form über eine COM-Clientanwendung ordnungsgemäß funktioniert, müssen Sie es in einer Windows Forms-Meldungsschleife ausführen. Verwenden Sie hierzu eines der folgenden Verfahren:

Durch das folgende Verfahren wird veranschaulicht, wie ein Windows Form in einem separaten Thread angezeigt wird.

Informationen zum Kopieren des in diesem Thema behandelten Codes als einzelne Auflistung finden Sie unter Gewusst wie: Unterstützen von COM-Interop durch das Anzeigen einzelner Windows Forms in einem eigenen Thread.

Prozedur

Legen Sie das Formular in einem separaten Thread ab, und rufen Sie die Application.Run-Methode auf, um ein Windows Forms-Nachrichtensystem in diesem Thread zu starten. Um diese Vorgehensweise zu verwenden, müssen Sie alle Aufrufe der nicht verwalteten Anwendung an das Formular marshallen, indem Sie die Invoke-Methode verwenden.

Dieser Ansatz setzt voraus, dass jede Instanz eines Formulars in einem eigenen Thread unter Verwendung einer eigenen Meldungsschleife ausgeführt wird. Es können nicht mehrere Meldungsschleifen pro Thread ausgeführt werden. Deshalb kann die Meldungsschleife der Clientanwendung nicht geändert werden. Sie können jedoch die .NET Framework-Komponente ändern, um einen neuen Thread zu beginnen, der eine eigene Meldungsschleife verwendet.

So erstellen Sie jede Instanz eines Windows Forms in einem neuen Thread

  1. Erstellen Sie ein neues Klassenbibliotheksprojekt, und nennen Sie es COMWinform.

  2. Löschen Sie die Class1.vb-Standarddatei.

  3. Klicken Sie im Menü Projekt auf Klasse hinzufügen.

  4. Wählen Sie die Vorlage COM-Klasse aus.

  5. Geben Sie in das Feld Name den Namen COMForm.vb ein, und klicken Sie dann auf Hinzufügen.

  6. Fügen Sie die folgenden Codeanweisungen am Anfang der Datei COMForm vor der Klassendefinition ein.

    Imports System.Windows.Forms
    Imports System.Runtime.InteropServices
    
  7. Fügen Sie den folgenden Code unter der Konstruktordefinition in der COMForm-Klassendefinition ein.

    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. Klicken Sie im Menü Projekt auf Klasse hinzufügen, und wählen Sie die Vorlage Klasse aus.

  9. Geben Sie in das Feld Name den Namen FormManager.vb ein, und klicken Sie dann auf Hinzufügen.

  10. Ersetzen Sie den Inhalt der Datei FormManager durch folgenden Code:

    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. Klicken Sie im Menü Projekt auf Windows Form hinzufügen und dann auf Hinzufügen.

  12. Fügen Sie dem Formular einige TextBox-Steuerelemente und ein Button-Steuerelement hinzu.

  13. Doppelklicken Sie auf Button1, um einen Click-Ereignishandler hinzuzufügen.

  14. Fügen Sie dem Click-Ereignishandler den folgenden Code hinzu.

    Private Sub Button1_Click( _
    ByVal sender As System.Object, _
    ByVal e As System.EventArgs) _
    Handles Button1.Click
        MessageBox.Show("Clicked button")
    End Sub
    
  15. Erstellen Sie die Projektmappe.

    Durch diesen Schritt wird das Projekt auf diesem Computer auch für COM-Interop registriert.

So erstellen Sie eine ausführbare Datei, die COM-Interop veranschaulicht

  1. Starten Sie Microsoft Visual Basic 6.0.

  2. Erstellen Sie ein neues EXE-Standardprojekt.

  3. Klicken Sie im Menü Projekt auf Verweise.

  4. Fügen Sie einen Verweis auf die COMWinform-Typbibliothek hinzu, die beim Erstellen der Visual Basic 2005-Projektmappe generiert wurde.

    - oder -

    Falls die Typbibliothek nicht in der Liste angezeigt wird, klicken Sie auf Durchsuchen, um die Datei der Typbibliothek (.tlb) manuell zu suchen.

  5. Fügen Sie dem Formular eine Schaltfläche hinzu.

  6. Klicken Sie im Menü Ansicht auf Code, und fügen Sie dem Formularmodul den folgenden Code hinzu.

[Visual Basic]

Option Explicit

Private Sub Command1_Click()
    Dim frm As COMWinform.COMForm
    Set frm = New COMWinform.COMForm
    frm.ShowForm1
End Sub
  1. Klicken Sie im Menü Datei auf EXE erstellen, um das Projekt zu kompilieren.

  2. Führen Sie die kompilierte ausführbare Visual Basic 6.0-Datei aus.

  3. Klicken Sie auf die Schaltfläche, um das Windows Form aus der Klassenbibliothek anzuzeigen, das Sie früher erstellt haben.

  4. Legen Sie den Fokus auf eines der TextBox-Steuerelemente im Windows Form fest, und drücken Sie die TABULATORTASTE, um zwischen den Steuerelementen hin und her zu wechseln.

    Beachten Sie, dass mit der TABULATORTASTE der Fokus von Steuerelement zu Steuerelement verschoben werden kann. Beachten Sie auch, dass das Click-Ereignis der Schaltfläche ausgelöst wird, wenn Sie die EINGABETASTE drücken.

Siehe auch

Aufgaben

Gewusst wie: Unterstützen von COM-Interop durch Anzeigen eines Windows Forms mit der ShowDialog-Methode

Konzepte

Verfügbarmachen von .NET Framework-Komponenten in COM

Verpacken einer Assembly für COM

Registrieren von Assemblys mit COM

Übersicht über Windows Forms und nicht verwaltete Anwendungen