Professional Documents
Culture Documents
LEAME.TXT
Este es un libro para gente familiarizada con el lenguaje de programación C que desea
aprender a escribir aplicaciones para el sistema operativo Microsoft Windows 95. Conocer el
lenguaje C es uno de los tres requisitos para utilizar este libro. El segundo es que haya
instalado Microsoft Visual C++ 4.0 para desarrollo de 32 bits. El tercero es que usted
realmente trabaje con Windows y comprenda los fundamentos de su interfaz de usuario.
Como probablemente ya sabrá, Windows 95 es la encarnación más reciente de un sistema
operativo gráfico introducido por primera vez en noviembre de 1985 para ejecutarse en
máquinas IBM PC y compatibles. En términos de penetración de mercado, Windows casi ha
barrido completamente a la competencia que pudo haber tenido en la década pasada y se ha
convertido en el estándar de facto para PC. Hoy en día, si usted está escribiendo un
programa para PC, está escribiendo un programa para Windows.
Piense en este capítulo como su primer día de clase. A pesar de la tendencia de algunos
profesores en comenzar inmediatamente con el contenido más abrupto del material del
curso, la mayoría de nosotros prefiere una introducción más relajada. Por tanto, en este
capítulo explicaré algunas características históricas de Windows, las reglas básicas de este
libro e, incluso (y espero que sea indulgente conmigo), haré un breve comentario sobre mi
persona y cómo se escribió este libro.
No puedo, sin embargo, garantizar que este capítulo vaya a estar totalmente libre de
preocupaciones. Usted es un programador, usted es un ingeniero de software y, como
cualquier otro ingeniero, su papel es afrontar (y, por suerte, a menudo satisfacer) el difícil
trabajo de convertir el mundo en un lugar más cómodo. Usted está construyendo carreteras y
puentes que acercan a la gente a sus lugares de destino y estas estructuras tienen que ser
robustas, sólidas y rápidas.
Quizá la revolución real en el diseño de programas comenzó con los primeros procesadores
de texto interactivos (por ejemplo, WordStar) y hojas de cálculo interactivas (VisiCalc), que
incorporaban formas primitivas del elemento más fundamental en el diseño actual de
interfaces de usuario. Se trata, por supuesto, del menú. El menú en estas primeras
aplicaciones interactivas no estaba bien implementado, pero la idea estaba presente y
lentamente el menú fue haciéndose cada vez más complejo y sofisticado. Mirando hacia
atrás, el menú parece obvio: presenta todas las opciones del programa para que el usuario
pueda activarlas. Por supuesto, en los primeros momentos, la falta de memoria limitaba al
programador impidiéndole diseñar una buena interfaz de usuario. Los programas poco
1
Por ejemplo, el entorno gráfico GEM (Graphical Environment Manager) de Digital Rescareh, en el cual se
ejecutaban las primeras versiones de Ventura Publisher. (N. del T.)
1
amigables con el usuario son más cortos y fáciles de escribir; los programas con una interfaz
de usuario cuidada son más grandes y más difíciles de escribir. En este caso se puede
aplicar el refrán «No es oro todo lo que reluce». Alguien tiene que hacer el trabajo sucio. Y
como programador, usted ha elegido ser esa persona.
Afortunadamente, una buena parte de este duro trabajo ya ha sido hecho para usted por los
diseñadores y programadores del sistema operativo Microsoft Windows.95. Estos héroes
desconocidos han implementado mucho del código requerido para crear objetos modernos
de interfaz de usuario y visualizar la salida del programa usando texto con formato
enriquecido y gráficos. Sin embargo, para hacer esto también tuvieron que crear
necesariamente una completa interfaz de programación de aplicaciones (API: Application
Programming Interface) que puede intimidar bastante a los programadores que se asoman a
Windows por primera vez. Esto no es exclusivo de Windows 95: es cierto en cualquier
interfaz de usuario moderna.
por primera vez a la programación para entornos gráficos, Windows puede ser muy
extraño. Y se va a dar cuenta de ello.
Lo que voy a enseñarle en este libro es lo que yo considero una programación «clásica»
de Windows. Utilizo el simple y viejo lenguaje C (no C++) y utilizo directamente la
interfaz de programación de aplicaciones (API) en vez de cualquier «envoltorio» que
oculte la API bajo una interfaz más fácil. A pesar de los avances en Windows 95 frente
a las primeras versiones de Windows, la mayoría de los programas de este libro no
parecen muy diferentes de los programas que se podrían haber escrito (y se escribieron)
hace 10 años para Microsoft Windows versión 1.0.
En un sentido, este libro muestra el camino más duro para la programación Win
dows, pero es también el camino más básico, fundamental, versátil y potente. Literal
mente, usted no puede hacer nada más con Windows utilizando otros enfoques. Al con
trario, aprendiendo la programación clásica de Windows a través de C y las API, puede
entender más claramente cómo interáctúan Windows y su aplicación, y esto a menudo
puede ser un conocimiento muy útil. Este enfoque establece unos conceptos básicos que
usted nunca rechazará. Creame.
Aunque enseño programación Windows clásica, no le recomiendo necesariamente
que se limite a ella. En la actualidad, usted tiene varias opciones que facilitan la progra
mación Windows. Una opción popular es C++, generalmente usada en conjunción
con librerías de clases como Object Windows Library (OWL) de Borland o Microsoft
Foundation Classes (MFC). Otras opciones son Visual Basic de Microsoft y Delphi de
Borland. También hay disponibles productos generadores de código que hacen por usted
el trabajo repetitivo en la programación Windows. Incluso puede crear aplicaciones
Windows utilizando lenguajes de instrucciones sencillas (seripts) como ToolBook de
Asymetrix.
2
los IDE. Pienso que son buenos. Sin embargo, sus tareas a menudo ocultan en vez
de ayudar a aprender la programación clásica de Windows. En pocas palabras, no deseo
enseñarle cómo aprender a crear cuadros de diálogo en un IDE, en vez de eso lo que
deseo es enseñarle a diseñar sus propios cuadros de diálogo y gestionar el proceso de
entrada de información en ellos.
Por esta razón, el código en este libro se muestra como si se creara en un editor
de textos corriente y el programa se compilase desde la antigua línea de órdenes del
MS-DOS. Esto será más obvio cuando el tema a tratar sean los scripts de recursos, que
Poco después de la introducción del IBM PC en otoño de 198 1, llegó a ser evidente que
el sistema operativo predominante para el PC (y compatibles) sería MS-DOS, cuyas
Léame. TXT 7
3
Debido a las limitaciones impuestas por memoria y hardware, los entornos gráficos
sofisticados se desarrollaron lentamente. Apple Computers demostró una alternativa posible
cuando anunció su malogrado Lisa en enero de 1983, y luego definió un estándar para
entornos gráficos con el Macintosh en enero de 1984, el cual (a pesar de su pequeña
cuota de mercado) todavía es considerado el estándar con el cual se miden y comparan
los restantes entornos gráficos.
Windows fue anunciado por Microsoft Corporation en noviembre de 1983 (después
de Lisa y antes de Macintosh) y comenzó a venderse dos años más tarde en noviembre de
1985. Durante los dos años siguientes, la versión Microsoft Windows 1.0 fue seguida de
varias actualizaciones para soportar el mercado internacional y proporcionar controla
dores adicionales de adaptadores de vídeo e impresoras.
Windows versión 2.0 apareció en noviembre de 1987. Esta versión incorporaba
varios cambios en la interfaz de usuario. El más significativo de estos cambios era la
utilización de ventanas superpuestas en vez de las ventanas en cascada de Windows 1.x.
Windows 2.0 también incluía mejoras al teclado y a la interfaz del ratón, particularmente
para menús y cuadros de diálogo.
Hasta este momento, Windows sólo requería un mieroprocesador Intel 8086 u 8088
trabajando en «modo real» para acceder a 1 megabyte (MB) de memoria. Windows/386
(comercializada poco después de Windows 2.0) utilizaba el «modo virtual 86» del mi
eroprocesador 80386 para ejecutar en una ventana y en multitarea algunos programas
MS-DOS que acceden directamente al hardware. Por simetría, Windows versión 2.1 fue
renombrada como Windows/286.
Windows versión 3.0 apareció el 22 de mayo de 1990. Las antiguas versiones Win
dows/286 y Windows/386 se fusionaron en un producto con esta nueva actualización. El
gran cambio en Windows 3.0 era el soporte del modo protegido de los microprocesado
res Intel 80286, 80386 y 80486 2 . Esto dio a Windows y a las aplicaciones Windows
acceso hasta a 16 MB de memoria. Los programas del shell de Windows para ejecutar
programas y mantener archivos fueron completamente reconstruidos. Windows 3.0 fue
la primera versión común en las computadoras de los usuarios, tanto en casa como en la
oficina.
Windows versión 3.1 apareció en abril de 1992. Varias características significativas
eran la tecnología de fuentes TrueType (que trajo a Windows fuentes de contorno esca
lables), multimedia (sonido y música), OLE y cuadros de diálogo comunes. Además,
' Desde hace varios años, Intel suprimió los dígitos «80» en el nombre de los
mieroprocesadores, que
son más conocidos como 286, 386 y 486. (N. del T)
8 Introducción
4
Windows 4.0) apareció en agosto de 1995. Igual que Windows NT, Windows 95 también
soporta un modelo de programación de 32 bits (por tanto, requiere un microprocesa
dor 80386 o superior). Aunque carece de algunas características de Windows NT, como
una amplia seguridad y transportabilidad a máquinas RISC, Windows 95 tiene la ventaja
de ejecutarse en máquinas con sólo 4 MB de memoria.
Obviamente, los programas escritos para las versiones Windows de 16 bits anteriores
a Windows NT y Windows 95 normalmente no son transportables de una forma automá
tica y transparente a las nuevas versiones Windows de 32 bits (en los próximos capítulos
haré algunas consideraciones necesarias para crear aplicaciones transportables).
Microsoft ha intentado distinguir sus diferentes plataformas definiendo un conjun
to de API (librería de funciones). La API Win 16 es la que utiliza Windows 3. 1. La API
Win32 que es la que utiliza Windows NT y Windows 95. Pero espere, hay más. Micro
soft permitió a los programadores escribir aplicaciones de 32 bits para Windows 3. 1; las
llamadas a funciones de 32 bits se traducían en llamadas de 16 bits mediante una librería
de enlace dinámico (DLL) '. La API se llamó Win32s («s» de «subconjunto» porque la
API solamente utilizaba funciones en Winl6). También, en un momento la API de Win
dows 95 fue llamada Win32c («c» de «compatible»), pero este término ha sido abando
nado.
Léame. TXT 9
A principios de 1988, la primera edición de Programming Windows fue uno de los pri
meros libros en programación Windows que llegó a las librerías. Mientras me preparaba
para revisar Programming Windows para Windows 95, advertí que 1995 era el décimo
aniversario de Windows y, por tanto, el décimo aniversario de los orígenes de este libro
Este hecho es a la vez estimulante y un poco preocupante.
Cuando recuerdo la historia de este libro, advierto que debo mucho a mi asociación
con mucha gente maravillosa de la industria informática. Así es cómo empezó.
En la primavera de 1985 colaboraba de forma independiente escribiendo artículos
en PC Magazine y pasaba mucho tiempo por sus oficinas en One Park Avenue en Nueva
York. En varias ocasiones nos visitó Steve Balimer de Microsoft (ahora vicepresidente
ejecutivo de ventas y soporte), que nos mostraba la última versión beta de un producto
conocido como Windows. Aquellos de nosotros interesados en Windows nos trasladába
mos a la oficina del editor senior John Dickinson para analizarlo. John era uno de los
pocos compañeros de PC Magazine que tenía una EGA en su máquina y que, por tanto,
podía ejecutar Windows en color. Jugábamos con estas primeras versiones de Windows
durante algún tiempo (normalmente, hasta que nos cansábamos de que se quedara col
gado) y luego esperábamos la próxima visita de Ballmer con una versión más estable.
Un día en la primavera de 1985 le pregunté a John Dickinson cómo se podía escribir
un programa que se ejecutara bajo Windows. John rápidamente abrió un cajón de su
escritorio y sacó varios montones de papeles fotocopiados y cerca de 10 disquetes que
Balimer había dejado algunas semanas atrás.
La pila de hojas y disquetes resultó ser la versión prelirninar del primer Windows
Software Development Kit (SDK), completado con un compilador de C. Me llevé el
paquete a casa, instalé el SDK en un disco Bernoulli (en aquel tiempo trabajaba con un
IBM PC de dos dísquetes), e instantáneamente llegué a ser un programador WindoW1s
aproximadamente después de seis meses de confusión total. Mientras realizaba esta ex
periencia de aprendizaje y me peleaba con la documentación, una idea cruzaba conti
5
nuamente mi cabeza: «Yo podría explicar todo esto mucho mejor que lo hace Microsoft».
Windows versión 1.0 apareció finalmente en noviembre de 1985, pero en aquel
tiempo no había forma de predecir que Windows dominaría un día el mercado. Al con
trario, tenía varios competidores, incluyendo TopView de IBM, GEM de Digital Research
y DESQview de Quarterdeck. El tema de portada de la revista PC Magazine del 25 de
febrero de 1985 hablaba de «Window Wars!» (La guerra de las ventanas). Este fue el
primer tema de portada que escribí para la revista, aunque fui relegado a analizar TopView
en vez de Windows.
10 Introducción
Me llevó casi otro año tener la confianza suficiente para explicar la programación
en Windows en un artículo, lo que ocurrió en el número de diciembre de 1986 de Micro
soft Systems Journal. Creo que este escrito, que presentaba una versión primitiva del
programa WHATSIZE que encontrará en el Capítulo 4, es el primer artículo sobre pro
gramación Windows que apareció en una revista. Ocurrió que conocía al primer editor
de MSJ (Jonathan Lazarus) porque había sido vicepresidente en Ziff-Davis, empresa
editora de PC Magazine. Jon posteriormente se fue a trabajar a Microsoft, donde actual
mente desempeña el cargo de vicepresidente de relaciones estratégicas.
Escribir sobre Windows en MSJ llamó la atención de Microsoft Press, pero de una
forma un tanto rocambolesca. Conocí a Tandy Trower (actualmente director de diseño
de interfaces de usuario en Microsoft) en una conferencia de lenguajes de Microsoft en
Redmond, Washington, en octubre de 1986, y le comenté que me gustaba escribir artículos
de programación Windows en MSJ. El dio mi nombre a Susan Lammers, que era editora
jefe de Microsoft Press. La gente de Microsoft Press ya conocia mi nombre porque yo fui
el primer redactor en revisar la infame primera versión de MS-DOS Encyc1opedia e
informar de que contenía numerosos defectos y errores, lo que le hizo entrar en desven
taja en el mercado y catapultó al éxito a la mucho más completa obra de Ray Duncan.
Durante la feria Comdex Fall de noviembre de 1986 en Las Vegas, me reuní con el
editor de adquisiciones Claudette Moore (ahora un agente de libros informáticos en
Massachusetts) y diseñarnos un esquema del libro. Originalmente, Programming Windows
se concibió como un libro mucho más pequeño, dirigido tanto a programadores como a
usuarios avanzados. A medida que iba trabajando en el libro durante el año siguiente (en
el que tuve que cambiar el enfoque de Windows 1.0 a Windows 2.0), creció en tamaño y
amplió sus objetivos.
Lo que usted tiene en sus manos es la cuarta edición de Programming Windows
«Programación en Windows 95». Lo revisé para Windows 3.0 y luego de nuevo para
Windows 3. 1. Desde que el libro se publicó por primera vez, muchos programadores
Windows me han dicho que Programming Windows fue el punto de inicio con el cual se
enfrentaron a un entorno a menudo extraño. Nada podría agradecer más; no necesaria
mente para colmar mi ego, sino porque he ayudado de alguna forma a conseguir que
Windows sea el éxito que actualmente es.
ALGUNOS REQUISITOS
Muy bien, el primer día de clase está llegando a su fin. En el próximo capítulo em
pezaremos viendo algo del código Windows. Para ello, necesita tener instalado Mi
crosoft Visual C++ 4.0. En su archivo AUTOEXEC.BAT necesita incluir la instrucción
siguiente:
CALL \MSDEV\BIN\WVARS32.BAT
Este es un archivo incluido en VC++ que establece las variables de entorno DOS nece
sarias para compilar programas desde la línea de órdenes de MS-DOS. Simplemente
Léame. TXT 11
establece las trayectorias de unidad y directorio para los archivos de cabecera, archivos
de librerías y archivos binarios. También necesitará utilizar una segunda instrucción
CALL en su archivo AUTOEXEC.BAT para ejecutar el archivo por lotes MSC.BAT,
mostrado en la Figura 1-1. También se encarga de definir variables de entorno que se
usan en los archivos make de los próximos capítulos.
6
MSC.BAT
REM ---------------------------------------------------------------
REM MSC.BAT -- inicializar entorno para NMAKE de MS C/C++ 7.0
REM -------------------------------------------------------------
SET CC=cl
SET CFLAGS=-c -DSTRICT -G3 -Ow -W3 -Zp -Tp
SET CFLAGSMT=-C -DSTRICT -G3 -MT -Ow -W3 -Zp -Tp
SET LINKER=link
SET GUIFLAGS=-SUBSYSTEM:windows
SET DLLFLAGS=-SUBSYS'FEM:,,vindows -DLL
SET GUIL,IBS=-DEFAULTLIB:user32.lib gdi32.1ib winrnm.lib coindlg32.lib comctl32.lib
SET RC=re
SET RCURS=-r -DWIN32
Fígura 1-1. Ejecute este archivo para compilar los programas de este libro.
Capítulo 2
Hola, Windows 95
Si usted es nuevo en la programación para un entorno gráfico tal como Microsoft Win
dows 95, probablemente lo encontrará muy diferente de cualquier otra cosa que haya
experimentado. Windows tiene la reputación de ser fácil para los usuarios, pero difícil
para los programadores. Es bastante común para los principiantes quedarse perplejos por
la arquitectura de Windows y la estructura de las aplicaciones que se ejecutan bajo el
sistema. Si le pasa esto, no se asuste pensando que ha perdido una parte vital de su
cerebro necesaria para llegar a ser un buen programador Windows. La confusión inicial
es normal y no permita que alguien le diga que no es así.
La programación Windows es extraña, es misteriosa, es retorcida, es delicada, es
incómoda, es fascinante. No es ni obvia ni evidente y puede pasar algún tiempo antes de
que experimente el deseo de gritar «¡Eureka!». Una estimación común es que los progra
madores tienen que pasar una curva de aprendizaje de 6 meses antes de llegar a estar
cómodo en la construcción de programas Windows, e incluso después de ese plazo, el
aprendizaje nunca termina. Mí única esperanza es que este libro pueda reducir algunas
semanas (o quizá un mes o dos) la curva de aprendizaje típica.
Usted puede estar preguntándose: «Si la programacion Windows es tan dificil, ¿por
qué preocuparse?».
Bien, la respuesta es, «Usted probablemente no tenga elección». Después de todo,
Windows ha alcanzado un éxito tan importante en el mercado de los compatibles PC que
la programación para MS-DOS (utilizando modo texto u modo gráfico) ya no es rentable
ni recomendable. Si usted escribe aplicaciones comerciales, los analistas de software de
las revistas de informática prácticamente ignorarán su producto si no está escrito para
Windows 95. Si trabaja en programación especializada para una compañía, sus usuarios
(y sus empleados) se quejarán amargamente si su programa no se integra correctamente
con las aplicaciones Windows que ellos utilizan.
Pero hay mejores razones para elegir Windows como su plataforma.
LA DIFERENCIA WINDOWS
Windows proporciona ventajas significativas tanto a los usuarios como a los programa
dores respecto al convencional entorno MS-DOS. Los beneficios a los usuarios y los
13
7
14 Introducción
Conceptos GUI
Todas las interfaces de usuario gráficas utilizan gráficos en una pantalla de vídeo.
Los gráficos ofrecen mejor utilización de la pantalla, un entorno visual rico para mos
trar información y la posibilidad de un sistema de vídeo WYSIWYG (lo que se ve
es lo que se imprime) de gráficos y texto formateado preparado para un documento
impreso.
En los primeros días, el sistema de vídeo se utilizaba únicamente para mostrar el
texto que el usuario escribía en el teclado. En una interfaz gráfica de usuario, el sistema
de vídeo por sí mismo se convierte en una fuente de entradas del usuario. El sistema de
vídeo muestra varios objetos gráficos en forma de ¡conos y controles de entrada como
botones y barras de desplazamiento. Utilizando el teclado (o más directamente, un dis
positivo de apuntamiento como un ratón), el usuario puede manipular directamente estos
objetos en la pantalla. Los objetos gráficos se pueden arrastrar, los botones se pueden
pulsar y las barras de desplazamiento se pueden desplazar.
La interacción entre el usuario y un programa llega a ser por tanto más íntima. En
vez de un ciclo de información unidireccional desde el teclado al programa y luego al
sistema de vídeo, el usuario interactúa directamente con los objetos de la pantalla.
8
Hola, Windows 95 15
La mayoría de las funciones del programa se activan a través del menú del programa.
Cuando la información es demasiado grande para caber en una única pantalla se solucio
na mediante barras de desplazamiento. Algunas opciones de menú invocan cuadros de
diálogo, en los cuales el usuario introduce información adicional. Un cuadro de diálogo
que aparece en casi todos los programas Windows permite abrir un archivo. Este cuadro
de diálogo parece-el mismo (o muy similar) en varios programas Windows diferentes y
casi siempre se invoca desde la misma opcion de menú.
Una vez que ya conoce cómo utilizar una aplicación Windows, está en buena posi
ción para aprender a usar otra. Los menús y cuadros de diálogo permiten a los usuarios
experimentar con un nuevo programa y explorar sus características. La mayoría de los
programas Windows tienen tanto una interfaz de teclado como una interfaz de ratón.
Aunque la mayoría de las funciones de Windows se pueden controlar a través del tecla
do, utilizar el ratón es a menudo más fácil para muchas acciones.
Desde la perspectiva del programador, para conseguir una interfaz de usuario con
sistente y coherente con las aplicaciones Windows hay que utilizar las rutinas predefini
das en Windows que permiten construir menús y cuadros de diálogo. Todos los menús
tienen las mismas interfaces de teclado y ratón porque Windows (y no el propio progra
ma) se encargan de realizar este trabajo.
Ventajas de la Multitarea
9
10
16 Introducción
Gestión de memoria
Un sistema operativo no puede implementar multitarea sin hacer algo de gestión de
memoria. A medida que se cargan nuevos programas y van terminando los viejos pro
gramas, la memoria se va fragmentando. El sistema tiene que ser capaz de consolidar el
espacio de memoria libre. Esto requiere que el sistema mueva bloques de código y datos
en memoria.
Incluso Windows 1, ejecutándose en un microprocesador 8088, era capaz de reali
zar este tipo de gestión de memoria. En el modo real, esto sólo se puede llevar a cabo
como una hazaña impresionante de ingeniería de software. Los programas que se ejecu
tan en Windows pueden colapsar la memoria, pues un programa puede contener más
código del que se puede almacenar en memoria a la vez. Windows puede descargar
código de la memoria y recargarlo posteriormente desde el archivo EXE del programa.
Un usuario puede ejecutar varias copias, llamadas «Instancias», de un programa; todas
estas instancias comparten el mismo código en memoria. Los programas ejecutándose
en Windows pueden compartir rutinas localizadas en otros archivos llamados «librerías
de enlace dinámico» (~ynamic link libraries). Windows incluye un mecanismo para en
lazar el programa con las rutinas de las librerías de enlace dinámico en tiempo de eje
cución. Windows por sí mismo es básicamente un conjunto de librerías de enlace diná
mico.
Por tanto, incluso en Windows 1, el límite de memoria de 640 kilobyte (KB) de la
arquitectura del PC estaba superado efectivamente sin requerir memoria adicional. Pero
Microsoft no se detuvo aquí: Windows 2 ofreció a las aplicaciones Windows acceso a la
memoria expandida (EMS), mientras que Windows 3 trabajaba en modo protegido para
ofrecer a las aplicaciones Windows acceso de hasta 16 MB de memoria extendida. Y
ahora Windows 95 barre estas viejas restricciones al ser un sistema operativo completa
mente de 32 bits con un espacio de memoria plano'.
' Un espacio plano de direcciones de memoria (flat address space) significa que el
programador pue
de utilizar toda la memoria de forma lineal, accediendo directamente a cualquier dirección
de memoria sin
recurrir a bloques de segmento ni descriptores (memoria extendida), ni tener que
conmutar bancos de
memoria (memoria expandida). (N. del T)
11
Hola, Windows 95 17
se ejecutará en cualquier tarjeta de vídeo o cualquier impresora para la que exista una
controlador Windows. El programador no necesita determinar el tipo de dispositivo que'
está instalado en el sistema.
Crear una interfaz gráfica independiente de¡ dispositivo en el IBM PC no fue una
tarea sencilla para los ingenieros de Windows. El diseño de] PC estaba basado en el
principio de la arquitectura abierta. Los fabricantes de hardware independientes fueron
animados a desarrollar periféricos para el PC y lo hicieron en gran número. Aunque
habían aparecido varios estándares, los programas de MS-DOS convencionales para el
PC tenían que soportar individualmente varias configuraciones de hardware. Por ejem
plo, es bastante común para un procesador de texto MS-DOS que se venda con uno 0 dos
disquetes llenos de pequeños archivos, cada uno de los cuales utiliza una impresora
determinada. Los programas Windows 95 no requieren estos controladores porque su
soporte es parte de Windows.
El compromiso Windows
La programación para Windows 95 es una apuesta a todo o nada. Por ejemplo, no puede
escribir una aplicación MS-DOS y utilizar Windows para algunos gráficos. Si desea
utilizar alguna parte de Windows, tiene que comprometerse completamente con un pro
grama diseñado para Windows.
La razón de esta afirmación se comprenderá mejor a medida que aprenda la es
tructura de un programa Windows. Cualquier cosa en Windows está interconectada.
Si desea dibujar un gráfico en el sistema de vídeo, necesita algo llamado «handle a
un contexto de dispositivo». Para obtenerlo, necesita un «handle a una ventana». Para
recibir y procesar mensajes necesita un «procedimiento de ventana». Y en ese punto
ya está escribiendo un programa Windows. No se puede volar si no se deja de pisar el
suelo.
12
18 Introducción
mación C que soporte Windows 95 '. Los archivos de cabecera son una parte importante
de la documentación técnica de Windows. Puede que desee imprimir los archivos de
cabecera o utilizar un examinador de archivos para una referencia rápida.
En su programa Windows, puede utilizar las llamadas a funciones Windows gene
ralmente de la misma forma que usa las funciones de la librería C como strIen. La prin
cipal diferencia es que el código para las funciones de la librería C se enlaza con el
código del programa durante el proceso de compilación, mientras que el código para las
funciones Windows se localiza fuera de su programa en librerías de enlace diná
mico (DLL).
Cuando usted ejecuta un programa Windows, se comunica con Windows a través de
un proceso llamado «enlace dinárnico» (dynam¡c linking). Un archivo EXE contiene
referencias a las distintas librerías de enlace dinámico que utiliza y a las funciones
incluidas en las librerías. La mayoría de las DLL se localizan en el subdirectorio
SYSTEM de su directorio Windows. Cuando un programa Windows se carga en memo
ria, las llamadas a función del programa se resuelven como puntos de entrada a las
funciones en las librerías de enlace dinámico, las cuales se cargan en memoria si es que
no lo estaban.
Cuando usted enlaza un programa Windows para producir un ejecutable, tiene que
enlazarlo con unas «librerías de importación» especiales proporcionadas con su entorno
de programación. Estas librerías de importación contienen los nombres de las librerías
de enlace dinámico de todas las funciones Windows, así como información de referencia
para dichas funciones. El enlazador o finker utilizar esta información para construir la
tabla en el archivo EXE que resuelve las llamadas a funciones Windows cuando se
carga el programa.
Cuando programa para Windows usted está realmente comprometiéndose con un tipo de
programación orientada a objetos (OOP: Object Oriented Programming). Esto es más
evidente en el objeto con el que está trabajando durante más tiempo en Windows: el
objeto que da a Windows su nombre, el objeto que pronto parecerá asumir característi
cas antropomórficas, el objeto que puede incluso aparecer en sus sueños, el objeto cono
cido como la «ventana».
Como ya mencioné anteriormente, las ventanas son áreas rectangulares de la panta
lla. Una ventana recibe la entrada del usuario desde el teclado o el ratón y visualiza
salida gráfica en su superficie.
Una ventana de aplicación normalmente contiene la barra de título del pro
grama, una línea de menús, bordes para cambiar el tamaño y quiza alguna barra de
desplazamiento. Los cuadros de diálogo son ventanas adicionales. Además, la super-
' Por ejemplo, Microsoft Visual C++, Borland C++, Symantec C++ o PowerBuilder Optima
C++.
(N. del T.)
13
Hola, Windows 95 19
El procedimiento de ventana
Usted estará acostumbrado a la idea de un programa que hace llamadas al sistema opera
tivo. Así es como un programa abre un archivo, por ejemplo. Lo que no es tan fácil de
aceptar es la idea de un sistema operativo haciendo llamadas a un programa. Pero esto es
fundamental en la arquitectura orientada a objetos de Windows 95.
14
20 Introducción
#include <std¡o.h>
main ()
15
Hola, Windows 95 21
En este capítulo, mostraré un programa similar escrito para Microsoft Windows 95.
El Programa se llama HOLAWIN y crea una ventana que muestra la cadena de texto
«Hola, Windows 95» y también reproduce un archivo de sonido con mi voz' recitando
las mismas palabras.
Para que no quede asustado por la impresión al ver el código del programa HO
LAWIN, le aviso ahora que el archivo con el código fuente HOLAWIN.C tiene un tama
ño de 80 líneas. La mayoría de estas 80 líneas son redundantes y tendrá que utilizar unas
línea.s similares en casi todos los programas Windows que escriba.
En vez de preguntar por qué el programa «Hola, Windows 95» es tan largo y com
plejo, vamos a preguntar por qué el tradicional programa «Hola, mundo» es tan corto y
simple.
16
22 Introducción
El programa «Hola, mundo» es tan simple porque está diseñado para una época más
simple, con computad.oras más simples y dispositivos de salida más simples. Se trata de
un programa totalmente alejado de los programas actuales, que no estájugando el mismo
juego que la competencia.
La Figura 2-1 rriuestra dos de los tres archivos necesarios para crear el programa «HO
LAWIN». Estos son el archivo make HOLAWIN.MAK y el archivo con el código fuente
HOLAWIN.C. El tercer archivo se almacena en el disco CD-ROM con el nombre
HOLAWIN.WAV. Se trata de un archivo de sonido en formato de onda que contiene el
texto hablado.
HOLAWIN.MAK
# -------------------------
# Archivo make HOLAWIN.MAK
# -------------------------
holawin.exe : holawin.obj
$(LINKER) $(GUIFLAGS) -OUT:holawin.exe holawin.obj $(GUILIBS)
holawin.obj : holawin.c
$(CC) $(CFLAGS) holawin.c
HOLAWIN.C
#include <windows.h>
(continúa)
17
Figura2-1. El programa HOLA WIN.
18
Hola, Windows 95 23
TranslateMessage (&msg)
DispatchMessage (&msg)
return msg.wParam ;
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM
lParam)
HDC hdc
PAINTSTRUCT ps
RECT rect
switch (iMsg)
case M-CREATE :
PlaySound ("holawin.wav", NULL, SND-FILENAME 1 SND~_ASYNC)
return 0 ;
case WH_PAINT:
19
hdc = BeginPaint (hwnd, &ps) ;
(continúa)
20
24 Introducción
case W_DESTROY:
PostQuitMessage (0)
re~urn U
NMAKE HOLAWIN.MAK
Si todo sale bien, puede ejecutar el programa desde la línea de órdenes de la ventana
DOS escribiendo:
HOLAWIN
21
22
Cuando se piensa detenidamente, se comprueba que esta ventana tiene una increíble
funcionalidad en sus 80 líneas de código. Usted puede pinchar en la barra de título con el
puntero de] ratón y mover la ventana alrededor de la pantalla. Puede pinchar en las
esquinas de la ventana y modificar su tamaño. Cuando la ventana cambia de tamaño, el
programa repone automáticamente la cadena de texto «Hola, Windows 95» en el nuevo
centro de la pantalla. Puede pulsar el botón maximizar y aumentar HOLAWIN para que
ocupe toda la pantalla. Puede hacer clic en el botón minimizar y quitar la ventana de la
pantalla. Puede invocar todas estas funciones desde el menú de sistema 5 . También puede
cerrar la ventana y terminar el programa seleccionando la opción Cerrar en el menú de
sistema, haciendo clic en el botón cerrar en la parte derecha de la barra de título o
haciendo doble clic en el icono del menú de sistema.
Aunque puede estar satisfecho al ver que HOLAWIN tiene toda la funcionalidad de
un programa Windows normal, seguramente no estará tan contento cuando examine el
código fuente requerido para crear este programa. Pero ármese de valor mientras voy
diseccionando paso a paso este programa y analizándolo exhau sti vani ente.
1 El menú de sistema (también llamado menú de control) se activa pulsando el icono situado
en la
esquina superior izquierda de todas las ventanas y contiene órdenes para realizar las
operaciones más
habituales con una ventana (cerrar, mover, cambiar el tamaño, maximizar y rninimizar). (N.
del T.)
23
26 Introducción
El archivo make
Para facilitar la compilación de programas Windows puede utilizar la utilidad NMAKE
incluida en Microsoft Visual C++ 4.0. Cuando desee cambiar algo en el archivo fuente
HOLAWIN.C, todo lo que necesita es ejecutar NMAKE como se mostró anteriormente
para crear el ejecutable HOLAWIN.EXE actualizado.
Un archivo make está formado por una o más secciones, cada una de las cuales
empieza con una línea justificada a la izquierda -que contiene un archivo de destino, una
coma y uno o más archivos dependientes. Esta línea tiene debajo una o más líneas de
orden indentadas'. Estas órdenes crean el archivo de destino a partir de los archivos
dependientes. Si la fecha y hora de última modificación de cualquiera de los archivos
dependientes es posterior a la fecha y hora de] archivo de destino, NMAKE ejecuta las
líneas de orden indentadas.
Normalmente, NMAKE sólo actualizará el archivo de destino en la primera sección
del archivo make. Sin embargo, si uno de los archivos dependientes es a su vez un archi
vo de destino en otra sección del archivo make, NMAKE actualizará primero ese destino.
El archivo make HOLAWIN.MAK tiene dos secciones. La primera sección ejecuta
el enlazador si HOLAWIN.OBJ se ha modificado posteriormente a HOLAWIN.EXE.
La segunda sección ejecuta el cOmpilador si HOLAWIN.C se ha modificado después de
HOLAWIN.OBJ. Puesto que HOLAWIN.OBJ es un archivo de destino en la primera
sección y un archivo dependiente en la segunda sección, NMAKE comprobará si es ne
cesario actualizar HOLAWIN.OBJ antes de recrear HOLAWIN.EXE. Por tanto, el archivo
make se ejecuta realmente de abajo a arriba. Ejecutar el compilador C crea el módulo
objeto HOLAWIN.OBJ a partir del archivo fuente HOLAWIN.C. Ejecutar el enlazador
(linker) crea el ejecutable HOLAWIN.EXE a partir de HOLAWIN.0B.J.
En el Capítulo 1, expliqué cómo las macro o identificadores del archivo make se
establecen a través de variables del entorno definidas por los archivos por lotes que se
vieron en ese capítulo. La mayoría de las veces esto supone definir varios parámetros o
flags del compilador y nombres de librería del enlazador, por tanto regrese a esa parte
del Capítulo 1 si está interesado en más detalles, .
El archivo fuente C
El segundo archivo de la Figura 2-1 es HOLAWIN.C (véanse páginas anteriores), el
archivo con el código fuente C. ¡Y puede pasar un momento antes de que reconozca que
este programa está escrito en 0
Primero echaremos un vistazo general a HOLAWIN.C antes de entrar en detalles.
El archivo sólo contiene dos funciones: WinMain y WndProe. WinMain es el punto de
entrada al programa, el equivalente a la función estándar main del lenguaje C. Todos los
programas Windows tienen una función WinMain.
` Una línea indentada es una línea cuyo comienzo está tabulado algunos espacios respecto a
la línea
anterior. (N. del T.)
24
Hola, Windows 95 27
25
28 Introducción
ldentificadores en mayúsculas
Seguramente habrá advertido que se utilizan varios ideritificadores en mayúsculas en
HOLAWIN.C. Estos identificadores están definidos en los archivos de cabecera de Win
dows. Varios de los identificadores contienen un prefijo de dos o tres letras seguido de
un subrayado:
Prefijo Categoría
cs Estilo de clase (class style)
IDI Número ID para un icono
IDC Número ID para un cursor
ws Estilo de ventana (window style)
Cw Opción para crear ventana (create window)
wM Mensaje de ventana (window message)
SNI) Opción de sonido
DT Opción para dibujar texto (draw text)
26
Hola, Windows 95 29
Estructura Significado
MSG Estructura mensaje
WN13CLASSEX Estructura clase de ventana
PAINTSTRUCT Estructura dibujo
RECT Estructura rectángulo
Las dos primeras estructuras de datos se utilizan en WinMain para definir dos es
tructuras con nombre insg y wndelass. Las otras dos se utilizan en WndProc para definir
dos estructuras llamadas ps y rect.
27
30 Introducción
Identificador Significado
Los handles se utilizan con bastante frecuencia en Windows. Antes de que termine
este capítulo, también encontrará HICON (un handle de icono), HCURSOR (un handle
de cursor o puntero del ratón) y HBRUSH (un handle de una brocha gráfica).
Un handle es simplemente un número (normalmente con un tamaño de 32 bits) que
identifica un objeto. Los handles en Windows son similares a los handles de un archivo
utilizados en C convencional o en programación MS-DOS. Un programa casi siempre
obtiene un handle llamando a una función Windows. El programa utiliza el handle en
otras funciones Windows para identificar el objeto. El valor real del handle no es impor
tante para el programa, aunque sí para Windows.
Notación húngara
Puede advertir que algunas de las variables en HOLAWIN.C tienen nombres peculiares.
Por ejemplo, szCmdLine, es uno de los parámetros pasados a WinMain.
Muchos programadores Windows utilizan una convención para nombrar las varia
bles que se conoce como notación húngara, en honor a Charles Simonyi, un legendario
programador de Microsoft. En pocas palabras, en la notación húngara el nombre de la
variable comienza con una letra o letras minúsculas que indican el tipo de dato de la
variable. Por ejemplo, el prefijo sz en szCmdLine significa que es una «cadena de carac
teres que termina con el valor cero» (en inglés, string with zero). El prefijo h en hInstan
ce y hPrevInstance indica que es un «handic». El prefijo i en ¡CmdShow indica que es un
«entero» (en inglés, integer). Los dos últimos parámetros de WndProc también utilizan
notación húngara, aunque, como expliqué anteriormente, wParam debería llamarse pro
piamente u¡Param (de unsigned int). Pero como estos dos parámetros están definidos
usando los tipos de datos WPARAM y LPARAM, he preferido mantener sus nombres
tradicionales.
Cuando se nombran las variables de una estructura puede utilizar el nombre de la
estructura (o una abreviación del nombre de la estructura) en minúsculas como un prefi
jo al nombre de la variable o como el propio nombre completo de la variable. Por ejem
plo, en la función WinMain de HOLAWIN.C la variable msg es una estructura de] tipo
MSG y wndclass es una estructura del tipo WNDCLASSEX. En la función WndProe, ps
es una estructura PAINTSTRUCT y rect es una estructura RECT.
28
Hola, Windows 95 31
c char
by BYTE (unsigned char)
n short
i int
x, y int (usada como coordenada-x o coordenada-y)
cx1 Cy int (usado como longitud x o y; c indica «contador»)
bof BOOL (int)J indicaflag
WWORD (unsigned int)
1 LONG (long)
dw DWORD (unsigned long)
fn función
S cadena (string)
SZ cadena terminada con un byte 0 (string with zero)
h handle
p puntero
Una vez finalizado este vistazo general a HOLAWIN.C, podemos empezar ahora el
análisis del programa línea a línea. El código comienza con una instrucción #include
para incluir el archivo de cabecera WINDOWS.H:
#include <windows.h>
29
32 Introducción
30
Hola, Windows 95 33
UINT cbSize
UINT style ;
WNEPROC lpfnWndProc
int cbClsExtra
int cbWndExtra
HINSTANCEhInstance
HICON hTcon ;
HCURSOR hCursor
HBRUSH hbrBackground
LKSTR lpszMenuName
LKSTR IpszClassName
HICON hIconSm
WNDCLASSEX
Conviene hacer algunos comentarios sobre los tipos de datos y la notación húngara.
Los prefijos LP y 1p significan «puntero largo» (long pointer), que es una herencia de
Windows 16 bits, donde los programadores tenían que distinguir entre puntero cortos
(short o near) de 16 bits y punteros largos (long ofar) de 32 bits. En Windows 95, todos
los punteros tienen un tamaño de 32 bits. He intentado eliminar todos los prefijos 1 en los
punteros de los ejemplos de este libro, pero es muy probable que los continúe viendo en
otros listados Windows.
También notará que se utiliza la notación húngara. Por ejemplo, el prefijo 1pfn signi
fica «puntero largo a función» (longpointer to afunction). El prefijo cb significa «con
tador de bytes». El prefijo hbr es «handle de una brocha» (handle to a brush).
31
32
34 Introducción
En WinMain, tiene que definir una estructura del tipo WNDCLASSEX, general
mente, como ésta:
WNDCLASSEX wndc1ass ;
Regi~LerClassEx (&wndc1ass) ;
w_ndc1assApfnWndProc = WndProc ;
wndclass.cbClsExtra = 0
33
wndc1ass.cbWndExtra = 0
34
Hola, Windows 95 35
wndclass.hInstance = hInstance ;
La instrucción
y la instrucción
definen el icono utilizado para todas las ventanas creadas basándose en esa clase de
ventana. El icono es una imagen pequeña en mapa de bits (bitmap) que aparece en la
barra de tareas de Windows y en la parte izquierda de la barra de título de la ventana.
Posteriormente en este libro aprenderá a crear ¡conos personalizados para sus
programas
Windows. Por ahora, adoptaremos un enfoque sencillo y utilizaremos un icono
predefinido.
Para obtener un handle a un icono predefinido, tiene que llamar a la función LoadIcon
con el primer parámetro definido a NULL. (Cuando cargue su propio icono personaliza
do, este parámetro debe identificar el handle de instancia del programa.) El segundo
parámetro es un identificador que comienza con IDI («1D de un icono») y que está
definido en los archivos de cabecera de Windows. El icono IDI APPLICATION es
simplemente un pequeño dibujo de una ventana. La función LoadIcon devuelve un handle
a este icono. No tendremos que preocuparnos realmente del valor de este handle. Se
utiliza simplemente para establecer el valor de los campos hIcon y hIconSm. Estos cam
pos se definen en la estructura "DCLASSEX para ser del tipo HICON, es decir, «handle
de icono».
La instrucción:
es muy similar a las dos instrucciones anteriores. La función LoadCursor carga un cur
sor de ratón predefinido conocido como IDC - ARROW y devuelve un handle a este
cursor. Este handle se asigna al campo hCursor de la estructura WNDCLASSEX. Cuan
do el cursor del ratón se sitúe sobre el área cliente de una ventana creada basándose en
esta clase de ventana, el cursor se convierte en una flecha pequeña.
El siguiente campo especifica el color de fondo del área cliente de las ventanas
creadas basándose en esta clase de ventana. El prefijo hbr del nombre de campo hbrBac
kground significa «handle a una brocha» (handle to a brush). Una brocha (brush) es un
35
36
36 Introducción
término gráfico que designa un patrón de puntos coloreados utilizados para rellenar un
área de la ventana. Windows tiene varias brochas estándares o en «stock». La llamada a
GetStockObject de la siguiente instrucción devuelve un handle a una brocha blanca-
Esto significa que el fondo del área cliente de la ventana será blanco sólido, que es
la opción elegida normalmente.
El campo siguiente establece el menú de la clase de ventana. HOLAWIN no tiene
menú, por tanto este campo recibe el valor NULL:
wndclass.ipszMenuName = NULL ;
wndc1ass.1pszClassName = szAppNarre ;
RegisterClassEx (&wndc1ass) ;
Crear la ventana
La clase de ventana define características generales de una ventana, permitiendo a la
misma clase de ventana ser utilizada para crear diferentes ventanas. Cuando usted real
mente crea una ventana llamando a CreateWindow, puede establecer otros aspectos más
detallados sobre esa ventana en particular.
Los programadores que comienzan a trabajar en Windows se confunden a veces con
la distinción entre la clase de ventana y la ventana, y en por qué todas las características
de una ventana no se pueden establecer de una vez. En realidad, dividir la información
de esta manera es muy conveniente. Por ejemplo, todos los botones de una ventana se
crean basándose en la misma clase de ventana. El procedimiento de ventana asociado
con en esta clase de ventana está localizado dentro del propio sistema Windows. La clase
de ventana es responsable de procesar la entrada de teclado o ratón sobre los botones y
definir la apariencia visual de dichos botones en pantalla. Todos los botones trabajan de
la misma forma en este aspecto. Pero no todos los botones son iguales. Pueden tener
diferentes tamaños, diferentes posiciones en la pantalla y diferentes cadenas de texto.
Estas últimas características son parte de la definición de la ventana.
En vez de usar una estructura de datos tal como hace RegisterClassEx, la llamada a
CreateWindow requiere que toda la información se pase como parámetros a la función.
Esta es la llamada a la función CreateWindow que se realiza en HOLAWIN.C:
37
Hola, Windows 95 37
Para facilitar la lectura, he utilizado el símbolo // para comentarios de una línea que
describen los parámetros de la función CreateWindow.
El parámetro descrito como «nombre de la clase de ventana» es szAppName, que
contiene la cadena «HolaWin» -el nombre de la clase de ventana que hemos registrado
anteriormente. De esta forma se asocia la ventana con la clase de ventana.
La ventana creada por este programa es una ventana normal superpuesta con
una barra de título, un menú de sistema (menú de control) a la izquierda de la barra
de título; ¡conos minimizar, maximizar y cerrar en la derecha de la barra de título;
y un borde de la ventana que permite modificar su tamaño. Este es un estilo estándar de
las ventanas, y su nombre es WS - OVERLAPPEDWINDOW, que aparece en el paráme~
tro «estílo de ventana». El «título de ventana» es el texto que aparecerá en la barra de
título.
Los parámetros «posición x inicial» y «posición y inicial» establecen la posición
inicial de la esquina superior izquierda de la ventana, relativa a la esquina superior
izquierda de la pantalla. Usando el identificador CW - USEDEFAULT para estos pará
metros, estamos indicando que deseamos que Windows utilice la posición por defecto
para una ventana superpuesta. (CW - USEDEFAULT está definido como Ox8OOOOOOO.)
Por defecto, las ventanas superpuestas que se visualizan posteriormente se colocan des
plazadas un valor horizontal y vertical respecto a la esquina superior izquierda de la
pantalla. Similarmente, los parámetros «tamaño x inicial» y «tamaño y inicial» especifi
can el ancho y la altura de la ventana. De nuevo, el identificador CW - USEDEFAULT
indica que deseamos que Windows utilice un tamaño por defecto para la ventana.
El parámetro etiquetado como «handle de la ventana padre» se define a NULL por
que esta ventana no tiene ventana padre. (Cuando existe una relación padre-hijo entre
dos ventanas, la ventana hijo siempre aparece en la superficie de su padre.) El «handle
de instancia del programa» se define al handle de instancia pasado al programa como
parámetro de WinMain. Finalmente, un puntero a «parámetros de creación» está defini
do a NULL. Puede utilizar este parámetro para apuntar a algunos datos que puede desear
más tarde referenciar en su programa.
La llamada a CreateWindow devuelve un handle a la ventana creada. Este handle se
guarda en la variable hwnd, que está definida como del tipo HWND (handle de ventana,
handle to a window). Todas las ventanas de Windows tienen un handle. Su programa
utilizar el handle para identificar la ventana. Muchas funciones Windows requieren un
parámetro hwnd para que Windows sepa sobre qué ventana se aplica la función. Si un
38
38 Introducción
programa crea varias ventanas, cada una tiene un handle diferente. El handle de ventana
es uno de los handles más importantes que gestiona Windows.
Visualizar la ventana
Después de llamar a la función CreateWindow, la ventana se ha creado internamente en
Windows. Sin embargo, la ventana no aparece todavía en la pantalla. Se necesitan dos
llamadas a función. La primera es:
UpdateW¡ndow (hwnd) ;
obliga luego a que se dibuje el área cliente de la ventana. Esto se realiza enviando al
procedimiento de ventana (la función WndProc en HOLAWIN.C) un mensaje WM-PAINT.
Pronto explicaremos cómo WndProc actúa con este mensaje.
El bucle de mensajes
Después de llamar a UpdateWindow, la ventana se ve completamente en pantalla. El
programa tiene que tomar ahora el control para leer la posible entrada de ratón o teclado
del usuario. Windows mantiene una «cola de mensajes» para cada programa ejecutándo
se en Windows. Cuando se produce un evento de entrada, Windows traduce el evento en
un «mensaje» que coloca en la cola de mensajes del programa.
Un programa recupera los mensajes de la cola de mensajes ejecutando un bloque de
código conocido como el «bucle de mensajes»:
TranslateMessage (&msg)
Dispatchmessage (&msg)
return msg.wParam ;
39
Hola, Windows 95 39
La variable msg es una estructura del tipo MSG, que está definida en los archivos de
cabecera de Windows de la siguiente forma:
HWND hwnd
UINT message ;
WPARAM wParam
LPARAM lParam
DWORD time ;
POINT pt ;
MSG
LONG x
LONG y
POINT ;
Esta llamada pasa a Windows un puntero a la estructura NISG llamado msg. Los
parárnetros segundo, tercero y cuarto se definen a NULL o 0 para indicar que el progra
ma desea todos los mensajes de todas las ventanas creadas por el programa. Windows
rellena los campos de la estructura de mensaje con los valores correspondientes al si
guiente mensaje de la cola de mensajes. Los campos de esta estructura son:
40
40 Introducción
TranslateMessage (&rnsg)
devuelve la estructura msg a Windows para una traducción del teclado. (Trataré esto
más tarde en el Capítulo 5.) La instrucción:
DispatchMeesage (&msg~ ;
pasa de nuevo a Windows la estructura msg. Luego, Windows envía el mensaje al proce
dimiento de ventana adecuado para que se procese, es decir, Windows llama al procedi
miento de ventana. El procedimiento de ventana en HOLAWIN es la función WndProc.
Después de que WndProc procesa el mensaje, lo devuelve a Windows, que está todavía
dando servicio a la llamada a DispatchMessage. Cuando Windows regresa a HOLAWIN
después de la llamada a DispatchMessage, el bucle de mensajes continúa con la siguien
te llamada a GetMessage.
El procedimiento de ventana
Todo lo que he descrito de forma tan exhaustiva en realidad es redundante: se ha regis
trado la clase de ventana, se ha creado la ventana, se ha visualizado la ventana en panta
lla y el programa ha entrado en el bucle de mensajes para recuperar mensajes desde la
cola de mensajes.
La acción real ocurre en el procedimiento de ventana, que determina lo que la ven
tana muestra en su área cliente y cómo la ventana responde a la entrada del usuario.
En HOLAWIN, el procedimiento de ventana es la función llamada WndProc. Un
procedimiento de ventana puede tener cualquier nombre (siempre que no coincida con
algún otro nombre, por supuesto). Un programa Windows puede contener más de un
procedimiento de ventana. Un procedimiento de ventana siempre está asociado con una
particular clase de ventana que usted ha registrado llamando a RegisterClassEx. La fun
ción CreateWindow crea una ventana según una clase de ventana particular. Se puede
crear más de una ventana basada en la misma clase de ventana.
Un procedimiento de ventana se define siempre de la siguiente forma:
LRESULT CALLBACK WndProc (HWND hwnd, UINT ¡Msg, WPARAM wParam, LPARAM
lParam)
41
Hola, Windows 95 41
Advierta que los cuatro parámetros del procedimiento de ventana son los mismos
que los primeros cuatro parámetros de la estructura MSG.
El primer parámetro es hwnd, el handle de la ventana que recibe el mensaje. Este es
el mismo handle devuelto por la función CreateWindow. Para un programa como HO
LAWIN, que sólo crea una ventana, éste es el único handle de ventana que el programa
conoce. Si un programa crea múltiples ventanas basadas en una misma clase de ventana
(y, por tanto, con el mismo procedimiento de ventana), entonces hwnd identifica la ven
tana en particular que recibe el mensaje.
El segundo parámetro es un número (exactamente, un entero sin signo o UINT) que
identifica el mensaje. Los últimos dos parámetros (un WPARAM llamado wParam y un
LPARAM llamado lParam) proporcionan más información sobre el mensaje. Estos pa
rámetros reciben el nombre de «parámetros mensaje» y su contenido es específico según
el tipo de mensaje.
switch (iMsg)
case W~t_CREATE :
[procesar mensaje WCREATE]
return 0 ;
case WM_PAINT:
[procesar mensaje W_PAINTI
return 0 ;
case WI~._DESTROY:
[procesar mensaje rYMDESTROYI
return 0 ;
42
42 Introducción
Es esencial llamar a DefiVindowProc para gestionar por defecto todos los mensajes
que no se tienen en cuenta en su procedimiento de ventana.
El mensaje WM-PAINT
El segundo mensaje que procesa WndProc es WM - PAINT. Este mensaje es extremada
mente importante en la programación Windows. Informa a un programa cuándo parte o
todo el área cliente de una ventana es «no válida» y se tiene que redibujar.
¿Cómo llega a ser no válido un área cliente? Cuando la ventana se crea por primera
vez, todo el área cliente es no válido porque el programa no ha dibujado todavía nada en
pantalla. El primer mensaje WM - PAINT (que normalmente se genera cuando el progra
ma llama a UpdateW¡ndow en WinMain) indica al procedimiento de ventana que dibuje
algo en el área cliente.
Cuanto usted cambia el tamaño de HOLAWIN, el área cliente también llega a ser no
válido. Recordará que el parámetro de «estilo» de la estructura wndc1ass de HOLAWIN
estaba definido con los identificadores (o flags) CS-HREDRAW y CS - VREDRAN.
Esto le indica a Windows que invalide la ventana entera cuando cambie de tamaño.
Luego, el procedimiento de ventana recibe un mensaje WM - PAINT.
Cuando minimiza HOLAWIN y luego restaura la ventana a su tamaño anterior,
Windows no guarda el contenido del área cliente, pues en un entorno gráfico esto sería
necesitar mucha memoria. En vez de ello, Windows invalida la ventana. El procedimien
43
Hola, Windows 95 43
44
44 Introducción
pos left y top siempre están a 0. Los campos right y bottom se definen al ancho y la altura
del área cliente en pixeIs (puntos).
WniProc no hace nada con la estructura RECT excepto pasar un puntero a dicha
estructura como cuarto parámetro de la función DrawText:
Como su nombre indica, DrawText dibuja texto. Ya que esta función dibuja algo, el
primer parámetro es un handle al dispositivo de contexto devuelto por BeginPaint. El
segundo parámetro es el texto a dibujar y el tercer parámetro se define a -1 para indicar
que la cadena de texto se termina con un byte 0.
El último parámetro es una serie de identificadores oflags definidos en los archivos
de cabecera de Windows. En este caso indican que el texto se debe ver como una única
línea centrada horizontal y verticalmente dentro del rectángulo especificado por el cua
tro parámetro. Por tanto, esta llamada a función hace que la cadena «Hola, Windows 95»
aparezca centrada en el área cliente.
Cuando el área cliente sea no válido (por ejemplo, cuando cambie el tamaño de la
ventana), WndProc recibe un nuevo mensaje WM-PAINT. WndProc obtiene el nuevo
tamaño de la ventana llamando a GetClientRect y muestra el texto en el nuevo centro de
la ventana.
El mensaje WM-DESTROY
El mensaje WM - DESTROY es otro mensaje importante. Este mensaje indica que Win
dows está en el proceso de destruir una ventana como respuesta a una orden del usuario.
El mensaje es resultado de que el usuario ha hecho clic en el botón Cerrar, o ha seleccio
nado Cerrar en el menú de sistema del programa, o ha pulsado Alt-F4.
HOLAWIN responde a este mensaje llamando a:
PostQuitMessage (0) ;
45
Hola, Windows 95 45
No me llames, yo te llamaré
46
46 Introducción
47
Hola, Windows 95 47
Los mensajes pueden introducirse en la cola o permanecer fuera de ella. Los mensa
jes en la Cola son aquellos que son situados en la cola de mensajes del programa por
Windows y recuperados y repartidos por el bucle de mensajes. Los mensajes que están
fuera de la cola son enviados directamente a la ventana cuando Windows llama al proce
dimiento de ventana. El resultado es que el procedimiento de ventana obtiene todos los
mensajes de la ventana -tanto los que se introducen en la cola como los que no lo
hacen-. Estructuralmente, los programas Windows son muy límpios porque tienen un
único punto central de procesamiento de mensajes. Se dice que los mensajes de la cola se
mandan a la cola de mensajes, mientras que los mensajes fuera de la cola se envían al
procedimiento de ventana.
Los mensajes que se introducen en la cola son principalmente aquellos que se pro
ducen debido a una entrada del usuario en forma de pulsaciones de tecla (por ejemplo,
WM - KEYDOWN o WM-KEYUP), caracteres del teclado (WM-CHAR), movimientos
del ratón (WM-MOUSEMOVE ) y clies de los botones del ratón (WM - LBUTTONDOWN).
Entre los mensajes en cola también se encuentran el mensaje del temporizador
(WM-TIMER), el mensaje redibujar (WM-PAINT) y el mensaje terminar (WM-QUIT).
Los mensajes fuera de la cola son todos los demás. En ocasiones, los mensajes fuera de
la cola se generan a partir de mensajes de la cola. Cuando usted pasa un mensaje fuera de
la cola a DefW¡ndowProc dentro del procedimiento de ventana, a menudo Windows
procesa el mensaje enviando al procedimiento de ventana otros mensajes.
Obviamente, este proceso es complejo, pero afortunadamente la mayoría de la com
plejidad es un problema de Windows antes que un problema de nuestro programa. Desde
la perspectiva del procedimiento de ventana, estos mensajes vienen de una forma orde
nada y sineronizada. El procedimiento de ventana puede hacer algo con estos mensajes
o ignorarlos. Por esta razón, el procedimiento de ventana recibe el nombre de «el último
hook». Los mensajes notifican al procedimiento de ventana de casi todo lo que afecta a
la ventana.
Frecuentemente, los mensajes fuera de la cola se generan llamando a ciertas funcio
nes de Windows o enviando explícitamente un mensaje a través de la función SendMes
sage. (Los mensajes también se pueden situar en la cola de mensajes con PostMessage.)
Por ejemplo, cuando WinMain llama a CreateWindow, Windows crea la ventana y
durante el proceso envía un mensaje WM-CREATE al procedimiento de ventana. Cuan
do WinMain llama a ShowW¡ndow, Windows envía los mensajes WM-SIZE y
WM-SHOWWINDOW al procedimiento de ventana. Cuando WinMaín llama a Upda
te Window, Windows envía el mensaje WM - PAINT al procedimiento de ventana.
Los mensajes no son como las interrupciones hardware. Mientras esté procesando
un mensaje en un procedimiento de ventana, el programa no será interrumpido por otro
mensaje. Sólo cuando el procedimiento de ventana llama a una función que genera un
nuevo mensaje, entonces el procedimiento de ventana procesará el mensaje antes de que
la función regrese.
El bucle de mensajes y el procedimiento de ventana no se ejecutan coneurrentemen
te. Cuando el procedimiento de ventana está procesando un mensaje de la cola, es el
resultado de una llamada a DispatchMessage en WinMain. DispatchMessage no termina
hasta que el procedimiento de ventana ha procesado el mensaje.
48
49
48 Introducción
Pero advierta que el procedimiento de ventana tiene que ser reentrante. Es decir,
Windows a menudo llama a WndProc con un mensaje nuevo como resultado de WndProc
llamando a DejWindowProc con un mensaje anterior. En la mayoría de los casos, el
hecho de que el procedimiento de ventana sea reentrante no presenta problemas, pero
debe tener cuidado.
Por ejemplo, suponga que define una variable mientras está procesando un men
saje en el procedimiento de ventana, y luego llama a una función Windows. Des
pués de regresar de esa función, ¿puede estar seguro de que la variable es todavía la
misma? No necesariamente -no si la función Windows particular que llamó ha ge
nerado otro mensaje y el procedimiento de ventana cambió la variable mientras procesa
ba el segundo mensaje-. Esta es una de las razones por las que ciertas opciones de
optimización de los compiladores tienen que desactivarse cuando se compilan progra
mas Windows.
En algunos casos, el procedimiento de ventana tiene que conservar la información
que obtiene de un mensaje y usarla mientras está procesando otro mensaje. La informa
ción tiene que guardarse en variables definidas como static en el procedimiento de ven
tana o guardarse en variables globales.
Por supuesto, comprenderá mucho mejor todos estos conceptos cuando los procedi
mientos de ventana se amplíen para procesar más mensajes.
50
Hola, Windows 95 49
La curva de aprendizaje
Sí, corno seguramente habrá deducido de este capítulo, la programación Windows
es ciertamente algo diferente de la programación para un entorno convencional como
MS-DOS. Nadie defenderá que la programación para Windows es fácil.
Cuando comencé a aprender la programación para Windows, decidí hacer lo que
siempre había hecho cuando aprendía un nuevo sistema operativo o un nuevo lenguaje:
escribir un sencillo programa de volcado hexadecimal para ver el contenido de un archi
vo. En el entorno convencional MS-DOS, un programa de este tipo requiere procesa
miento de la línea de órdenes, gestión básica de entrada y salida de archivos y presenta
ción de salida en pantalla. Sin embargo, mi programa de volcado hexadecimal para Windows
se convirtió pronto en un monstruo. Necesitaba que aprendiera menús, cuadros de diálo
go, barras de desplazamiento y otros objetos por el estilo. Como primer programa Win
dows, definitivamente no era el más indicado, principalmente porque le dediqué dema
siado tiempo.
No obstante, cuando terminé el programa, era muy diferente de cualquier otro pro
grama de volcado hexadecimal que había escrito. En -vez de obtener el nombre del archi
vo como un parámetro en la línea de órdenes, WINDUMP (como llamé al programa)
presentaba una lista mostrando todos los archivos del directorio activo. En vez de escri
bir su salida a la pantalla como un sencillo teletipo, WINDUMP tenía barras de despla
zamiento, por lo que permitía moverse a cualquier parte del archivo. Como una opción
extra, incluso podía ejecutar dos copias de WINDUMP para comparar archivos uno al
lado del otro. En resumen, WINDUMP era el primer programa de volcado hexadecimal
que había escrito del que estaba orgulloso.
Lo que tiene que preguntarse a sí mismo es lo siguiente: ¿Deseo que mis programas
utilicen una interfaz de usuario moderna y productiva, que incluya menús, cuadros de
diálogo, barras de desplazamiento y gráficos? Si su respuesta es sí, entonces la pregunta
que surge es: ¿deseo escribir por mí mismo todo este código para menús, cuadros de
diálogo, barras de desplazamiento y gráficos? ¿0 prefiero aprovechar todo el código que
ya tiene Windows? En otras palabras, ¿es más fácil aprender a usar 1000 llamadas a
funciones o crear usted mismo todas las funciones? ¿es más fácil orientar su mente a la
arquitectura basada en mensajes de Windows o utilizar la entrada del usuario de un
modelo tradicional?
Si piensa escribir usted mismo su propia interfaz de usuario, tiene que cerrar este
libro y empezar su trabajo inmediatamente. En caso contrario, el resto de nosotros va
mos a aprender a visualizar y desplazar texto en una ventana.
51