Cómo hacer que un programa entregue el control
doevents
-------------------
Hay una sección de código en el programa que debe procesarse durante mucho tiempo (fuera del bucle) para que el programa no pueda hacer otras cosas. ¿Cómo puedo hacer que el programa ceda el control y haga otra cosa? (C# WinForm
Subprocesos
-------------------
Capítulo de mensajes de VC
El concepto de mensaje se puede expresar de la siguiente manera: "En el entorno WINDOWS, un mensaje es un conjunto de datos fijos que se pasan desde la función de llamada de WINDOWS a la función de salida de la aplicación. (Consulte "Desarrollador de Microsoft Windows 3' 's Workshop "Book, Microsoft Press, Richard Wilton). Cualquiera que haya estudiado programación SDK comprenderá muy claramente el concepto de mensajes al leer estas palabras.
Si no puede comprender este concepto, podemos comenzar desde Explíquelo desde otra perspectiva. Primero, introduzcamos algunos conocimientos sobre los mensajes. Esto es muy importante. Hay un solo sistema de mensajería en el sistema WINDOWS, y hay muchas colas de mensajes. Enviar un mensaje a cualquier aplicación Una aplicación puede enviar un mensaje a cualquier aplicación una vez que se recibe un mensaje (por supuesto, las aplicaciones también pueden enviarse mensajes entre sí), si así lo desea. Para manejar este mensaje, debe manejar este mensaje. Los diferentes mensajes se manejarán de diferentes maneras. Por ejemplo, el mensaje WM_PAINT notificará a la aplicación que muestre algo en la pantalla. No es necesario escribir los mensajes, porque el marco del programa generado cuando se usa VC para programar ya puede manejar estos mensajes.
Por ejemplo, usamos VC para crear una aplicación de diálogo básica, que contiene dos botones. : BUTTONA y BUTTONB, cuando hace clic en BUTTONA, BUTTONB se ocultará. Durante el proceso de programación, programará el evento BN_CLICKED de BUTTONA para ocultar BUTTONB. Después de ocultarlo, ya no habrá BUTTONB en la parte superior. un mensaje WM_PAINT para notificar a la aplicación que vuelva a dibujar la interfaz de la aplicación para mostrar que ya no hay un botón BUTTIONB en la parte superior de la aplicación. Necesitamos el evento BN_CLICKED. Para mostrar que el evento BN_CLICKED no es necesario, necesitamos agregar otro. fragmento de código del programa, es decir, si hacemos clic en el botón BUTTONA, el sistema de mensajes recibirá el mensaje BN_CLICKED y lo enviará al marco del programa que construimos, y luego ejecutará el código que agregamos. El evento WM_PAINT no es necesario. , y el marco del programa lo manejará automáticamente. Tómese la molestia de hacer esto.
Creo que ahora debería comprender el concepto de mensajes. Si no, puede conectarse y encontrar algunos artículos mejores. eso te será más útil.
I. Introducción
Con la promoción continua del sistema operativo Windows, muchos kits de desarrollo de software brindan la función de desarrollar aplicaciones basadas en la plataforma Windows. Aunque estos kits de desarrollo no son los mismos, los más populares incluyen Visual C, Visual Basic, Delphi, C Builder, etc., pero el software desarrollado en estos diferentes lenguajes tiene una cosa en común: todos se ejecutan en el sistema operativo Windows. plataforma y debe aceptar el mecanismo operativo de Windows.
Como alma del sistema operativo Windows, el mecanismo de mensajería debe ser aceptado por muchas aplicaciones desarrolladas en diferentes lenguajes que se ejecutan bajo el sistema operativo Windows. Por lo tanto, para escribir programas de Windows en profundidad, debe tener un conocimiento completo del mecanismo operativo de Windows. Este artículo realizará un análisis más profundo basado en el mecanismo de operación de mensajes del sistema operativo Windows.
2. Mecanismo controlado por eventos de Windows
Muchos de nosotros usamos VC, Delphi, etc. Como lenguaje de desarrollo, los programadores han venido paso a paso desde Basic y C en DOS. Cuando comenzaron a aprender programación, la mayoría de ellos comenzaron con el entorno de programación en DOS, por lo que estaban acostumbrados al controlador de proceso en DOS. Después de acostumbrarse al método de programación secuencial basado en procesos en DOS, al hacer la transición al entorno de desarrollo en Windows, a menudo se siente incapaz de adaptarse al enfoque basado en eventos adoptado por Windows. Dado que los mecanismos operativos de los dos sistemas operativos, DOS y Windows, son completamente diferentes, cualquier programa en DOS adopta un método de programación secuencial basado en procesos. Este tipo de programa tiene un comienzo obvio, un proceso obvio y un final obvio, por lo que toda la secuencia de eventos o procesos del programa se puede controlar directamente a través del programa. Incluso cuando se manejan excepciones, el proceso sigue siendo secuencial y tiene una estructura impulsada por el proceso. Windows está controlado por eventos, es decir, el flujo del programa no está controlado por la secuencia de eventos, sino por la ocurrencia de eventos. Todos los eventos están desordenados, por lo que los programadores no saben al escribir un programa qué presionará el usuario primero. .Qué botón, no sabes qué mensaje activará primero el programa. Por tanto, nuestra principal tarea es ordenar y gestionar la información que enviará o recibirá la aplicación que desarrollemos. La programación basada en eventos gira en torno a la generación y procesamiento de mensajes; los mensajes son información sobre eventos que han ocurrido.
En tercer lugar, el bucle de mensajes de Windows
El sistema operativo Windows mantiene una cola de mensajes para cada aplicación en ejecución. Cuando ocurre un evento, Windows no envía el evento de estímulo directamente a la aplicación, sino que primero lo convierte en un mensaje de Windows y luego lo agrega a la cola de mensajes de la aplicación. La aplicación necesita recibir estos mensajes a través del bucle de mensajes. La biblioteca de clases utilizada en MFC encapsula bien WinAPI y, al mismo tiempo, proporciona una interfaz de programación orientada a objetos, lo que permite a los programadores de Windows programar de manera orientada a objetos y proporciona la parte de programación más tediosa de la programación del SDK, lo que lo enfoca. sobre la implementación de funciones e introduce buenas funciones de encapsulación para evitar que operemos directamente parte del código central. El bucle y la recepción de mensajes se pueden representar simplemente mediante un mapa de mensajes similar al siguiente:
BEGIN_MESSAGE_MAP(CTEMMSView, CFormView)
/{{AFX_MSG_MAP(CTEMMSView)
ON_WM_LBUTTONDOWN LBUTTONDOWN()
ON_COMMAND(ID_OPENDATA, OnOpenData)
ON_WM_TIMER()
ON_WM_PAINT()
/// }}AFX_MSG_MAP
END_ MESSAGE_MAP()
Aunque el mapa de mensajes anterior es muy conciso y facilita el procesamiento de mensajes durante la programación, obviamente es difícil entender cómo participan los mensajes en los bucles y la distribución. . Por tanto, es necesario profundizar en el núcleo de programación de Windows encapsulado por MFC a través del código SDK (Software Developer Kit) y estudiar su funcionamiento.
En la programación de SDK, normalmente agrega código en la función WinMain que sirve como punto de entrada para una aplicación de Windows, maneja el bucle de mensajes para recuperar los mensajes enviados por Windows y luego WinMain asigna estos mensajes a las funciones de ventana correspondientes y los procesa:
......
MSG msg; //definir el nombre del mensaje
while (GetMessage (amp; msg, NULL, 0, 0))
{
TranslateMessage (amp;msg); //traducir mensaje
DispatchMessage (amp;msg); //retirar el mensaje
}
return msg.wParam;
Aunque la oración anterior es simple, es el código clave de todos los programas de Windows. Su tarea es obtener, interpretar y distribuir mensajes. Análisis:
La estructura MSG se define en el archivo de encabezado de la siguiente manera:
typedef struct tagMSG
{
HWND hwnd
Mensaje UINT;
WPARAM wParam;
LPARAM lParam
DWORD hora
PUNTO pt; /p>
}MSG, *PMSG;
Los significados específicos de sus miembros de datos son los siguientes:
hwnd: el identificador de ventana al que se enviará el mensaje. Este parámetro se puede utilizar para decidir en qué ventana recibir el mensaje.
Mensaje: número de mensaje, utilizado para identificar de forma única el tipo de mensaje. Cada tipo de información está predefinido en la documentación de Windows.
wParam: Parámetro del mensaje de 32 bits, cuyo significado exacto depende del propio mensaje.
lParam: Igual que el anterior.
hora: la hora en la que el mensaje se coloca en la cola de mensajes. Lo que se escribe en este campo no es la fecha actual, sino el valor de tiempo medido después de que se inicia Windows.
>este campo para mantener el orden correcto de los mensajes.
pt: El mouse coordina cuando la información se coloca en la cola de información.
El bucle de mensajes comienza llamando a GetMessage, que recibe un mensaje de la cola de mensajes. Los cuatro parámetros de esta función permiten el acceso controlado al mensaje; el primer parámetro especifica la dirección de la estructura MSG que recibe el mensaje; el segundo parámetro representa el identificador de la ventana, que generalmente está vacío para indicar que desea obtenerlo todo; la información creada por la aplicación. Mensaje para la ventana; el tercer y cuarto parámetro se utilizan para especificar el rango del mensaje. Los últimos tres parámetros están configurados con valores predeterminados y se utilizan para recibir todos los mensajes enviados a cualquier ventana que pertenezca a esta aplicación. GetMessage() devuelve VERDADERO después de recibir cualquier mensaje que no sea WM_QUIT; si GetMessage recibe un mensaje WM_QUIT, devuelve FALSO para salir del bucle de mensajes y finalizar el programa. Por lo tanto, un bucle de mensajes que utiliza GetMessage() puede continuar hasta que se reciba un WM_QUIT. Cuando se leen mensajes distintos de WM_QUIT usando GetMessage, primero se interpretan a través de la función TranslateMessage(), pero esto no funciona para la mayoría de los mensajes. La clave aquí es la función DispatchMessage(), que pasa el mensaje de Windows obtenido a través de GetMessage al procedimiento de ventana especificado para la ventana en la estructura MSG.
Una vez que el controlador de mensajes ha procesado el mensaje, el código regresa al bucle para comenzar a recibir otro mensaje, completando un bucle de mensajes completo.
Porque el sistema operativo Windows es un sistema operativo multitarea no privado. Windows puede ceder el control de la CPU a otra aplicación sólo después de que la aplicación cede voluntariamente el control. En el bucle de mensajes, debe haber una función del sistema que pueda ceder el control para lograr la multitarea colaborativa. Solo GetMessage, PeekMessage y WaitMessage pueden completar esta función. Si la aplicación no llama a una de estas tres funciones durante mucho tiempo, no se pueden realizar otras tareas. Si la función GetMessage no puede encontrar una aplicación esperando procesar el mensaje, automáticamente entregará el control y Windows entregará el control de la CPU a otras aplicaciones que esperan obtener el control. Dado que cualquier aplicación de Windows contiene un bucle de mensajes, esta transferencia implícita de control garantiza que la aplicación compuesta *** tenga el control. Una vez que el mensaje destinado a la aplicación llega a la cola de aplicaciones, comienza la ejecución de la siguiente instrucción en la instrucción GetMessage. El bucle de mensajes que utiliza la función GetMessage esperará hasta que no haya mensajes en la cola de mensajes. Si es necesario, puede utilizar este tiempo para realizar operaciones que requieren mucho tiempo, como operaciones del puerto de E/S, pero debe utilizar la función PeekMessage en su lugar. de GetMessage en el bucle de mensajes. El método de uso de PeekMessage es similar a GetMessage. El siguiente es un ejemplo típico de un bucle de mensajes que utiliza la función PeekMessage:
MSG msg;
BOOL bDone=FALSE
do{
;if(PeekMessage(amp;msg,NULL,0,0,PM_REMOVE)){
if(msg.message==WM_QUIT)
bDone=TRUE
p>else{
TranslateMessage(amp;msg);
DispatchMessage(amp;msg); >}
// Sin procesamiento de mensajes, operación larga
else{
......// Operación larga
} p>
} while(!bDone)
...
La función PeekMessage regresa inmediatamente independientemente de si hay un mensaje en la cola de mensajes de la aplicación. Para esperar a que nuevos mensajes entren en la cola, puede combinar la función WaitMessage sin valor de retorno con PeekMessage para implementar un bucle de mensajes.
4. Procesamiento de mensajes de Windows
El proceso de procesamiento de mensajes de Windows generalmente comienza con una declaración de cambio. Para cada ID de mensaje, procesa una declaración de caso, que es funcionalmente similar al mensaje de MFC. mapeo:
switch(uMsgId)
{
case WM_TIMER:
//Manejar el mensaje del temporizador WM_TIMER
p>return 0;
case WM_LBUTTONDOWN:
//Maneja el mensaje de clic izquierdo del mouse WM_ LBUTTONDOWN
Esta es la primera vez que se utiliza el mapeo de mensajes MFC.
ruturn 0;
......
default:
//Otros mensajes son manejados por esta función de controlador predeterminada
return DefWindowProc(hwnd, uMsgId, wParam, lParam);
}
Es importante que cuando termine de procesar el mensaje, devuelva 0; de lo contrario, Windows seguirá intentando. Para los mensajes que no se procesarán en el programa, el procedimiento de ventana los enviará todos a DefWindowProc para su procesamiento predeterminado y devolverá el valor de retorno de esta función. La función DefWindowProc puede considerarse como la función más importante en la jerarquía de mensajería. Esta función emite el mensaje WM_SYSCOMMAND, que el sistema utiliza para realizar varias operaciones comunes para la mayoría de las ventanas en un entorno Windows, como actualizar el encabezado de texto de la ventana. En MFC, puede utilizar la siguiente parte del código para lograr la misma función que el código SDK anterior:
BEGIN_MESSAGE_MAP(CTEMMSView, CFormView)
//{{AFX_MSG_MAP(CTEMMSView) )
ON_WM_ LBUTTONDOWN()
ON_WM_TIMER()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
Resumen: Entorno Windows Proporciona una gran cantidad de recursos del sistema sobre los cuales crear aplicaciones que cumplan una variedad de objetivos y funciones. Para profundizar en la programación de Windows, primero debe tener una comprensión completa del mecanismo operativo del sistema Windows. Este artículo solo proporciona un análisis y una explicación más profundos de un mecanismo operativo importante de Windows: el mecanismo de mensajes. Es útil desarrollar ideas de programación en Windows. Para obtener una discusión más detallada sobre algunos problemas, consulte la sección "Referencia del SDK" en la ayuda en línea de MSDN.