En todos los sistemas de comunicación entre procesos hemos hablado de "notificar al proceso destino".
Vamos a tratar esta tema, aunque en realidad no tenga mucho que ver con los archivos proyectados, pero sí con su uso más importante. Además, la aplicación de ejemplo en Visual C++, utiliza la notificación junto con los archivos proyectados, para comunicar varios procesos entre sí.
La notificación de procesos consiste en informar a un proceso de cierto dato, normalmente un descriptor.
Existen varios métodos para notificar a un proceso de que ha ocurrido "algo", aunque ahora sólo voy a exponer el más típico: los mensajes de ventana.
La explicación completa de qué son los mensajes de ventana o el bucle de mensajes, cómo funcionan, y cómo los implementa internamente Win32 sería muy extensa, así que vamos a suponer que todo el mundo sabe lo que es un mensaje, aunque no comprendamos muy bien qué ocurre internamente.
El sistema de mensajes se basa en registrar un mensaje especial, y notificarlo a todas las ventanas del sistema.
A este mensaje sólo responderán aquellas aplicaciones que hayan registrado previamente este mensaje, es decir, nuestras aplicaciones.
El paso de registrar el mensajes es sencillo, nos bastan con la siguiente función del API:
UINT RegisterWindowMessage(
LPCTSTR lpNombre
nombre del mensaje
);
Símplemente indicando una cadena con el nombre del mensaje, el sistema nos retorna un identificador de mensaje único, dentro del rango 0xC000 hasta 0xFFFF. Cuando se intenta registrar varias veces el mismo nombre de mensaje, el sistema retornará el mismo identificador.
En nuestro ejemplo para Visual C++, puede verse el uso que he dado a esta función dentro del método Registrar de la clase CNotificacion.
Una vez registrado, debemos lanzarlo a todas las aplicaciones del sistema, a través de la función PostMensage o SendMessage. No vamos a entrar en la diferencia entre ambas funciones, y lo dejaremos para otra ocasión, en que tratemos en profundidad los mensajes de ventana.
La sintaxis de ambas funciones es la misma, así que sólo explicaré una de ellas:
LRESULT SendMessage(
HWND hWnd, descriptor de ventana destino
UINT Msg,
identificador del mensaje a enviar
WPARAM wParam, primer parámetro
LPARAM lParam
segundo parámetro
);
Los parámetros son los siguientes:
- hWnd: descriptor de la ventana destino. Los mensajes de ventana (como su propio nombre indica) se envían a una ventana específica. Este valor podemos obtenerlo a través de cualquier función que nos retorne un descriptor de ventana (como CreateWindow, GetWindow, FindWindow, etc.).
Existe un valor especial contenido en la constante HWND_BROADCAST. Este valor le indica a Windows que distribuya el mensaje por todas las ventanas del sistema, no sólo a una ventana concreta.
- Msg: indica el identificador del mensaje a pasar. En nuestro caso concreto, este valor lo obtendremos a través de la función RegisterWindowMessage, aunque para otros casos, podemos utilizar un mensaje predefinido por el sistema (normalmente una constante que comienza por WM_) o un mensaje de usuario (cualquier valor superior a WM_USER, vamos: 1024).
- wParam: en este parámetro se puede pasar cualquier valor de 32 bits como parámetro. La interpretación que se dará a este valor depende del mensaje que pasemos. En nuestro caso, vamos a utilizar este valor para pasar el descriptor de la ventana que envía el mensaje.
- lParam: este parámetro funciona como wParam, pudiendo pasarse otro valor de 32 bits.
En el ejemplo para Visual C++, se usa la función SendMessage junto con el parámetro especial HWND_BROADCAST dentro del método Enviar de la clase CNotificacion.
El último paso que debemos dar, es interceptar el mensaje que recibe la aplicación. Para ello he utilizado una técnica llamada "Subclasificación del bucle de mensajes", aunque no voy a entrar a detallarla, ya que para ello, lo primero que tendría que hacer es explicar qué es un bucle de mensajes. Símplemente diré que me he apoyado en la VCL de C++Builder para simplificar el código, concretamente en la propiedad WindowProc de la clase TControl.
En el ejemplo para C++Builder puede verse cómo hacer la "subclasificación" dentro de la clase TMainForm, a través del método SubClassWndProc.