Procedura dettagliata: supporto dell'interoperabilità COM mediante la visualizzazione di ogni Windows Form nel relativo thread

È possibile risolvere i problemi di interoperabilità COM visualizzando il form in un ciclo di messaggi .NET Framework, creato utilizzando il metodo Application.Run.

Perché un Windows Form funzioni correttamente da un'applicazione client COM, è necessario eseguirlo in un ciclo di messaggi Windows Form. Per eseguire questa operazione, adottare uno degli approcci seguenti:

Nella procedura riportata di seguito viene descritto come visualizzare un Windows Form in un thread separato.

Per copiare il codice nell'argomento corrente come un elenco singolo, vedere Procedura: supportare l'interoperabilità COM mediante la visualizzazione di ogni Windows Form nel relativo thread.

Procedura

Inserire il form in un thread separato e chiamare il metodo Application.Run per avviare un message pump di Windows Form su tale thread. Per utilizzare questo approccio, è necessario effettuare il marshalling di tutte le chiamate al form dall'applicazione non gestita utilizzando il metodo Invoke.

Per questo approccio è necessario che ciascuna istanza di un form venga eseguita nel proprio thread tramite un proprio ciclo di messaggi. Non è possibile eseguire più di un ciclo di messaggi per thread. Di conseguenza, non è possibile modificare il ciclo di messaggi dell'applicazione client. È tuttavia possibile modificare il componente .NET Framework per l'avvio di un nuovo thread che utilizza il corrispondente ciclo di messaggi.

Per creare ciascuna istanza di un Windows Form in un nuovo thread

  1. Creare un nuovo progetto Libreria di classi e denominarlo COMWinform.

  2. Eliminare il file Class1.vb predefinito.

  3. Scegliere Aggiungi classe dal menu Progetto.

  4. Selezionare il modello Classe COM.

  5. Digitare COMForm.vb nella casella Nome, quindi fare clic su Aggiungi.

  6. Inserire le dichiarazioni di codice riportate di seguito all'inizio del file COMForm, prima della definizione della classe.

    Imports System.Windows.Forms
    Imports System.Runtime.InteropServices
    
  7. Nella definizione della classe COMForm, inserire il codice riportato di seguito dopo la definizione del costruttore.

    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. Scegliere Aggiungi classe dal menu Progetto e selezionare il modello Classe.

  9. Digitare FormManager.vb nella casella Nome, quindi fare clic su Aggiungi.

  10. Sostituire il contenuto del file FormManager con il codice riportato di seguito.

    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. Scegliere Aggiungi Windows Form dal menu Progetto, quindi fare clic su Aggiungi.

  12. Aggiungere al form alcuni controlli TextBox e un controllo Button.

  13. Fare doppio clic su Button1 per aggiungere un gestore eventi Click.

  14. Aggiungere il codice seguente al gestore eventi 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. Compilare la soluzione.

    Con questo passaggio, il progetto viene anche registrato per l'interoperabilità COM sul computer.

Per creare un file eseguibile che dimostri l'interoperabilità COM

  1. Avviare Microsoft Visual Basic 6.0.

  2. Creare un nuovo progetto EXE standard.

  3. Scegliere Riferimenti dal menu Progetto.

  4. Aggiungere un riferimento alla libreria dei tipi COMWinform generata durante la compilazione della soluzione Visual Basic 2005.

    -oppure-

    Se non è presente in elenco, fare clic su Sfoglia per individuare manualmente il file della libreria dei tipi (TLB).

  5. Aggiungere un pulsante al form.

  6. Scegliere Codice dal menu Visualizza e aggiungere il codice seguente al modulo del form.

[Visual Basic]

Option Explicit

Private Sub Command1_Click()
    Dim frm As COMWinform.COMForm
    Set frm = New COMWinform.COMForm
    frm.ShowForm1
End Sub
  1. Scegliere Make.EXE dal menu File per compilare il progetto.

  2. Eseguire il file eseguibile di Visual Basic 6.0 compilato.

  3. Fare clic sul pulsante per visualizzare Windows Form dalla libreria di classi creata precedentemente.

  4. Impostare lo stato attivo su uno dei controlli TextBox in Windows Form, quindi premere il tasto TAB per spostarsi tra i controlli.

    Notare che il tasto TAB sposta lo stato attivo da un controllo all'altro. Inoltre l'evento Click del pulsante viene generato quando si preme INVIO.

Vedere anche

Attività

Procedura: supportare l'interoperabilità COM visualizzando un Windows Form con il metodo ShowDialog

Concetti

Esposizione di componenti .NET Framework a COM

Preparazione di un assembly per COM

Registrazione di assembly presso COM

Cenni preliminari su Windows Form e applicazioni non gestite