Acerca de los mensajes y las colas de mensajes

A diferencia de las aplicaciones basadas en MS-DOS, las aplicaciones basadas en Windows están controladas por eventos. No realizan llamadas de función explícitas (como llamadas de biblioteca en tiempo de ejecución de C) para obtener la entrada. En su lugar, esperan a que el sistema pase la entrada a ellos.

El sistema pasa toda la entrada de una aplicación a las distintas ventanas de la aplicación. Cada ventana tiene una función, denominada procedimiento de ventana, que el sistema llama cada vez que tiene entrada para la ventana. El procedimiento de ventana procesa la entrada y devuelve el control al sistema. Para obtener más información sobre los procedimientos de ventana, vea Procedimientos de ventana.

Si una ventana de nivel superior deja de responder a los mensajes durante más de varios segundos, el sistema considera que la ventana no responde. En este caso, el sistema oculta la ventana y la reemplaza por una ventana fantasma que tiene el mismo orden Z, ubicación, tamaño y atributos visuales. Esto permite al usuario moverlo, cambiar su tamaño o incluso cerrar la aplicación. Sin embargo, estas son las únicas acciones disponibles porque la aplicación realmente no responde. Cuando está en el modo del depurador, el sistema no genera una ventana fantasma.

En esta sección se describen los temas siguientes:

Mensajes de Windows

El sistema pasa la entrada a un procedimiento de ventana en forma de mensaje. Tanto el sistema como las aplicaciones generan mensajes. El sistema genera un mensaje en cada evento de entrada, por ejemplo, cuando el usuario escribe, mueve el mouse o hace clic en un control como una barra de desplazamiento. El sistema también genera mensajes en respuesta a los cambios en el sistema provocados por una aplicación, como cuando una aplicación cambia el grupo de recursos de fuente del sistema o cambia el tamaño de una de sus ventanas. Una aplicación puede generar mensajes para dirigir sus propias ventanas para realizar tareas o comunicarse con ventanas en otras aplicaciones.

El sistema envía un mensaje a un procedimiento de ventana con un conjunto de cuatro parámetros: un identificador de ventana, un identificador de mensaje y dos valores denominados parámetros de mensaje. El identificador de ventana identifica la ventana para la que está previsto el mensaje. El sistema lo usa para determinar qué procedimiento de ventana debe recibir el mensaje.

Un identificador de mensaje es una constante con nombre que identifica el propósito de un mensaje. Cuando un procedimiento de ventana recibe un mensaje, usa un identificador de mensaje para determinar cómo procesar el mensaje. Por ejemplo, el identificador de mensaje WM_PAINT indica al procedimiento de ventana que el área cliente de la ventana ha cambiado y se debe volver a pintar.

Los parámetros de mensaje especifican datos o la ubicación de los datos utilizados por un procedimiento de ventana al procesar un mensaje. El significado y el valor de los parámetros del mensaje dependen del mensaje. Un parámetro de mensaje puede contener un entero, marcas de bits empaquetadas, un puntero a una estructura que contiene datos adicionales, etc. Cuando un mensaje no usa parámetros de mensaje, normalmente se establecen en NULL. Un procedimiento de ventana debe comprobar el identificador del mensaje para determinar cómo interpretar los parámetros del mensaje.

Tipos de mensajes

En esta sección se describen los dos tipos de mensajes:

mensajes de System-Defined

El sistema envía o publica un mensaje definido por el sistema cuando se comunica con una aplicación. Usa estos mensajes para controlar las operaciones de las aplicaciones y proporcionar información de entrada y otra información para que las aplicaciones se procesen. Una aplicación también puede enviar o publicar mensajes definidos por el sistema. Las aplicaciones suelen usar estos mensajes para controlar el funcionamiento de las ventanas de control creadas mediante clases de ventana registradas previamente.

Cada mensaje definido por el sistema tiene un identificador de mensaje único y una constante simbólica correspondiente (definida en los archivos de encabezado del kit de desarrollo de software (SDK) que indica el propósito del mensaje. Por ejemplo, el WM_PAINT constante solicita que una ventana pinte su contenido.

Las constantes simbólicas especifican la categoría a la que pertenecen los mensajes definidos por el sistema. El prefijo de la constante identifica el tipo de ventana que puede interpretar y procesar el mensaje. A continuación se muestran los prefijos y sus categorías de mensajes relacionadas.

Prefijo Categoría de mensaje Documentación
ABM y ABN Barra de herramientas de escritorio de la aplicación Mensajes y notificaciones de Shell
ACM y ACN Animation (control) Mensajes de control de animación y notificaciones de control de animación
BCM, BCN, BM y BN Button (control) Mensajes de controlde botón y notificaciones de control de botón
CB y CBN ComboBox (control) Mensajes de control comboBox y notificaciones de control ComboBox
CBEM y CBEN Control ComboBoxEx Mensajes ComboBoxEx y notificaciones comboBoxEx
CCM Control general Mensajes de control
CDM Cuadro de diálogo Común Mensajes comunes del cuadro de diálogo
DFM Menú contextual predeterminado Mensajes y notificaciones de Shell
DL Cuadro de lista de arrastrar Arrastrar notificaciones de cuadro de lista
DM Control de botón de inserción predeterminado Mensajes del cuadro de diálogo
DTM y DTN Control de selector de fecha y hora Mensajes del selector de fecha y hora y notificaciones del selector de fecha y hora
EM y EN Edit (control) Editar mensajes de control, editar notificaciones de control, mensajes de edición enriquecidos y notificaciones de edición enriquecidas
HDM y HDN Control de encabezado Mensajes de control de encabezado y notificaciones de control de encabezado
HKM Control de teclas activas Mensajes de control de teclas activas
IPM e IPN control de dirección IP Mensajes de dirección IP y notificaciones de dirección IP
LB y LBN Control de cuadro de lista Mensajes de cuadro delista y notificaciones de cuadro de lista
LM Control SysLink Mensajes de control SysLink
LVM y LVN Control de vista de lista Mensajes de vista de lista y notificaciones de vista de lista
MCM y MCN Control de calendario de mes Mensajes de calendario demes y notificaciones de calendario de mes
PBM Barra de progreso Mensajes de la barra de progreso
PGM y PGN Control Pager Mensajes de control de buscapersonas y notificaciones de control de buscapersonas
PSM y PSN Hoja de propiedades Mensajes de hoja de propiedades y notificaciones de hoja de propiedades
RB y RBN Control rebar Mensajes de control de barra de rebar y notificaciones de control de barras
SB y SBN Ventana de la barra de estado Mensajes de la barrade estado y notificaciones de la barra de estado
SBM Scroll Bar (control) Mensajes de barra de desplazamiento
SMC Menú shell Mensajes y notificaciones de Shell
STM y STN Control estático Mensajes de control estáticos y notificaciones de control estático
TB y TBN Barra de herramientas Mensajes de control de la barra de herramientas y notificaciones de control de barra de herramientas
TBM y TRBN Control de barra de seguimiento Mensajes de control de la barra de seguimiento y notificaciones de control de barra de seguimiento
TCM y TCN Control Tab Tab Control Messages and Tab Control Notifications
TDM y TDN Cuadro de diálogo tarea Mensajes de cuadro de diálogo de tareas y notificaciones del cuadro de diálogo de tareas
TTM y TTN Control de información sobre herramientas Mensajes de control de información sobreherramientas y notificaciones de control de información sobre herramientas
TVM y TVN Control de vista de árbol Mensajes de vista de árbol y notificaciones de vista de árbol
UDM y UDN Control arriba hacia abajo Mensajes ascendentes y notificaciones hacia abajo
WM General
Mensajes del Portapapeles
Notificaciones del Portapapeles
Notificaciones comunes del cuadro de diálogo
Notificaciones de cursor
Mensaje de copia de datos
Mensajes del Administrador de ventanas de escritorio
mensajes de Administración de dispositivos
Notificaciones del cuadro de diálogo
Mensajes dinámicos de intercambio de datos
Notificaciones dinámicas de intercambio de datos
Notificaciones de enlace
Mensajes del acelerador de teclado
Notificaciones del acelerador de teclado
Mensajes de entrada de teclado
Notificaciones de entrada de teclado
Notificaciones de menú
Notificaciones de entrada del mouse
Varios mensajes de interfaz de documento
Notificaciones de entrada sin procesar
Notificaciones de barra de desplazamiento
Notificaciones del temporizador
Mensajes de ventana
Notificaciones de ventana

Los mensajes generales de ventana cubren una amplia gama de información y solicitudes, incluidos los mensajes para la entrada del mouse y el teclado, la entrada de menús y el cuadro de diálogo, la creación y administración de ventanas y el intercambio dinámico de datos (DDE).

mensajes de Application-Defined

Una aplicación puede crear mensajes para que los usen sus propias ventanas o para comunicarse con las ventanas de otros procesos. Si una aplicación crea sus propios mensajes, el procedimiento de ventana que los recibe debe interpretar los mensajes y proporcionar el procesamiento adecuado.

Los valores de identificador de mensaje se usan de la siguiente manera:

  • El sistema reserva valores de identificador de mensaje en el intervalo 0x0000 a través de 0x03FF (el valor de WM_USER – 1) para los mensajes definidos por el sistema. Las aplicaciones no pueden usar estos valores para los mensajes privados.
  • Los valores del intervalo 0x0400 (el valor de WM_USER) a través de 0x7FFF están disponibles para los identificadores de mensaje para las clases de ventana privada.
  • Si la aplicación está marcada con la versión 4.0, puede usar valores de identificador de mensaje en el intervalo 0x8000 (WM_APP) a través de 0xBFFF para mensajes privados.
  • El sistema devuelve un identificador de mensaje en el intervalo 0xC000 a través de 0xFFFF cuando una aplicación llama a la función RegisterWindowMessage para registrar un mensaje. Se garantiza que el identificador de mensaje devuelto por esta función es único en todo el sistema. El uso de esta función evita conflictos que pueden surgir si otras aplicaciones usan el mismo identificador de mensaje con fines diferentes.

Enrutamiento de mensajes

El sistema usa dos métodos para enrutar los mensajes a un procedimiento de ventana: publicar mensajes en una cola primero en salir denominada cola de mensajes, un objeto de memoria definido por el sistema que almacena temporalmente mensajes y envía mensajes directamente a un procedimiento de ventana.

Los mensajes que se publican en una cola de mensajes se denominan mensaje en cola. Estos son principalmente el resultado de la entrada del usuario introducida a través del mouse o el teclado, como WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_KEYDOWN y mensajes de WM_CHAR . Otros mensajes en cola incluyen el temporizador, la pintura y los mensajes de cierre: WM_TIMER, WM_PAINT y WM_QUIT. La mayoría de los demás mensajes, que se envían directamente a un procedimiento de ventana, se denominan mensajes no puestos en cola.

Mensajes en cola

El sistema puede mostrar cualquier número de ventanas a la vez. Para enrutar la entrada del mouse y el teclado a la ventana adecuada, el sistema usa colas de mensajes.

El sistema mantiene una sola cola de mensajes del sistema y una cola de mensajes específica del subproceso para cada subproceso de GUI. Para evitar la sobrecarga de crear una cola de mensajes para subprocesos que no son de GUI, todos los subprocesos se crean inicialmente sin una cola de mensajes. El sistema crea una cola de mensajes específica del subproceso solo cuando el subproceso realiza su primera llamada a una de las funciones de usuario específicas; ninguna llamada a función de GUI da como resultado la creación de una cola de mensajes.

Cada vez que el usuario mueve el mouse, hace clic en los botones del mouse o los tipos del teclado, el controlador del dispositivo para el mouse o el teclado convierte la entrada en mensajes y los coloca en la cola de mensajes del sistema. El sistema quita los mensajes, de uno en uno, de la cola de mensajes del sistema, los examina para determinar la ventana de destino y, a continuación, los envía a la cola de mensajes del subproceso que creó la ventana de destino. La cola de mensajes de un subproceso recibe todos los mensajes de mouse y teclado para las ventanas creadas por el subproceso. El subproceso quita los mensajes de su cola y dirige al sistema para enviarlos al procedimiento de ventana adecuado para su procesamiento.

A excepción del mensaje de WM_PAINT , el mensaje de WM_TIMER y el mensaje de WM_QUIT , el sistema siempre envía mensajes al final de una cola de mensajes. Esto garantiza que una ventana recibe sus mensajes de entrada en la secuencia correcta primero en salir (FIFO). El mensaje WM_PAINT , el mensaje WM_TIMER y el mensaje de WM_QUIT , sin embargo, se mantienen en la cola y se reenvía al procedimiento de ventana solo cuando la cola no contiene otros mensajes. Además, se combinan varios mensajes de WM_PAINT para la misma ventana en un único mensaje de WM_PAINT , consolidando todas las partes no válidas del área de cliente en una sola área. La combinación de WM_PAINT mensajes reduce el número de veces que una ventana debe volver a dibujar el contenido de su área de cliente.

El sistema envía un mensaje a la cola de mensajes de un subproceso rellenando una estructura msg y, a continuación, copiándola en la cola de mensajes. La información de MSG incluye: el identificador de la ventana para la que está previsto el mensaje, el identificador del mensaje, los dos parámetros de mensaje, la hora en que se publicó el mensaje y la posición del cursor del mouse. Un subproceso puede publicar un mensaje en su propia cola de mensajes o en la cola de otro subproceso mediante la función PostMessage o PostThreadMessage .

Una aplicación puede quitar un mensaje de su cola mediante la función GetMessage . Para examinar un mensaje sin quitarlo de su cola, una aplicación puede usar la función PeekMessage . Esta función rellena MSG con información sobre el mensaje.

Después de quitar un mensaje de su cola, una aplicación puede usar la función DispatchMessage para dirigir el sistema para enviar el mensaje a un procedimiento de ventana para su procesamiento. DispatchMessage toma un puntero a MSG rellenado por una llamada anterior a la función GetMessage o PeekMessage . DispatchMessage pasa el identificador de ventana, el identificador de mensaje y los dos parámetros de mensaje al procedimiento de ventana, pero no pasa el tiempo en que se publicó el mensaje o la posición del cursor del mouse. Una aplicación puede recuperar esta información llamando a las funciones GetMessageTime y GetMessagePos mientras procesa un mensaje.

Un subproceso puede usar la función WaitMessage para producir el control a otros subprocesos cuando no tiene mensajes en su cola de mensajes. La función suspende el subproceso y no vuelve hasta que se coloca un nuevo mensaje en la cola de mensajes del subproceso.

Puede llamar a la función SetMessageExtraInfo para asociar un valor a la cola de mensajes del subproceso actual. A continuación, llame a la función GetMessageExtraInfo para obtener el valor asociado al último mensaje recuperado por la función GetMessage o PeekMessage .

Mensajes no puestos en cola

Los mensajes no puestos en cola se envían inmediatamente al procedimiento de ventana de destino, omitiendo la cola de mensajes del sistema y la cola de mensajes de subprocesos. Normalmente, el sistema envía mensajes no puestos en cola para notificar a una ventana de eventos que lo afectan. Por ejemplo, cuando el usuario activa una nueva ventana de aplicación, el sistema envía a la ventana una serie de mensajes, incluidos WM_ACTIVATE, WM_SETFOCUS y WM_SETCURSOR. Estos mensajes notifican a la ventana que se ha activado, que la entrada del teclado se dirige a la ventana y que el cursor del mouse se ha movido dentro de los bordes de la ventana. Los mensajes no puestos en cola también pueden dar lugar cuando una aplicación llama a determinadas funciones del sistema. Por ejemplo, el sistema envía el mensaje WM_WINDOWPOSCHANGED después de que una aplicación use la función SetWindowPos para mover una ventana.

Algunas funciones que envían mensajes no puestos en cola son BroadcastSystemMessage, BroadcastSystemMessageEx, SendMessage, SendMessageTimeout y SendNotifyMessage.

Tratamiento de mensajes

Una aplicación debe quitar y procesar los mensajes publicados en las colas de mensajes de sus subprocesos. Normalmente, una aplicación de un solo subproceso usa un bucle de mensajes en su función WinMain para quitar y enviar mensajes a los procedimientos de ventana adecuados para su procesamiento. Las aplicaciones con varios subprocesos pueden incluir un bucle de mensajes en cada subproceso que crea una ventana. En las secciones siguientes se describe cómo funciona un bucle de mensajes y se explica el rol de un procedimiento de ventana:

Bucle de mensajes

Un bucle de mensajes simple consta de una llamada de función a cada una de estas tres funciones: GetMessage, TranslateMessage y DispatchMessage. Tenga en cuenta que si se produce un error, GetMessage devuelve –1, por lo tanto, la necesidad de las pruebas especiales.

MSG msg;
BOOL bRet;

while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{ 
    if (bRet == -1)
    {
        // handle the error and possibly exit
    }
    else
    {
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
    }
}

La función GetMessage recupera un mensaje de la cola y lo copia en una estructura de tipo MSG. Devuelve un valor distinto de cero, a menos que encuentre el mensaje WM_QUIT , en cuyo caso devuelve FALSE y finaliza el bucle. En una aplicación de un solo subproceso, finalizar el bucle de mensajes suele ser el primer paso para cerrar la aplicación. Una aplicación puede finalizar su propio bucle mediante la función PostQuitMessage , normalmente en respuesta al mensaje WM_DESTROY en el procedimiento de ventana de la ventana principal de la aplicación.

Si especifica un identificador de ventana como el segundo parámetro de GetMessage, solo se recuperan los mensajes de la ventana especificada de la cola. GetMessage también puede filtrar los mensajes de la cola, recuperando solo los mensajes que se encuentran dentro de un intervalo especificado. Para obtener más información sobre el filtrado de mensajes, vea Filtrado de mensajes.

El bucle de mensajes de un subproceso debe incluir TranslateMessage si el subproceso va a recibir la entrada de caracteres del teclado. El sistema genera mensajes de clave virtual (WM_KEYDOWN y WM_KEYUP) cada vez que el usuario presiona una tecla. Un mensaje de clave virtual contiene un código de clave virtual que identifica qué tecla se presionó, pero no su valor de carácter. Para recuperar este valor, el bucle de mensajes debe contener TranslateMessage, que convierte el mensaje de clave virtual en un mensaje de caracteres (WM_CHAR) y lo vuelve a colocar en la cola de mensajes de la aplicación. Después, el mensaje de carácter se puede quitar en una iteración posterior del bucle de mensajes y enviarse a un procedimiento de ventana.

La función DispatchMessage envía un mensaje al procedimiento de ventana asociado al identificador de ventana especificado en la estructura MSG . Si el identificador de ventana es HWND_TOPMOST, DispatchMessage envía el mensaje a los procedimientos de ventana de todas las ventanas de nivel superior del sistema. Si el identificador de la ventana es NULL, DispatchMessage no hace nada con el mensaje.

El subproceso principal de una aplicación inicia su bucle de mensajes después de inicializar la aplicación y crear al menos una ventana. Una vez iniciado, el bucle de mensajes continúa recuperando mensajes de la cola de mensajes del subproceso y para enviarlos a las ventanas adecuadas. El bucle de mensajes finaliza cuando la función GetMessage quita el mensaje WM_QUIT de la cola de mensajes.

Solo se necesita un bucle de mensajes para una cola de mensajes, incluso si una aplicación contiene muchas ventanas. DispatchMessage siempre envía el mensaje a la ventana adecuada; esto se debe a que cada mensaje de la cola es una estructura MSG que contiene el identificador de la ventana a la que pertenece el mensaje.

Puede modificar un bucle de mensajes de varias maneras. Por ejemplo, puede recuperar mensajes de la cola sin enviarlos a una ventana. Esto es útil para las aplicaciones que publican mensajes que no especifican una ventana. También puede dirigir GetMessage para buscar mensajes específicos, dejando otros mensajes en la cola. Esto resulta útil si debe omitir temporalmente el orden FIFO habitual de la cola de mensajes.

Una aplicación que use teclas de aceleración debe ser capaz de traducir mensajes de teclado en mensajes de comando. Para ello, el bucle de mensajes de la aplicación debe incluir una llamada a la función TranslateAccelerator . Para obtener más información sobre las teclas de aceleración, vea Aceleradores de teclado.

Si un subproceso usa un cuadro de diálogo modelado, el bucle de mensajes debe incluir la función IsDialogMessage para que el cuadro de diálogo pueda recibir la entrada del teclado.

Procedimiento de ventana

Un procedimiento de ventana es una función que recibe y procesa todos los mensajes enviados a la ventana. Cada clase de ventana tiene un procedimiento de ventana y cada ventana creada con esa clase usa ese mismo procedimiento de ventana para responder a los mensajes.

El sistema envía un mensaje a un procedimiento de ventana pasando los datos del mensaje como argumentos al procedimiento. A continuación, el procedimiento de ventana realiza una acción adecuada para el mensaje; comprueba el identificador del mensaje y, al procesar el mensaje, usa la información especificada por los parámetros del mensaje.

Normalmente, un procedimiento de ventana no omite un mensaje. Si no procesa un mensaje, debe devolver el mensaje al sistema para su procesamiento predeterminado. El procedimiento de ventana lo hace llamando a la función DefWindowProc , que realiza una acción predeterminada y devuelve un resultado del mensaje. A continuación, el procedimiento de ventana debe devolver este valor como resultado de su propio mensaje. La mayoría de los procedimientos de ventana procesan solo algunos mensajes y pasan los demás al sistema mediante una llamada a DefWindowProc.

Dado que todas las ventanas que pertenecen a la misma clase comparten un procedimiento de ventana, puede procesar mensajes para varias ventanas diferentes. Para identificar la ventana específica afectada por el mensaje, un procedimiento de ventana puede examinar el identificador de ventana pasado con un mensaje. Para obtener más información sobre los procedimientos de ventana, vea Procedimientos de ventana.

Filtrado de mensajes

Una aplicación puede elegir mensajes específicos para recuperar de la cola de mensajes (mientras se omiten otros mensajes) mediante la función GetMessage o PeekMessage para especificar un filtro de mensajes. El filtro es un intervalo de identificadores de mensaje (especificados por un identificador primero y último), un identificador de ventana o ambos. GetMessage y PeekMessage usan un filtro de mensajes para seleccionar los mensajes que se van a recuperar de la cola. El filtrado de mensajes es útil si una aplicación debe buscar en la cola de mensajes los mensajes que han llegado más adelante en la cola. También es útil si una aplicación debe procesar mensajes de entrada (hardware) antes de procesar los mensajes publicados.

Las constantes WM_KEYFIRST y WM_KEYLAST se pueden usar como valores de filtro para recuperar todos los mensajes de teclado; las constantes WM_MOUSEFIRST y WM_MOUSELAST se pueden usar para recuperar todos los mensajes del mouse.

Cualquier aplicación que filtre los mensajes debe asegurarse de que se pueda publicar un mensaje que satisfaga el filtro de mensajes. Por ejemplo, si una aplicación filtra un mensaje de WM_CHAR en una ventana que no recibe la entrada del teclado, la función GetMessage no devuelve. Esto bloquea eficazmente la aplicación.

Publicar y enviar mensajes

Cualquier aplicación puede publicar y enviar mensajes. Al igual que el sistema, una aplicación publica un mensaje copiandolo en una cola de mensajes y envía un mensaje pasando los datos del mensaje como argumentos a un procedimiento de ventana. Para publicar mensajes, una aplicación usa la función PostMessage . Una aplicación puede enviar un mensaje llamando a la función SendMessage, BroadcastSystemMessage, SendMessageCallback, SendMessageTimeout, SendNotifyMessage o SendDlgItemMessage .

Publicar mensajes

Normalmente, una aplicación publica un mensaje para notificar a una ventana específica que realice una tarea. PostMessage crea una estructura MSG para el mensaje y copia el mensaje en la cola de mensajes. El bucle de mensajes de la aplicación finalmente recupera el mensaje y lo envía al procedimiento de ventana adecuado.

Una aplicación puede publicar un mensaje sin especificar una ventana. Si la aplicación proporciona un identificador de ventana NULL al llamar a PostMessage, el mensaje se publica en la cola asociada al subproceso actual. Dado que no se especifica ningún identificador de ventana, la aplicación debe procesar el mensaje en el bucle de mensajes. Esta es una manera de crear un mensaje que se aplica a toda la aplicación, en lugar de a una ventana específica.

En ocasiones, es posible que desee publicar un mensaje en todas las ventanas de nivel superior del sistema. Una aplicación puede publicar un mensaje en todas las ventanas de nivel superior llamando a PostMessage y especificando HWND_TOPMOST en el parámetro hwnd .

Un error de programación común es suponer que la función PostMessage siempre publica un mensaje. Esto no es cierto cuando la cola de mensajes está llena. Una aplicación debe comprobar el valor devuelto de la función PostMessage para determinar si el mensaje se ha publicado y, si no lo ha sido, volver a publicarlo.

enviar mensajes

Normalmente, una aplicación envía un mensaje para notificar a un procedimiento de ventana que realice una tarea inmediatamente. La función SendMessage envía el mensaje al procedimiento de ventana correspondiente a la ventana especificada. La función espera hasta que el procedimiento de ventana finaliza el procesamiento y, a continuación, devuelve el resultado del mensaje. Las ventanas primarias y secundarias suelen comunicarse mediante el envío de mensajes entre sí. Por ejemplo, una ventana primaria que tiene un control de edición como su ventana secundaria puede establecer el texto del control enviando un mensaje a él. El control puede notificar a la ventana primaria los cambios en el texto que lleva a cabo el usuario enviando mensajes de vuelta al elemento primario.

La función SendMessageCallback también envía un mensaje al procedimiento de ventana correspondiente a la ventana especificada. Sin embargo, esta función devuelve inmediatamente. Después de que el procedimiento de ventana procese el mensaje, el sistema llama a la función de devolución de llamada especificada. Para obtener más información sobre la función de devolución de llamada, vea la función SendAsyncProc .

En ocasiones, es posible que desee enviar un mensaje a todas las ventanas de nivel superior del sistema. Por ejemplo, si la aplicación cambia la hora del sistema, debe notificar a todas las ventanas de nivel superior sobre el cambio mediante el envío de un mensaje de WM_TIMECHANGE . Una aplicación puede enviar un mensaje a todas las ventanas de nivel superior llamando a SendMessage y especificando HWND_TOPMOST en el parámetro hwnd . También puede difundir un mensaje a todas las aplicaciones llamando a la función BroadcastSystemMessage y especificando BSM_APPLICATIONS en el parámetro lpdwRecipients .

Mediante el uso de la función InSendMessage o InSendMessageEx , un procedimiento de ventana puede determinar si está procesando un mensaje enviado por otro subproceso. Esta funcionalidad es útil cuando el procesamiento de mensajes depende del origen del mensaje.

Interbloqueos de mensajes

Un subproceso que llama a la función SendMessage para enviar un mensaje a otro subproceso no puede continuar ejecutándose hasta que se devuelva el procedimiento de ventana que recibe el mensaje. Si el subproceso receptor produce el control mientras se procesa el mensaje, el subproceso de envío no puede continuar ejecutándose, porque espera a que SendMessage se devuelva. Si el subproceso receptor está asociado a la misma cola que el remitente, puede provocar que se produzca un interbloqueo de aplicación. (Tenga en cuenta que los enlaces de diario conectan subprocesos a la misma cola).

Tenga en cuenta que el subproceso receptor no necesita producir el control explícitamente; llamar a cualquiera de las funciones siguientes puede hacer que un subproceso produzca un control implícitamente.

Para evitar posibles interbloqueos en la aplicación, considere la posibilidad de usar las funciones SendNotifyMessage o SendMessageTimeout . De lo contrario, un procedimiento de ventana puede determinar si otro subproceso envió un mensaje que ha recibido llamando a la función InSendMessage o InSendMessageEx . Antes de llamar a cualquiera de las funciones de la lista anterior mientras se procesa un mensaje, el procedimiento de ventana debe llamar primero a InSendMessage o InSendMessageEx. Si esta función devuelve TRUE, el procedimiento de ventana debe llamar a la función ReplyMessage antes de cualquier función que haga que el subproceso produzca control.

Difusión de mensajes

Cada mensaje consta de un identificador de mensaje y dos parámetros, wParam y lParam. El identificador del mensaje es un valor único que especifica el propósito del mensaje. Los parámetros proporcionan información adicional específica del mensaje, pero el parámetro wParam suele ser un valor de tipo que proporciona más información sobre el mensaje.

Una difusión de mensajes es simplemente el envío de un mensaje a varios destinatarios del sistema. Para difundir un mensaje desde una aplicación, use la función BroadcastSystemMessage , especificando los destinatarios del mensaje. En lugar de especificar destinatarios individuales, debe especificar uno o varios tipos de destinatarios. Estos tipos son aplicaciones, controladores instalables, controladores de red y controladores de dispositivo de nivel de sistema. El sistema envía mensajes de difusión a todos los miembros de cada tipo especificado.

Normalmente, el sistema difunde mensajes en respuesta a los cambios que tienen lugar en los controladores de dispositivos de nivel del sistema o en los componentes relacionados. El controlador o el componente relacionado difunde el mensaje a las aplicaciones y otros componentes para notificarles el cambio. Por ejemplo, el componente responsable de las unidades de disco difunde un mensaje cada vez que el controlador de dispositivo de la unidad de disquete detecta un cambio de medios, como cuando el usuario inserta un disco en la unidad.

El sistema difunde mensajes a los destinatarios en este orden: controladores de dispositivos de nivel de sistema, controladores de red, controladores instalables y aplicaciones. Esto significa que los controladores de dispositivos de nivel de sistema, si se eligen como destinatarios, siempre obtienen la primera oportunidad de responder a un mensaje. Dentro de un tipo de destinatario determinado, no se garantiza que ningún controlador reciba un mensaje determinado antes de cualquier otro controlador. Esto significa que un mensaje destinado a un controlador específico debe tener un identificador de mensaje único globalmente para que ningún otro controlador lo procese involuntariamente.

También puede difundir mensajes a todas las ventanas de nivel superior especificando HWND_BROADCAST en la función SendMessage, SendMessageCallback, SendMessageTimeout o SendNotifyMessage .

Las aplicaciones reciben mensajes a través del procedimiento de ventana de sus ventanas de nivel superior. Los mensajes no se envían a ventanas secundarias. Los servicios pueden recibir mensajes a través de un procedimiento de ventana o sus controladores de control de servicio.

Nota

Los controladores de dispositivos de nivel de sistema usan una función relacionada de nivel de sistema para difundir mensajes del sistema.

Mensajes de consulta

Puede crear sus propios mensajes personalizados y usarlos para coordinar las actividades entre las aplicaciones y otros componentes del sistema. Esto es especialmente útil si ha creado sus propios controladores instalables o controladores de dispositivo de nivel de sistema. Los mensajes personalizados pueden transportar información hacia y desde el controlador y las aplicaciones que usan el controlador.

Para sondear a los destinatarios el permiso para llevar a cabo una acción determinada, use un mensaje de consulta. Puede generar sus propios mensajes de consulta estableciendo el valor BSF_QUERY en el parámetro dwFlags al llamar a BroadcastSystemMessage. Cada destinatario del mensaje de consulta debe devolver TRUE para que la función envíe el mensaje al siguiente destinatario. Si algún destinatario devuelve BROADCAST_QUERY_DENY, la difusión finaliza inmediatamente y la función devuelve un cero.