Introducción

Requisitos previos

Para el presente curso supondré que estás familiarizado con la programación en C y C++ y también con las aplicaciones y el entorno Windows, al menos al nivel de usuario. Sin embargo, no se requerirán muchos más conocimientos.

El curso pretende ser una explicación de la forma en que se realizan los programas en Windows usando el API. Las explicaciones de las funciones y los mensajes del API son meras traducciones del fichero de ayuda de WIN32 de Microsoft, y sólo se incluyen como complemento.

Para empezar, vamos a ponernos en antecedentes. Veamos primero algunas características especiales de la programación en Windows.

Independencia de la máquina

Los programas Windows son independientes de la máquina en la que se ejecutan (o al menos deberían serlo), el acceso a los dispositivos físicos se hace a través de interfaces, y nunca se accede directamente a ellos. Esta es una de las principales ventajas para el programador, ya que no hay que preocuparse por el modelo de tarjeta gráfica o de impresora, la aplicación funcionará con todas, y será el sistema operativo el que se encargue de que así sea.

Recursos

Un concepto importante es el de recurso. Desde el punto de vista de Windows, un recurso es todo aquello que puede ser usado por una o varias aplicaciones. Existen recursos físicos, que son los dispositivos que componen el ordenador, como la memoria, la impresora, el teclado o el ratón y recursos virtuales o lógicos, como los gráficos, los iconos o las cadenas de caracteres.

Por ejemplo, si nuestra aplicación requiere el uso de un puerto serie, primero debe averiguar si está disponible, es decir, si existe y si no lo está usando otra aplicación; y después lo reservará para su uso. Esto es necesario porque este tipo de recurso no puede ser compartido.

Lo mismo pasa con la memoria o con la tarjeta de sonido, aunque son casos diferentes. Por ejemplo, la memoria puede ser compartida, pero de una forma general, cada porción de memoria no puede compartirse, (al menos en los casos normales, veremos que es posible hacer aplicaciones con memoria compartida), y se trata de un recurso finito. Las tarjetas de sonido, dependiendo del modelo, podrán o no compartirse por varias aplicaciones. Otros recursos como el ratón y el teclado también se comparten, pero se asigna su uso automáticamente a la aplicación activa, a la que normalmente nos referiremos como la que tiene el "foco", es decir, la que mantiene contacto con el usuario.

Desde nuestro punto de vista, como programadores, también consideramos recursos varios componentes como los menús, los iconos, los cuadros de diálogo, las cadenas de caracteres, los mapas de bits, los cursores, etc. En sus programas, el Windows almacena separados el código y los recursos, dentro del mismo fichero, y estos últimos pueden ser editados por separado, permitiendo por ejemplo, hacer versiones de los programas en distintos idiomas sin tener acceso a los ficheros fuente de la aplicación.

Ventanas

La forma en que se presentan las aplicaciones Windows (al menos las interactivas) ante el usuario, es la ventana. Supongo que todos sabemos qué es una ventana: un área rectangular de la pantalla que se usa de interfaz entre la aplicación y el usuario.

Cada aplicación tiene al menos una ventana, la ventana principal, y todas las comunicaciones entre usuario y aplicación se canalizan a través de una ventana. Cada ventana comparte el espacio de la pantalla con otras ventanas, incluso de otras aplicaciones, aunque sólo una puede estar activa, es decir, sólo una puede recibir información del usuario.

Eventos

Los programas en Windows están orientados a eventos, esto significa que normalmente los programas están esperando a que se produzca un acontecimiento que les incumba, y mientras tanto permanecen aletargados o dormidos.

Un evento puede ser por ejemplo, el movimiento del ratón, la activación de un menú, la llegada de información desde el puerto serie, una pulsación de una tecla...

Esto es así porque Windows es un sistema operativo multitarea, y el tiempo del microprocesador ha de repartirse entre todos los programas que se estén ejecutando. Si los programas fueran secuenciales puros, esto no sería posible, ya que hasta que una aplicación finalizara, el sistema no podría atender al resto.

Estructura de programa secuencial:

Secuencial
Programa secuencial

Estructura de programa por eventos:

Eventos
Programa orientado a eventos

Proyectos

Debido a la complejidad de los programas Windows, normalmente los dividiremos en varios ficheros fuente, que compilaremos por separado y enlazaremos juntos.

Cada compilador puede tener diferencias, más o menos grandes, a la hora de trabajar con proyectos. Sin embargo creo que no deberías tener grandes dificultades para adaptarte a cada uno de ellos.

En el presente curso trabajaremos con el compilador de "Bloodshed", que es público y gratuito, y puede descargarse de Internet en la siguiente URL: http://www.bloodshed.net/.

Para crear un proyecto Windows usando este compilador elegiremos el menú "File/New Project". Se abrirá un cuadro de diálogo donde podremos elegir el tipo de proyecto. Elegiremos "Windows Application" y "C++ Project". A continuación pulsamos "Aceptar".

El compilador crea un proyecto con un fichero C++, con el esqueleto de una aplicación para una ventana, a partir de ahí empieza nuestro trabajo.

Convenciones

En parte para que no te resulte muy difícil adaptarte a la terminología de Windows, y a la documentación existente, y en parte para seguir mi propia costumbre, en la mayoría de los casos me referiré a componentes y propiedades de Windows con sus nombres en inglés. Por ejemplo, hablaremos de "button", "check box", "radio button", "list box", "combo box" o "property sheet", aunque algunas veces traduzca sus nombre a español, por ejemplo, "dialog box" se nombrará a menudo como "cuadro de diálogo".

Además hablaremos a menudo de ventanas "overlapped" o superponibles, que son las ventanas corrientes. Para el término "pop-up" he desistido de buscar una traducción.

También se usaran a menudo, con relación a "check boxes", términos ingleses como checked, unchecked o grayed, en lugar de marcado, no marcado o gris.

Owner-draw, es un estilo que indica que una ventana o control no es la encargada de actualizarse en pantalla, esa responsabilidad es transferida a la ventana dueña del control o ventana.

Para "bitmap" se usará a menudo la expresión "mapa de bits".

Controles

Los controles son la forma en que las aplicaciones Windows intercambian datos con el usuario. Normalmente se usan dentro de los cuadros de diálogo, pero en realidad pueden usarse en cualquier ventana.

Existen bastantes, y los iremos viendo poco a poco, al mismo tiempo que aprendemos a manejarlos.

Los más importantes y conocidos son:

  • control estatic: son etiquetas, marcos, iconos o dibujos.
  • control edit: permiten que el usuario introduzca datos alfanuméricos en la aplicación.
  • control list box: el usuario puede escoger entre varias opciones de una lista.
  • control combo box: es una combinación entre un edit y un list box.
  • control scroll bar: barras de desplazamiento, para la introducción de valores entre márgenes definidos.
  • control button: realizan acciones o comandos, de button de derivan otros dos controles muy comunes:
    • control check box: permite leer variables de dos estados "checked" o "unchecked"
    • control radio button: se usa en grupos, dentro de cada grupo sólo uno puede ser activado.

Comentarios de los usuarios (27)

jose
2010-07-11 16:03:33

vale callampa lops ejemplos no sirven

Joaquin Lopez
2011-07-14 19:08:10

Existe la posibilidad de manejar una grilla por API ?

Es un control muy importante y muy usado hoy en dia.

que waa
2012-05-23 03:01:32

jajaja ctm me cag.o en c++ mas de 50 lineas para generar una puta ventana... mientras que en java e lineas y la wea esta lista

Salvador Pozo
2012-05-23 15:32:54

Bueno, a cada uno lo suyo.

Efectivamente, para crear una aplicación GUI en C se requieren muchas líneas de código, pero cada lenguaje tiene sus ventajas y sus inconvenientes.

La ventaja de Java no es que haya que escribir menos líneas, sino que alguien se ha tomado la molestia de escribirlas por ti. La desventaja es que tendrás que aguantarte si lo que ese alguien ha escrito no está bien documentado, no te gusta, o no hace lo que esperas o tan bien o tan rápido como quisieras.

Una aplicación escrita en C siempre se ejecutará más rápido, o al menos podrá ser mejor optimizada que una en Java.

Una aplicación C no requiere la instalación de una máquina virtual. Funcionará mejor en máquinas con memoria limitada o en equipos antiguos. También funcionará mejor cuando el sistema esté ejecutando muchos programas, en equipos servidores, en aplicaciones de tiempo real, etc.

Por otra parte, Java puede ser más productivo, de modo que si todo lo anterior no es un problema para ti, Java puede ser una mejor opción.

El API que se explica aquí es la capa más baja del sistema operativo Windows, eso significa que cualquier compiador o intérprete de alto nivel terminará usando las funciones, estructuras y mensajes que se usan aquí. Eso sí, antes pasarán por más procesos intermedios. También significa que nos deja más tarea a los programadores, así que hay que valorar estas cosas antes de decidirse por un lenguaje u otro.

Suerte.

Antonio Arjona Melches
2013-01-17 22:23:05

Hola amigos.

Me gustaría seguir este curso, pero tengo el problema de ser usuario exclusivo de Linux, y en una maquina poco potente.

Las soluciones que se me ocurren son:

intentar instalar un IDE en Wine

Montar una maquina virtual, pero no tengo Windows Original, y no se si mi equipo lo aguantaría...

También me han hablado, de la compilación cruzada pero no encuentro referencias al respecto, y codeblocks no me reconoce el compilador Mingw.

Gracias.

Salvador Pozo
2013-01-22 19:14:18

Hola, Antonio:

Pues no tengo mucha experiencia con Linux, pero tal vez la mejor opción sería instalar wine. Ten en cuenta, en todo caso, que wine es una adaptación, y que algunas cosas no tienen por qué funcionar exactamente igual que como se describe en este curso.

Desde luego, la solución ideal sería instalar un Windows, pero eso ya depende de ti...

O tal vez usar alguna librería multiplataforma, aunque en ese caso este curso te servirá de poco. :)

Hasta pronto.

Antonio
2013-01-23 00:50:54

Gracias, ya tengo el problema resuelto...

Incluso la depuración.

Todo esta muy bien explicado en la pagina del compilador minGW:

http://mingw-cross.sourceforge.net

A parte acabo de conseguir un antiguo portátil 686 con Win98 y dev++, que para la mayor parte del curso seguro que es perfectamente valido...

Respecto a las librerías multiplataforma, tengo en el punto de mira GTK+, que es la que usa mi SO, pero todo a su debido tiempo...

ivan
2013-05-26 01:59:57

tengo un gran problema no tengo ninguna de las librerias

para poder utilizar todos estos recursos ayuda alguien

podria responderme y desirme donde puedo descargarla

esta es la fecha de hoy 25/5/2013-25 de mayo del 2013 ayudaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.

Salvador Pozo
2013-05-28 18:01:30

Las librerías forman parte del sistema operativo. Si tienes instalado Windows, seguro que dispones de todas las librerías necesarias.

Otra cosa son los ficheros de cabecera, y las librerías estáticas. Esos no están incluidos en el sistema operativo.

Sin embargo, sí suelen estar incluidos con el compilador.

Si descargas un IDE con MinGW, como Dev-C++ o mejor, Code::Blocks, se incluyen todos los ficheros necesarios para crear aplicaciones Windows.

ivan
2013-07-21 18:17:17

Garcias por aclararme las dudas.

pero no entiendo por que no me funcina ningun ejemplo

me faltan las las librerias parec

andres
2013-10-07 01:16:29

Hola, soy nuevo en esto, podrian ayudarme por favor

hice este programa:

http://imageshack.us/scaled/landing/5/zaok.png

como ven hay un campo de texto y un botón, lo que quiero es que va a ser tipo password, es decir que devuelva true si la clave es correcta y de lo contrario devuelva false, por favor lo necesito urgente, al menos me pueden dar una fuente que me pueda servir? ya sea de este curso o fuera

si necesitan el codigo fuente aqui esta:

http://pastebin.com/bM4v6QMN

gracias.

Steven R. Davidson
2013-10-08 17:42:00

Hola Andrés,

Como el cuadro de edición sirve para escribir contraseñas, podrías usar el estilo ES_PASSWORD que automáticamente muestra asteriscos (o puntos). Puedes consultar el capítulo 39 del curso del API de MS-Windows yendo a: http://winapi.conclase.net/curso/?cap=039c#CEDA_PASSWORD

Para leer la constraseña, necesitas invocar 'GetDlgItemText()' o incluso con 'SendMessage()' junto con el mensaje 'WM_GETTEXT', para obtener el texto de la ventana (el control en sí); otra forma es invocando 'GetWindowText()'. Puedes consultar el capítulo 7 del curso del API de MS-Windows yendo a: http://winapi.conclase.net/curso/?cap=007b#CED_MODIFICAR

Espero que esto te ayude.

Steven

andres
2013-10-08 22:17:32

Mira Steven gracias por tu ayuda pero aun tengo problemas.

Primero no se porque no me sirven los programas de esta web, cuando compilo el código no me devuelve error, pero al abrir el programa se abren dos shells sin ninguna función ni utilidad.

entonces lo que pasa es que tengo este código:

switch (message)                  
    {
           case WM_CREATE:{

hTextbox = CreateWindow(TEXT("EDIT"), TEXT("insert text here"),         /* Creamos el campo de texto */
                               WS_VISIBLE|WS_CHILD|WS_BORDER|ES_AUTOHSCROLL,
                               10,10,300,20,
                               hwnd, (HMENU) ID_TEXTBOX, NULL, NULL);
                               hpass = 151820;               /* Variable que contiene la contraseña */
                  hTexbox = CreateWindow(TEXT("button"), TEXT("Register"),          /*   Creamos el boton para comprobar la contraseña  */
                               WS_VISIBLE|WS_CHILD,
                               10,40,80,20,
                               hwnd, (HMENU) ID_BTN, NULL, NULL);
           SetMenu(hwnd, hMenubar);
           break;}
           
           case WM_COMMAND:{
...

hpass es la variable que contiene la contraseña previamente declarada, entonces lo que quiero es saber como utilizar por ejemplo WM_GETTEXT para copiar el texto que introdujeron en el campo de texto y lo guarde en otra variable por ejemplo en una llamada xpass, posteriormente compare las dos variables al clickar sobre el boton, y de ahi introducir un condicional que por ejemplo si son iguales muestre un mensaje con Messagebox() diciendo que son correctas de lo contrario (else) muestre un mensaje diciendo que no son correctas, eso es todo agradeceria si me ayudan.

Steven R. Davidson
2013-10-09 19:38:27

Hola Andrés,

Los primeros ejemplos completos y descargables no hacen mucho más que mostrar una ventana con un menú. Sin embargo, no debería haber ninguna consola abierta. Una posible razón de que esto ocurra sea porque ejecutas la aplicación directamente desde el IDE (Dev-C++, Code::Blocks, etc.). Por cierto, aconsejo construir el proyecto para lanzamiento ("release", en inglés) en lugar de depuración ("debug", en inglés).

Has dado con la solución al problema: "...compare las dos variables al clickar sobre el boton...". Hacemos esto bajo el procesamiento del mensaje 'WM_COMMAND' para el botón, 'hwndTexbox', que por cierto cambiaría este nombre a 'hwndRegistrar' o algo descriptivo. El código sería algo así,

case WM_COMMAND:
  if( (HWND)lParam == hwndRegistrar )
  {
    TCHAR pszContrasenna[100] = TEXT("");
    int nContrasenna = 0;

    // Obtenemos el texto del cuadro de edición
    int nCant = GetWindowText( hwndTextBox, pszContrasenna, 100 );
    pszContrasenna[nCant] = 0;  // Carácter nulo

    nContrasenna = _ttoi( pszContrasenna );  // #incluye <tchar.h>

    if( nContrasenna == hPass )
    {
      ...
    }
    else
    {
      ...
    }
  }
break;

La otra solución es guardar la contraseña como una cadena de caracteres y así no tienes que hacer conversiones a enteros; puedes comparar cadenas directamente y también puedes aceptar otros caracteres como contraseñas.

Espero que esto te ayude.

Steven

andres
2013-10-10 01:44:11

perdon, pero hice lo que me dijiste y me aparecio este error, no quiero molestar tanto con este programa pero ya verifique todo y no se cual es el error

In function 'LRESULT WindowProcedure(HWND__*, UINT, WPARAM, LPARAM)': 
too few arguments to function 'int MessageBoxA(HWND__*, const CHAR*, const CHAR*, UINT)' 
declared here
too few arguments to function 'int MessageBoxA(HWND__*, const CHAR*, const CHAR*, UINT)' 
declared here
[main.o] Error 1

aquí esta el código completo y el error esta en el código que pusiste, desactive el trozo de codigo del WM_COMMAND comentandolo y no dio error.

http://pastebin.com/tWCzZNPk

otra cosa porque no nos comunicamos por correo para no hacer spam, bueno me agregan a antony_4821@hotmail.com

andres
2013-10-10 03:31:41

ah no no, no se molesten en responderme, ignoren lo anterior, ya lo resolvi es que falto ponerle el titulo al messagebox por falta de argumentos, es decir en vez de

MessageBox(hwnd, "cracked", MB_OK );

era

MessageBox(hwnd, "cracked", "cracked", MB_OK | MB_ICONEXCLAMATION);

listo ya esta resuelto, MUCHAS GRACIAS

wary
2013-11-22 14:05:08

que tal amigos estoy creando un juego en borland c++ 5.02 pero no encuentro la manera de trabajar la parte grafica, el juego ya esta terminado pero no he encontrado la manera de iniciar con esa parte que es muy importante

Steven R. Davidson
2013-11-22 18:37:46

Hola Wary,

Si usas el API de MS-Windows, lo que te interesa es la GDI. En nuestro curso, puedes dirigirte al capítulo 16 yendo a: http://winapi.conclase.net/curso/?cap=016#inicio

Espero que este te oriente.

Steven

Milton Parra
2014-05-20 18:58:49

En el ejemplo win002.c se crea un menú desde el programa principal, mientras que en el ejemplo win003 se hace mediante un archivo de recursos "file.rc". Las instrucciones cambian en ambos ejemplos; mis inquietudes son:

1. Estas instrucciones son propias del lenguaje C o de Win32.

2. El archivo de recursos no lo veo relacionado ni en el programa principal, ni en el archivo de encabezado. Quién lo localiza, el compilador o Win32 y cómo.

3. Dónde puedo encontrar el archivo de ayuda de Win32 al que hacen referencia?

Salvador Pozo
2014-05-20 20:08:23

Hola Milton:

> Estas instrucciones son propias del lenguaje C o de Win32.

La mayor parte de las sentencias que se usan en estos ejemplos son llamadas a funciones del API de Windows.

Te recuerdo que para este curso se asume que se tienen conocimientos previos de C o C++. En ese caso te será bastante fácil distinguir qué son sentencias C (palabras reservadas del lenguaje) y llamadas a funciones del API.

> El archivo de recursos no lo veo relacionado ni en el programa principal, ni en el archivo de encabezado. Quién lo localiza, el compilador o Win32 y cómo.

Cuando se crean programas GUI es recomendable usar proyectos, de ese modo es el IDE el que se encarga de compilar cada fichero fuente con el compilador que le corresponde.

Los ficheros de recursos se compilan con un compilador especial, que generalmente se incluye con el compilador de C/C++. MingW incluye ese compilador, que genera un fichero con la extensión .res que posteriormente se enlaza con el resto de los ficheros objeto.

Dónde puedo encontrar el archivo de ayuda de Win32 al que hacen referencia?

Puedes consultar la documentación online del API en esta dirección:

http://msdn.microsoft.com/es-es/library/ms123401.aspx

Es mejor opción que el fichero, ya que está más actualizada.

En cualquier caso, puedes localizar el fichero hlp en Internet, busca "win32 api hlp" en Google, y elige una fuente fiable. En Windows 7 necesitarás instalar el programa winhlp32.exe para poder abrirlo, desde:

http://www.microsoft.com/es-ES/download/details.aspx?id=5143

Hasta pronto.

Steven R. Davidson
2014-05-20 20:26:03

Hola Milton,

1. Tienes que tener cuidado con el término "instrucciones". Si te refieres a las funciones, como por ejemplo, 'CreateMenu()', 'AppendMenu()', 'SetMenu()', etc., entonces son funciones propias del API de MS-Windows. Usamos el lenguaje C (o incluso C++) estándar, pero usamos las funciones propias de las bibliotecas de MS-Windows.

Si te refieres a los términos en el fichero de recursos como, 'BEGIN', 'END', 'POPUP', 'MENUITEM', 'SEPARATOR', etc., entonces son propios de la sintaxis del fichero de recursos que el compilador de recursos entiende.

2. El fichero de recursos es compilado por otro compilador (de recursos de MS-Windows). Básicamente, la idea es que se deja "hueco" dentro del ejecutable de la aplicación dedicado a guardar datos de diversos recursos. Puedes hacer esto manualmente con plantillas de recursos, como por ejemplo con la función 'LoadMenuIndirect()' y previamente creando una plantilla de menú de tipo, 'MENUTEMPLATE'. Existen otros tipos de plantillas y otras funciones para manipular tales plantillas en memoria. También existen tablas de cadenas de caracteres o de bytes, al igual que imágenes para crear cursores, iconos, etc..

3. Tenemos una "mini-referencia" en nuestra página. Puedes ir a:

- Funciones: http://winapi.conclase.net/curso/?winfun=lista#inicio

- Mensajes: http://winapi.conclase.net/curso/?winmsg=lista#inicio

- Macros: http://winapi.conclase.net/curso/?winmac=lista#inicio

- Estructuras: http://winapi.conclase.net/curso/?wintip=lista#inicio

- Constantes: http://winapi.conclase.net/curso/?wincte=lista#inicio

- Recursos: http://winapi.conclase.net/curso/?winrec=lista#inicio

También quedan accesibles en el curso del API de MS-Windows en el menú horizontal en la parte superior de cada página.

La referencia oficial es la documentación del API de MS-Windows que está en la página de MSDN: http://msdn.microsoft.com/es-ES/

Espero que todo esto te aclare las dudas.

Steven

ivan
2014-06-08 22:10:25

Hola podrian darme algun ejemplo sencillo de como reproducir sonidos esque lo necesito para crear un videojuego pero no se como reproducir un sonido tambien me gustaria saver reproducir algun video, porfavor....

ivan
2014-10-24 22:44:44

hola mi jente me e descardado code::block y cuando compilo para crear una aplicacion con la WinApi o OpenGl se abre una espantosa ventana de ms-dos alguna idea de como solucionar esto

ivan
2014-10-24 22:55:11

como puedo utilizar solo c++

como mi lenguage en con code::block con cualquier tipo de proyecto sin diferencia

Carlos
2016-06-27 20:02:13

Saludos. Quiero empezar con el curso, pero tengo una duda. ¿Es necesario C++ o se puede solo con C?. ¿Podrían recomendarme a la fecha de hoy 27/6/2016 que compilador es el más conveniente para aprender?.

Muchas gracias por su respuesta.

Jose Villalobos
2016-11-16 01:35:02

hola que tal queria saber si tienes un ejemplo de un programa que imprima una imagen en pantalla

Steven R. Davidson
2016-12-05 16:25:36

Hola José,

Los capítulos de la GDI, del 16 al 29, tratan de la parte gráfica del API de MS-Windows. Aconsejamos consultar el capítulo 23 ( http://winapi.conclase.net/curso/index.php?cap=023 ) para cargar imágenes y mostrarlas en una aplicación de MS-Windows. Principalmente, necesitas conseguir un manipulador de mapa de bits (HBITMAP) y luego cargarlo en un DC, tanto si es de memoria como si es directamente a la pantalla.

Espero que esto te oriente.

Steven