Ficheros de recursos

Veamos ahora una forma más sencilla y más frecuente de implementar menús.

Lo normal es implementar los menús desde un fichero de recursos, el sistema que hemos visto sólo se usa en algunas ocasiones, para crear o modificar menús durante la ejecución de la aplicación.

Es importante adquirir algunas buenas costumbres cuando se trabaja con ficheros de recursos.

  1. Usaremos siempre etiquetas como identificadores para los ítems de los menús, y nunca valores numéricos literales.
  2. Crearemos un fichero de cabecera con las definiciones de los identificadores, en nuestro ejemplo se llamará "win003.h".
  3. Incluiremos este fichero de cabecera tanto en el fichero de recursos y como en el del código fuente de nuestra aplicación.

Partimos de un proyecto nuevo: win003. Pero usaremos el código modificado del ejemplo1.

Para ello creamos un nuevo proyecto de tipo GUI, al que llamaremos Win003, y copiamos el contenido de "ejemplo1.c" en un fichero vacío al que nombraremos como "win003.c".

A continuación crearemos el fichero de identificadores.

Añadimos el fichero de cabecera a nuestro proyecto. Desde Code::Blocks ésto se hace pulsando con el botón derecho del ratón "Archivo nuevo" o el menú de "Archivo->nuevo", nos preguntará si queremos añadir el archivo al proyecto, a lo que contestaremos que sí, y le pondremos un nombre, en este caso "win003.h".

Introducimos en é los identificadores:

#define CM_PRUEBA 100 
#define CM_SALIR 101

En el fichero "win003.c" añadimos la línea:

#include "win003.h"

Justo después de la línea "#include <windows.h>".

Ahora añadiremos el fichero de recursos. Para ello haremos lo mismo que hemos hecho con el fichero "ids.h", pero usaremos el nombre "win003.rc".

En la primera línea introducimos la siguiente línea:

#include "win003.h"

Y a continuación escribimos:

Menu MENU
BEGIN
   POPUP "&Principal"
      BEGIN
         MENUITEM "&Prueba", CM_PRUEBA
         MENUITEM SEPARATOR
         MENUITEM "&Salir", CM_SALIR
      END
END

En un fichero de recursos podemos crear toda la estructura de un menú fácilmente. Este ejemplo crea una barra de menú con una columna "Principal", con dos opciones: "Prueba" y "Salir", y con un separador entre ellas.

La sintaxis es sencilla, definimos el menú mediante una cadena identificadora, sin comillas, seguida de la palabra MENU. Entre las palabras BEGIN y END podemos incluir items, separadores u otras columnas. Para incluir columas usamos una sentencia del tipo POPUP seguida de la cadena que se mostrará como texto en el menú. Cada POPUP se comporta del mismo modo que un MENU.

Los ítems se crean usado la palabra MENUITEM seguida de la cadena que se mostrará en el menú, una coma, y el comando asignado a ese ítem, que puede ser un número entero, o, como en este caso, una macro definida.

Los separadores se crean usando MENUITEM seguido de la palabra SEPARATOR.

Observarás que las cadenas que se muestran en el menú contienen un símbolo & en su interior, por ejemplo "&Prueba". Este símbolo indica que la siguiente letra puede usarse para activar la opción del menú desde el teclado, usando la tecla [ALT] más la letra que sigue al símbolo &. Para indicar eso, en pantalla, esa letra se muestra subrayada, en este ejemplo "Prueba".

Ya podemos cerrar el cuadro de edición del fichero de recursos.

Para ver más detalles sobre el uso de este recurso puedes consultar las claves: MENU, POPUP y MENUITEM.

Cómo usar los recursos de menú

Ahora tenemos varias opciones para usar el menú que acabamos de crear.

Primero veremos cómo cargarlo y asignarlo a nuestra ventana, ésta es la forma que más se parece a la del ejemplo del capítulo anterior. Para ello basta con insertar este código antes de llamar a la función ShowWindow:

   HMENU hMenu; 
   ... 
   hMenu = LoadMenu(hInstance, "Menu");
   SetMenu(hWnd, hMenu);

O simplemente:

   SetMenu(hWnd, LoadMenu(hInstance, "Menu"));

La función LoadMenu se encarga de cargar el recurso de menú, para ello hay que proporcionarle un manipulador de la instancia a la que pertenece el recurso y el nombre del menú.

Otro sistema, más sencillo todavía, es asignarlo como menú por defecto de la clase. Para esto basta con la siguiente asignación:

   WNDCLASSEX wincl;
   ...
   wincl.lpszMenuName = "Menu"; 

Y por último, también podemos asignar un menú cuando creamos la ventana, especificándolo en la llamada a CreateWindowEx:

    hwnd = CreateWindowEx(
           0,
           "NUESTRA_CLASE",
           "Ejemplo 003",
           WS_OVERLAPPEDWINDOW,
           CW_USEDEFAULT,
           CW_USEDEFAULT,
           544,
           375,
           HWND_DESKTOP,
           LoadMenu(hInstance, "Menu"), /* Carga y asignación de menú */
           hInstance,
           NULL
    );

El tratamiento de los comandos procedentes del menú es igual que en el apartado anterior.

Ejemplo 3


  Nombre Fichero Fecha Tamaño Contador Descarga
D Ejemplo 3 win003.zip 2004-01-18 2433 bytes 1938

Comentarios de los usuarios (11)

Daniel
2009-12-27 08:18:45

Que tal, estoy apenas iniciando con este curso, y quisiera pedirle un favor, los ejemplos ya no estan disponibles para descarga, agradeceria mucho que los volviera a subir o en su defecto mandarmelos a mi correo.

De verdad que esta excelente el curso, muchas gracias y saludos!!!

pepe
2010-07-11 00:09:15

mismo problema con los ejemplos alguna posibilidad de conseguirlos?

Anónimo
2010-07-31 13:31:23

Si os descargáis el curso WinApi entero (en formato pdf), ahí están los ejemplos.

Saludos.

david tadeo
2011-01-22 04:27:55

hola, buenos los cursos, ya voy en elcapitulo 9, hechenle ganas y creen los ejemplos ustedes si no los pueden bajar, no es dificil si prestan atencion y mas aun si saben programar en C o C++ o algun otro lenguaje estructurado, eso les facilitaria mucho la comprension de estos cursos saludos y animo

ebfm
2013-02-12 21:01:45

Ya descargue el win003.zip pero la ventana se muestra sin el menú.

ebfm
2013-02-12 23:20:06

Acabo de descargar otro ejemplo empaquetado en zip, esta hecho en VCPP y utiliza el mismo método para crear los menús y estos no se muestran al ejecutar directamente el exe. Pero si funciona bien si lo ejecuto desde la ventana que me muestra winrar. Es decir sin desempaquetar.

EBFM
2013-02-15 16:40:12

Ya encontre mi problema. Los archivos no forman parte de un proyecto.

Alejandro
2014-07-08 09:51:19

A mí me sucede igual, el ejemplo 3 no genera Menú alguno. Leyendo el caso anterior, me pregunto: ¿qué se supone que he de hacer para incluir todos los archivos en un mismo proyecto?

Gracias

Steven R. Davidson
2014-07-08 16:26:24

Hola Alejandro,

Esto depende del IDE (Entorno Integrado de Desarrollo) que uses. Los ejemplos están hechos y probados con Code::Blocks, que de hecho el fichero del proyecto se incluye en los ejemplos de formato ZIP.

Si usas el proyecto que damos, no hay que hacer nada excepto construir (build) el proyecto: CTRL+F9. Cuando termine, ejecuta (run) el programa: CTRL+F10. Si no usas nuestro proyecto, entonces crea uno desde el menú: File->New->Project... En el cuadro de diálogo, elige "Win32 GUI project" como el tipo de proyecto; luego elige "frame based". Indica el nombre del proyecto y su ubicación. Ahora agrega los ficheros yendo al menú: Project->Add files...

Si usas otro IDE, entonces tendrás que seguir los pasos para crear un proyecto y agregar ficheros a ello, según te indique tal IDE. Típicamente, existe alguna opción para crear un proyecto de GUI usando el API de MS-Windows y luego otra opción para agregar ficheros a tal proyecto.

Espero que esto te oriente.

Steven

Angel Ferreira
2014-10-09 12:45:38

Hola buenos dias!

Quisiera saber si puedo contar con usted para el desarrollo de una barra de herramientas que tenga un menu con algunas particularidades.

Por favor aviseme si podemos conversar via Skype o a traves de otra herramienta.

saludos,

skype: aferreirag

Carlos Obregón
2015-02-27 18:58:50

Hola, Excelente pagina. Mi consulta es la siguiente, estoy usando Netbeans IDE 8.0.2 para aprender a usar WinAPI, en la parte de recursos de menu, no reconoce la extención rc y tampoco reconoce las palabras MENU, MENUITEM, POPUP, BEGIN, END. será que no puedo usar esto en netbeans, en codeblocks no ocurre ningún problema.