Ventana win32

Con el uso de C++ podemos acceder al API de Windows por lo que podemos crear aplicaciones a bajo nivel interactuando con el api win32, por lo general este método de programación es difícil de aprender por la gran cantidad de código que debemos escribir, en este tutorial veremos de manera sencilla como crear una ventana con win32.

Crear una ventana win32


Primero creamos un proyecto Visual C++ tipo win32 vacío, de esta manera:




Debemos agregar un archivo .cpp en el cual escribiremos nuestras primeras líneas de código, estas son:

#include <Windows.h>

int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR cmdLine, int cmdShow)
{

}

Acabamos de incluir los archivos necesarios para el funcionamiento de nuestra aplicación Window.h, también definimos el punto de entrada de nuestra aplicación la función wWinMain la cual procedemos a explicar:

WINAPI es la convención de llamada se refiere a la forma como serán tratados y liberados los parámetros de las funciones, no necesitamos profundizar en esto solo nos basta con saber que la mayoría de la funciones del api de Windows utilizan WINAPI que es un tipo definido para __stdcall.

HINSTANE es un identificador para la instancia de nuestra aplicación que estemos ejecutando, el segundo parámetro también es de este tipo pero en la actualidad no se usa.

LPSTR es un puntero a una cadena que contiene los argumentos pasados por línea de comandos, el último parámetro es de tipo int y nos indica cómo debe mostrarse la ventana, maximizada por ejemplo.

Registrar la clase de ventana


Creamos una estructura de tipo WNDCLASS para registrar la clase de ventana, esta contiene varios campos pero solo veremos los que son necesarios para crear una ventana, los demás los inicializaremos a cero.

WNDCLASS wc = {0};

wc.lpszClassName = L"class name";
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = wndProc;
wc.hInstance = hInst;

RegisterClass(&wc);

lpszClassName: nombre que asignaremos a la clase, el que deseemos.

style: estilos de clase, existen muchos otros, en este caso le indican a la ventana que debe volver a dibujarse cuando cambia de tamaño horizontal o vertical.

lpfnWndProc: puntero a la función que se encargara de manejar los mensajes que se produzcan en nuestra aplicación, por ejemplo cuando se cierra la ventana se producen varios mensajes o cuando la ventana cambia de tamaño.

HRESULT WINAPI wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
       switch (msg)
       {
       case WM_DESTROY:
             PostQuitMessage(0);
             break;
       default:
             return DefWindowProc(hWnd, msg, wParam, lParam);
       }

       return 0;
} 

Esta es la función que maneja los mensajes el parámetro HWND identifica a la ventana que produjo el mensaje, el UINT identifica el mensaje ejemplo WM_DESTROY se produce cuando se hace clic en el botón de cerrar la ventana, capturamos los mensajes con un switch si no procesaremos el mensaje debemos llamar a la función DefWindowProc la cual procesara los mensajes con la opción por defecto, los parámetros WPARAM y LPARAM contienen información concerniente al mensaje enviado.

hInstance: le asignamos la instancia de la aplicación.

Por último la función RegisterClass en la encargada de registrar la clase de ventana.

Crear la ventana


La función CreateWindow es la encargada de crear la ventana devuelve un HWND que se un identificador para la ventana, una vez creada podemos llamar a ShowWindow para mostrar la ventana pasamos como parámetros la ventana que queremos mostrar y cmdShow que indica cómo debe mostrarse la ventana, también debemos llamar a UpdateWindow para indicarle a la ventana que debe actualizarse.

HWND hWnd = CreateWindow(
       L"class name",       //Nombre de clase de ventana = wc.lpszClassName
       L"Primera Venatana", //Titulo de la ventana
       WS_OVERLAPPEDWINDOW, //Estilos para la ventana
       CW_USEDEFAULT, 0,    //Posicion x, y CW_USEDEFAULT = valor por defecto
       CW_USEDEFAULT, 0,    //Tamaño ancho y alto
       NULL, NULL,          //Ventana padre y menu
       hInst, NULL );       //Instancia

ShowWindow(hWnd, cmdShow);
UpdateWindow(hWnd);

Bucle de mensajes


Nuestra aplicación debe estar pendiente de los mensajes que se producen, cuando ocurre una acción, mover el ratón por ejemplo el sistema envía el mansaje apropiado para informarnos de esta acción, pero los mensajes no se envían directamente a la aplicación si no que son envidas a la cola de mensajes, por lo que debemos estar frecuentemente verificando su existe un mensaje en la cola de mensajes, lo haremos con un bucle while.

La función GetMessage escribe un mensaje de la cola de mensajes en la estructura MSG, esta función devuelve 0 si se ha recibido el mensaje WM_QUIT que se recibe cuando la ventana debe cerrarse con esto detendremos el while, se devolverá un valor distinto de 0 si es cualquier otro mensaje entonces lo enviaremos a la función que maneja los mensajes la cual definimos previamente, si hubo algún error el valor devuelto será -1 si deseamos manejar este error debemos modificar el bucle while para que cuando el valor devuelto sea -1 obtener el error y procesarlo según nos convenga.

MSG msg;

while (GetMessage(&msg, NULL, 0, 0))
{
       DispatchMessage(&msg);
}

Con esto finalizamos la creación de una ventana con el api de Windows o win32, hay muchas cosas más por aprender que iremos viendo poco a poco según vayan avanzando nuestros conocimientos, aquí les dejo el código  completo y nos vemos en la próxima.

Comentarios

Entradas populares de este blog

Conectar SQL Server con Java

Entrenar OpenCV en Detección de Objetos

Procesamiento de imágenes en OpenCV

Conociendo la clase cv::Mat de OpenCV

Acceso a la webcam con OpenCV