Compartir a través de


Tutorial: Admitir la interoperabilidad COM al mostrar formularios Windows Forms en un subproceso compartido

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 nuevo subproceso con un bucle de mensajes compartido.

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

Procedimiento

Este enfoque es similar al que se muestra en Tutorial: Admitir la interoperabilidad COM al mostrar cada formulario Windows Forms en su propio subproceso. No obstante, en lugar de mostrar cada formulario en su propio subproceso utilizando su propio bucle de mensajes, este enfoque crea un bucle de mensajes compartido que se ejecuta únicamente en un nuevo subproceso del componente .NET Framework.

Este enfoque representa con más precisión el comportamiento de una aplicación de Windows Forms estándar. Este enfoque también facilita compartir recursos entre varios formularios, porque todos los formularios se ejecutan en el mismo subproceso. La solución en Tutorial: Admitir la interoperabilidad COM al mostrar cada formulario Windows Forms en su propio subproceso crea un nuevo subproceso para cada formulario. Esa solución requiere código de sincronización de subprocesos adicional para compartir recursos entre formularios distintos.

Dado que este enfoque es más similar al comportamiento de una aplicación de Windows Forms, verá que con formularios Windows Forms de .NET Framework se abrirá la aplicación cliente cuando se detenga el bucle de mensajes de .NET Framework. Este comportamiento aparece cuando el usuario cierra el formulario que está designado como el principal de la clase ApplicationContext. Se utiliza ApplicationContext para iniciar el bucle de mensajes.

En los ejemplos de código siguientes, el formulario principal de la clase ApplicationContext se establece en el primer formulario que la aplicación cliente abre. Por consiguiente, cuando el usuario cierra esa instancia de formulario, el programa sale del bucle de mensajes de .NET Framework y se cerrarán todos los demás formularios Windows Forms.

Para crear un bucle de mensajes compartido en un nuevo subproceso con el fin de que todos los formularios lo utilicen

  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.

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

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

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