Compartir a través de


Tutorial: Admitir la interoperabilidad COM al mostrar cada formulario Windows Forms en su propio subproceso

Puede resolver problemas de interoperabilidad COM mostrando el formulario en un bucle de mensajes de .NET Framework, que puede crear utilizando el método Application.Run.

Para que un formulario Windows Forms funcione correctamente desde una aplicación cliente COM, debe ejecutarlo en un bucle de mensajes de formularios Windows Forms. Para ello, utilice uno de los enfoques siguientes:

El procedimiento siguiente muestra cómo presentar un formulario Windows Forms en un subproceso independiente.

Para copiar el código de este tema como un listado sencillo, vea Cómo: Admitir la interoperabilidad COM al mostrar cada formulario Windows Forms en su propio subproceso.

Procedimiento

Coloque el formulario en un subproceso independiente y llame al método Application.Run para iniciar el suministro de mensajes de formularios Windows Forms en ese subproceso. Para utilizar este enfoque, debe calcular referencias de cualquier llamada al formulario desde la aplicación no administrada utilizando el método Invoke.

Este enfoque requiere que cada instancia de un formulario se ejecute en su propio subproceso utilizando su propio bucle de mensajes. No puede tener más de un bucle de mensajes en ejecución por subproceso. Por consiguiente, no puede cambiar el bucle de mensajes de la aplicación cliente. Sin embargo, puede modificar el componente .NET Framework para iniciar un nuevo subproceso que utiliza su propio bucle de mensajes.

Para crear cada instancia de un formulario Windows Forms en un nuevo subproceso

  1. Cree un nuevo proyecto de bibliotecas de clase y denomínelo COMWinform.

  2. Elimine el archivo Class1.vb predeterminado.

  3. En el menú Proyecto, haga clic en Agregar clase.

  4. Seleccione la plantilla Clase COM.

  5. En el cuadro Nombre, escriba COMForm.vb y, a continuación, haga clic en Agregar.

  6. Pegue las instrucciones de código siguientes en la parte superior del archivo COMForm, antes de la definición de clase.

    Imports System.Windows.Forms
    Imports System.Runtime.InteropServices
    
  7. En la definición de clase COMForm, pegue el código siguiente bajo la definición de constructor.

    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. En el menú Proyecto, haga clic en Agregar clase y seleccione la plantilla Clase.

  9. En el cuadro Nombre, escriba FormManager.vb y, a continuación, haga clic en Agregar.

  10. Reemplace el contenido del archivo FormManager con el código siguiente:

    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. En el menú Proyecto, haga clic en Agregar Windows Forms y haga clic en Agregar.

  12. Agregue algunos controles TextBox y un control Button al formulario.

  13. Haga doble clic en Button1 para agregar un controlador de eventos Click.

  14. Agregue el código siguiente al controlador de eventos 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. Genere la solución.

    Este paso también registra el proyecto para la interoperabilidad COM en este equipo.

Para crear un archivo ejecutable que muestra la interoperabilidad COM

  1. Inicie Microsoft Visual Basic 6.0.

  2. Cree un nuevo proyecto EXE estándar.

  3. En el menú Proyecto, haga clic en Referencias.

  4. Agregue una referencia a la biblioteca de tipos COMWinform que se generó cuando generó la solución de Visual Basic 2005.

    O bien

    Si no aparece en la lista, haga clic en Examinar para buscar manualmente el archivo de biblioteca de tipos (.tlb).

  5. Agregue un botón al formulario.

  6. En el menú Ver, haga clic en Código y, a continuación, agregue el código siguiente al módulo de formulario.

[Visual Basic]

Option Explicit

Private Sub Command1_Click()
    Dim frm As COMWinform.COMForm
    Set frm = New COMWinform.COMForm
    frm.ShowForm1
End Sub
  1. En el menú Archivo, haga clic en Generar EXE para compilar el proyecto.

  2. Ejecute el archivo ejecutable de Visual Basic 6.0 compilado.

  3. Haga clic en el botón para mostrar el formulario Windows Forms de la biblioteca de clases que creó previamente.

  4. Establezca el foco en uno de los controles TextBox del formulario Windows Forms y, a continuación, presione la tecla TAB para desplazarse de un control a otro.

    Observe que la tecla TAB mueve el foco de un control a otro. Observe también que al presionar la tecla ENTRAR se provoca el evento Click del botón.

Vea también

Tareas

Cómo: Admitir la interoperabilidad COM al mostrar un formulario Windows Forms con el método ShowDialog

Conceptos

Exponer componentes de .NET Framework en COM

Empaquetar un ensamblado para COM

Registrar ensamblados con COM

Información general sobre formularios Windows Forms y aplicaciones no administradas