lunes, 12 de diciembre de 2016

Como hacer una Ventana simple en C++ (Corrección para Visual Studio)


Código para Visual Studio

  El video que encabeza esta entrada fue un tutorial publicado hace bastante tiempo, lastimosamente en el momento no me di cuenta de que el código no estaba estandarizado, por lo que solo funcionaba bajo el compilador que yo estaba usando, que en este caso era MinGW, algunos usuarios que vieron el tutorial intentaron compilar ese código en visual studio y como era de esperar no les funcionó. 
  La buena noticia es que los cambios son realmente mínimos y continuación les explico con detalle cada punto, como verán no es para nada largo.

LPCWSTR

  Estas son las iniciales en inglés de: Long Pointer to Constant Wide String, que básicamente en español denota una cadena de texto muy larga, MinGW no establece ninguna diferencia entre un array de caracteres y cualquier otro tipo de string, pero el compilador de Visual Studio si lo hace y casi todo el texto que se usa en la aplicación es de este tipo por lo tanto tendremos que crearlo de esta forma: 
LPCWSTR mitexto = L"Hola mundo";
o si lo vamos a colocar de forma anónima simplemente: L"Hola mundo"

   A continuación voy a listar los sectores en el código que deben ser modificados:
  • Nombre de la clase de ventana: en codeblocs hacemos algo así: char claseVtn[] = "clase de ventana",  pero en VS deberemos crearla variable de esta forma : LPCWSTR claseVtn = L"clase de ventana";
  • El segundo y tercer parámetro de MessageBox, como bien saben, el primer parámetro indica el texto que va a aparecer en el dialogo, y el segundo, el texto que aparece en la parte de arriba. los podemos pasar directamente de forma anónima, pero debemos hacerlo de la siguiente forma:  L"Texto en el message box", la llamada completa debería quedar así : MessageBox(HWND_DESKTOP, L"Texto en el message box", L"Titulo", MB_OK); si aún tienes dudas con esta función te dejo este enlace a la referencia completa en microsoft: MessageBox function
  • El segundo parámetro en "CreateWindow", o tercero si usamos "CreateWindowEx", este parámetro indica el texto que aparece como título de nuestra ventana, al igual que en el punto anterior lo podemos pasar de forma anónima agregandole una "L" al principio y fuera de las comillas, de la siguiente forma: L"Mi ventana", la llamada a la función debería quedar de la siguiente forma: CreateWindow(claseVtn, L"Mi ventana" .........) con el método tradicional pero si usamos la versión extendida sería así: CreateWindowEx(NULL, claseVtn, L"Mi ventana"........) Para más información te dejo la referencia para ambas funciones: CreateWindow()   CreateWindowEx()

stdafx.h

  Esta es una cabecera pre-compilada que se agrega por defecto en todos los proyectos de visual studio, hay que colocarla de otro modo nuestro código no va a compilar.

#include "stdafx.h"

  Si por alguna razón no queremos usarla, debemos hacer lo siguiente:
  • Clic con el botón secundario en el nombre del proyecto (no es donde dice "Solution") y hacemos clic en "Propiedades" (Properties si lo tienes en inglés)
  • Expande la sección que dice C/C++
  • Busca la sección que dice "Cabeceras precompiladas" ó "Precompiled Headers"
  • En la ventana principal, la opción "Cabecera precompilada" (Precompiled header si lo tienes en iglés) establece la opción de no usar cabeceras precompiladas


  Es de hacer notar que esa opción no afecta en nada el comportamiento de nuestra ventana, por lo que podemos dejar las opciones tal cual están por defecto y simplemente hacer el include.

LNK2019

  Una vez intentas realizar la compilación, te aparece el siguiente error:
LNK2019 unresolved external symbol _main referenced in function "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ)

Mas hacia la derecha te aparece, en la columna "File": MSVCRTD.lib

  Este es un error del enlazador, VS diferencia muy bien que archivos enlazar para una aplicación win32, hay dos formas de solucionar este error:
  1. Al momento de crear nuestro proyecto especifica: Win32 Project y no Win32 console Project
  2. Si ya creaste tu proyecto como aplicación de consola, haz lo siguiente: Haz clic secundario en el nombre de tu proyecto, luego en propiedades, expande la sección que dice "Linker" y en la ventana principal, donde dice : "Subsystem" cambia el valor que aparece "Console (/SUBSYSTEM:CONSOLE)" por "Windows (/SUBSYSTEM:WINDOWS)"

winProc must return a value

  Esto si se podría decir que es un error mío, ya que de la forma en la cual lo hice no es lo correcto, sin embargo no es algo grave para MinGW y por lo tanto no muestra ningún error. Sin embargo si nos fijamos "winProc" debería retornar un valor, ya que no comienza con "void", la forma de subsanarlo es muy simple, la función "DefWindowProc" la llamamos desde el "return", de la siguiente manera, al final de nuestro "proceso de ventana" :
return DefWindowProc(hwnd, msj, wparam, lparam);

  Esto como dije antes, es mas un error mío que una diferencia de compiladores, por lo que deberían hacerlo así siempre, sin importar si usas visual studio o no.

Eso es todo por ahora

   Con estas correcciones debería funcionar perfectamente en Visual Studio, si tienen algún otro problema, solo comenten tanto aquí como en el canal de youtube y yo con mucho gusto les aclaro lo antes posible.

Descargas




2 comentarios:

  1. Felicitaciones me gusto tu video y este blog explicas muy bien.

    ResponderEliminar
    Respuestas
    1. Gracias, hay un nuevo video en el canal acerca de este mismo tema, en él, enseño acerca de los controles de windows y como responder a algunos eventos

      Eliminar