Pregunta

En una aplicación Win32 C++, iniciamos un bucle de mensajes que recupera mensajes de una cola, los traduce y luego los envía.Finalmente, cada mensaje llega a nuestro WndProc donde se puede manejar el evento asociado.

Entiendo esa parte.Lo que no entiendo son los acontecimientos intermedios.Específicamente:

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

Si alguien sabe las respuestas a lo anterior, por favor satisfaga mi curiosidad.Gracias.

¿Fue útil?

Solución

El sistema operativo mantiene una cola de mensajes, donde pone los eventos (por ejemplo, de las interrupciones o de otras fuentes). A continuación, envía los mensajes de dicha cola a todas las ventanas, dependiendo del mensaje (por ejemplo, no va a enviar mensajes clave a una ventana que no está seleccionado).

Las aplicaciones pueden tener su propia cola para procesar los mensajes. Esas colas se crean bajo petición (sólo si es necesario ).

La traducción de un mensaje se utiliza para crear mensajes que no son eventos 'reales'. Por ejemplo, el mensaje WM_CONTEXTMENU se 'traduce' ya sea de un clic con el botón derecho del ratón o la tecla de menú contextual, o Shift-F10. El WM_CHAR se traduce de mensajes WM_KEYDOWN. Y, por supuesto, muchos otros mensajes se 'traduce' de esa manera.

Un mensaje se envía a todas las ventanas que debe recibirla. El sistema operativo decide en función del tipo de mensaje si una ventana debe recibir ese mensaje o no. La mayoría de los mensajes se esperaban por el sistema, es decir, el mensaje no conseguirá publicado a otra ventana hasta que fue procesada por la ventana. Esto tiene un gran impacto para los mensajes de difusión: Si una ventana no vuelve al manejar ese mensaje, la cola es bloqueado y otras ventanas no recibirán el mensaje más.

Otros consejos

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

Cuando se llama a SendMessage, si la ventana de destino es propiedad de la hebra actual, la llamada no pasa por la cola de mensajes de la ventana y el gestor de ventanas llamadas directamente al WindowProc en la ventana de destino. Si la ventana de destino es propiedad de otro hilo, el gestor de ventanas llama efectivamente PostMessage y bombas mensajes de ventana hasta que la ventana de destino vuelve del procedimiento de ventana.

Cuando se llama a PostMessage, los comisarios del gestor de ventanas los parámetros del mensaje e inserta el objeto correspondiente a la cola de mensajes de la ventana de destino. Cuando se llama al lado GetMessage el mensaje se elimina de la cola de mensajes.

El gestor de ventanas también registra para eventos primas de entrada de los dispositivos de entrada (teclado y / o ratón) y que genera mensajes para los eventos de entrada. A continuación, inserta los mensajes en la cola como apropiado (el procesamiento de eventos de entrada es complicado porque depende de qué mensajes ya están en la cola de mensajes para la ventana).

Como se indica Stefan, TranslateMessage simplemente traduce teclas de aceleración -., Por ejemplo, que convierte secuencias de teclas para mensajes WM_COMMAND

Diferentes tipos de controladores de interrupciones del sistema operativo deben colocar mensajes en dicha 'cola de mensajes', pero ¿en qué lugar del espacio de direcciones del proceso reside esta cola?¿Cómo se expone al código del controlador de interrupciones?

Las ventanas están asociadas con subprocesos.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 el hardware.Utilizando 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 cola de subprocesos adecuada.

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

Los mensajes que se envían normalmente se procesan directamente (sin pasar por la cola).

Los detalles se vuelven complicados.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 en realidad se publican en la cola del receptor en lugar de procesarse directamente, pero el sistema hace que parezca un envío de bloqueo normal desde el punto de vista de la persona que llama.Se produce hilaridad si esto puede causar un punto muerto (debido a los envíos circulares al hilo original).

Los libros de Jeffrey Richter tienen muchos (¿todos?) detalles sangrientos.Mi edición es antigua (Windows avanzado).La edición actual parece llamarse Windows a través de C/C++.

El sistema operativo hace MUCHO trabajo para que el flujo 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 clave virtuales y, cuando reconoce una combinación de tecla hacia abajo/tecla arriba, agrega mensajes de caracteres.Si no llamas Traducir mensaje, no recibirás 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 creo recordar que los mensajes WM_CHAR llegan justo antes de WM_KEYUP.

Una vez enviado por DispatchMessage(), ¿por qué lugares 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).

Para hacer frente a la última de preguntas adicionales, un mensaje enviado irá a su WindowProc después de haber sido van pasando por todos los ganchos (WH_CALLWNDPROC)

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 del proceso en absoluto. Por lo que los controladores de interrupción pueden acceder a él (probablemente a través de la HAL (Hardware Abstraction Layer) del núcleo).

  2. En Win16, esa llamada tomó las distintas subpartes de un mensaje más grande y puré en un todo. Así TranslateMessage añadiría la WM_KEYPRESS cuando se encontró la secuencia WM_KEYDOWN WM_KEYUP correspondiente. También sería convertir varios mensajes de botón de clic en mensajes de DoubleClick basada en el ajuste interno y las marcas de tiempo de los mensajes. Si todavía lo hace en Win32, no sé.

  3. DispatchMessage es probablemente donde ganchos mensaje de la ventana se procesan. Así que si hay un gancho en la ventana, o bien se llama aquí o cuando el GetMessage se llama. No estoy seguro. Aparte de eso, DispatchMessage simplemente busca la dirección WndProc asociado a la ventana y lo llama. No hay mucho más para que haga.

Espero que ayude.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top