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:
Utilice el método Form.ShowDialog para mostrar el formulario Windows Forms. Para obtener más información, vea Cómo: Admitir la interoperabilidad COM al mostrar un formulario Windows Forms con el método ShowDialog.
Muestre cada formulario Windows Forms en un subproceso independiente. Para obtener más información, vea Tutorial: Admitir la interoperabilidad COM al mostrar cada formulario Windows Forms en su propio subproceso.
Cree un bucle de mensajes compartido en un nuevo subproceso del componente .NET Framework.
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
Cree un nuevo proyecto de bibliotecas de clase y denomínelo COMWinform.
Elimine el archivo Class1.vb predeterminado.
En el menú Proyecto, haga clic en Agregar clase.
Seleccione la plantilla Clase COM.
En el cuadro Nombre, escriba COMForm.vb y, a continuación, haga clic en Agregar.
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
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
En el menú Proyecto, haga clic en Agregar clase y seleccione la plantilla Clase.
En el cuadro Nombre, escriba FormManager.vb y, a continuación, haga clic en Agregar.
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
En el menú Proyecto, haga clic en Agregar Windows Forms y haga clic en Agregar.
Agregue algunos controles TextBox y un control Button al formulario.
Haga doble clic en Button1 para agregar un controlador de eventos Click.
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
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
Inicie Microsoft Visual Basic 6.0.
Cree un nuevo proyecto EXE estándar.
En el menú Proyecto, haga clic en Referencias.
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).
Agregue un botón al formulario.
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
En el menú Archivo, haga clic en Generar EXE para compilar el proyecto.
Ejecute el archivo ejecutable de Visual Basic 6.0 compilado.
Haga clic en el botón para mostrar el formulario Windows Forms de la biblioteca de clases que creó previamente.
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
Conceptos
Exponer componentes de .NET Framework en COM
Empaquetar un ensamblado para COM
Información general sobre formularios Windows Forms y aplicaciones no administradas