Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Actualización: noviembre 2007
En este tema se describe cómo implementar un bucle de mensajes para la interacción con Windows Presentation Foundation (WPF), ya sea utilizando la exposición del bucle de mensajes existente en Dispatcher, o bien creando un bucle de mensajes independiente en el lado de Win32 del código de interacción.
ComponentDispatcher y el bucle de mensajes
Un escenario normal para la interacción y la compatibilidad de eventos de teclado consiste en implementar IKeyboardInputSink, o en crear subclases de las clases que ya implementan IKeyboardInputSink, como HwndSource o HwndHost. Sin embargo, la compatibilidad con receptor de teclado no satisface todas las necesidades posibles de bucle de mensajes que puedan presentarse al enviar y recibir mensajes a través de los límites de interacción. Para ayudar a formalizar la arquitectura de bucle de mensajes de la aplicación, Windows Presentation Foundation (WPF) proporciona la clase ComponentDispatcher, que define un protocolo simple que puede seguir un bucle de mensajes.
ComponentDispatcher es una clase estática que expone varios miembros. El ámbito de cada método está asociado implícitamente al subproceso que realiza la llamada. Un bucle de mensajes debe llamar a algunas de esas API en los momentos críticos (como se define en la sección siguiente).
ComponentDispatcher proporciona eventos para los que otros componentes (como el receptor de teclado) pueden realizar escuchas. La clase Dispatcher llama a todos los métodos ComponentDispatcher adecuados en la secuencia apropiada. Si implementa su propio bucle de mensajes, el código es responsable de llamar a los métodos ComponentDispatcher de un modo similar.
Al llamar a los métodos ComponentDispatcher para un subproceso, sólo se invocarán los controladores de eventos que se registraron en ese subproceso.
Escribir bucles de mensajes
A continuación, se muestra una lista de comprobación de los miembros de ComponentDispatcher que utilizará si escribe su propio bucle de mensajes:
PushModal: el bucle de mensajes debe llamar a este método para indicar que el subproceso es modal.
PopModal: el bucle de mensajes debe llamar a este método para indicar que el subproceso ha dejado de ser modal.
RaiseIdle: el bucle de mensajes debe llamar a este método para indicar que ComponentDispatcher debe provocar el evento ThreadIdle. ComponentDispatcher no provocará el evento ThreadIdle si la propiedad IsThreadModal es true, pero los bucles de mensajes pueden optar por llamar a RaiseIdle aunque ComponentDispatcher no pueda responder mientras se encuentra en estado modal.
RaiseThreadMessage: el bucle de mensajes debe llamar a este método para indicar que hay un nuevo mensaje disponible. El valor devuelto indica si el mensaje lo administró un agente de escucha de un evento de ComponentDispatcher. Si RaiseThreadMessage devuelve true (se ha administrado), el distribuidor no debe hacer nada más con el mensaje. Si el valor devuelto es false, se espera que el distribuidor llame a la función TranslateMessage de Win32 y, a continuación, a DispatchMessage.
Utilizar ComponentDispatcher y el control de mensajes existente
A continuación, se muestra una lista de comprobación de los miembros de ComponentDispatcher que utilizará si se basa en el bucle de mensajes inherente de WPF.
IsThreadModal: devuelve si la aplicación ha pasado a ser modal (por ejemplo, se ha insertado un bucle de mensajes modal). ComponentDispatcher puede realizar el seguimiento de este estado porque la clase mantiene un recuento de llamadas del bucle de mensajes a PushModal y PopModal.
Los eventos ThreadFilterMessage y ThreadPreprocessMessage siguen las reglas estándar para las invocaciones de delegado. Se invocan todos los delegados en un orden no especificado y aunque el primero marque el mensaje como administrado.
ThreadIdle: indica un momento adecuado y eficaz para efectuar el procesamiento en inactividad (es decir, cuando no hay ningún otro mensaje pendiente para el subproceso). El evento ThreadIdle no se provoca si el subproceso es modal.
ThreadFilterMessage: se provoca para todos los mensajes procesados por el suministro de mensajes.
ThreadPreprocessMessage: se provoca para todos los mensajes que no se administraron durante el evento ThreadFilterMessage.
Un mensaje se considera administrado si, después del evento ThreadFilterMessage o ThreadPreprocessMessage, el parámetro handled pasado por referencia en los datos del evento es true. Los controladores de eventos deben omitir el mensaje si handled es true, porque esto significa que otro controlador distinto ha administrado antes el mensaje. Los controladores de ambos eventos pueden modificar el mensaje. El distribuidor debe enviar el mensaje modificado y no el mensaje original sin modificar. El evento ThreadPreprocessMessage se entrega a todos los agentes de escucha, pero la intención de la arquitectura es que sólo invoque código en respuesta al mensaje la ventana de nivel superior que contiene el indicador de ventana HWND al que están destinados los mensajes.
Cómo trata HwndSource los eventos ComponentDispatcher
Si HwndSource es una ventana de nivel superior (sin ningún HWND primario), se registrará con ComponentDispatcher. Si se provoca el evento ThreadPreprocessMessage, y si el mensaje está dirigido a HwndSource o a ventanas secundarias, HwndSource llama a su secuencia de receptor de teclado: IKeyboardInputSink.TranslateAccelerator, TranslateChar y OnMnemonic.
Si HwndSource no es una ventana de nivel superior (tiene un HWND primario), no se realizará ninguna administración. Se espera que sólo la ventana de nivel superior efectúe la administración, y que haya una ventana de nivel superior con compatibilidad con el receptor de teclado como parte de cualquier escenario de interacción.
Si se llama a WndProc para HwndSource sin haber llamado antes a un método de receptor de teclado adecuado, la aplicación recibirá los eventos de nivel de teclado más alto, como KeyDown. Sin embargo, no se llamará a ningún método de receptor de teclado, con lo que se omiten las características deseables del modelo de acciones del teclado, como la compatibilidad con las teclas de acceso. Esto puede deberse a que el bucle de mensajes no notifique correctamente al subproceso pertinente en ComponentDispatcher, o a que el HWND primario no invoque las respuestas de receptor de teclado apropiadas.
Un mensaje que va al receptor de teclado podría no enviarse al HWND si se han agregado enlaces para ese mensaje mediante el método AddHook. El mensaje podría administrarse directamente en el nivel de suministro de mensajes y no enviarse a la función DispatchMessage.
Vea también
Conceptos
Información general sobre la interoperabilidad de WPF y Win32
Información general sobre acciones del usuario