Winapi4

1576
© Julio de 2004, Salvador Pozo Coronado Con Clase: http:\winapi.conclase.net

description

aa

Transcript of Winapi4

  • Julio de 2004, Salvador Pozo Coronado

    Con Clase: http:\winapi.conclase.net

  • Tabla de contenido

    Tabla de contenido.

    Introduccin Requisitos previos

    Independencia de la mquina

    Recursos

    Ventanas

    Eventos

    Proyectos

    Convenciones

    Controles

    1 Componentes de una ventana

    El borde de la ventana

    Barra de ttulo

    Caja de minimizar

    Caja de maximizar

    Caja de cerrar

    Caja de control de men

    Men

    Barra de men

    Barra de desplazamiento horizontal

    Barra de desplazamiento vertical

    El rea de cliente

    2 Notacin hngara Ejemplos

    3 Estructura de un programa Windows GUI

    Ficheros de cabecera

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=999 (1 de 16) [25/07/2004 19:46:31]

  • Tabla de contenido

    Prototipos

    Funcin de entrada, WinMain

    Parmetros de entrada de WinMain

    Funcin WinMain tpica

    Declaracin

    Inicializacin

    Bucle de mensajes

    Definicin de funciones

    4 El procedimiento de ventana Sintaxis

    Prototipo de procedimiento de ventana

    Implementacin de procedimiento de ventana simple

    Primer ejemplo de programa Windows GUI

    5 Mens 1 Usando las funciones para insercin tem a tem

    Uso bsico de MessageBox

    Respondiendo a los mensajes del men

    Ejemplo 2

    Ficheros de recursos

    Cmo usar los recursos de men

    Ejemplo 3

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=999 (2 de 16) [25/07/2004 19:46:31]

  • Tabla de contenido

    6 Dilogo bsico Ficheros de recursos

    Procedimiento de dilogo

    Sintaxis

    Prototipo de procedimiento de dilogo

    Implementacin de procedimiento de dilogo para nuestro ejemplo

    Pasar parmetros a un cuadro de dilogo

    Ejemplo 4

    7 Control bsico Edit Fichero de recursos

    El procedimiento de dilogo y los controles edit

    Variables a editar en los cuadros de dilogo

    Iniciar controles edit

    Devolver valores a la aplicacin

    Aadir la opcin de cancelar

    Ejemplo 5

    Editar nmeros

    Fichero de recursos para editar enteros

    Variables a editar en los cuadros de dilogo

    Iniciar controles edit de enteros

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=999 (3 de 16) [25/07/2004 19:46:31]

  • Tabla de contenido

    Devolver valores a la aplicacin

    Ejemplo 6

    8 Control bsico ListBox Ficheros de recursos

    Iniciar controles listbox

    Devolver valores a la aplicacin

    Ejemplo 7

    9 Control bsico Button

    Ficheros de recursos

    Iniciar controles button

    Tratamiento de acciones de los controles button

    Ejemplo 8

    10 Control bsico Static Ficheros de recursos

    Iniciar controles static

    Tratamiento de acciones de los controles static

    Ejemplo 9

    11 Control bsico ComboBox Ficheros de recursos

    Iniciar controles ComboBox

    Devolver valores a la aplicacin

    Ejemplo 10

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=999 (4 de 16) [25/07/2004 19:46:31]

  • Tabla de contenido

    12 Control bsico Scrollbar Ficheros de recursos

    Iniciar controles Scrollbar

    Iniciar controles scrollbar: estructura SCROLLINFO

    Procesar los mensajes procedentes de controles Scrollbar

    Procesar mensajes de scrollbar usando SCROLLINFO

    Devolver valores a la aplicacin

    Ejemplo 11

    Ejemplo 12

    13 Control bsico Groupbox Ficheros de recursos

    Iniciar controles GroupBox

    Devolver valores a la aplicacin

    Ejemplo 13

    14 Control bsico Checkbox Ficheros de recursos

    Iniciar controles CheckBox

    Procesar mensajes de los CheckBox

    Devolver valores a la aplicacin

    Ejemplo 14

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=999 (5 de 16) [25/07/2004 19:46:31]

  • Tabla de contenido

    15 Control bsico RadioButton Ficheros de recursos

    Iniciar controles RadioButton

    Procesar mensajes de los RadioButtons

    Devolver valores a la aplicacin

    Ejemplo 15

    16 El GDI Objetos del GDI

    17 Objetos bsicos del GDI:El Contexto de dispositivo, DC

    Actualizar el rea de cliente de una ventana, el mensaje WM_PAINT

    Colores

    18 Objetos bsicos del GDI:La pluma (Pen)

    Plumas de Stock

    Plumas cosmticas y geomtricas

    Crear una pluma

    Seleccionar una pluma

    Destruir una pluma

    Ejemplo 16

    19 Funciones para el trazado de lneas

    Trazado de arcos, funcin Arc

    Curvas Bzier

    Funciones Poly

    Funcin LineDDA y funciones callback LineDDAProc

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=999 (6 de 16) [25/07/2004 19:46:31]

  • Tabla de contenido

    Ejemplo 17

    20 Objetos bsicos del GDI:El pincel (Brush)

    Pinceles lgicos Pinceles slidos

    Pinceles de Stock

    Pinceles de tramas (Hatch)

    Pinceles de patrones

    Crear un pincel

    Seleccionar un pincel

    Destruir un pincel

    Ejemplo 18

    21 Funciones para el trazado de figuras rellenas

    Pintando trozos de elipses, funciones Chord y Pie

    Modos de relleno de polgonos

    Ejemplo 19

    22 Objetos bsicos del GDI:La paleta (Palette)

    Capacidades de Color de los dispositivos

    Definiciones de valores de color

    Aproximaciones de colores y mezclas de pixels (dithering)

    Mezclas de colores (ROP)

    Paletas de colores

    La paleta por defecto

    Paleta lgica

    Paleta de sistema

    Ejemplo 20

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=999 (7 de 16) [25/07/2004 19:46:31]

  • Tabla de contenido

    23 Objetos bsicos del GDI:El Mapa de Bits (Bitmap)

    Tipos de mapas de bits

    Crear un mapa de bits

    Fichero de recursos

    Fichero BMP

    Mostrar un mapa de bits

    Funciones de visualizacin de mapas de bits

    BitBlt

    StretchBlt

    PlgBlt (Slo en Windows NT)

    (Slo en Windows NT)

    Cdigos ROP ternarios

    Cdigos ROP cudruples

    Pinceles creados a partir de mapas de bits PatBlt

    ExtFloodFill

    Estructuras de datos BITMAP

    Modos de estiramiento (stretch modes)

    Mapas de bits de stock

    Ejemplo 21

    24 Objetos bsicos del GDI:La Fuente (Font)

    Mostrar un texto simple

    Cambiar el color del texto

    Ejemplo 22

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=999 (8 de 16) [25/07/2004 19:46:31]

  • Tabla de contenido

    Crear fuentes personalizadas

    Altura y anchura media de carcter

    El ngulo de escape

    El ngulo de orientacin

    Peso

    Cursiva

    Subrayado

    Tachado

    Conjunto de caracteres

    Precisin de salida

    Precisin de recorte

    Calidad

    Paso y familia

    Nombre

    Fuentes de stock

    Alineamientos de texto

    Separacin de caracteres

    Medidas de cadenas

    Justificar texto

    Ejemplo 23

    25 Objetos bsicos del GDI:Rectngulos y Regiones

    Rectngulos

    Funciones para trabajar con rectngulos Asignar rectngulos

    Comparaciones de rectngulos

    Modificar rectngulos

    Operaciones con rectngulos

    Ejemplo 24

    Regiones

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=999 (9 de 16) [25/07/2004 19:46:31]

  • Tabla de contenido

    Funciones para regiones Crear regiones

    Combinar regiones

    Comparar regiones

    Rellenar regiones

    Mover una regin

    Comprobar posiciones

    Destruir regiones

    Ejemplo 25

    26 Objetos bsicos del GDI:El camino (Path)

    Crear un camino

    Operaciones con caminos

    Ejemplo 26

    27 Objetos bsicos del GDI:El recorte (Clipping)

    Regiones de recorte y el mensaje WM_PAINT

    Funciones relacionadas con el recorte

    Seleccionar regiones de recorte

    Caminos de recorte

    Ejemplo 27

    28 Objetos bsicos del GDI:Espacios de coordenadas y transformaciones

    Definiciones

    Transformaciones Traslaciones

    Cambio de escala

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=999 (10 de 16) [25/07/2004 19:46:31]

  • Tabla de contenido

    Rotaciones

    Cambio de ejes

    Reflexiones

    Aplicar transformaciones

    Combinar transformaciones

    Cambios de escala y plumas

    Ejemplo 28

    Ventanas y viewports Extensiones

    Orgenes

    Mapeos

    Modos de mapeo predefinidos

    Modo por defecto

    Transformaciones definidas por el usuario

    Modos grficos y sentido de los arcos

    Otras funciones

    Ejemplo 29

    29 Objetos bsicos del GDI:Plumas geomtricas

    Atributos de las plumas geomtricas Anchura

    Estilo de lnea

    Color

    Patrn

    Rayado

    Estilo de final (tapn)

    Estilo de unin

    Crear una pluma geomtrica

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=999 (11 de 16) [25/07/2004 19:46:31]

  • Tabla de contenido

    Seleccionar una pluma geomtrica

    Destruir una pluma geomtrica

    30 Objetos bsicos de usuario:El Caret

    Recibir y perder el foco

    Crear y destruir carets

    Mostrar y ocultar carets

    Procesar mensajes WM_PAINT

    Cambiar posicin de un caret

    Cambiar velocidad de parpadeo de un caret

    Ejemplo 31

    31 Objetos bsicos del usuario:El icono

    Punto activo

    Tamaos

    Asociar iconos a una aplicacin

    Tipos

    Iconos en ficheros de recursos

    Iconos en controles estticos

    Mostrar iconos

    Destruccin de iconos

    Ejemplo 32

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=999 (12 de 16) [25/07/2004 19:46:31]

  • Tabla de contenido

    32 Objetos bsicos del usuario:El cursor

    Cursor de clase

    Cursores de recursos

    Cursores estndar

    Similitud entre iconos y cursores

    El punto activo (Hot Spot)

    Crear cursores

    Posicin del cursor

    Apariencia

    Modificar el cursor de clase

    El mensaje WM_SETCURSOR

    Ocultar y mostrar

    Confinar el cursor

    Destruccin de cursores

    Ejemplo 33

    33 El ratn Capturar el ratn

    Configuracin

    Mensajes Mensajes del rea de cliente

    Mensajes del rea de no cliente

    Mensaje WM_NCHITTEST

    Mensaje WM_MOUSEACTIVATE

    Otros mensajes de ratn

    Mensaje WM_MOUSEWHEEL (Windows NT)

    Trazar eventos del ratn (Windows NT)

    Mensaje WM_MOUSELEAVE (Windows NT)

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=999 (13 de 16) [25/07/2004 19:46:31]

  • Tabla de contenido

    Mensaje WM_MOUSEHOVER (Windows NT)

    Ejemplo 34

    Arrastrar objetos

    Ejemplo 35

    34 El teclado El Foco del teclado

    Ventanas inhibidas

    Ejemplo 36

    Mensajes de pulsacin de teclas

    Nombres de teclas

    El bucle de mensajes

    Ejemplo 37

    Mensajes de carcter Teclas muertas

    Estado de teclas

    Ejemplo 38

    Hot keys

    Ejemplo 39

    Cdigos de teclas virtuales

    35 Cadenas Recursos de cadenas Fichero de recursos

    Cargar cadenas desde recursos

    Funciones para cadenas

    Ejemplo 40

    36 Aceleradores Recursos de aceleradores Fichero de recursos

    Cargar aceleradores desde recursos

    Bucle de mensajes para usar aceleradores

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=999 (14 de 16) [25/07/2004 19:46:31]

  • Tabla de contenido

    Crear tablas de aceleradores sin usar recursos

    Combinar aceleradores y mens

    Aceleradores globales

    Diferencia entre acelerador y men

    Ejemplo 41

    37 Mens 2 Marcas en mens Mens como checkboxes

    Mens como radiobuttons

    Ejemplo 42

    Inhibir y oscurecer tems

    Ejemplo 43

    Ms sobre ficheros de recursos

    Sentencia MENUITEM y POPUP

    Detalles sobre cadenas de tems

    Sentencia MENUEX

    Items marcados y no marcados

    Items activos, inactivos u oscurecidos

    Separadores y lneas de ruptura

    Cargar recursos

    tems por defecto

    Ejemplo 44

    Mens flotantes o contextuales

    Ejemplo 45

    Acceso por teclado Mnemnicos

    Aceceso de teclado estndar

    Aceleradores

    Modificar mens

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=999 (15 de 16) [25/07/2004 19:46:31]

  • Tabla de contenido

    El men de sistema Modificar el men de sistema

    Ejemplo 46

    Destruccin de mens

    Mensajes de men

    Mapas de bits en tems de men

    Modificar mapas de bits de check

    Items de mapas de bits

    Ejemplo 47

    Glosario

    Tabla de contenido

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=999 (16 de 16) [25/07/2004 19:46:31]

  • Introduccin

    Introduccin

    Requisitos previos

    Para el presente curso supondr que ests familiarizado con la programacin en C y C++ y tambin con las aplicaciones y el entorno Windows, al menos al nivel de usuario. Sin embargo, no se requerirn muchos ms conocimientos.

    El curso pretende ser una explicacin 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 slo se incluyen como complemento.

    Para empezar, vamos a ponernos en antecedentes. Veamos primero algunas caractersticas especiales de la programacin en Windows.

    Independencia de la mquina

    Los programas Windows son independientes de la mquina en la que se ejecutan (o al menos deberan serlo), el acceso a los dispositivos fsicos se hace a travs 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 grfica o de impresora, la aplicacin 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 fsicos, que son los dispositivos que componen el ordenador, como la memoria, la impresora, el teclado o el ratn y recursos virtuales o lgicos, como los grficos, los iconos o las cadenas de caracteres.

    Por ejemplo, si nuestra aplicacin requiere el uso de un puerto serie, primero debe averiguar si est disponible, es decir, si existe y si no lo est usando otra aplicacin; y despus 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

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=000 (1 de 5) [25/07/2004 19:46:32]

  • Introduccin

    general, cada porcin 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, podrn o no compartirse por varias aplicaciones. Otros recursos como el ratn y el teclado tambin se comparten, pero se asigna su uso automticamente a la aplicacin 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, tambin consideramos recursos varios componentes como los mens, los iconos, los cuadros de dilogo, las cadenas de caracteres, los mapas de bits, los cursores, etc. En sus programas, el Windows almacena separados el cdigo 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 aplicacin.

    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 aplicacin y el usuario.

    Cada aplicacin tiene al menos una ventana, la ventana principal, y todas las comunicaciones entre usuario y aplicacin se canalizan a travs de una ventana. Cada ventana comparte el espacio de la pantalla con otras ventanas, incluso de otras aplicaciones, aunque slo una puede estar activa, es decir, slo una puede recibir informacin del usuario.

    Eventos

    Los programas en Windows estn orientados a eventos, esto significa que normalmente los programas estn 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 ratn, la activacin de un men, la llegada de informacin desde el puerto serie, una pulsacin 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 estn

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=000 (2 de 5) [25/07/2004 19:46:32]

  • Introduccin

    ejecutando. Si los programas fueran secuenciales puros, esto no sera posible, ya que hasta que una aplicacin finalizara, el sistema no podra atender al resto.

    Ejemplo de programa secuencial:

    Ejemplo de programa por 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, ms o menos grandes, a la hora de trabajar con proyectos. Sin embargo creo que no deberas tener grandes dificultades para adaptarte a cada uno de ellos.

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=000 (3 de 5) [25/07/2004 19:46:32]

  • Introduccin

    En el presente curso trabajaremos con el compilador de "Bloodshed", que es pblico 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 dilogo donde podremos elegir el tipo de proyecto. Elegiremos "Windows Application" y "C++ Project". A continuacin pulsamos "Aceptar".

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

    Convenciones

    En parte para que no te resulte muy difcil adaptarte a la terminologa de Windows, y a la documentacin existente, y en parte para seguir mi propia costumbre, en la mayora de los casos me referir a componentes y propiedades de Windows con sus nombres en ingls. Por ejemplo, hablaremos de "button", "check box", "radio button", "list box", "combo box" o "property sheet", aunque algunas veces traduzca sus nombre a espaol, por ejemplo, "dialog box" se nombrar a menudo como "cuadro de dilogo".

    Adems hablaremos a menudo de ventanas "overlapped" o superponibles, que son las ventanas corrientes. Para el trmino "pop-up" he desistido de buscar una traduccin.

    Tambin se usaran a menudo, con relacin a "check boxes", trminos 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 duea del control o ventana.

    Para "bitmap" se usar a menudo la expresin "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 dilogo, pero en realidad pueden usarse en cualquier ventana.

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

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=000 (4 de 5) [25/07/2004 19:46:32]

  • Introduccin

    aprendemos a manejarlos.

    Los ms importantes y conocidos son:

    l control estatic: son etiquetas, marcos, iconos o dibujos.l control edit: permiten que el usuario introduzca datos alfanumricos en

    la aplicacin.l control list box: el usuario puede escoger entre varias opciones de una

    lista.l control combo box: es una combinacin entre un edit y un list box.l control scroll bar: barras de desplazamiento, para la introduccin de

    valores entre mrgenes definidos.l control button: realizan acciones o comandos, de button de derivan

    otros dos controles muy comunes: m control check box: permite leer variables de dos estados

    "checked" o "unchecked"m control radio button: se usa en grupos, dentro de cada grupo

    slo uno puede ser activado.

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=000 (5 de 5) [25/07/2004 19:46:32]

  • 1 Componentes ventana

    Captulo 1 Componentes de una ventana

    Veamos ahora los elementos que componen una ventana, aunque ms adelante veremos que no todos tienen por qu estar presentes en todas las ventanas.

    El borde de la ventana

    Hay varios tipos, dependiendo de que estn o no activas las opciones de cambiar el tamao de la ventana. Se trata de un rea estrecha alrededor de la ventana que permite cambiar su tamao (1).

    Barra de ttulo

    Zona en la parte superior de la ventana que contiene el icono y el ttulo de la ventana, esta zona tambin se usa para mover la ventana a travs de la pantalla, y mediante doble clic, para cambiar entre el modo maximizado y tamao normal (2).

    Caja de minimizar

    Pequea rea cuadrada situada en la parte derecha de la barra de ttulo que sirve para disminuir el tamao de la ventana. Antes de la aparicin del Windows 95 la ventana se converta a su forma icnica, pero desde la aparicin del Windows 95 los iconos desaparecieron, la ventana se oculta y slo permanece un botn en la barra de estado (3).

    Caja de maximizar

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=001 (1 de 3) [25/07/2004 19:46:32]

  • 1 Componentes ventana

    Pequea rea cuadrada situada en la parte derecha de la barra de ttulo que sirve para agrandar la ventana para que ocupe toda la pantalla. Cuando la ventana est maximizada, se sustituye por la caja de restaurar (4).

    Caja de cerrar

    Pequea rea cuadrada situada en la parte derecha de la barra de ttulo que sirve para cerrar la ventana. (5)

    Caja de control de men

    Pequea rea cuadrada situada en la parte izquierda de la barra de ttulo, normalmente contiene el icono de la ventana, y sirve para desplegar el men del sistema (6).

    Men

    O men del sistema. Se trata de una ventana especial que contiene las funciones comunes a todas las ventanas, tambin accesibles desde las cajas y el borde, como minimizar, restaurar, maximizar, mover, cambiar tamao y cerrar. Este men se despliega al pulsar sobre la caja de control de men.

    Barra de men

    Zona situada debajo de la barra de ttulo, contiene los mens de la aplicacin (7).

    Barra de scroll horizontal

    Barra situada en la parte inferior de la ventana, permite desplazar horizontalmente la vista del rea de cliente (8).

    Barra de scroll vertical

    Barra situada en la parte derecha de la ventana, permite desplazar verticalmente la vista del rea de cliente (9).

    El rea de cliente

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=001 (2 de 3) [25/07/2004 19:46:32]

  • 1 Componentes ventana

    Es la zona donde el programador sita los controles, y los datos para el usuario. En general es toda la superficie de la ventana lo que no est ocupada por las zonas anteriores (10).

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=001 (3 de 3) [25/07/2004 19:46:32]

  • 2 Notacin Hngara

    Captulo 2 Notacin Hngara

    La notacin hngara es un sistema usado normalmente para crear los nombres de variables cuando se programa en Windows. Es el sistema usado en la programacin del sistema operativo, y tambin por la mayora de los programadores. A veces tambin usaremos este sistema en algunos ejemplos de este curso.

    Consiste en prefijos en minsculas que se aaden a los nombres de las variables, y que indican su tipo. El resto del nombre indica, lo ms claramente posible, la funcin que realiza la variable.

    Prefijo Significadob Booleanoc Carcter (un byte)dw Entero largo de 32 bits sin signo (DOBLE WORD)f Flags empaquetados en un entero de 16 bitsh Manipulador de 16 bits (HANDLE)l Entero largo de 32 bitslp Puntero a entero largo de 32 bitslpfn Puntero largo a una funcin que devuelve un enterolpsz Puntero largo a una cadena terminada con ceron Entero de 16 bitsp Puntero a entero de 16 bitspt Coordenadas (x, y) empaquetadas en un entero de 32 bitsrgb Valor de color RGB empaquetado en un entero de 32 bitssz Cadena terminada en cerow Entero corto de 16 bits sin signo (WORD)Ejemplos

    nContador: la variable es un entero que se usar como contador.

    szNombre: una cadena terminada con cero que almacena un nombre.

    bRespuesta: una variable booleana que almacena una respuesta.

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=002 [25/07/2004 19:46:33]

  • 3 Estructura de programa

    Captulo 3 Estructura de un programa Windows GUI

    Hay algunas diferencias entre la estructura de un programa C/C++ normal, y la correspondiente a un programa Windows GUI. Algunas de estas diferencias se deben a que los programas GUI ests basados en mensajes, otros son sencillamente debidos a que siempre hay un determinado nmero de tareas que hay que realizar.

    // Ficheros include:#include

    // Prototipos:LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

    // Funcin de entrada:int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow){ // Declaracin: // Inicializacin: // Bucle de mensajes: return Message.wParam;}

    // Definicin de funciones:

    Cabeceras

    Lo primero es lo primero, para poder usar las funciones del API de Windows hay que incluir al menos un fichero de cabecera, pero generalmente no bastar con uno.

    El fichero lo que hace es incluir la mayora de los ficheros de cabecera corrientes en aplicaciones GUI, pero podemos incluir slo los que necesitemos, siempre que sepamos cuales son. Por ejemplo, la funcin WinMain est declarada en el fichero de cabecera winbase.h.

    Generalmente esto resultar incmodo, ya que para cada nueva funcin, mensaje o estructura tendremos que comprobar, y si es necesario, incluir nuevos ficheros. Es mejor usar windows.h directamente.

    Prototipos

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=003 (1 de 5) [25/07/2004 19:46:34]

  • 3 Estructura de programa

    Cada tipo (o clase) de ventana que usemos en nuestro programa (normalmente slo ser una), o cada cuadro de dilogo (de estos puede haber muchos), necesitar un procedimiento propio, que deberemos declarar y definir. Siguiendo la estructura de un programa C, esta es la zona normal de declaracin de prototipos.

    Funcin de entrada, WinMain

    La funcin de entrada de un programa Windows es "WinMain", en lugar de la conocida "main". Normalmente, la definicin de esta funcin cambia muy poco de una aplicaciones a otras. Se divide en tres partes claramente diferenciadas: declaracin, inicializacin y bucle de mensajes.

    Parmetros de entrada de "WinMain"

    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)

    La funcin WinMain tiene cuatro parmetros de entrada:

    l hInstance es un manipulador para la instancia del programa que estamos ejecutando. Cada vez que se ejecuta una aplicacin, Windows crea una Instancia para ella, y le pasa un manipulador de dicha instancia a la aplicacin.

    l hPrevInstance es un manipulador a instancias previas de la misma aplicacin. Como Windows es multitarea, pueden existir varias versiones de la misma aplicacin ejecutndose, varias instancias. En Windows 3.1, este parmetro nos serva para saber si nuestra aplicacin ya se estaba ejecutando, y de ese modo se podan compartir los datos comunes a todas las instancias. Pero eso era antes, ya que en Win32 usa un segmento distinto para cada instancia y este parmetro es siempre NULL, slo se conserva por motivos de compatibilidad.

    l lpszCmdParam, esta cadena contiene los argumentos de entrada del comando de lnea.

    l nCmdShow, este parmetro especifica cmo se mostrar la ventana. Para ver sus posibles valores consultar valores de ncmdshow. Se recomienda no usar este parmetro en la funcin ShowWindow la primera vez que se sta es llamada. En su lugar debe usarse el valor SW_SHOWDEFAULT.

    Funcin WinMain tpica

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=003 (2 de 5) [25/07/2004 19:46:34]

  • 3 Estructura de programa

    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow){ /* Declaracin: */ HWND hwnd; MSG mensaje; WNDCLASSEX wincl;

    /* Inicializacin: */ /* Estructura de la ventana */ wincl.hInstance = hInstance; wincl.lpszClassName = "NUESTRA_CLASE"; wincl.lpfnWndProc = WindowProcedure; wincl.style = CS_DBLCLKS; wincl.cbSize = sizeof (WNDCLASSEX);

    /* Usar icono y puntero por defecto */ wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION); wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION); wincl.hCursor = LoadCursor (NULL, IDC_ARROW); wincl.lpszMenuName = NULL; wincl.cbClsExtra = 0; wincl.cbWndExtra = 0; wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Registrar la clase de ventana, si falla, salir del programa */ if(!RegisterClassEx(&wincl)) return 0;

    hwnd = CreateWindowEx( 0, "NUESTRA_CLASE", "Ejemplo 001", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 544, 375, HWND_DESKTOP, NULL, hThisInstance, NULL );

    ShowWindow(hwnd, SW_SHOWDEFAULT); /* Bucle de mensajes: */ while(TRUE == GetMessage(&mensaje, 0, 0, 0)) { TranslateMessage(&mensaje); DispatchMessage(&mensaje); }

    return mensaje.wParam;}

    Declaracin

    En la primera zona declararemos las variables que necesitamos para nuestra

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=003 (3 de 5) [25/07/2004 19:46:34]

  • 3 Estructura de programa

    funcin WinMain, que como mnimo sern tres:

    l HWND hWnd, un manipulador para la ventana principal de la aplicacin. Ya sabemos que nuestra aplicacin necesitar al menos una ventana.

    l MSG Message, una variable para manipular los mensajes que lleguen a nuestra aplicacin.

    l WNDCLASSEX wincl, una estructura que se usar para registrar la clase particular de ventana que usaremos en nuestra aplicacin. Existe otra estructura para registrar clases que se usaba antiguamente, pero que ha sido desplazada por esta nueva versin, se trata de WNDCLASS.

    Inicializacin

    Esta zona se encarga de registrar la clase o clases de ventana, crear la ventana y visualizarla en pantalla.

    Para registrar la clase primero hay que rellenar adecuadamente la estructura WNDCLASSEX, que define algunas caractersticas que sern comunes a todas las ventanas de una misma clase, como color de fondo, icono, men por defecto, el procedimiento de ventana, etc. Despus hay que llamar a la funcin RegisterClassEx.

    En el caso de usar una estructura WNDCLASS se debe registrar la clase usando la funcin RegisterClass.

    A continuacin se crea la ventana usando la funcin CreateWindowEx, la funcin CreateWindow ha cado prcticamente en desuso. Cualquiera de estas dos funciones nos devuelve un manipulador de ventana que podemos necesitar en otras funciones, sin ir ms lejos, la siguiente.

    Pero esto no muestra la ventana en la pantalla. Para que la ventana sea visible hay que llamar a la funcin ShowWindow. La primera vez que se llama a sta funcin, despus de crear la ventana, se puede usar el parmetro nCmdShow de WinMain como parmetro o mejor an, como se recomienda por Windows, el valor SW_SHOWDEFAULT.

    Bucle de mensajesEste es el ncleo de la aplicacin, como se ve en el ejemplo el programa permanece en este bucle mientras la funcin GetMessage retorne con un valor

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=003 (4 de 5) [25/07/2004 19:46:34]

  • 3 Estructura de programa

    TRUE.

    while(TRUE == GetMessage(&mensaje, 0, 0, 0)) { TranslateMessage(&mensaje); DispatchMessage(&mensaje); }

    Este es el bucle de mensajes recomendable, aunque no sea el que se usa habitualmente. La razn es que la funcin GetMessage puede retornar tres valores: TRUE, FALSE -1. El valor -1 indica un error, as que en este caso se debera abandonar el bucle.

    El bucle de mensajes que encontraremos habitualmente es este:

    while(GetMessage(&mensajee, 0, 0, 0)) { TranslateMessage(&mensaje); DispatchMessage(&mensaje); }

    NOTA: El problema con este bucle es que si GetMessage regresa con un valor -1, que indica un error, la condicin del "while" se considera verdadera, y el bucle contina. Si el error es permanente, el programa jams terminar.

    La funcin TranslateMessage se usa para traducir los mensajes de teclas virtuales a mensajes de carcter. Veremos esto con ms detalle en el captulo dedicado al teclado (cap. 34).

    Los mensajes traducidos se reenvan a la lista de mensajes del proceso, y se recuperarn con las siguientes llamadas a GetMessage.

    La funcin DispatchMessage enva el mensaje al procedimiento de ventana, donde ser tratado adecuadamente. El prximo captulo est dedicado al procedimiento de ventana, y al final de l estaremos en disposicin de crear nuestro primer programa Windows.

    Definicin de funciones

    En esta parte definiremos, entre otras cosas, los procedimientos de ventana, que se encargan de procesar los mensajes que lleguen a cada ventana.

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=003 (5 de 5) [25/07/2004 19:46:34]

  • 4 Proc. de ventana

    Captulo 4 El procedimiento de ventana

    Cada ventana tiene una funcin asociada, esta funcin se conoce como procedimiento de ventana, y es la encargada de procesar adecuadamente todos los mensajes enviados a una determinada clase de ventana. Es la responsable de todo lo relativo al aspecto y al comportamiento de una ventana.

    Normalmente, estas funciones estn basadas en una estructura "switch" donde cada "case" corresponde aun determinado tipo de mensaje.

    Sintaxis

    LRESULT CALLBACK WindowProcedure( HWND hwnd, // Manipulador de ventana UINT msg, // Mensaje WPARAM wParam, // Parmetro palabra, vara LPARAM lParam // Parmetro doble palabra, vara );

    l hwnd es el manipulador de la ventana a la que est destinado el mensaje.l msg es el cdigo del mensaje.l wParam es el parmetro de tipo palabra asociado al mensaje.l lParam es el parmetro de tipo doble palabra asociado al mensaje.

    Podemos considerar este prototipo como una plantilla para crear nuestros propios procedimientos de ventana. El nombre de la funcin puede cambiar, pero el valor de retorno y los parmetros deben ser los mismos. El miembro lpfnWndProc de la estructura WNDCLASS es un puntero a una funcin de este tipo, esa funcin es la que se encargar de procesar todos los mensajes para esa clase de ventana. Cuando registremos nuestra clase de ventana, tendremos que asignar a ese miembro el puntero a nuestro procedimiento de ventana.

    Para ms detalles sobre la funcin de procedimiento de ventana, consultar WindowProc.

    Prototipo de procedimiento de ventana

    LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);

    Implementacin de procedimiento de ventana simple

    /* Esta funcin es llamada por la funcin del API DispatchMessage() */LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){ switch (msg) /* manipulador del mensaje */

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=004 (1 de 2) [25/07/2004 19:46:34]

  • 4 Proc. de ventana

    { case WM_DESTROY: PostQuitMessage(0); /* enva un mensaje WM_QUIT a la cola de mensajes */ break; default: /* para los mensajes de los que no nos ocupamos */ return DefWindowProc(hwnd, msg, wParam, lParam); } return 0;}

    En general, habr tantos procedimientos de ventana como programas diferentes y todos sern distintos, pero tambin tendrn algo en comn: todos ellos procesarn los mensajes que lleguen a una clase de ventana.

    En este ejemplo slo procesamos un tipo de mensaje, se trata de WM_DESTROY que es el mensaje que se enva a una ventana cuando se recibe un comando de cerrar, ya sea por men o mediante el icono de aspa en la esquina superior derecha de la ventana.

    Este mensaje slo sirve para informar a la aplicacin de que el usuario tiene la intencin de abandonar la aplicacin, y le da una oportunidad de dejar las cosas en su sitio: cerrar ficheros, liberar memoria, guardar variables, etc. Incluso, la aplicacin puede decidir que an no es el momento adecuado para abandonar la aplicacin. En el caso del ejemplo, efectivamente cierra la aplicacin, y lo hace envindole un mensaje WM_QUIT, mediante la funcin PostQuitMessage.

    El resto de los mensajes se procesan en el caso "default", y simplemente se cede su tratamiento a la funcin del API que hace el proceso por defecto para cada mensaje, DefWindowProc.

    Este es el camino que sigue el mensaje WM_QUIT cuando llega, ya que el proceso por defecto para este mensaje es cerrar la aplicacin.

    En posteriores captulos veremos como se complica paulatinamente esta funcin, aadiendo ms y ms mensajes.

    Primer ejemplo de programa Windows

    Ya estamos en condiciones de crear nuestro primer programa Windows, que slo mostrar una ventana en pantalla.

    Nombre Fichero Fecha Tamao Descarga

    Ejemplo 1 win001.zip 2004-01-18 1968 bytes

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=004 (2 de 2) [25/07/2004 19:46:34]

  • 5 Mens 1

    Captulo 5 Mens 1

    Ahora que ya sabemos hacer el esqueleto de una aplicacin Windows, veamos el primer medio para comunicarnos con ella.

    Supongo que todos sabemos lo que es un men: se trata de una ventana un tanto especial, del tipo pop-up, que contiene una lista de comandos u opciones entre las cuales el usuario puede elegir.

    Cuando se usan en una aplicacin, normalmente se agrupan varios mens bajo una barra horizontal, (que no es otra cosa que un men), dividida en varias zonas o tems.

    Cada tem de un men, (salvo los separadores y aquellos que despliegan nuevos mens), tiene asociado un identificador. El valor de ese identificador se usar por la aplicacin para saber qu opcin se activ por el usuario, y decidir las acciones a tomar en consecuencia.

    Existen varias formas de aadir un men a una ventana, veremos cada una de ellas por separado.

    Tambin es posible desactivar o inhibir algunas opciones para que no estn disponibles para el usuario.

    Usando las funciones para insercin tem a tem

    Este es el sistema ms rudimentario, pero como ya veremos en el futuro, en ocasiones puede ser muy til. Empezaremos viendo este sistema porque ilustra mucho mejor la estructura de los mens.

    Tomemos el ejemplo del captulo anterior y definamos algunas constantes:

    #define CM_PRUEBA 100#define CM_SALIR 101

    Y aadamos la declaracin de una funcin en la zona de prototipos:

    void InsertarMenu(HWND);

    Al final del programa aadimos la definicin de esta funcin:

    void InsertarMenu(HWND hWnd){ HMENU hMenu1, hMenu2; hMenu1 = CreateMenu(); /* Manipulador de la barra de men */ hMenu2 = CreateMenu(); /* Manipulador para el primer men pop-up */

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=005 (1 de 7) [25/07/2004 19:46:35]

  • 5 Mens 1

    AppendMenu(hMenu2, MF_STRING, CM_PRUEBA, "&Prueba"); /* 1 tem */ AppendMenu(hMenu2, MF_SEPARATOR, 0, NULL); /* 2 tem (separador) */ AppendMenu(hMenu2, MF_STRING, CM_SALIR, "&Salir"); /* 3 tem */ /* Insercin del men pop-up */ AppendMenu(hMenu1, MF_STRING | MF_POPUP, (UINT)hMenu2, "&Principal"); SetMenu (hWnd, hMenu1); /* Asigna el men a la ventana hWnd */}

    Y por ltimo, slo nos queda llamar a nuestra funcin, insertaremos sta llamada justo antes de visualizar la ventana.

    ... InsertarMenu(hWnd); ShowWindow(hWnd, SW_SHOWDEFAULT);...

    Veamos cmo funciona "InsertarMenu".

    La primera novedad son las variables del tipo HMENU. HMENU es un tipo de manipulador especial para mens. Necesitamos dos variables de este tipo, una para manipular la barra de men, hMenu1. La otra para manipular cada uno de los mens pop-up, en este caso slo uno, hMenu2.

    De momento haremos una barra de men con un nico elemento que ser un men pop-up. Despus veremos como implementar mens ms complejos.

    Para crear un men usaremos la funcin CreateMenu, que crea un men vaco.

    Para ir aadiendo tems a cada men usaremos la funcin AppendMenu. Esta funcin tiene varios argumentos:

    El primero es el men donde queremos insertar el nuevo tem.

    El segundo son las opciones o atributos del nuevo tem, por ejemplo MF_STRING, indica que se trata de un tem de tipo texto, MF_SEPARATOR, es un tem separador y MF_POPUP, indica que se trata de un men que desplegar un nuevo men pop-up.

    El siguiente parmetro puede tener distintos significados:

    l Puede ser un identificador de comando, este identificador se usar para comunicar a la aplicacin si el usuario selecion un determinado tem.

    l Un manipulador de men, si el tem tiene el flag MF_POPUP, en este caso hay que hacer un casting a (UINT).

    l O tambin puede ser cero, si se trata de un separador.

    El ltimo parmetro es el texto del tem, cuando se ha especificado el flag MF_STRING, ms adelante veremos que los tems pueden ser tambin bitmaps. Normalmente se trata de una cadena de texto. Pero hay una peculiaridad interesante, para indicar la tecla que activa un determinado tem de un men se muestra la letra correspondiente subrayada.

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=005 (2 de 7) [25/07/2004 19:46:35]

  • 5 Mens 1

    Esto se consigue insertando un '&' justo antes de la letra que se quiere usar como atajo, por ejemplo, en el tem "&Prueba" esta letra ser la 'P'.

    Por ltimo SetMenu, asigna un men a una ventana determinada. El primer parmetro es el manipulador de la ventana, y el segundo el del men.

    Prueba estas funciones y juega un rato con ellas. A continuacin veremos cmo hacer que nuestra aplicacin responda a los mensajes del men.

    Uso bsico de MessageBox

    Antes de aprender a visualizar texto en la ventana, usaremos un mecanismo ms simple para informar al usuario de cualquier cosa que pase en nuestra aplicacin. Este mecanismo no es otro que el cuadro de mensaje (message box), que consiste en una pequea ventana con un mensaje para el usuario y uno o varios botones, segn el tipo de cuadro de mensaje que usemos. En nuestros primeros ejemplos, el cuadro de mensaje slo incluir el botn de "Aceptar".

    Para visualizar un cuadro de mensaje simple, usaremos la funcin MessageBox. En nuestros ejemplos bastar con la siguiente forma:

    MessageBox(hWnd, "Texto de mensaje", "Texto de ttulo", MB_OK);

    Esto mostrar un pequeo cuadro de dilogo con el texto y el ttulo especificados y un botn de "Aceptar". El cuadro se cerrar al pulsar el botn o al pulsar la tecla de Retorno.

    Respondiendo a los mensajes del men

    Las activaciones de los mens se reciben mediante un mensaje WM_COMMAND.

    Para procesar estos mensajes, si slo podemos recibir mensajes desde un men, nicamente nos interesa la palabra de menor peso del parmetro wParam del mensaje.

    Modifiquemos el procedimiento de ventana para procesar los mensajes de nuestro men:

    LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){ switch (msg) /* manipulador del mensaje */ { case WM_COMMAND: switch(LOWORD(wParam)) { case CM_PRUEBA: MessageBox(hwnd, "Comando: Prueba", "Mensaje de men", MB_OK); break; case CM_SALIR: MessageBox(hwnd, "Comando: Salir", "Mensaje de men", MB_OK); /* enva un mensaje WM_QUIT a la cola de mensajes */ PostQuitMessage(0); break;

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=005 (3 de 7) [25/07/2004 19:46:35]

  • 5 Mens 1

    } break; case WM_DESTROY: /* enva un mensaje WM_QUIT a la cola de mensajes */ PostQuitMessage(0); break; default: /* para los mensajes de los que no nos ocupamos */ return DefWindowProc(hwnd, msg, wParam, lParam); } return 0;}

    Sencillo, no?.

    Observa que hemos usado la macro LOWORD para extraer el identificador del tem del parmetro wParam. Despus de eso, todo es ms fcil.

    Tambin se puede ver que hemos usado la misma funcin para salir de la aplicacin que para el mensaje WM_DESTROY: la funcin PostQuitMessage.

    Ejemplo 2

    Este ejemplo contiene todo lo que hemos visto sobre los mens hasta ahora.

    Nombre Fichero Fecha Tamao Descarga

    Ejemplo 2 win002.zip 2004-01-18 2328 bytes

    Ficheros de recursos

    Veamos ahora una forma ms sencilla y ms frecuente de implementar mens.

    Lo normal es implementar los mens desde un fichero de recursos, el sistema que hemos visto slo se usa en algunas ocasiones, para crear o modificar mens durante la ejecucin de la aplicacin.

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

    1. Usaremos siempre etiquetas como identificadores para los tems de los mens, y nunca valores numricos literales.

    2. Crearemos un fichero de cabecera con las definiciones de los identificadores, en nuestro ejemplo se llamar "ids.h".

    3. Incluiremos este fichero de cabecera tanto en el fichero de recursos y como en el del cdigo fuente de nuestra aplicacin.

    Partimos de un proyecto nuevo: win003. Pero usaremos el cdigo modificado del ejemplo1.

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=005 (4 de 7) [25/07/2004 19:46:35]

  • 5 Mens 1

    Para ello creamos un nuevo proyecto de tipo GUI, al que llamaremos Win003, y copiamos el contenido de "ejemplo1.c" en el fichero "main.cpp", al que renombraremos como "win003.c".

    A continuacin crearemos el fichero de identificadores.

    Aadimos el fichero de cabecera a nuestro proyecto. Si ests usando Dev-C++, sto se hace pulsando con el botn derecho del ratn sobre el nodo del proyecto y eligiendo el tem de "Buevo cdigo fuente" en el men que se despliega.

    Despus lo renombramos, el mecanismo es similar, pulsamos con el botn derecho sobre el tem "SiNombre1" y elegimos la opcin de "Renombrar archivo" del men que se despliegue. Como nuevo nombre elegimos: "ids.h".

    Introducimos en los identificadores:

    #define CM_PRUEBA 100 #define CM_SALIR 101

    En el fichero "win003.c" aadimos la lnea:

    #include "ids.h"

    Justo despus de la lnea "#include ".

    Ahora aadiremos 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 lnea introducimos la siguiente lnea:

    #include "ids.h"

    Y a continuacin escribimos:

    Menu MENUBEGIN POPUP "&Principal" BEGIN MENUITEM "&Prueba", CM_PRUEBA MENUITEM SEPARATOR MENUITEM "&Salir", CM_SALIR ENDEND

    En un fichero de recursos podemos crear toda la estructura de un men fcilmente. Este ejemplo crea una barra de men con una columna "Principal", con dos opciones:

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=005 (5 de 7) [25/07/2004 19:46:35]

  • 5 Mens 1

    "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 nmero entero, o, como en este caso, una macro definida.

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

    Observars que las cadenas que se muestran en el men contienen un smbolo & en su interior, por ejemplo "&Prueba". Este smbolo indica que la siguiente letra puede usarse para activar la opcin del men desde el teclado, usando la tecla [ALT] ms la letra que sigue al smbolo &. Para indicar eso, en pantalla, esa letra se muestra subrayada, en este ejemplo "Prueba".

    Ya podemos cerrar el cuadro de edicin del fichero de recursos.

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

    Cmo usar los recursos de men

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

    Primero veremos cmo cargarlo y asignarlo a nuestra ventana, sta es la forma que ms se parece a la del ejemplo del captulo anterior. Para ello basta con insertar este cdigo antes de llamar a la funcin ShowWindow:

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

    O simplemente:

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

    La funcin 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.

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=005 (6 de 7) [25/07/2004 19:46:35]

  • 5 Mens 1

    Otro sistema, ms sencillo todava, es asignarlo como men por defecto de la clase. Para esto basta con la siguiente asignacin:

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

    Y por ltimo, tambin podemos asignar un men cuando creamos la ventana, especificndolo 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 asignacin de men */ hInstance, NULL );

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

    Ejemplo 3

    Nombre Fichero Fecha Tamao Descarga

    Ejemplo 3 win003.zip 2004-01-18 2478 bytes

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=005 (7 de 7) [25/07/2004 19:46:35]

  • 6 Dilogo bsico

    Captulo 6 Dilogo bsico

    Los cuadros de dilogo son la forma de ventana ms habitual de comunicacin entre una aplicacin Windows y el usuario. Para facilitar la tarea del usuario a la hora de introducir datos, existen varios tipos de controles, cada uno de ellos diseado para un tipo especfico de informacin. Los ms comunes son los "static", "edit", "button", "listbox", "scroll", "combobox", "group", "checkbutton" y "ratiobutton". A partir de Windows 95 se indrodujeron varios controles nuevos: "updown", "listview", "treeview", "gauge", "tab" y "trackbar".

    En realidad, un cuadro de dilogo es una ventana normal, aunque con algunas peculiaridades. Tambin tiene su procedimiento de ventana (procedimiento de dilogo), pero puede devolver un valor a la ventana que lo invoque.

    Igual que los mens, los cuadros de dilogo se pueden construir durante la ejecucin o a partir de un fichero de recursos.

    Ficheros de recursos

    La mayora de los compiladores de C/C++ que incluyen soporte para Windows poseen herramientas para la edicin de recursos: mens, dilogos, bitmaps, etc. Sin embargo considero que es interesante que aprendamos a construir nuestros recursos con un editor de textos, cada compilador tiene sus propios editores de recursos, y no tendra sentido explicar cada uno de ellos. El compilador que usamos "Dev C++", en su versin 4, tiene un editor muy limitado y no aconsejo su uso. De hecho, en la versin actual ya no se incluye, y los ficheros de recursos se editan en modo texto.

    De modo que aprenderemos a hacer cuadros de dilogo igual que hemos aprendido a hacer mens: usando el editor de texto.

    Para el primer programa de ejemplo de programa con dilogos, que ser el ejemplo 4, partiremos de nuevo del programa del ejemplo 1. Nuestro primer dilogo ser muy sencillo: un simple cuadro con un texto y un botn de "Aceptar".

    Este es el cdigo del fichero de recursos:

    #include #include "IDS.H"

    Menu MENU BEGIN POPUP "&Principal" BEGIN MENUITEM "&Dilogo", CM_DIALOGO ENDEND

    DialogoPrueba DIALOG 0, 0, 118, 48STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTIONCAPTION "Dilogo de prueba"FONT 8, "Helv"BEGIN CONTROL "Mensaje de prueba", TEXTO, "static", SS_LEFT | WS_CHILD | WS_VISIBLE,

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=006 (1 de 8) [25/07/2004 19:46:36]

  • 6 Dilogo bsico

    8, 9, 84, 8 CONTROL "Aceptar", IDOK, "button", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 56, 26, 50, 14END

    Necesitamos incluir el fichero "windows.h" ya que en l se definen muchas constantes, como por ejemplo "IDOK" que es el identificador que se usa para el botn de "Aceptar".

    Tambin necesitaremos el fichero "ids.h", para definir los identificadores que usaremos en nuestro programa, por ejemplo el identificador del comando de men para abrir nuestro dilogo.

    /* Identificadores */

    /* Identificadores de comandos */#define CM_DIALOGO 101#define TEXTO 100

    Lo primero que hemos definido es un men para poder comunicarle a nuestra aplicacin que queremos abrir un cuadro de dilogo.

    A continuacin est la definicin del dilogo, que se compone de varias lneas. Puedes ver ms detalles en el apartado de recursos dedicado al recurso dilogo.

    De momento bastar con un identificador, como el que usbamos para los mens, y adems las coordenadas y dimensiones del dilogo.

    En cuanto a los estilos, las constantes para definir los estilos de ventana, que comienzan con "WS_", puedes verlos con detalle en la seccin de constantes "estilos de ventana". Y los estilos de dilogos, que comienzan con "DS_", en "estilos de dilogo".

    Para empezar, hemos definido los siguientes estilos:

    l DS_MODALFRAME: indica que se crear un cuadro de dilogo con un marco de dialog-box modal que puede combinarse con una barra de ttulo y un men de sistema.

    l WS_POPUP: crea una ventana "pop-up".l WS_VISIBLE: crea una ventana inicialmente visible.l WS_CAPTION: crea una ventana con una barra de ttulo, (incluye el estilo

    WS_BORDER).

    La siguiente lnea es la de CAPTION, en ella especificaremos el texto que aparecer en la barra de ttulo del dilogo.

    La lnea de FONT sirve para especificar el tamao y el tipo de fuente de caracteres que usar nuestro dilogo.

    Despus est la zona de controles, en nuestro ejemplo slo hemos incluido un texto esttico y un botn.

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=006 (2 de 8) [25/07/2004 19:46:36]

  • 6 Dilogo bsico

    Un control esttico (static) nos sirve para mostrar textos o rectngulos, que podemos usar para informar al usuario de algo, como etiquetas o como adorno. Para ms detalles ver control static.

    CONTROL "Mensaje de prueba", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 8, 9, 84, 8

    l CONTROL es una palabra clave que indica que vamos a definir un control.l A continuacin, en el parmetro text, introducimos el texto que se mostrar.l id es el identificador del control. Como los controles static no se suelen manejar por

    las aplicaciones no necesitamos un identificador, as que ponemos -1.l class es la clase de control, en nuestro caso "static".l style es el estilo de control que queremos. En nuestro caso es una combinacin de un

    estilo esttico y varios de ventana: m SS_LEFT: indica un simple rectngulo y el texto suministrado se alinea en su

    interior a la izquierda. m WS_CHILD: crea el control como una ventana hija. m WS_VISIBLE: crea una ventana inicialmente visible.

    l coordenada x del control.l coordenada y del control.l width: anchura del control.l height: altura del control.

    El control button nos sirve para comunicarnos con el dilogo, podemos darle comandos del mismo tipo que los que proporciona un men. Para ms detalles ver recurso button.

    CONTROL "Aceptar", IDOK, "button", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 56, 26, 50, 14

    l CONTROL es una palabra clave que indica que vamos a definir un control.l A continuacin, en el parmetro text, introducimos el texto que se mostrar en su

    interior.l id es el identificador del control. Nuestra aplicacin recibir este identificador junto

    con el mensaje WM_COMMAND cuando el usuario active el botn. La etiqueta IDOK est definida en el fichero Windows.h.

    l class es la clase de control, en nuestro caso "button".l style es el estilo de control que queremos. En nuestro caso es una combinacin de

    varios estilos de button y varios de ventana: m BS_PUSHBUTTON: crea un botn corriente que enva un mensaje

    WM_COMMAND a su ventana padre cuando el usuario selecciona el botn.m BS_CENTER: centra el texto horizontalmente en el rea del botn.m WS_CHILD: crea el control como una ventana hija.m WS_VISIBLE: crea una ventana inicialmente visible.m WS_TABSTOP: define un control que puede recibir el foco del teclado

    cuando el usuario pulsa la tecla TAB. Presionando la tecla TAB, el usuario mueve el foco del teclado al siguiente control con el estilo WS_TABSTOP.

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=006 (3 de 8) [25/07/2004 19:46:36]

  • 6 Dilogo bsico

    l coordenada x del control.l coordenada y del control.l width: anchura del control. l height: altura del control.

    Procedimiento de dilogo

    Como ya hemos dicho, un dilogo es bsicamente una ventana, y al igual que aquella, necesita un procedimiento asociado que procese los mensajes que le sean enviados, en este caso, un procedimiento de dilogo.

    Sintaxis

    BOOL CALLBACK DialogProc( HWND hwndDlg, // manipulador del cuadro de dilogo UINT uMsg, // mensaje WPARAM wParam, // primer parmetro del mensaje LPARAM lParam // segundo parmetro del mensaje );

    l hwndDlg identifica el cuadro de dilogo y es el manipulador de la ventana a la que est destinado el mensaje.

    l msg es el cdigo del mensaje.l wParam es el parmetro de tipo palabra asociado al mensaje.l lParam es el parmetro de tipo doble palabra asociado al mensaje.

    La diferencia con el procedimiento de ventana que ya hemos visto est en el tipo de valor de retorno, que es el caso del procedimiento de dilogo es de tipo booleano. Puedes consultar una sintaxis ms completa de esta funcin en DialogProc.

    Excepto en la respuesta al mensaje WM_INITDIALOG, el procedimiento de dilogo debe retornar con un valor no nulo si procesa el mensaje y cero si no lo hace. Cuando responde a un mensaje WM_INITDIALOG, el procedimiento debe retornar cero si llama a la funcin SetFocus para poner el foco a uno de los controles del cuadro de dilogo. En otro caso, debe retornar un valor distinto de cero, y el sistema pondr el foco en el primer control del dilogo que pueda recibirlo.

    Prototipo de procedimiento de dilogo

    El prototipo es parecido al de los procedimientos de ventana:

    BOOL CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);

    Implementacin de procedimiento de dilogo para nuestro ejemplo

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=006 (4 de 8) [25/07/2004 19:46:36]

  • 6 Dilogo bsico

    Nuestro ejemplo es muy sencillo, ya que nuestro dilogo slo puede proporcionar un comando, as que slo debemos responder a un tipo de mensaje WM_COMMAND y al mensaje WM_INITDIALOG.

    Segn hemos explicado un poco ms arriba, del mensaje WM_INITDIALOG debemos retornar con un valor distinto de cero si no llamamos a SetFocus, como es nuestro caso.

    Este mensaje lo usaremos para inicializar nuestro dilogo antes de que sea visible para el usuario, siempre que haya algo que inicializar, claro.

    Cuando procesemos el mensaje WM_COMMAND, que ser siempre el que procede del nico botn del dilogo, cerraremos el dilogo llamando a la funcin EndDialog y retornaremos con un valor distinto de cero.

    En cualquier otro caso retornamos con FALSE, ya que no estaremos procesando el mensaje.

    Nuestra funcin queda as:

    BOOL CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam){ switch (msg) /* manipulador del mensaje */ { case WM_INITDIALOG: return TRUE; case WM_COMMAND: EndDialog(hDlg, FALSE); return TRUE; } return FALSE;}

    Bueno, slo nos falta saber cmo creamos un cuadro de dilogo. Para ello usaremos un comando de men, por lo tanto, el dilogo se activar desde el procedimiento de ventana.

    LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){ static HINSTANCE hInstance; switch (msg) /* manipulador del mensaje */ { case WM_CREATE: hInstance = ((LPCREATESTRUCT)lParam)->hInstance; return 0; break; case WM_COMMAND: switch(LOWORD(wParam)) { case CM_DIALOGO: DialogBox(hInstance, "DialogoPrueba", hwnd, DlgProc); break; } break; case WM_DESTROY: PostQuitMessage(0); /* enva un mensaje WM_QUIT a la cola de mensajes */ break; default: /* para los mensajes de los que no nos ocupamos */ return DefWindowProc(hwnd, msg, wParam, lParam); } return 0;

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=006 (5 de 8) [25/07/2004 19:46:36]

  • 6 Dilogo bsico

    }

    En este procedimiento hay varias novedades:

    Primero hemos declarado una variable esttica "hInstance" para tener siempre a mano un manipulador de la instancia actual.

    Para inicializar este valor hacemos uso del mensaje WM_CREATE, que se enva a una ventana cuando es creada, antes de que se visualice por primera vez. Aprovechamos el hecho de que nuestro procedimiento de ventana slo recibe una vez este mensaje y de que lo hace antes de poder recibir ningn otro mensaje o comando. En el futuro veremos que se usa para toda clase de inicializaciones.

    El mensaje WM_CREATE tiene como parmetro en lParam un puntero a una estructura CREATESTRUCT que contiene informacin sobre la ventana. En nuestro caso slo nos interesa el campo hInstance.

    La otra novedad es la llamada a la funcin DialogBox, que es la que crea el cuadro de dilogo.

    Nota: Bueno, en realidad DialogBox no es una funcin, sino una macro, pero dado su formato y el modo en que se usa, la consideraremos como una funcin.

    Esta funcin necesita varios parmetros:

    1. Un manipulador a la instancia de la aplicacin, que hemos obtenido al procesar el mensaje WM_CREATE.

    2. Un identificador de recurso de dilogo, este es el nombre que utilizamos para el dilogo al crear el recurso, entre comillas.

    3. Un manipulador a la ventana a la que pertenece el dilogo.4. Y la direccin del procedimiento de ventana que har el tratamiento del dilogo.

    Y ya tenemos nuestro primer ejemplo del uso de dilogos, en captulos siguientes empezaremos a conocer ms detenidamente cmo usar cada uno de los controles bsicos: Edit, List Box, Scroll Bar, Static, Button, Combo Box, Group Box, Check Button y Radio Button. Le dedicaremos un captulo a cada uno de ellos.

    Pasar parmetros a un cuadro de dilogo

    Tenemos otra opcin a la hora de crear un dilogo. En lugar de usar la macro DialogBox, podemos usar la funcin DialogBoxParam, que nos permite enviar un parmetro extra al procedimiento de dilogo. Este parmetro se enva a travs del parmetro lParam del procedimiento de dilogo, y puede contener un valor entero, o lo que es mucho ms til, un puntero.

    Esta funcin tiene los mismos parmetros que DialogBox, ms uno aadido. Este quinto parmetro es el que podemos usar para pasar y recibir valores desde el procedimiento de dilogo.

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=006 (6 de 8) [25/07/2004 19:46:36]

  • 6 Dilogo bsico

    Por ejemplo, supongamos que queremos saber cuntas veces se ha invocado un dilogo. Para ello llevaremos la cuenta en el procedimiento de ventana, incrementando esa cuenta cada vez que recivamos un comando para mostrar el dilogo. Adems, pasaremos ese valor como parmetro lParam al procedimiento de dilogo.

    static veces;... case WM_COMMAND: switch(LOWORD(wParam)) { case CM_DIALOGO: DialogBox(hInstance, "DialogoPrueba", hwnd, DlgProc); break; case CM_DIALOGO2: veces++; DialogBoxParam(hInstance, "DialogoPrueba2", hwnd, DlgProc2, veces); break; } break;

    Finalmente, nuestro procedimiento de dilogo tomar ese valor y lo usar para crear el texto de un control esttico. (Cmo funciona esto lo veremos en otro captulo, de momento sirva como ejemplo).

    BOOL CALLBACK DlgProc2(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam){ char texto[25]; switch (msg) /* manipulador del mensaje */ { case WM_INITDIALOG: sprintf(texto, "Veces invocado: %d", lParam); SetWindowText(GetDlgItem(hDlg, TEXTO), texto); return TRUE; case WM_COMMAND: EndDialog(hDlg, FALSE); return TRUE; } return FALSE;}

    Hemos usado la funcin estndar sprintf para conseguir un texto esttico a partir del parmetro lParam. Posteriormente, usamos ese texto para modificar el control esttico TEXTO.

    Usamos la misma plantilla de dilogo para ambos ejemplos, y aprovechamos el control esttico para mostrar nuestro mensaje. La funcin SetWindowText se usa para cambiar el ttulo de una ventana, pero tambin sirve para cambiar el texto de un control esttico.

    Cuando usemos cuadros de dilogo para pedir datos al usuario veremos que este modo de crearlos nos facilita en intercambio de datos entre la aplicacin y los procedimientos de dilogo. De otro modo tendramos que acudir a variables globales.

    Ejemplo 4

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=006 (7 de 8) [25/07/2004 19:46:36]

  • 6 Dilogo bsico

    Nombre Fichero Fecha Tamao Descarga

    Ejemplo 4 win004.zip 2004-05-17 2921 bytes

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=006 (8 de 8) [25/07/2004 19:46:36]

  • 7 Control Edit

    Captulo 7 Control bsico Edit

    Tal como hemos definido nuestro dilogo en el captulo 6, no tiene mucha utilidad. Los dilogos se usan para intercambiar informacin entre la aplicacin y el usuario, en ambas direcciones. El ejemplo 4 slo lo hace en una de ellas.

    En el captulo anterior hemos usado dos controles (un texto esttico y un botn), aunque sin saber exactamente cmo funcionan. En este captulo veremos el uso del control de edicin.

    Un control edit es una ventana de control rectangular que permite al usuario introducir y editar texto desde el teclado.

    Cuando est seleccionado muestra el texto que contiene y un cursor intermitente que indica el punto de insercin de texto. Para seleccionarlo el usuario puede hacer un click con el ratn en su interior o usar la tecla [TAB]. El usuario podr entonces introducir texto, cambiar el punto de insercin, o seleccionar texto para ser borrado o movido usando el teclado o el ratn.

    Un control de este tipo puede enviar mensajes a su ventana padre mediante WM_COMMAND, y la ventana padre puede enviar mensajes a un control edit en un cuadro de dilogo llamando a la funcin SendDlgItemMessage. Veremos algunos de estos mensajes en este captulo, y el resto el captulos ms avanzados.

    Fichero de recursos

    Empezaremos definiendo el control edit en el fichero de recursos, y lo aadiremos a nuestro dialogo de prueba.

    #include #include "IDS.H"

    Menu MENU BEGIN POPUP "&Principal" BEGIN MENUITEM "&Dilogo", CM_DIALOGO ENDEND

    DialogoPrueba DIALOG 0, 0, 118, 48STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTIONCAPTION "Dilogo de prueba"FONT 8, "Helv"BEGIN CONTROL "Texto:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 8, 9, 28, 8 CONTROL "", ID_TEXTO, "EDIT", ES_LEFT | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP,

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=007 (1 de 10) [25/07/2004 19:46:37]

  • 7 Control Edit

    36, 9, 76, 12 CONTROL "Aceptar", IDOK, "BUTTON", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 56, 26, 50, 14END

    Hemos hecho algunas modificaciones ms. Para empezar, el control static se ha convertido en una etiqueta para el control edit, que indica al usuario qu tipo de informacin debe suministrar.

    Hemos aadido el control edit a continuacin del control static. Veremos que el orden en que aparecen los controles dentro del cuadro de dilogo es muy importante, al menos en aquellos controles que tengan el estilo WS_TABSTOP, ya que ese orden ser el mismo en que se activen los controles cuando usemos la tecla TAB. Para ms detalles acerca de los controles edit ver controles edit.

    Pero ahora veamos cmo hemos definido nuestro control edit:

    CONTROL "", ID_TEXTO, "EDIT", ES_LEFT | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 36, 9, 76, 12

    l CONTROL es una palabra clave que indica que vamos a definir un control.l A continuacin, en el parmetro text, introducimos el texto que se mostrar

    en el interior del control, en este caso, ninguno.l id es el identificador del control. Los controles edit necesitan un

    identificador para que la aplicacin pueda acceder a ellos. Usaremos un identificador definido en IDS.h.

    l class es la clase de control, en nuestro caso "EDIT".l style es el estilo de control que queremos. En nuestro caso es una

    combinacin de un estilo edit y varios de ventana:m ES_LEFT: indica que el texto en el interior del control se alinear a

    la izquierda. m WS_CHILD: crea el control como una ventana hija.m WS_VISIBLE: crea una ventana inicialmente visible.m WS_BORDER: se crea un control que tiene de borde una lnea fina.m WS_TABSTOP: define un control que puede recibir el foco del

    teclado cuando el usuario pulsa la tecla TAB. Presionando la tecla TAB, el usuario mueve el foco del teclado al siguiente control con el estilo WS_TABSTOP.

    l coordenada x del control.l coordenada y del control.l width: anchura del control. l height: altura del control.

    El procedimiento de dilogo y los controles

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=007 (2 de 10) [25/07/2004 19:46:37]

  • 7 Control Edit

    edit

    Para manejar el control edit desde nuestro procedimiento de dilogo tendremos que hacer algunas modificaciones.

    Para empezar, los controles edit tambin pueden generar mensajes WM_COMMAND, de modo que debemos diferenciar el control que origin dicho mensaje y tratarlo de diferente modo segn el caso.

    case WM_COMMAND: if(LOWORD(wParam) == IDOK) EndDialog(hDlg, FALSE); return TRUE;

    En nuestro caso sigue siendo sencillo: slo cerraremos el dilogo si el mensaje WM_COMMAND proviene del botn "Aceptar".

    La otra modificacin afecta al mensaje WM_INITDIALOG.

    case WM_INITDIALOG: SetFocus(GetDlgItem(hDlg, ID_TEXTO)); return FALSE;

    De nuevo es una modificacin sencilla, tan slo haremos que el foco del teclado se coloque en el control edit, de modo que el usuario pueda empezar a escribir directamente, tan pronto como el dilogo haya aparecido en pantalla.

    Para hacer eso usaremos la funcin SetFocus. Pero esta funcin requiere como parmetro el manipulador de ventana del control que debe recibir el foco, este manipulador lo conseguimos con la funcin GetDlgItem, que a su vez necesita como parmetros un manipulador del dilogo y el identificador del control.

    Variables a editar en los cuadros de dilogo

    Quizs has notado que a nuestro programa le falta algo.

    Efectivamente, podemos introducir y modificar texto en el cuadro de dilogo, pero no podemos asignar valores iniciales al control de edicin ni tampoco podemos hacer que la aplicacin tenga acceso al texto introducido por el usuario.

    Lo primero que tenemos que tener es algn tipo de variable que puedan compartir los procedimientos de ventana de la aplicacin y el del dilogo. En nuestro caso se trata slo de una cadena, pero segn se aadan ms parmetros al cuadro de edicin, estos datos pueden ser ms complejos, as que usaremos un sistema que

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=007 (3 de 10) [25/07/2004 19:46:37]

  • 7 Control Edit

    nos valdr en todos los casos.

    Se trata de crear una estructura con todos los datos que queremos que el procedimiento de dilogo comparta con el procedimiento de ventana:

    typedef struct stDatos { char Texto[80];} DATOS;

    Lo ms sencillo es que estos datos sean globales, pero no ser buena idea ya que no es buena prctica el uso de variables globales.

    Tampoco parece muy buena idea declarar los datos en el procedimiento de ventana, ya que este procedimiento se usa para todas las ventanas de la misma clase, y tendramos que definir los datos como estticos.

    Pero recordemos que tenemos un modo de pasar parmetros al cuadro de dilogo, usando la funcin DialogBoxParam, a travs del parmetro lParam.

    Aunque esta opcin parece que nos limita a valores enteros, y slo permite pasar valores al procedimiento de dilogo, en realidad se puede usar para pasar valores en ambos sentidos, bastar con enviar un puntero en lugar de un entero.

    Para ello haremos un casting del puntero al tipo LPARAM. Dentro del procedimiento de dilogo haremos otro casting de LPARAM al puntero.

    Esto nos permite declarar la variable que contiene los datos dentro del procedimiento de ventana, en este caso, de forma esttica.

    static DATOS Datos;... DialogBoxParam(hInstance, "DialogoPrueba", hwnd, DlgProc, (LPARAM)&Datos);

    En el caso del procedimiento de dilogo:

    static DATOS *Datos;... case WM_INITDIALOG: Datos = (DATOS *)lParam;

    Daremos valores iniciales a las variables de la aplicacin, dentro del procedimiento de ventana, al procesar el mensaje WM_CREATE:

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=007 (4 de 10) [25/07/2004 19:46:37]

  • 7 Control Edit

    case WM_CREATE: /* Inicializacin de los datos de la aplicacin */ strcpy(Datos.Texto, "Inicial");

    Iniciar controles edit

    Ahora tenemos que hacer que se actualice el contenido del control edit al abrir el cuadro de dilogo.

    El lugar adecuado para hacer esto es en el proceso del mensaje WM_INITDIALOG:

    case WM_INITDIALOG: SendDlgItemMessage(hDlg, ID_TEXTO, EM_LIMITTEXT, 80, 0L); Datos = (DATOS *)lParam; SetDlgItemText(hDlg, ID_TEXTO, Datos->Texto); SetFocus(GetDlgItem(hDlg, ID_TEXTO)); return FALSE;

    Hemos aadido dos llamadas a dos nuevas funciones del API. La primera es a SendDlgItemMessage, que enva un mensaje a un control. En este caso se trata de un mensaje EM_LIMITTEXT, que sirve para limitar la longitud del texto que se puede almacenar y editar en el control edit. Es necesario que hagamos esto, ya que el texto que puede almacenar nuestra estructura de datos est limitado a 80 caracteres.

    Tambin hemos aadido una llamada a la funcin SetDlgItemText, que hace exactamente lo que pretendemos: cambiar el contenido del texto en el interior de un control edit.

    Devolver valores a la aplicacin

    Tambin queremos que cuando el usuario est satisfecho con los datos que ha introducido, y pulse el botn de aceptar, el dato de nuestra aplicacin se actualice con el texto que hay en el control edit.

    Esto lo podemos hacer de varios modos. Como veremos en captulos ms avanzados, podemos responder a mensajes que provengan del control cada vez que cambia su contenido.

    Pero ahora nos limitaremos a leer ese contenido cuando procesemos el comando generado al pulsar el botn de "Aceptar".

    case WM_COMMAND:

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=007 (5 de 10) [25/07/2004 19:46:37]

  • 7 Control Edit

    if(LOWORD(wParam) == IDOK) { GetDlgItemText(hDlg, ID_TEXTO, Datos->Texto, 80); EndDialog(hDlg, FALSE); } return TRUE;

    Para eso hemos aadido la llamada a la funcin GetDlgItemText, que es simtrica a SetDlgItemText.

    Ahora puedes comprobar lo que pasa cuando abres varias veces seguidas el cuadro de dilogo modificando el texto cada vez.

    Con esto parece que ya controlamos lo bsico de los controles edit, pero an hay algo ms.

    Aadir la opcin de cancelar

    Es costumbre dar al usuario la oportunidad de arrepentirse si ha modificado algo en un cuadro de dilogo y, por la razn que sea, cambia de idea.

    Para eso se suele aadir un segundo botn de "Cancelar".

    Empecemos por aadir dicho botn en el fichero de recursos:

    DialogoPrueba DIALOG 0, 0, 118, 48STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTIONCAPTION "Dilogo de prueba"FONT 8, "Helv"{ CONTROL "Texto:", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 8, 9, 28, 8 CONTROL "", ID_TEXTO, "EDIT", ES_LEFT | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 36, 9, 76, 12 CONTROL "Aceptar", IDOK, "BUTTON", BS_DEFPUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 8, 26, 45, 14 CONTROL "Cancelar", IDCANCEL, "BUTTON", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 61, 26, 45, 14}

    Hemos cambiado las coordenadas de los botones, para que el de "Aceptar" aparezca a la izquierda. Adems, el botn de "Aceptar" lo hemos convertido en el botn por defecto, aadiendo el estilo BS_DEFPUSHBUTTON. Haciendo eso, podemos simular la pulsacin del botn de aceptar pulsando la tecla de "intro".

    El identificador del botn de "Cancelar" es IDCANCEL, y est definido en

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=007 (6 de 10) [25/07/2004 19:46:37]

  • 7 Control Edit

    Windows.h.

    Ahora tenemos que hacer que nuestro procedimiento de dilogo manipule el mensaje del botn de "Cancelar".

    case WM_COMMAND: switch(LOWORD(wParam)) { case IDOK: GetDlgItemText(hDlg, ID_TEXTO, Datos->Texto, 80); EndDialog(hDlg, FALSE); break; case IDCANCEL: EndDialog(hDlg, FALSE); break; } return TRUE;

    Como puedes ver, slo leemos el contenido del control edit si se ha pulsado el botn de "Aceptar".

    Ejemplo 5

    Nombre Fichero Fecha Tamao Descarga

    Ejemplo 5 win005.zip 2004-05-17 3077 bytes

    Editar nmeros

    En muchas ocasiones necesitaremos editar valores de nmeros enteros en nuestros dilogos.

    Para eso, el API tiene previstas algunas constantes y funciones, (aunque no es as para nmeros en coma flotante, para los que tendremos que crear nuestros propios controles).

    Bien, vamos a modificar nuestro ejemplo para editar valores numricos en lugar de cadenas de texto.

    Fichero de recursos para editar enteros

    Empezaremos aadiendo una constante al fichero de identificadores: "IDS.h":

    #define ID_NUMERO 100

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=007 (7 de 10) [25/07/2004 19:46:37]

  • 7 Control Edit

    Y redefiniendo el control edit en el fichero de recursos, al que aadiremos el flag ES_NUMBER para que slo admita caracteres numricos:

    DialogoPrueba DIALOG 0, 0, 118, 48STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTIONCAPTION "Dilogo de prueba"FONT 8, "Helv"BEGIN CONTROL "Nmero:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 8, 9, 28, 8 CONTROL "", ID_NUMERO, "EDIT", ES_NUMBER | ES_LEFT | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 36, 9, 76, 12 CONTROL "Aceptar", IDOK, "BUTTON", BS_DEFPUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 8, 26, 45, 14 CONTROL "Cancelar", IDCANCEL, "BUTTON", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 61, 26, 45, 14END

    Variables a editar en los cuadros de dilogo

    Ahora modificaremos la estructura de los datos para que el dato a editar sea de tipo numrico:

    typedef struct stDatos { int Numero;} DATOS;

    Al igual que antes, daremos valores iniciales a las variables del dilogo al procesar el mensaje WM_CREATE.

    case WM_CREATE: /* Inicializacin de los datos de la aplicacin */ Datos.Numero = 123;

    Por supuesto, pasaremos un puntero a esta estructura a la funcin DialogBoxParam, haciendo uso el parmetro lParam:

    static DATOS Datos;... DialogBoxParam(hInstance, "DialogoPrueba", hwnd, DlgProc, (LPARAM)&Datos);

    Iniciar controles edit de enteros

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=007 (8 de 10) [25/07/2004 19:46:37]

  • 7 Control Edit

    Ahora tenemos que hacer que se actualice el contenido del control edit al abrir el cuadro de dilogo.

    El lugar adecuado para hacer esto es en el proceso del mensaje WM_INITDIALOG:

    static DATOS *datos;... case WM_INITDIALOG: datos = (DATOS *)lParam; SetDlgItemInt(hDlg, ID_NUMERO, (UINT)datos->Numero, FALSE); SetFocus(GetDlgItem(hDlg, ID_NUMERO)); return FALSE;

    En este caso no es necesario limitar el texto que podemos editar en el control, ya que, como veremos, las propias funciones del API se encargan de capturar y convertir el contenido del control en un nmero, de modo que no tenemos que preocuparnos de que no quepa en nuestra variable.

    Tambin hemos modificado la funcin a la que llamamos para modificar el contenido del control, ahora usaremos SetDlgItemInt, que cambia el contenido de un control edit con un valor numrico.

    Devolver valores a la aplicacin

    Por ltimo leeremos el contenido cuando procesemos el comando generado al pulsar el botn de "Aceptar".

    BOOL NumeroOk; int numero;... case WM_COMMAND: switch(LOWORD(wParam)) { case IDOK: numero = GetDlgItemInt(hDlg, ID_NUMERO, &NumeroOk, FALSE); if(NumeroOk) { datos->Numero = numero; EndDialog(hDlg, FALSE); } else MessageBox(hDlg, "Nmero no vlido", "Error", MB_ICONEXCLAMATION | MB_OK); break;

    Para eso hemos aadido la llamada a la funcin GetDlgItemInt, que es simtrica a SetDlgItemInt. El proceso difiere del usado para capturar cadenas, ya que en este caso la funcin nos devuelve el valor numrico del contenido del control edit.

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=007 (9 de 10) [25/07/2004 19:46:37]

  • 7 Control Edit

    Tambin devuelve un parmetro que indica si ha habido algn error durante la conversin. Si el valor de ese parmetro es TRUE, significa que la conversin se realiz sin problemas, si es FALSE, es que ha habido un error. Si nuestro programa detecta un error visualizar un mensaje de error y no permitir abandonar el cuadro de dilogo.

    Pero si ha habido un error, el valor de retorno de GetDlgItemInt ser cero. Esto nos causa un problema. Si leemos el valor directamente en datos->Numero y el usuario introduce un valor no vlido, y despus pulsa "Cancelar", el valor devuelto no ser el original, sino 0. Para evitar eso hemos usado una variable local, y el valor de datos->Numero slo se actualiza antes de salir con "Aceptar" y con un valor vlido.

    Por ltimo, hemos usado el flag BM_ICONEXCLAMATION en el MessageBox, que aade un icono al cuadro de mensaje y el sonido predeterminado para alertar al usuario.

    Ejemplo 6

    Nombre Fichero Fecha Tamao Descarga

    Ejemplo 6 win006.zip 2004-05-17 3141 bytes

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=007 (10 de 10) [25/07/2004 19:46:37]

  • 8 Control ListBox

    Captulo 8 Control bsico ListBox

    Los controles edit son muy tiles cuando la informacin a introducir por el usuario es imprevisible o existen muchas opciones. Pero cuando el nmero de opciones no es muy grande y son todas conocidas, es preferible usar un control ListBox.

    Ese es el siguiente control bsico que veremos. Un ListBox consiste en una ventana rectangular con una lista de cadenas entre las cuales el usuario puede escoger una o varias.

    El usuario puede seleccionar una cadena apuntndola y haciendo clic con el botn del ratn. Cuando una cadena se selecciona, se resalta y se enva un mensaje de notificacin a la ventana padre. Tambin se puede usar una barra de scroll con los listbox para desplazar listas muy largas o demasiado anchas para la ventana.

    Ficheros de recursos

    Empezaremos definiendo el control listbox en el fichero de recursos, y lo aadiremos a nuestro dilogo de prueba:

    #include #include "IDS.H"

    Menu MENU BEGIN POPUP "&Principal" BEGIN MENUITEM "&Dilogo", CM_DIALOGO ENDEND

    DialogoPrueba DIALOG 0, 0, 118, 135STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTIONCAPTION "Dilogo de prueba"FONT 8, "Helv"BEGIN CONTROL "Lista:", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 8, 9, 28, 8 CONTROL "", ID_LISTA, "listbox", LBS_STANDARD | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 9, 19, 104, 99 CONTROL "Aceptar", IDOK, "BUTTON", BS_DEFPUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 8, 116, 45, 14 CONTROL "Cancelar", IDCANCEL, "BUTTON", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 61, 116, 45, 14END

    Hemos aadido el control listbox a continuacin del control static. Para ms detalles acerca de los controles listbox ver control listbox.

    Ahora veamos cmo hemos definido nuestro control listbox:

    CONTROL "", ID_LISTA, "listbox", LBS_STANDARD | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 9, 19, 104, 99

    l CONTROL es la palabra clave que indica que vamos a definir un control.

    http://localhost/conclase/winapi/curso/para-pdf/index.php?cap=008 (1 de 4) [25/07/2004 19:46:38]

  • 8 Control ListBox

    l A continuacin, en el parmetro text, en el caso de los listbox no tiene ninguna funcin. Lo dejaremos como cadena vaca.

    l id es el identificador del control. Los controles listbox necesitan un identificador para que la aplicacin pueda acceder a ellos. Usaremos un identificador definido en IDS.h.

    l class es la clase de control, en nuestro caso "LISTBOX".l style es el estilo de control