Procédure pas à pas : prise en charge de l'interopérabilité COM en affichant chaque Windows Form sur son propre thread

Mise à jour : novembre 2007

Vous pouvez résoudre les problèmes d'interopérabilité COM en affichant le formulaire dans une boucle de message .NET Framework, laquelle est créée à l'aide de la méthode Application.Run.

Pour qu'un Windows Form fonctionne correctement à partir d'une application cliente COM, vous devez l'exécuter sur une boucle de message Windows Forms. Pour cela, utilisez l'une des approches suivantes :

La procédure suivante montre comment afficher un Windows Form sur un thread distinct.

Pour copier le code dans cette rubrique sous forme de liste unique, consultez Comment : prendre en charge l'interopérabilité COM en affichant chaque Windows Form sur son propre thread.

Procédure

Placez le formulaire sur un thread distinct et appelez la méthode Application.Run pour démarrer une pompe de messages Windows Forms sur ce thread. Pour utiliser cette approche, vous devez marshaler tous les appels passés au formulaire à partir de l'application non managée en utilisant la méthode Invoke.

Cette approche requiert que chaque instance d'un formulaire s'exécute sur son propre thread en utilisant sa propre boucle de message. Plusieurs boucles de message ne peuvent pas s'exécuter par thread. Par conséquent, vous ne pouvez pas modifier la boucle de message de l'application cliente. Toutefois, vous pouvez modifier le composant .NET Framework pour démarrer un nouveau thread qui utilise sa propre boucle de message.

Pour créer chaque instance d'un Windows Form sur un nouveau thread

  1. Créez un projet Bibliothèque de classes et nommez-le COMWinform.

  2. Supprimez le fichier Class1.vb par défaut.

  3. Dans le menu Projet, cliquez sur Ajouter une classe.

  4. Sélectionnez le modèle Classe COM.

  5. Dans la zone Nom, tapez COMForm.vb, puis cliquez sur Ajouter.

  6. Collez les instructions de code suivantes au haut du fichier COMForm, avant la définition de classe.

    Imports System.Windows.Forms
    Imports System.Runtime.InteropServices
    
  7. Dans la définition de classe COMForm, collez le code suivant sous la définition de constructeur.

    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. Dans le menu Projet, cliquez sur Ajouter une classe, puis sélectionnez le modèle Classe.

  9. Dans la zone Nom, tapez FormManager.vb, puis cliquez sur Ajouter.

  10. Remplacez le contenu du fichier FormManager par le code suivant.

    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. Dans le menu Projet, cliquez sur Ajouter un formulaire Windows, puis cliquez sur Ajouter.

  12. Ajoutez des contrôles TextBox et un contrôle Button au formulaire.

  13. Double-cliquez sur Bouton1 pour ajouter un gestionnaire d'événements Click.

  14. Ajoutez le code suivant au gestionnaire d'événements 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. Générez la solution.

    Cette étape enregistre également le projet pour COM Interop sur cet ordinateur.

Pour créer un fichier exécutable qui présente COM Interop

  1. Démarrez Microsoft Visual Basic 6.0.

  2. Créer un projet EXE standard.

  3. Dans le menu Projet, cliquez sur Références.

  4. Ajoutez une référence à la bibliothèque de types COMWinform qui a été générée lorsque vous avez conçu la solution Visual Basic 2005.

    - ou -

    Si vous ne la voyez pas dans la liste, cliquez sur Parcourir pour repérer manuellement le fichier bibliothèque de types (.tlb).

  5. Ajoutez un bouton au formulaire.

  6. Dans le menu Affichage, cliquez sur Code, puis ajoutez le code suivant au module de formulaire.

[Visual Basic]

Option Explicit

Private Sub Command1_Click()
    Dim frm As COMWinform.COMForm
    Set frm = New COMWinform.COMForm
    frm.ShowForm1
End Sub

Voir aussi

Tâches

Comment : prendre en charge COM Interop en affichant un Windows Form avec la méthode ShowDialog

Procédure pas à pas : prise en charge de l'interopérabilité COM en affichant les Windows Forms sur un thread partagé

Concepts

Exposition de composants .NET Framework à COM

Empaquetage d'un assembly pour COM

Inscription d'assemblys dans COM

Vue d'ensemble des applications Windows Forms et non managées