2009-04-19 12 views
11

En una aplicación Win32 C++, iniciamos un bucle de mensaje que recupera mensajes de una cola, los traduce y luego los distribuye. Eventualmente, cada mensaje llega a nuestro WndProc donde se puede manejar el evento asociado.¿Cómo se implementa la programación basada en eventos de Win32 bajo el capó?

Entiendo esa parte. Lo que no entiendo es lo que hay entre las cosas que pasan. Específicamente:

  1. Diferentes tipos de controladores de interrupción del sistema operativo deben colocar mensajes en dicha 'cola de mensajes', pero ¿dónde reside el espacio de direcciones del proceso? ¿Cómo está expuesto al código del controlador de interrupción?
  2. ¿Qué significa 'traducir' el mensaje? ¿Qué hace realmente la llamada a TranslateMessage()?
  3. Una vez enviado por DispatchMessage(), ¿en qué lugar pasa el mensaje antes de llegar a mi WndProc (es decir, qué hace el sistema operativo con él)?

Si alguien conoce las respuestas a las preguntas anteriores, tenga la bondad de satisfacer mi curiosidad. Gracias.

Respuesta

6

El sistema operativo mantiene una cola de mensajes, donde coloca los eventos (por ejemplo, de interrupciones u otras fuentes). A continuación, envía los mensajes de esa cola a todas las ventanas, según el mensaje (por ejemplo, no enviará mensajes clave a una ventana que no tiene foco).

Las aplicaciones pueden tener su propia cola para procesar mensajes. Esas colas se crean on request (solo si es necesario).

Traducir un mensaje se utiliza para crear mensajes que no son eventos 'reales'. Por ejemplo, el mensaje WM_CONTEXTMENU se 'traduce' desde un clic con el botón derecho del mouse, o desde la tecla de menú contextual, o cambia-F10. WM_CHAR se traduce de los mensajes WM_KEYDOWN. Y, por supuesto, muchos otros mensajes se 'traducen' de esa manera.

Se publica un mensaje en cada ventana que debe recibirlo. El sistema operativo decide dependiendo del tipo de mensaje si una ventana debe recibir ese mensaje o no. La mayoría de los mensajes son esperados por el sistema, es decir, el mensaje no se publicará en otra ventana hasta que la ventana lo haya procesado.Esto tiene un gran impacto para los mensajes de difusión: si una ventana no regresa al manejar ese mensaje, la cola es blocked y otras ventanas ya no recibirán el mensaje.

+3

Esto está todo mal. Las partes correctas son correctas solo si la pregunta era sobre Win16, donde todo el sistema operativo y las aplicaciones se programaban de forma cooperativa en un solo hilo. –

1

No es absolutamente positivo acerca de esto, pero mi mejor conjetura dice:

  1. La cola es un objeto del sistema al que se accede con llamadas a la API de Win32. No está en su espacio de direcciones de proceso en absoluto. Entonces los manejadores de interrupciones pueden acceder a él (probablemente a través del HAL (Capa de abstracción de hardware) del núcleo).

  2. En Win16, esa llamada tomó las distintas subpartidas de un mensaje más grande y las convirtió en un todo. Así que TranslateMessage agregaría WM_KEYPRESS cuando encuentre la secuencia WM_KEYDOWN WM_KEYUP correspondiente. También convertiría varios botones en los mensajes de doble clic en la configuración interna y las marcas de tiempo de los mensajes. Si todavía hace esto en Win32, no lo sé.

  3. DispatchMessage es probablemente donde se procesan los ganchos de mensaje de ventana. Entonces, si hay un gancho en su ventana, se llama aquí o cuando se llama a GetMessage. No estoy seguro. Aparte de eso, DispatchMessage solo busca la dirección WndProc asociada a la ventana y la llama. No hay mucho más que hacer.

Espero que ayude.

6

Depende de cómo se envía su mensaje y cómo se maneja.

Cuando llama a SendMessage, si la ventana de destino es propiedad de la cadena actual, la llamada pasa por alto la cola de mensajes para la ventana y el administrador de ventanas llama directamente al proceso de ventana en la ventana de destino. Si la ventana de destino es propiedad de otro hilo, el administrador de ventanas llama efectivamente a PostMessage y bombea mensajes de ventana hasta que la ventana de destino retorna desde el proceso de ventana.

Cuando llama a PostMessage, el administrador de ventanas clasifica los parámetros del mensaje e inserta el objeto correspondiente en la cola de mensajes para la ventana de destino. Cuando vuelva a llamar a GetMessage, el mensaje se eliminará de la cola de mensajes.

El administrador de ventanas también se registra para los eventos de entrada sin formato desde los dispositivos de entrada (teclado y/o mouse) y genera mensajes para esos eventos de entrada. A continuación, inserta esos mensajes en la cola según corresponda (el procesamiento de los eventos de entrada es complicado porque depende de qué mensajes ya están en la cola de mensajes para la ventana).

Como Stefan indicó, TranslateMessage solo traduce las teclas del acelerador, por ejemplo, convierte secuencias de teclas en mensajes WM_COMMAND.

1

Para hacer frente a la última de preguntas adicionales, un mensaje enviado se vaya a su WindowProc después de que ha sido canalizado a través de todos los ganchos (WH_CALLWNDPROC)

4

Diferentes tipos de OS manejador de interrupciones debe ser la colocación de mensajes en dicha cola de mensajes' ', pero ¿dónde reside el espacio de direcciones del proceso? ¿Cómo está expuesto al código del controlador de interrupción?

Las ventanas están asociadas a los hilos. Cada hilo con una ventana tiene una cola de hilos en el espacio de direcciones del proceso. El sistema operativo tiene una cola interna en su propio espacio de direcciones para los eventos generados por hardware. Usando detalles del evento y otra información de estado (por ejemplo, qué ventana tiene el foco), el sistema operativo traduce los eventos de hardware en mensajes que luego se colocan en la fila de hilos adecuada.

Los mensajes que se publican se colocan directamente en la cola de subprocesos para la ventana de destino.

Los mensajes que se envían generalmente se procesan directamente (omitiendo la cola).

Los detalles se ponen peludos. Por ejemplo, las colas de subprocesos son más que listas de mensajes; también mantienen cierta información de estado. Algunos mensajes (como WM_PAINT) no están realmente en cola, sino que se sintetizan a partir de la información de estado adicional cuando consulta la cola y está vacía. Los mensajes enviados a ventanas propiedad de otros hilos se publican en la cola del receptor en lugar de procesarse directamente, pero el sistema hace que parezca un envío de bloqueo regular desde el punto de vista de la persona que llama. La hilaridad se produce si esto puede causar un punto muerto (debido a los envíos circulares de vuelta al hilo original).

Los libros de Jeffrey Richter tienen mucho (¿todo?) De los detalles sangrientos. Mi edición es antigua (Windows avanzado). La edición actual parece llamarse Windows via C/C++.

El sistema operativo realiza MUCHO trabajo para hacer que la secuencia de mensajes parezca racional (y relativamente simple) para la persona que llama.

¿Qué significa 'traducir' el mensaje? ¿Qué hace realmente la llamada a TranslateMessage()?

Busca mensajes de teclas virtuales y, cuando reconoce una combinación de combinación de teclas, agrega mensajes de caracteres. Si no llama al TranslateMessage, no recibirá mensajes de caracteres como WM_CHAR.

Sospecho que envía el mensaje del personaje directamente antes de regresar (en lugar de publicarlo). Nunca lo he comprobado, pero parece recordar que los mensajes WM_CHAR llegan justo antes de WM_KEYUP.

Una vez enviado por DispatchMessage(), ¿en qué lugar pasa el mensaje antes de llegar a mi WndProc (es decir, qué hace el sistema operativo con él)?

DispatchMessage pasa el mensaje al WndProc para la ventana de destino. En el camino, algunos ganchos pueden tener la oportunidad de ver el mensaje (y posiblemente interferir con él).

Cuestiones relacionadas