Compartir a través de


Escribir el procedimiento de ventana

La función DispatchMessage llama al procedimiento de ventana de la ventana que es el destino del mensaje. El procedimiento de ventana tiene la siguiente firma.

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

Hay cuatro parámetros:

  • hwnd es un identificador de la ventana.
  • uMsg es el código del mensaje. Por ejemplo, el mensaje WM_SIZE indica que se cambió el tamaño de la ventana.
  • wParam y lParam contienen datos adicionales que pertenecen al mensaje. El significado exacto depende del código del mensaje.

LRESULT es un valor entero que el programa devuelve a Windows. Contiene la respuesta de su programa a un mensaje en concreto. El significado de este valor depende del código del mensaje. CALLBACK es la convención de llamada para la función.

Un procedimiento de ventana típico es simplemente una instrucción switch grande que cambia en el código del mensaje. Agregue casos para cada mensaje que desee gestionar.

switch (uMsg)
{
    case WM_SIZE: // Handle window resizing

    // etc
}

Los datos adicionales del mensaje se incluyen en los parámetros lParam y wParam . Ambos parámetros son valores enteros del tamaño del ancho de un cursor (32 bits o 64 bits). El significado de cada uno depende del código del mensaje (uMsg). Para cada mensaje, deberá buscar el código de este en MSDN y convertir los parámetros en el tipo de datos correcto. Normalmente, los datos son o bien un valor numérico, o un cursor a una estructura. Algunos mensajes no tienen datos.

Por ejemplo, la documentación del mensaje WM_SIZE indica que:

  • wParam es una marca que indica si la ventana se ha minimizado, maximizado o cambiado de tamaño.
  • lParam contiene el nuevo ancho y alto de la ventana como valores de 16 bits empaquetados en un número de 32 o 64 bits. Tendrá que realizar algún cambio de bits para obtener estos valores. Afortunadamente, el archivo de encabezado WinDef.h incluye macros auxiliares para ello.

Un procedimiento de ventana típico gestiona docenas de mensajes, por lo que puede crecer bastante. Una manera de hacer que el código sea más modular es colocar la lógica para controlar cada mensaje en una función independiente. En el procedimiento de ventana, convierta los parámetros wParam y lParam en el tipo de datos correcto y pase esos valores a la función. Por ejemplo, para gestionar el mensaje WM_SIZE , el procedimiento de ventana tendría el siguiente aspecto:

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_SIZE:
        {
            int width = LOWORD(lParam);  // Macro to get the low-order word.
            int height = HIWORD(lParam); // Macro to get the high-order word.

            // Respond to the message:
            OnSize(hwnd, (UINT)wParam, width, height);
        }
        break;
    }
}

void OnSize(HWND hwnd, UINT flag, int width, int height)
{
    // Handle resizing
}

Las macros LOWORD y HIWORD obtienen los valores de ancho y alto de 16 bits de lParam. (Busque este tipo de detalles en la documentación de MSDN para cada código de mensaje). El procedimiento de ventana extrae el ancho y el alto y, a continuación, pasa estos valores a la función OnSize.

Control de mensajes predeterminado

Si no controla un mensaje concreto en su procedimiento de ventana, pase directamente los parámetros del mensaje a la función DefWindowProc. Esta función realiza la acción predeterminada para el mensaje, que varía según el tipo de mensaje.

return DefWindowProc(hwnd, uMsg, wParam, lParam);

Evitar cuellos de botella en el procedimiento de ventana

Al ejecutar el procedimiento de ventana, bloquea cualquier otro mensaje para las ventanas creadas en el mismo subproceso. Así, se evita un procesamiento largo dentro del procedimiento de ventana. Por ejemplo, supongamos que el programa abre una conexión TCP y espera indefinidamente a que el servidor responda. Si realiza esto dentro del procedimiento de ventana, puede que su IU no responda hasta que se complete la solicitud. Durante ese tiempo, la ventana no puede procesar la entrada del mouse o del teclado, volver a dibujarse o incluso cerrarse.

En lugar de eso, debe mover el trabajo a otro subproceso mediante una de las instalaciones multitarea integradas en Windows:

  • Cree un nuevo subproceso.
  • Use un grupo de subprocesos.
  • Use llamadas de E/S asincrónicas.
  • Use llamadas a procedimiento asincrónico.

Siguiente

Dibujo de la ventana