Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 72

1

INSTITUTO SUPERIOR TECNOLGICO


NORBERT WIENER

Manual del Alumno


ASIGNATURA:

VISUAL C++

PROGRAMA: S3C
Lima-Per

Curso: Visual C++

INDICE

Nro. Pag

1. INTRODUCCIN - QUE ES VISUAL C++ ?............ 6


2. CONCEPTOS PRELIMINARES................................... 7
2.1. Que es C ++ ?
2.2. Que es la Programacin Orientada a Objetos ?
2.3. El modelo de programacin Windows
3. EL ENTORNO DE DESARROLLO - INTRODUCCIN..13
3.1. El concepto de proyecto (workspace)
3.2. Posibilidades de programacin
4. EL GENERADOR DE APLICACIONES.........................15
5. CONSTRUCCIN DE UNA APLICACIN BSICA......17
6. EL ENTORNO DE DESARROLLO - VISOR DE
PROYECTOS...................................................................30
7. LA LIBRERA DE CLASES MFC - INTRODUCCIN....31
7.1. Filosofa de trabajo con la MFC
7.2. Las clases bsicas para interfaz de usuario
7.2.1. La clase CWinApp
7.2.2. El interfaz Documento/Vista
7.2.3. La ventana bsica CWnd
7.2.4. Una ventana principal - CFrameWnd
7.2.5. Las clases Vista
7.3. Clases bsicas de propsito general
7.3.1. La clase CString
Curso: Visual C++

7.3.2. La clase CFile


7.3.3. La clase CTime
7.3.4. La clase CRect
8. TRATAMIENTO DEL MENU.........................................48
8.1. Gestin de mensajes de comandos del men
8.2. Objetos capaces de gestionar mensajes de comando de men
9. GESTIN DE DILOGOS............................ .............52
9.1. Creacin de dilogos
9.2. Tratamiento de los controles de dilogos
9.3. Mensajes de comando de controles de dilogos
9.4. Inicializacin de dilogos
9.5. Un dilogo especial - CPropertySheet
10. EL INTERFAZ MDI.......................................................60
11. CLASES ORIENTADAS A ACCESO A BASES DE DATOS
.............................................................................62
11.1. Tratamiento mediante ODBC
11.2. Tratamiento mediante DAO
11.3. Las clases bsicas
11.3.1. La clase CDatabase
11.3.2. La clase CRecordset
11.3.3. Los recordsets parametrizados
11.4. Manejo de excepciones mediante CDBException

Curso: Visual C++

1. INTRODUCCIN - QUE ES VISUAL C++ ?


Como sabemos, Windows es el entorno ms popular de interfaz grfico
de usuario (GUI). Desde este punto de vista, Windows es un entorno
multitarea basado en ventanas, que representan programas, y que
permite ejecucin concurrente.
Para desarrollar programas, Windows provee una librera de rutinas y
funciones (SDK - Kit de desarrollo de software) que permiten gestionar
componentes como mens, dilogos, ventanas, etc.
Visual C++ es un entorno integrado de desarrollo que permite la
programacin orientada a objetos (POO) conjuntamente con el sistema
de desarrollo SDK (tambin denominado API) de Windows. Al ser un
entorno integrado Visual C++ incluye, entre otras, las siguientes
herramientas de desarrollo:
Editor de texto
Compilador/Enlazador
Depurador
Visor de datos y dependencias (Browser)
Pero si desde el punto de vista del usuario Windows es un sistema
amigable, desde el punto de vista del desarrollador observaremos todo
lo contrario. El SDK de Windows no es mas que un complejo conjunto
de funciones que aade adems numerosas definiciones de tipos de
datos nuevos para cualquier programador de C/C++ para DOS. Para
solucionar este problema, Visual C++ incluye la librera de clases MFC

Curso: Visual C++

(Microsoft Foundation Classes) que permite crear y gestionar de manera


intuitiva componentes tpicos de Windows. Esto es, la MFC es una
implementacin que utiliza el API encapsulando todas las estructuras y
llamadas a funciones en objetos fciles de utilizar. Basndose en la
potencia de la MFC, Visual C++ se convierte en un generador de
programas C++ para Windows.
El objetivo del presente curso es conocer el modelo de programacin
para Windows basado en la librera de clases MFC. En este documento
se destacarn ideas, conceptos y tratamientos generales, en ningn
momento pretende ser un manual completo de programacin con MFC.
1. CONCEPTOS PRELIMINARES
1

Que es C ++ ?

Como todos sabemos, "C" es un lenguaje de alto nivel, basado en


funciones, que permite desarrollos estructurados. Entre otras muchas
caractersticas contempla la definicin de estructuras de datos,
recursividad o indirecciones a datos o cdigo (punteros).
"C ++", por su parte, es un superconjunto de "C", al que recubre con una
capa de soporte a la POO. Permite por tanto la definicin, creacin y
manipulacin de objetos.
2.2 Que es la Programacin Orientada a Objetos ?
La POO es una nueva filosofa de programacin que se basa en la
utilizacin de objetos. El objetivo de la POO no es sino la meta de
cualquier modelo de programacin estructurada convencional: "imponer"

Curso: Visual C++

una serie de normas de desarrollo que aseguren y faciliten la


mantenibilidad y reusabilidad del cdigo.
Los mecanismos bsicos de la POO son: objetos, mensajes, mtodos y
clases.
Objetos. Un objeto es una entidad que tiene unos atributos
particulares (datos) y unas formas de operar sobre ellos (los
mtodos o funciones miembro). Es decir, un objeto incluye, por
una parte una serie de operaciones que definen su
comportamiento, y una serie de variables manipuladas por esas
funciones que definen su estado. Por ejemplo, una ventana
Windows contendr operaciones como "maximizar" y variables
como "ancho" y "alto" de la ventana.
Mensajes. En C++, un mensaje se corresponde con el nombre
de uno de los mtodos de un objeto. Cuando se pasa un
mensaje a un objeto, este responde ejecutando el cdigo de la
funcin asociada.
Mtodo. Un mtodo (funcin miembro) se implementa dentro de
un objeto y determina como tiene que actuar el objeto cuando
se produce el mensaje asociado. En C++ un mtodo se
corresponde con la definicin de la funcin miembro del objeto.
La estructura ms interna de un objeto est oculta, de tal
manera que la nica conexin con el exterior son los mensajes
Clases. Una clase es la definicin de un tipo de objetos. De esta
manera, una clase "Empleado" representara todos los
Curso: Visual C++

empleados de una empresa, mientras que un objeto de esa


clase (tambin denominado instancia) representara a uno de
esos empleados en particular.
Las principales caractersticas de la POO son: abstraccin,
encapsulamiento, herencia y polimorfismo:
Abstraccin. Es el mecanismo de diseo en la POO. Nos
permite extraer de un conjunto de entidades datos y
comportamientos comunes para almacenarlos en clases.
Encapsulamiento. Mediante esta tcnica conseguiremos que
cada clase sea una caja negra, de tal manera que los objetos de
esa clase se puedan manipular como unidades bsicas. Los
detalles de la implementacin se encuentran dentro de la clase,
mientras que desde el exterior, un objeto ser simplemente una
entidad que responde a una serie de mensajes pblicos
(tambin denominados interfaz de la clase).
Herencia. Es el mecanismo que nos permite crear clases
derivadas (especializacin) a partir de clases bases
(generalizacin). Es decir, podramos tener la clase "Empleado"
(clase base) y la clase "Vendedor" derivando de la anterior. Una
librera de clases (como la MFC) no es ms que un conjunto de
definiciones de clases interconectadas por mltiples relaciones
de herencia.
Polimorfismo. Esta caracterstica nos permite disponer de
mltiples implementaciones de un mismo mtodo de clase,
Curso: Visual C++

dependiendo de la clase en la que se realice. Es decir, podemos


acceder a una variedad de mtodos distintos (con el mismo
nombre) mediante el mismo mecanismo de acceso. En C++ el
polimorfismo se consigue mediante la definicin de clases
derivadas, funciones virtuales y el uso de punteros a objetos.
Otros dos conceptos muy importantes en la POO son relativos a la
creacin y destruccin de objetos. En lenguajes estructurados
convencionales, cuando se define una variable se le reserva espacio en
memoria y, si no se inicializa expresamente, se hace por defecto (por
ejemplo, en C una variable global siempre se inicializa a 0, pero una
automtica no, por lo que si no se inicializa expresamente su contenido
inicial ser basura); por otra parte, cuando se destruye una variable (por
que se abandona el mbito de su definicin - scope -) se libera la
memoria que estaba ocupando. Si ahora hacemos el paralelismo
obligado entre variables y objetos para los lenguajes POO nos daremos
cuenta de que deben existir procedimientos especiales de construccin
y destruccin de objetos. En concreto, cada clase tiene dos funciones
miembro especiales denominadas constructor y destructor.
Constructor -> Funcin miembro que es automticamente
invocada cada vez que se define un objeto, su objetivo es la
inicializacin del mismo. Toma el mismo nombre que la clase,
puede recibir parmetros y podemos tener varios constructores
definidos.

Curso: Visual C++

Destructor -> Funcin miembro invocada automticamente


cada vez que se destruye un objeto. Su objetivo es realizar
operaciones como liberacin de memoria, cerrar ficheros
abiertos, etc. Toma el mismo nombre de la clase comenzado
primero por el carcter "~", no toma parmetros y no admite la
sobrecarga (slo puede existir uno en cada clase).
En muchos casos, para las clases mas sencillas, podemos encontrar
clases que no tiene constructor o destructor, ninguno de los dos. En
C++, siempre existen constructores y destructores por defecto que
realizan una inicializacin/liberacin estndar.
1

El modelo de programacin Windows

El modelo de programacin propuesto por Windows es totalmente


diferente al modelo de ejecucin secuencial de DOS. Al ser Windows un
entorno multitarea los programas tienen que estar preparados para
compartir los recursos de la maquina (procesador, memoria, teclado,
ratn ). Esto supone que Windows ha de disponer de mtodos que
permitan suspender tareas para activar otras en funcin de las
circunstancias del momento (por ejemplo, por accin del usuario).
Pero por parte de las aplicaciones, este hecho supone que han de
cooperar en la comparticin de esos recursos. Las aplicaciones
Windows se limitan a "esperar" mensajes procedentes del sistema,
procesarlos y volver al estado de espera. Este modelo de programacin
se conoce como "orientado al evento".

Curso: Visual C++

10

Mensaje. Es una notificacin a la aplicacin de que ha ocurrido


algo de inters y que por lo tanto debe de realizarse alguna
accin especfica. El origen del mensaje puede ser el usuario
(haciendo click con el ratn dentro e una ventana), la propia
aplicacin (mandndose un mensaje a si misma) o Windows
(pidiendo, por ejemplo, que se repinte la ventana tras ocultarse
otra que tuviese delante). Dado que la unidad mnima de
ejecucin en Windows es una ventana, los mensajes van
realmente dirigidos a ellas.
Ventana y procedimiento de ventana. En Windows, una
aplicacin se representa fsicamente por su ventana principal
(aunque despus pueda desplegar diversas ventanas hijas).
Cada una de esas ventanas dispone de una serie de
propiedades y un cdigo asociado (lo que concuerda con el
principio de la POO, en el concepto de objeto). Al cdigo
asociado a cada ventana se le denomina procedimiento de
ventana. Es una funcin que recibe los mensajes, los procesa y
devuelve el control a Windows para quedar en espera.
Otra de las caractersticas especficas de Windows frente a DOS es el
uso de recursos por parte de las aplicaciones, como son iconos, mens,
mapas de bits, cursores, plantillas de dilogos, etc. Las aplicaciones
Windows disponen por tanto de recursos (grficos generalmente)
propios almacenados en lo que se llama el fichero de recursos). El
proceso de construccin de programas en Windows incorpora una fase

Curso: Visual C++

11

adicional al compilado y enlazado de los mdulos objeto y las libreras.


Hay un proceso final de compilacin y de enlazado (bind) del fichero de
recursos.
3. EL ENTORNO DE DESARROLLO - INTRODUCCIN.
El entorno de desarrollo viene representado por el icono "Developer
Studio". En l se integran entre otras las siguientes herramientas:
Editor orientado a la codificacin C/C++ (resaltando palabras
claves )
Compilador/Enlazador incremental, que acelera el proceso de
construccin de los programas.
Depurador visual, que permite visualizar y modificar el contenido
de variables y reas de memoria.
Visor de datos (browser) que permite fcilmente controlar
dependencias y referencias a funciones, datos, clases, etc.
Adems permite visualizar la jerarqua de las clases utilizadas
en los programas.
Herramientas complementarias como un analizador de ventanas
(Spy ++) o un trazador de funciones MFC.
1

El concepto de proyecto (workspace)


En Visual C++ la construccin de cualquier tipo de
programa se inscribe dentro del concepto de proyecto
(workspace). Un proyecto define los pasos a seguir para
alcanzar la construccin de un objetivo (un programa,

Curso: Visual C++

12

una DLL, etc.), en realidad es un concepto anlogo a lo


que se conoce como "makefile" en otros entornos
tpicos de desarrollo en C. En realidad, Visual C++
genera para cada proyecto dos ficheros que lo definen,
el fichero de workspace (con extensin wsp) y un
makefile (con extensin mak) estndar que permitira la
utilizacin del mismo proyecto en otro entorno distinto.
Desde el punto de vista funcional, el proyecto contiene
referencias a cada uno de los ficheros fuentes (C/C++,
con extensiones c y cpp respectivamente), objetos,
libreras o ficheros de recursos (extensin rc) que se
deben utilizar para construir el objetivo final del
proyecto.
En definitiva, para crear cualquier programa con Visual
C++ debemos comenzar creando un proyecto para l,
codificando y aadiendo los mdulos necesarios a dicho
proyecto, y definiendo los recursos asociados.
2

Posibilidades de programacin

Cuando se crea un nuevo proyecto (desde la opcin "Nuevo" del men


"Fichero" aparece un dilogo que nos permite especificar que se cree un
nuevo workspace), lo primero que solicita el sistema es determinar el
tipo de objetivo que se persigue con este proyecto. Destacar las
siguientes posibilidades:
Aplicacin (.EXE) basada en la MFC (MFC AppWizard)
Curso: Visual C++

13

Librera de enlace dinmico (.DLL) basada en la MFC. (MFC


AppWizard)
Aplicacin (.EXE) estndar para Windows (basada en el SDK)
Librera de enlace dinmico (.DLL) (basada en el SDK)
Aplicacin (.EXE) modelo DOS (Console application)
Librera esttica (.LIB)
Como ya hemos destacado anteriormente, el objetivo del presente curso
es el manejo de la librera MFC, por lo que nos centraremos
bsicamente en el primer punto (la construccin de una DLL con MFC
es totalmente similar).
4. EL GENERADOR DE APLICACIONES.
Ya sabemos que Visual C++, apoyado en la potencia de la MFC, es
capaz de convertirse en un generador de aplicaciones. Para ello dispone
de dos herramientas integradas complementarias:
AppWizard, que es el generador de aplicaciones propiamente
dicho. Con l podremos generar esqueletos de programas para
Windows basados en la MFC.
ClassWizard, herramienta de mantenimiento de los programas
generados con la anterior. Permite aadir o eliminar clases,
modificar los comportamientos de las mismas, etc.
Pero el cdigo generado mediante este mtodo presenta una
complejidad aadida a la natural de cualquier programa; junto con el
Curso: Visual C++

14

cdigo C/C++ y el de la MFC aparecen lneas (generalmente entre


comentarios) que son totalmente necesarias para el funcionamiento de
las dos herramientas anteriores, modificar cualquiera de esas lneas de
cdigo dar muchos problemas a la hora de utilizar ClassWizard para
modificarlo. De todas maneras, este "defecto" es bastante popular entre
los usuarios de cualquier generador de cdigo, para cualquier lenguaje.
El formato general de los proyectos generados con estas herramientas
suele tener las siguientes caractersticas:
Cada clase de nuestro programa dispondr de dos ficheros: Un
fichero de cabecera (extensiones .h o .hpp) y un fichero de
implementacin (.cpp). El fichero de cabecera contiene la
definicin de la clase (definiciones de sus miembros datos y
funciones - los mensajes -), mientras que el fichero fuente
contiene la implementacin de esas funciones miembro (los
mtodos de la clase).
Un fichero de recursos (extensin .rc), aunque ste es opcional.
Mdulos objetos (.obj) y libreras estticas (.lib) necesarias para
crear nuestro programa.
4. CONSTRUCCIN DE UNA APLICACIN BSICA
Seguiremos los siguientes pasos:
.1 Crear un nuevo proyecto. Desde el men "Fichero", en la opcin
"Nuevo".

Curso: Visual C++

15

.2 Seleccionar objetivo del proyecto. Seleccionaremos "aplicacin


basada en MFC"
.3 Nombrar el proyecto. Visual C++ organiza los proyectos de
manera que crea un subdirectorio nuevo con el nombre de cada
proyecto. Aunque esta "regla" siempre puede modificarse,
puede ser una buena forma de control de proyectos.
En estos momentos aparecer la secuencia de dilogos del generador
ClassWizard. Veamos cuales seran los pasos a seguir para crear una
aplicacin sencilla:
Paso 1. Permite identificar el modelo de ventana principal de nuestra
aplicacin: SDI, MDI o basada en dilogo. Nosotros elegiremos SDI.
Paso 2. Permite incorporar soporte a Bases de Datos en la
aplicacin. Esto lo veremos ms adelante. Seleccionaremos la
opcin sin soporte a bases de datos.
Paso 3. Relativo al soporte OLE. Igual que en el caso anterior.
Paso 4. Otras caractersticas de la aplicacin (barra de botones,
barra de estado, controles 3D )
Paso 5. Generacin de comentarios en el cdigo (si/no) y usos
posibles de las MFC (como DLL o como LIB). Se recomienda la
opcin DLL en cuanto al tamao y modularidad del programa, pero
deberemos asegurarnos de distribuir la DLL junto con nuestro
programa para que funcione correctamente.

Curso: Visual C++

16

Paso 6. Permite modificar el nombre de las clases MFC que se van


a generar, adems de especificar los ficheros en los que se
implementa y la clase base de la que derivan. Los nombres
generados por AppWizard suelen ser bastantes significativos.
A partir de este momento da comienzo la generacin del cdigo definido
antes. Como se habr observado, el nombre por defecto de las clases
generadas tiene mucho que ver con el nombre que le hayamos dado al
proyecto. De esta manera, si hubisemos llamado "curso1" al proyecto
tendramos la siguiente situacin:
Clase CCurso1App (mdulos curso1.h y curso1.cpp) que
representa una aplicacin Windows.
Clase CMainFrame (ficheros mainfrm.h y mainfrm.cpp) que
representan la ventana principal de la aplicacin.
Clases CCurso1Doc y CCurso1View (ficheros
curso1doc.h/curso1doc.cpp y curso1view.h/curso1view.cpp
respectivamente), representantes de lo que se conoce en el
mundo Windows como interfaz "Documento/Vista" y que
trataremos en adelante.
Clase CAboutDlg que representa el tpico dilogo de "Acerca
de " y que ha sido generado automticamente por AppWizard,
esta clase (rompiendo la norma habitual de la MFC) aparece
definida e implementada dentro los mismos ficheros que la clase
aplicacin (mdulos curso1.h y curso1.cpp). En el futuro
evitaremos este tipo de construcciones.
Curso: Visual C++

17

Curso: Visual C++

18

Curso: Visual C++

19

Curso: Visual C++

20

Curso: Visual C++

21

Curso: Visual C++

22

Curso: Visual C++

23

Curso: Visual C++

24

Curso: Visual C++

25

Curso: Visual C++

26

Curso: Visual C++

27

Curso: Visual C++

28

Curso: Visual C++

29

Curso: Visual C++

30

Curso: Visual C++

31

4. EL ENTORNO DE DESARROLLO - VISOR DE PROYECTOS


El Visor de Proyectos es una ventana a travs de la que podemos
visualizar el contenido de los proyectos, accedemos a la misma desde el
men "Ver" y la opcin "Proyecto". Est formada por 3 carpetas que nos
permiten visualizarlos desde distintos puntos de vista:
ClassView, o Visor de clases, representa el proyecto con las
clases que lo componen. Desde aqu podremos aadir
miembros datos o funciones fcilmente.
ResourceView, o Visor de recursos, que permite
aadir/modificar/eliminar recursos de la aplicacin.
FileView, o Visor de ficheros, que representa el proyecto
mediante la lista de ficheros fuente que lo componen.
Por ltimo aparece tambin la carpeta InfoView que permite un rpido
acceso a la ayuda en lnea.
Cada una de estas funcionalidades se utilizarn en funcin de la tarea a
realizar. La gestin y tratamiento de los recursos slo se puede hacer
mediante ResourceView, mientras que ClassView y FileView son casi
similares en cuanto a su objetivo ltimo: el mantenimiento del cdigo del
programa.

Curso: Visual C++

32

4. LA LIBRERA DE CLASES MFC - INTRODUCCIN.


A continuacin, y siguiendo en todo momento el cdigo de la aplicacin
bsica que acabamos de generar, procederemos a presentar las clases
mas utilizadas de la MFC. Esta librera est compuesta por cientos de
clases distintas, que desde el punto de vista funcional, las podemos
dividir en 4 grupos:
5. Clases orientadas al interfaz de usuario, representan ventanas,
mens, dilogos, etc.
6. Clases de propsito general, representando ficheros, strings,
datos de fecha y hora, etc.
7. Clases orientadas a bases de datos, representando tanto bases
de datos como conjuntos de registros seleccionados despus de
una consulta sobre una tabla, etc.
8. Clases para manejo de excepciones, para control avanzado de
errores de ejecucin.
.1 Filosofa de trabajo con la MFC.
El hecho de utilizar una librera de clases como la MFC aade
complejidad al desarrollo e impone una serie de normas de
programacin a las que regirse. La complejidad aadida deriva de la
necesidad de que el programador ahora no slo debe controlar C/C++,
sino que adems debe conocer las clases de la MFC para poder utilizar
su potencia.
Entran aqu en juego algunos conceptos que ya conocemos:
Curso: Visual C++

33

Herencia, Un buen nmero de las clases de la MFC son "no


instanciables", es decir, no podemos crear objetos de esa clase
con lo que no podremos utilizarla directamente. Esto significa
que el programador deber en muchos casos derivar sus
propias clases de alguna de la MFC (estas clases "prohibidas"
suelen ser abstracciones que dan pie a polimorfismos). Adems
debemos saber que clase es la mas ptima para que nos sirva
de clase base; por ejemplo: se debe saber que la clase MFC
CWinApp es la que da soporte a las aplicaciones Windows, y
que toda aplicacin debe derivar su propia versin de la clase
para poder funcionar (en realidad, un programa MFC comienza
con la creacin de un objeto de ese tipo y finaliza con la
destruccin del mismo). Tambin deberemos saber que si lo
que queremos es obtener una ventana de dilogo, deberemos
derivar nuestra propia clase desde CDialog (que es una clase
especializada para ello), en vez de desde CWnd (que
representa a una clase mas genrica y presentara muchos
problemas), por ejemplo, CDialog soporta que su plantilla haya
sido dibujada en los recursos de la aplicacin (al estilo de un
formulario de Visual Basic, ) mientras que CWnd no, lo que
nos obligara a pintar los botones con cdigo duro (programar su
tamao, posicin en pixeles dentro de la ventana padre ),
aunque no sera imposible. En definitiva, a la hora de derivar
clases de la MFC debemos tener en cuenta el concepto de
especializacin para obtener una programacin ms sencilla.
Curso: Visual C++

34

Polimorfismo. Pero la mayor potencia de la MFC reside en las


funciones polimrficas (virtuales). El mecanismo de herencia no
sera til si no se pudiese redefinir el comportamiento por
defecto de las clases de la MFC. Por ejemplo, supongamos que
hemos creado un dilogo (derivando una clase desde CDialog)
con nuestro propio diseo, supongamos que tiene unos campos
que deseamos inicializar con los datos de un empleado para
que aparezcan en pantalla, en este caso debemos ser capaces
de definir nuestro propio mtodo de inicializacin. Esto es
posible gracias a que este mtodo (en concreto denominado
OnInitDialog) es definido como virtual dentro de la clase base
CDialog, lo que da lugar a una funcin polimrfica. As, si en
nuestra clase derivada de CDialog redefinimos ese mtodo
OnInitDialog, nos aseguraremos que el procedimiento de
inicializacin que se ejecutar ser el nuestro. En definitiva, las
dos clases (CDialog como clase base y la nuestra como
derivada) responden al mismo mensaje (OnInitDialog) pero de
distinta manera (por que no comparten el mtodo).
Esta es la filosofa de trabajo que debemos seguir: derivar nuestras
clases de la clase MFC mas especializada en funcin de lo que
queramos, y utilizar las funciones virtuales que tenga para conseguir el
comportamiento deseado.
.1 Las clases bsicas para interfaz de usuario.

Curso: Visual C++

35

Para conseguir una mejor visin del funcionamiento de


la MFC, nos basaremos en el cdigo generado en el
punto 5.
.2

La clase CWinApp

Representa una aplicacin Windows. Cada programa debe tener un


objeto global o esttico (es decir, que exista durante todo el programa)
de una clase propia derivada de CWinApp. De hecho, otra caracterstica
de la programacin basada en MFC es que el cdigo carece de
programa principal (punto inicial de ejecucin como la funcin "main" de
C/C++ para DOS, UNIX, etc.), la ejecucin comienza con la creacin del
objeto CWinApp.
En realidad, es la MFC la que provee una funcin principal estndar
WinMain (este es el nombre que toma para las aplicaciones Windows)
que utilizarn todos los programas. Los pasos bsicos que sigue son
tres: inicializacin del programa, entrada en el bucle de mensajes y
finalizacin del programa. Vemoslo ms en detalle.
Inicializacin del programa. Se obtiene en dos fases distintas:
inicializacin de la aplicacin e inicializacin de la instancia de la
aplicacin. Para entender esto tenemos que tener en cuenta
que los programas Windows pueden ser "multi-instanciables",
podemos tener varios ejemplares del mismo programa
ejecutndose a la misma vez. Los ejemplos mas claros son
aplicaciones como el bloc de notas (notepad) o cualquier utilidad
de conexin remota (telnet). En definitiva, si queremos obtener

Curso: Visual C++

36

programas multi-instanciables tenemos que distinguir


operaciones de inicializacin que serviran a todos los
ejemplares y que por tanto se deberan realizar una sola vez, de
aquellas que son especficas a cada ejemplar (como crear cada
ejemplar su ventana principal).
Bucle de mensajes. Es la parte central de la ejecucin, no
finaliza hasta que no se cierra la ventana principal.
Finalizacin de la instancia. Permitir liberar recursos, cerrar
ficheros de trabajo, confirmar operaciones, etc.
Los detalles mas importantes de la clase CWinApp son los siguientes:
1. Miembros datos pblicos -> Destacar:
m_pszAppName, contiene el nombre de la aplicacin.
m_pMainWnd, contiene un puntero (referencia) a la
ventana principal de la aplicacin.
m_hInstance, identificador de la instancia del programa
que se est ejecutando.
m_hPrevInstance, identificador de la instancia previa del
programa (0 si no hay instancia previa). Sirve para
saber si se deben realizar tareas de "inicializacin de
aplicacin" (ver arriba).
m_lpCmdLine, lnea de comando con la que se llam al
programa (argumentos).

Curso: Visual C++

37

1. Constructor CWinApp -> Recibe un slo parmetro con el


nombre de la aplicacin (por defecto llevar NULL, nulo).
2. Miembros funciones pblicos -> La funcionalidad de esta
clase, como siempre, reside en funciones virtuales que se
pueden redefinir; destacan las siguientes:
InitApplication -> Invocada por el sistema
automticamente cuando se ejecuta la primera instancia
de un programa (cuando no existe instancia previa).
InitInstance -> Invocada por el sistema para cualquier
instancia del programa. Se suelen realizar operaciones
como la de creacin de la ventana principal, etc.
Run -> Que realiza el bucle de mensajes por defecto.
En la mayora de los casos este bucle es suficiente, con
lo que no tendremos por que redefinirlo.
ExitInstance -> Invocada por el sistema despus de
cerrarse su ventana principal.
Comparando el cdigo generado para nuestra primera aplicacin con lo
expuesto en este punto podemos comenzar a entender como funcionan
las cosas en el mundo MFC.
7.2.2 El interfaz Documento/Vista
El estndar Documento/Vista es una manera de enfocar el desarrollo de
aplicaciones para Windows. Se basa en los siguientes conceptos:

Curso: Visual C++

38

1. Documento, cualquier tipo de informacin que se presenta sobre


una ventana, podra ser tanto una hoja de clculo, como una
base de datos o algn tipo de grfico.
2. Vista (view), ventana que presenta el documento. Cada vista
presenta un nico documento.
3. Ventana marco (frame window), que contiene a la ventana vista
en su rea cliente.

Figura 1.- Interfaz documento/vista

Curso: Visual C++

39

De esta manera, cualquier tipo de informacin se puede interpretar


como un documento, que se presenta al usuario mediante una vista, que
se inscribe dentro de una ventana marco. Mientras la vista se ocupa
solamente de representar el documento, la ventana marco se puede
ocupar del tratamiento del men.
AppWizard genera todo su cdigo basndose en este estndar. Una
aplicacin SDI slo podr tener abierto un documento (la ventana
principal es tambin la ventana marco), mientras que una MDI podr
tener varios abiertos simultneamente (aqu la ventana principal puede
contener varias marcos con vistas). Sin embargo este enfoque no es el
mas idneo para un buen nmero de aplicaciones Windows SDI donde
la ventana principal no sirve sino como contenedor del men, y la
representacin o el manejo de los datos de la aplicacin se suele
realizar a travs de dilogos. Si es sin embargo mas til en el caso de
las aplicaciones MDI donde si que las ventanas marcos se utilizan como
formularios usuales, es decir, como ventanas para presentacin de
datos.

Figura 2.- Detalle de aplicacin MDI


Observando la figura basada en el entorno de desarrollo de Visual C++,
vemos que la ventana principal contiene dos ventanas marcos, la
primera representa en su vista el contenido del workspace que tenemos
abierto, mientras la segunda est representando un fichero de cdigo
fuente CPP.

Curso: Visual C++

40

Las clases MFC en las que se apoya el interfaz Documento/Vista son


las siguientes:
4. Clase CDocument-> funcionalidad bsica para documentos de
usuario. Un documento es un objeto que almacena cualquier
tipo de datos. Es una clase abstracta de la que tendremos que
derivar nuestros propios documentos.
5. Clase CView -> Ventana vista que presenta un documento. Es
una ventana "especial" que no contiene ni bordes ni ttulo ni
barra de men, orientada a circunscribirse dentro de otra
ventana marco. Existen otras clases derivadas de sta que
presentan mayor especializacin:
CScrollView, es una vista con soporte a las barras de
scroll.
CFormView, vista formulario, con controles al estilo de
los dilogos.
CEditView, vista orientada a la edicin de textos.
CRecordView, vista orientada a la visualizacin de
bases de datos.
1. Clase CDocTemplate -> Clase abstracta que aporta la
funcionalidad bsica para plantillas SDI o MDI. Al ser una clase
abstracta no la podremos utilizar directamente, tendremos que
utilizar sus clases derivadas: CSingleDocTemplate y
CMultiDocTemplate.
Curso: Visual C++

41

2. Clase CSingleDocTemplate -> derivada de CDocTemplate


representa la plantilla de interfaz SDI. Define la relacin
existente entre un documento (CDocument), una vista (CView,
) y una ventana marco que ser la ventana principal.
3. Clase CMultiDocTemplate-> derivada de CDocTemplate
representa la plantilla para interfaz MDI. Define la relacin entre
un documento, su vista y la ventana marco que ventana MDI
hija.
Toda aplicacin que se base en el Documento/Vista debe registrar en el
sistema las plantillas de documento que soporta antes de poder
utilizarlas, lo que se realiza a travs de la funcin
CWinApp::AddDocTemplate. As, una aplicacin SDI, que debe soportar
una nica plantilla de documento, debe crear un objeto
CSingleDocTemplate (donde se define la relacin entre documento,
vista y ventana marco) y registrarlo mediante el mtodo anterior. Una
vez realizado esto bastar con invocar la funcin
CDocTemplate::OpenDocumentFile() del objeto recin creado para
conseguir que se visualice la ventana principal de la aplicacin, con su
vista presentando el documento especificado (el enfoque en
aplicaciones MDI es algo distinto y se revisar posteriormente). Estas
operaciones se introducirn dentro del InitInstance de la aplicacin.
De todas maneras, en contra de lo que hemos dicho antes, no es difcil
adaptar cualquier aplicacin al protocolo requerido por el interfaz
documento vista, sin mucho impacto en la misma, gracias a que la
mayora de las funcionalidades estn predefinidas por defecto.
Curso: Visual C++

42

La ventana bsica CWnd

Es una de las clases mas importantes de la MFC ya que contiene las


funcionalidades bsicas de todas las clases de ventanas Windows.
Como siempre, al ser una abstraccin, no est muy orientada a la
utilizacin directa, mas bien siempre tenderemos a utilizar alguna de sus
clases derivadas, mas especializadas, como CFrameWindow (ventana
principal de aplicacin) o CDialog (para ventanas de dilogo).
Pero su principal inters reside en que es la clase responsable del
funcionamiento del mecanismo de paso de mensajes de Windows. ste
queda oculto por lo que se llama en la MFC mapa de mensajes. El mapa
de mensajes de una clase de ventana recoge la asociacin entre el
mensaje recibido del sistema y la funcin que se ejecutar como
respuesta. Todas estas funciones de respuesta (mtodos de clase) son
funciones virtuales que por tanto se pueden redefinir en todas las clases
derivadas.
Supongamos que estamos construyendo una aplicacin la cual
queremos que antes de finalizar descargue cierto contenido de memoria
en un fichero. Para ello deberamos ser capaces de contestar
adecuadamente al mensaje WM_CLOSE que el sistema manda a la
ventana principal cuando se tiene que cerrar. El mapa de mensajes de
la clase CWnd especifica que la funcin de respuesta ser
CWnd::OnClose(). Bastar entonces con que en nuestra clase ventana
principal redefinamos una nueva versin de esa funcin heredada. No
hace falta que conozcamos de memoria todo el mapa de mensajes por

Curso: Visual C++

43

defecto de CWnd (nombres de las funciones de respuesta, etc.), la


utilizacin de AppWizard automatiza todo este complejo tratamiento.
Los miembros datos y miembros funciones de esta clase son muy
numerosos y variados, los iremos comentando segn los vayamos
utilizando.
7. 2. 4. Una ventana principal - CFrameWnd
Derivando de CWnd, proporciona las funcionalidades bsicas de
cualquier ventana principal de aplicacin. Incluye soporte de mens,
barras de estado y barra de herramientas. Las aplicaciones SDI
derivarn de esta clase sus ventanas principales. Entre sus
caractersticas incluye ttulo, men de sistema y borde redimensionable.
De sus miembros funciones destacan:
Create -> Funcin que permite crear una ventana fsica y
asociarla con el objeto recin creado.
LoadFrame -> Funcin anloga a la anterior, per de mas alto
nivel (exige menos parmetros) que adopta muchos
comportamientos por defecto.
Derivando de CFrameWnd aparecen otras clases de ventanas mas
especializadas, son las siguientes:
CMDIFrameWnd-> Ventana principal para aplicaciones MDI.
CMDIChildWnd -> Ventanas MDI hijas (tienen la mayora de las
propiedades de cualquier ventana principal).
7.2.5 Las clases Vista

Curso: Visual C++

44

Como ya hemos comentado, la clase CView proporciona la


funcionalidad bsica para ventanas que se asocian a plantillas de
documentos y que realizan tareas de intermediarias entre el documento
y el usuario. Es la responsable de presentar la imagen del documento y
de interpretar las acciones del usuario sobre el mismo (modificaciones,
etc.). Entre estas funcionalidades cabe destacar:
CView::OnInitialUpdate, funcin miembro que permite la
inicializacin de la vista con los datos del documento.
CView::OnUpdate, invocada ante cualquier modificacin del
documento, permite actualizar la vista antes de que se repinte.
CView::OnDraw, funcin de pintado de la vista (utilizada casi
siempre para "documentos grficos").
CView::GetDocument, que permite obtener una referencia al
documento que se esta representando.
Las vistas mas especializadas se encuentran entre las siguientes clases
derivadas:
CEditView, donde la vista es una ventana de edicin de texto.
CListView, donde la vista es una lista.
CFormView, donde la vista utiliza una plantilla de dilogo de los
recursos de la aplicacin (al estilo de los formularios
tradicionales).

Curso: Visual C++

45

CRecordView, derivando de CFormView implementa adems


soporte para bases de datos, permitiendo asociar estticamente
campos de tablas con controles de la plantilla de dilogo que
utiliza.
7.3 Clases bsicas de propsito general.
Presentaremos a continuacin algunas de las clases de propsito
general mas importantes y utilizadas de la MFC.
7.3.1 La clase CString
La clase CString representa un string de caracteres. Cualquier
programador de C/C++ sabe lo tedioso que puede ser el manejo de este
tipo de dato ya que no est reconocido como tal en el ncleo de C.
Mientras que en otros lenguajes de alto nivel el string de caracteres es
un tipo de dato autnomo que dispone de sus propios operadores
(asignacin, concatenacin, comparacin, etc.), en C/C++ el string se
representa como una coleccin (array) de caracteres (que el tipo de dato
bsico), esto supone que cualquier operacin sobre ellos se debe
realizar mediante funciones de la librera estndar de C (strcpy, strcat,
strcmp, etc.).
La principal virtud de CString es precisamente esa, facilita el manejo de
strings de caracteres automatizando todo el tratamiento ptimo de la
memoria. Destacan las siguientes funcionalidades:
Funcin CString::GetLength, que permite conocer el nmero de
caracteres que contiene.

Curso: Visual C++

46

Funciones CString::GetAt/CString::SetAt, que permiten acceder


y modificar respectivamente el carcter del string que aparece
en una posicin dada.
Funciones CString::MakeUpper/CString::MakeLower, que
permiten convertir a maysculas/minsculas respectivamente.
Funcin CString::Find, que permite conocer si un determinado
string o carcter aparece dentro de otro string.
Pero adems, la clase CString tiene sobrecargados algunos de los
operadores de C/C++ lo que permite un manejo intuitivo de esta clase,
son los siguientes: asignacin (mediante =), concatenacin (mediante +
y +=) y comparacin (operadores ==, <, <=, etc.).
7.3.2 La clase CFile
Esta clase presenta las funcionalidades bsicas para el tratamiento de
ficheros, aportando funciones de alto nivel.
Funciones CFile::Open/CFile::Close para abrir y cerrar ficheros.
Funciones CFile::Read/CFile::Write, para lectura y escritura
Funciones CFile::Seek/CFile::SeekToBegin/CFile::SeekToEnd
que permiten posicionamiento directo dentro del fichero.
Funciones CFile::GetLenght/CFile::SetLenght que permiten
obtener y cambiar el tamao del fichero.
Funcin CFile::Rename/CFile::Remove que permiten renombrar
(mover) y eliminar ficheros respectivamente.
Curso: Visual C++

47

7.3.3 La clase CTime


CTime presenta las funcionalidades bsicas de tratamiento de fechas y
horas. Al estilo de como se hace en C/C++ mediante el tipo de dato
"time_t", representa un determinado instante de tiempo (con fecha,
horas, minutos y segundos). Destacan:
Funcin CTime::GetCurrentTime, que obtiene el instante actual.
Funciones de extraccin que permiten acceder a cualquiera de
los datos significativos que componen un CTime: el da del mes
el da de la semana, el mes, el ao, la hora, etc.
Funcin CTime::Format, que permite construir un string
formateado a partir de un CTime.
Operadores de asignacin, suma, resta y comparacin. Como
complementaria a esta clase aparece CTimeSpan que
representa un intervalo de tiempo. Las operaciones de suma se
realizan con esta clase, y una resta de dos fechas dadas
siempre da como resultado un CTimeSpan.
7.3.4 La clase CRect
CRect automatiza el tratamiento de rectngulos. En Windows este
concepto se utiliza continuamente ya que las posiciones o el tamao de
las ventanas se representan mediante los rectngulos que ocupan en la
pantalla.
Un rectngulo viene representado fsicamente por las coordenadas de
su esquina superior izquierda y la de su esquina inferior derecha. Estos
Curso: Visual C++

48

datos se almacenan en sus variables miembro pblicas: top, left, bottom


y right.
Dispone de funciones como:
CRect::Width/CRect::Height, que permiten saber el ancho/alto
de un rectngulo.
CRect::PtInRectque permite saber si un determinado punto
est contenido dentro de un rectngulo.
4. TRATAMIENTO DEL MENU.
Una de las principales vas de interaccin con el usuario, adems de los
dilogos, son los mens. De manera general, cada ventana principal de
aplicacin contiene un men. El mtodo que suele asociar la ventana
con el men es la funcin CFrameWnd::LoadFrame, esta recibe como
primer parmetro el identificador de los recursos de la ventana principal.
Seran el men, el icono y el ttulo de la ventana. En suma, si creamos
un men, un icono y un string todos con el mismo identificador, y
utilizamos ste en la llamada a LoadFrame, la ventana principal
aparecer con las caractersticas deseadas (este es el mtodo que se
suele seguir en la MFC).
De todas maneras, la MFC proporciona otro mtodo alternativo que
permite asociar o cambiar el men de una ventana. Mediante la funcin
CWnd::SetMenu podemos realizar tambin esta operacin.
Aunque en la mayora de los casos el men de una ventana es
constante durante toda la duracin de la misma, puede que en algn
momento necesitemos modificarlo dinmicamente, para ello se
Curso: Visual C++

49

proporciona la clase CMenu que aporta las funcionalidades bsicas para


tratamiento de mens y la funcin de ventana CWnd::GetMenu que
devuelve una referencia al objeto CMenu asociado con el men de la
ventana. Destacan:
CMenu::LoadMenu, que permite asociar un objeto CMenu con
un men diseado previamente en los recursos de la aplicacin.
CMenu::DeleteMenu, que permite eliminar elementos (items o
submens desplegables - popup -) de un determinado men.
CMenu::AppendMenu, que permite aadir items o submens a
un men.
CMenu::EnableMenuItem, que permite habilitar e inhabilitar
items de un men.
CMenu::CheckMenuItem, que permite "marcar" como
seleccionados elementos de un men.
CMenu::GetMenuState, que permite saber si un determinado
tem est habilitado o seleccionado.
Pero aunque hemos repasado hasta aqu los detalles de como asociar
un men a una ventana (CFrameWnd::LoadFrame o CWnd::SetMenu)
no hemos hecho ningn comentario de lo mas importante. Como
podemos capturar las selecciones del usuario dentro del men y
asociarles operaciones concretas ?. Este aspecto lo veremos a
continuacin.
8.1 Gestin de mensajes de comandos del men.
Curso: Visual C++

50

Las selecciones que el usuario realice dentro de un men se


notifican a la ventana propietaria mediante mensajes de
comando (WM_COMMAND). Cada uno de estos mensajes,
cuando son recibidos por una ventana, va acompaado del
identificador del tem de men seleccionado de manera que la
aplicacin pueda reconocer las operaciones a ejecutar. La forma
en que se puede asociar una funcin de respuesta a un tem de
men es bastante grfica y sencilla gracias al uso de
ClassWizard.
Para ello, bastar con abrir la ventana de ClassWizard
(CTRL+W o en el men "Ver" con la opcin "ClassWizard"),
seleccionar la clase que queremos que controle el mensaje en
cuestin, seleccionar el tem de men deseado y especificar el
nombre de la funcin miembro que funcionar como respuesta a
ese mensaje (tras presionar el botn de "Aadir funcin").
Desde ese momento, ClassWizard aadir los ficheros de
cabecera e implementacin de la clase seleccionada los datos
especficos de la nueva funcin definida; el programador ser el
responsable de completar la implementacin de la funcin con
el tratamiento adecuado.
Una caracterstica propia de todas las aplicaciones generadas
con AppWizard es que los items de men que no estn
asociados con ninguna funcin de respuesta aparecern
inhabilitados.

Curso: Visual C++

51

8. 2 Objetos capaces de gestionar mensajes de comando


de men.
En la MFC tanto el objeto aplicacin CWinApp como cualquier
ventana (objetos CWnd y derivados) es capaz de recibir
mensajes de comando procedentes del men de la aplicacin.
Aunque de alguna forma lo mas "real" es que la ventana sea la
encargada de gestionarlos (ya que es la propietaria del men y
adems en la programacin SDK de Windows, la aplicacin no
tiene entidad como tal y son solamente las ventanas los
elementos capaces de recibir mensajes del sistema, mediante
su ya conocido procedimiento de ventana) si que es verdad que
la eleccin siempre depende del programador. Todo esto quiere
decir que mediante ClassWizard podemos asociar un comando
del men con una funcin miembro de un objeto aplicacin.
De cualquier manera lo que siempre es una prctica
aconsejable es centralizar todas las funciones de respuesta
(tambin conocidas como manejadores de mensajes) dentro de
una misma clase.
4. GESTIN DE DILOGOS
Las ventanas de dilogos son uno de los elementos mas utilizados para
la interaccin con el usuario. De manera general un dilogo es una
ventana especial que contiene en su interior ventanas hijas que son
controles (botones, listas, cajas de edicin, listas desplegables, )
identificados por un nmero nico, adems, cuando un dilogo se
Curso: Visual C++

52

despliega, se convierte en una ventana exclusiva en el sentido de que


deja inhabilitada cualquier operacin con el resto de la aplicacin (este
efecto se conoce realmente con el nombre de dilogos modales, aunque
existe la posibilidad de crear tambin dilogos no modales). Las
plantillas de estos dilogos pueden disearse mediante herramientas
integradas en el entorno de desarrollo como es el ya conocido
ResourceView (tambin conocido como taller de recursos).
Es la clase CDialog, derivada de CWnd, la responsable de proporcionar
las funcionalidades bsicas de esta ventana especializada.
El constructor de la clase CDialog::CDialog, requiere dos
parmetros: el nombre de la plantilla de dilogo que utilizar (la
que hayamos diseado en los recursos) y una referencia a la
ventana padre del dilogo (casi siempre es la ventana que pide
que se visualice). Tambin existe un constructor por defecto (sin
parmetros) orientado a la creacin de dilogos no modales.
La funcin CDialog::DoModal, aplicada sobre un objeto
construido previamente permite visualizarlo en modo modal.
Esta funcin es sncrona en el sentido de que no devuelve el
control a la funcin llamante hasta que no se cierre el dilogo.
Devuelve un valor que podemos utilizar para indicar distintas
opciones de cierre del dilogo (por ejemplo podemos devolver
TRUE para indicar que se presion OK o FALSE para
Cancelar).

Curso: Visual C++

53

La funcin CDialog::EndDialog permite finalizar un dilogo


modal, recibe un parmetro que se corresponder con el valor
que devuelva DoModal.
La funcin CDialog::Create, aplicada sobre un objeto construido
previamente, permite crear dilogos no modales. Los dilogos
no modales no se finalizan con EndDialog sino que utilizaremos
la funcin estndar heredada de CWnd DestroyWindow.
Funcin CDialog::OnInitDialog, para inicializar el dilogo.
Funciones CDialog::OnOk/CDialog::OnCancel que permiten
realizar las operaciones de confirmacin o cancelacin del
objetivo del dilogo.
Pero CDialog es una clase abstracta, por lo que no la podremos utilizar
directamente (no se pueden crear objetos CDialog). El programador
deber derivar sus propias clases desde CDialog para crear sus propios
dilogos.
1

Creacin de dilogos

Los pasos para crear una ventana de dilogo son los siguientes:
1. Crear la plantilla de dilogo que se va a utilizar en el fichero de
recursos. Para ello utilizaremos ResourceView y las
herramientas de diseo de dilogos. El dilogo se podr
completar con los controles necesarios (cajas de edicin, listas,
botones, etc.). Cada uno de los controles deber llevar un
identificador nico.
Curso: Visual C++

54

2. Asignar un identificador a la plantilla de dilogo que se haya


diseado.
3. Invocar ClassWizard
4. Seleccionar botn "Aadir clase nueva"
5. Definir la nueva clase. Para ello le daremos un nombre y
seleccionaremos la clase base mas adecuada. En este caso
seleccionaremos la clase CDialog. El sistema automticamente
asignar un nombre a los ficheros de cabecera e
implementacin donde se codificar la clase (estos nombres los
podemos cambiar). Aparece una lista desplegable donde
seleccionaremos el identificador de la plantilla de dilogo
asociado (especificado en el paso 2).
El sistema genera entonces el esqueleto de la nueva clase, en los
ficheros especificados, aadindolos al proyecto. Bastar con completar
el cdigo generado e introducir una llamada al dilogo en algn punto
del programa (mediante la funcin CDialog::DoModal por ejemplo).
2

Tratamiento de los controles de dilogos.

La librera MFC aporta tambin clases representativas de los controles


tpicos de Windows. Esto nos permite crearlos de manera dinmica
(mediante cdigo) o manejarlos adecuadamente. De entre estas clases,
destacan:
CButton, representa cualquier tipo de botones (pushbuttons,
radio buttons o check boxes).
Curso: Visual C++

55

CComboBox, representa listas desplegables.


CListBox, representa listas.
CEdit, representando cajas de edicin.
CStatic, representando texto estticos.
Cada una de estas clases deriva de CWnd (no en vano son todas
ventanas especializadas) e incorpora funciones especficas que facilitan
su tratamiento (as por ejemplo las listas aportan funciones que permiten
saber el elemento que tiene seleccionado en cada momento).
Aunque un control puede aparecer dentro de cualquier ventana (se dice
que el control es una ventana hija) es en los dilogos donde mas se
utilizan. De manera general, la ventana padre debe ser capaz de
manejar los controles que la forman (rellenando una lista con las
opciones disponibles, presentando el DNI del empleado seleccionado en
la caja de edicin al efecto, etc.). Para conseguir esto disponemos de
dos mtodos:
1. Asociacin esttica de controles. Este mtodo consiste en la
creacin de objetos miembros de la clase de la ventana padre
(el dilogo) y su asociacin con cada uno de los controles. Es
decir, existe una variable miembro dentro del dilogo que
representa cada uno de los controles. De manera general no se
"mapearn" todos los controles a variables sino slo aquellos
que necesitemos (aquellos que vayamos a manejar en el
programa). Este trabajo se realiza mediante ClassWizard dentro

Curso: Visual C++

56

de su "subcarpeta" marcada como "Variables". As un botn se


mapea a un objeto CButton, una lista a un objeto CListBox, etc.
2. Asociacin dinmica de controles. Mediante este mtodo se
consiguen referencias a los controles durante la ejecucin del
programa. No existen variables miembro que se asocien a
controles de manera esttica (constante) sino que conseguimos
el mismo efecto cuando lo necesitamos. Para ello disponemos
de la funcin de ventana CWnd::GetDlgItem que recibe como
parmetro el identificador del control del que queremos obtener
una referencia. Hay que destacar que esta funcin es de la
ventana bsica CWnd, lo que significa que cualquier ventana
puede acceder a sus ventanas hijas (controles generalmente)
de la misma manera (abstraccin). Adems, mediante esa
funcin obtenemos referencias a objetos de distintas clases en
funcin del tipo de control que queramos, es decir, utilizamos la
misma funcin para acceder a botones, listas o cajas de edicin.
En realidad la funcin GetDlgItem devuelve referencias a
ventanas genricas (devuelve punteros a CWnd *) o lo que es lo
mismo, devuelve referencias a cualquier tipo de ventana (no
tiene por que ser controles).
3

Mensajes de comando de controles de dilogos.


De manera anloga a lo que comentamos con los items
de men, los controles informan a las ventanas padres
de las acciones que el usuario realiza sobre ellos. As

Curso: Visual C++

57

los botones informan de que se hizo "click" sobre ellos o


las cajas de edicin lo hacen de que se modific su
contenido. El mecanismo utilizado es tambin el
mensaje de comando WM_COMMAND aunque aqu
tiene un enfoque adicional.
Mientras los elementos de men slo informan de que
han sido seleccionados los controles pueden informar
de distintos eventos (dependiendo del tipo de control),
as siempre es distinto realizar un click sobre una lista
que un doble click. En definitiva, los mensajes de
comando de los controles de dilogos incorporan una
nueva informacin que se conoce como notificacin.
Las notificaciones recogidas por cada tipo de control
son distintas, dependiendo de su naturaleza.
La forma de aadir funciones manejadoras de mensajes
de controles a los dilogos es anloga a la que se
describi para los comandos de men. Lo realizaremos
mediante ClassWizard, pero adems de seleccionar el
identificador del control tendremos que seleccionar
tambin la notificacin a la que queremos aadir el
nuevo manejador.
4

Inicializacin de dilogos.
Una vez que hemos visto como obtener un vnculo con
los controles que forman un dilogo hemos de conocer

Curso: Visual C++

58

como inicializarlo para que presente al usuario el


aspecto seleccionado. El momento de inicializacin del
dilogo viene marcado por la llegada del mensaje
WM_INITDIALOG, cuyo manejador virtual es
CDialog::OnInitDialog. En nuestra clase de ventana de
dilogo redefiniremos esta funcin virtual para definir
nuestra propia inicializacin.
5

Un dilogo especial - CPropertySheet

La clase CPropertySheet presenta las funcionalidades bsicas de los


dilogos basados en pestaas o subcarpetas. En la imagen se presenta
un detalle del dilogo ClassWizard que es de este estilo.

Figura 3.- Detalle de dilogo con subcarpetas.


Estos dilogos estn compuestos por una serie de pginas
(subcarpetas), que vienen representadas en la MFC mediante la clase
CPropertySheet. Cada una de estas pginas es bsicamente un dilogo
de estilos especiales, pero cuentan con su plantilla correspondiente en
el fichero de recursos del proyecto.
Para construir dilogos de este tipo seguiremos los siguientes pasos:
1. Generar las pginas necesarias. Para ello necesitamos disear
las plantillas de cada una de ellas en los recursos, y aadir una
clase derivada de CPropertyPage que las represente (de
manera anloga a como se vio en el punto 9.1)

Curso: Visual C++

59

2. Aadir una clase derivada de CPropertySheet al proyecto


mediante ClassWizard.
3. Asociar a esta clase las pginas correspondientes. Se realiza
mediante la funcin miembro CPropertySheet::AddPage, que
recibe como parmetro una referencia a la clase CPropertyPage
a aadir. Estas operaciones se suelen realizar dentro del
constructor del propio objeto.
4. Crear un objeto de esa clase e invocar la funcin
CPropertySheet::DoModal
5. EL INTERFAZ MDI
El interfaz de documento mltiple es sensiblemente distinto al ya
conocido de documento simple (SDI) en el que nos hemos basada en
las exposiciones previas. Las aplicaciones MDI pueden tener abiertas
simultneamente varias ventanas marco, conteniendo vistas que
visualizan documentos. Las diferencias principales son las siguientes:
La ventana principal de la aplicacin derivar de
CMDIFrameWnd, y su objetivo principal no es contener una
vista como ventana cliente (segn el modelo SDI) sino controlar
y gestionar las ventanas marcos existentes.
Como ventana cliente de la ventana principal aparece la clase
de ventana MDICLIENT. Esta es la verdadera ventana padre de
las sucesivas ventanas marco que se vayan abriendo. La MFC
no contempla ninguna clase que represente este tipo de

Curso: Visual C++

60

ventanas ya que su comportamiento por defecto es totalmente


suficiente y estndar. De hecho, a primera vista puede quedar
oculta la existencia de esta ventana cliente ya que en ningn
momento necesitamos crearla (la crean las funciones por
defecto).
Las ventanas marcos derivarn de CMDIChildWnd y son "hijas"
de la ventana MDICLIENT de la ventana principal de la
aplicacin (recordar que en el modelo SDI la ventana principal
era a su vez ventana marco de documento).
De esta manera, para crear la ventana principal de la aplicacin la
funcin InitInstance invocar a la funcin CFrameWnd::LoadFrame(),
mientras para crear cualquier ventana marco con su vista y documento
tendremos que utilizar las funciones aportadas por los objetos
CMultiDocTemplate (como CDocTemplate::OpenDocumentFile) que
hayamos definido como plantillas soportadas por la aplicacin mediante
la funcin CWinApp::AddDocTemplate (es decir, el mismo tratamiento
descrito arriba para aplicaciones SDI).
Obviamente, las ventanas principales de este tipo de aplicaciones,
derivadas de CMDIFrameWnd contienen funcionalidades especializadas
en la gestin de las ventanas MDI hijas, destacan las siguientes:
CMDIFrameWnd::MDIGetActive, que permite obtener una
referencia a la ventana MDI hija (ventana marco con vista y
documento) que est activa.

Curso: Visual C++

61

Funciones como CMDIFrameWnd::MDITile que organiza en


mosaico las ventanas MDI hijas existentes,
CMDIFrameWnd::MDICascade que lo hace en cascada o
CMDIFrameWnd::MDIIconArrange que alinea en el rea cliente
de la ventana principal los iconos de las ventanas MDI hijas que
estn minimizadas.
La utilizacin del modelo SDI o MDI depender siempre de los requisitos
de nuestra aplicacin, de todas maneras el funcionamiento de ambos
modelos es muy similar en su concepcin y tratamiento gracias a las
abstracciones prestadas por la MFC.
1. CLASES ORIENTADAS A ACCESO A BASES DE DATOS
La MFC proporciona clases que proveen un interfaz de
alto nivel para el tratamiento de bases de datos. Para
ello se basa en dos mecanismos distintos pero de
funcionamiento y tratamiento muy similar:
.1 Tratamiento mediante ODBC
El trmino ODBC (Open Data Base Conectivity) indica
que su objetivo es conseguir un tratamiento estndar
para distintos sistemas gestores de bases de datos
(SGBD). Su funcionamiento se basa en el uso de
drivers. Estos drivers proveen un interfaz estndar de
programacin, ocultando los detalles internos de
funcionamiento de cada SGBD. El estndar ODBC est
muy extendido, proveen una librera de funciones C (el
Curso: Visual C++

62

API o SDK de ODBC) que se basa en un SQL estndar


como lenguaje de consulta utilizado, de manera que
podemos acceder con el mismo mtodo a tablas dBase,
Oracle o Informix () sin mas que disponer del driver
ODBC apropiado para cada SGBD.
Para utilizar una base de datos mediante ODBC entra
en juego lo que se denomina Origen de datos (DSN Data source name). Un origen de datos es una entidad
identificada por su nombre que especifica una base de
datos concreta, mediante ese DSN podremos acceder a
cualquier tabla de dicha base de datos. La definicin de
los DSN se consigue gracias al Administrador ODBC
que se suele encontrar dentro del Panel de Control de
Windows (puede que encontremos instalaciones en las
que no aparezca referencias al ODBC ya que es una
extensin de Windows no estndar, aunque en la
actualidad es instalado por la mayora de los SGBD mas
comerciales).
.2 Tratamiento mediante DAO
El modelo DAO (Data Access Object) es una extensin
del ODBC que est especializada y optimizada para el
acceso a bases de datos de Microsoft Access. DAO ha
sido incorporado a la MFC en la ltima versin

Curso: Visual C++

63

comercializada, ya que antes el tratamiento de bases de


datos Access estaba integrado dentro del propio ODBC.
Dado que el funcionamiento es totalmente anlogo
(aunque las clases DAO tienen tratamientos y
capacidades especficas) pero siendo ODBC un mtodo
mucho mas general, nos centraremos en el uso de este
ltimo para el desarrollo de este captulo, realizando el
paralelismo oportuno con el modelo DAO cuando sea
necesario.
.3 Las clases bsicas
Dos son los conceptos que se utilizan en el tratamiento
de bases de datos mediante MFC: la base de datos
(conjunto de tablas) y el recordset (conjunto de registros
de una tabla). Son representados mediante las clases
CDatabase y CRecordset.
.4

La clase CDatabase

Presta las funcionalidades bsicas para el tratamiento de bases de


datos. Encapsula la conexin con un DSN definido dentro del
administrador ODBC que nos permitir operar sobre la base de datos
asociada.
Funcin CDatabase::Connect que permite conectar un objeto
CDatabase con un DSN ODBC. Las funcin CDatabase::Close
permite liberar esa conexin.

Curso: Visual C++

64

Funciones de soporte a transacciones (encapsulamiento de


varias operaciones como una operacin atmica) como
CDatabase::BeginTrans (marca comienzo de una transaccin),
CDatabase::CommitTrans (que cierra y confirma las
operaciones realizadas) o CDatabase::Rollback (que cierra y
anula las operaciones). Obviamente, para que este enfoque
funcione el SGBD asociado al DSN debe ser transaccional, lo
que podemos averiguar mediante la funcin
CDatabase::CanTransact.
La funcin CDatabase::ExecuteSQL que ejecuta la sentencia
SQL que recibe como parmetro. Con esta funcin slo se
pueden realizar tareas de mantenimiento de la base de datos
como aadir tablas (CREATE TABLE ), modificarlas (ALTER
TABLE ), eliminarlas (DROP TABLE ), etc. Es decir, al nivel
de CDatabase el SQL se puede utilizar como lenguaje de
mantenimiento de datos, pero no como lenguaje de consulta
(sentencias SELECT ) que se reserva para el objeto
CRecordset.
En la mayora de los casos el trabajo se realizar sin la necesidad de
trabajar al nivel de CDatabase, ya que la mayora de las aplicaciones se
limitan a consultar y modificar registros de tablas, operaciones que se
realizan al nivel de CRecordset. Slo en el caso de que nuestra
aplicacin tenga requisitos de mantenimiento de la base de datos
(aadir/modificar/borrar tablas, gestin de permisos, usuarios )

Curso: Visual C++

65

necesitaremos trabajar al nivel de CDatabase, en cuyo caso bastar con


crear un objeto de esa clase, abrirlo, operar sobre l y cerrarlo; en
ningn caso necesitaremos derivar de CDatabase nuestras propias
clases para bases de datos.
El anlogo de CDatabase en el mundo DAO es CDaoDatabase.
.1

La clase CRecordset

Representa un conjunto de registros de una determinada tabla resultado


de realizar una consulta sobre ella (un SELECT del SQL), algo anlogo
al concepto de cursor, es decir, siempre se asocia a una tabla de una
base de datos. Presenta restricciones como la imposibilidad de realizar
consultas compuestas (registros de mas de una tabla) o las clsicas
uniones de las bases de datos relacionales.
La clase CRecordset es abstracta de manera que tendremos que derivar
nuestros propios recordsets de ella. Entre sus miembros destacan:
1. Su constructor recibe como parmetro una referencia al objeto
CDatabase al cual pertenece la tabla asociada. Por defecto lleva
un valor nulo lo que significa que el proceso por defecto
construye su propio CDatabase cuando es necesario.
2. La funcin CRecordset::GetDefaultConnect, que especifica la
tabla asociada al cursor y el DSN de la base de datos a la que
pertenece.
3. Miembro dato CRecordset::m_strFilter, que almacena la
sentencia SELECT con la que se accede a la tabla asociada al
recordset.
Curso: Visual C++

66

4. Miembro dato CRecordset::m_strSort, que almacena el(los)


nombre(s) de los campos por los que se quiere ordenar los
registros seleccionados.
5. Funciones como CRecordset::Open y CRecordset::Close que
permiten abrir y cerrar recordsets.
6. Funciones de navegacin en el recordset como
CRecordset::MoveFirst, CRecordset::MoveLast,
CRecordset::MoveNext o CRecordset::MovePrev.
7. Funciones como CRecordset::AddNew que permite aadir
nuevos registros, CRecordset::Edit que permite modificar el
registro activo o CRecordset::Delete para eliminar el registro
activo. En complemento a las dos primeras funciones aparece
CRecordset::Update, funcin necesaria para reflejar en la tabla
una insercin (AddNew) modificacin (Edit).
La clase anloga a CRecordset en el modelo DAO se denomina
CDaoRecordset
La creacin de los recordsets necesarios se realizar mediante
ClassWizard. Para ello procederemos a aadir una nueva clase al
proyecto, en el momento de especificar la clase base seleccionaremos
CRecordset. Tras confirmar la operacin el sistema nos pedir que
seleccionemos el DSN del origen de datos ODBC (para lo que debe

Curso: Visual C++

67

haber sido definido previamente en el administrador de ODBC). Una vez


realizado esto aparecer una lista con el nombre de todas las tablas que
forman la base de datos asociada al DSN seleccionado. Escogeremos
una de ellas que se asociar al nuevo objeto recordset. El sistema como
siempre crea un esqueleto de la nueva clase que incluye, entre otras
cosas, un constructor por defecto y la definicin de la conexin a la tabla
(en la funcin CRecordset::GetDefaultConnect). Adems, esta clase
incorpora un miembro dato por cada uno de los campos de la tabla
asociada, datos que serviremos para almacenar los valores del registro
actual en cada momento. Estas variables se mapean a cada campo,
relacin que se define en el cuerpo de la funcin
CRecordset::DoFieldExchange. Esta funcin es implementada por
ClassWizard y solo en algunos casos tendremos que modificarla (los
veremos a continuacin). Podemos destacar dos tipos de recordsets
distintos: Tipo Snapshot, donde el recordset es una vista esttica del
contenido de la tabla en el momento de su apertura. Cualquier
modificacin sobre la misma no se reflejara en el recordset hasta que
Curso: Visual C++

68

no volviese a abrirse. Tipo Dynaset, donde se representa una visin


dinmica de las tablas. Es mas utilizado aplicaciones que trabajan sobre
bases de datos multiusuario o compartidas, donde otras aplicaciones
pueden realizar modificaciones.
Para utilizar un determinado recordset bastar con crear un objeto de
esa clase, rellenar la informacin de la consulta en m_strFilter (si no va
relleno se recuperaran todos los registros de la tabla), la informacin de
ordenacin en m_strSort (opcional) y llamar a la funcin Open que
realiza la consulta apropiada. Cuando el recordset haya dejado de
utilizarse invocaremos la funcin Close que libera los recursos de la
conexin ODBC.

11.3.3 Los recordsets parametrizados


Uno de los mayores problemas que se le han achacado al ODBC ha
sido el excesivo tiempo de respuesta (factor por el que vio la luz el
modelo DAO). Aunque esto siempre ha dependido de la calidad del
driver y del propio SGBD lo cierto es que operaciones de apertura y
cerrado sobre algunas tablas son realmente lentas; esto, como no, se
agrava en el caso de acceso a bases de datos remotas (soportadas por
mltiples SGBDs como SQL Server, Informix net, etc.) cuando se
recuperan muchos registros.
Para solucionar, en alguna medida, este problema aparecen los
recordsets parametrizados. stos nos permiten modificar los criterios de
Curso: Visual C++

69

seleccin de registros de manera dinmica sin necesidad de cerrar y


volver a abrir el recordset. En su lugar se utiliza simplemente la funcin
CRecordset::Requery que no libera la conexin con el DSN asociado
por lo que es sensiblemente mas rpida.
Para parametrizar un determinado recordset seguiremos como sigue:
8. Incluir miembros datos dentro de la clase que nos servirn como
parmetros en las consultas. La inicializacin de estos nuevos
miembros la realizaremos en el constructor de la clase, as
como tambin inicializaremos el miembro
CRecordset::m_nParams con el nmero de parmetros que
hayamos definido.
9. Mapear los parmetros aadidos con los campos asociados.
Para ello tendremos que modificar la funcin DoFieldExchange
de la clase.
Una vez parametrizado, podremos modificar los criterios de bsqueda
del recordset de manera dinmica sin mas que modificar el valor de los
parmetros y refrescar el contenido del cursor mediante Requery.
La utilizacin de un recordset parametrizado es totalmente anloga a la
de uno estndar. Simplemente basta con rellenar el valor de los
parmetros antes de realizar la apertura de la tabla.
.1 Manejo de excepciones mediante CDBException
Cuando trabajamos con bases de datos se pueden producir situaciones
anmalas que provocan errores de ejecucin de las aplicaciones. Por
ejemplo, el intento de abrir una determinada tabla que ha sido abierta
Curso: Visual C++

70

previamente por otro usuario de modo exclusivo, o invocar la funcin de


pasar al siguiente registro cuando ya se ha alcanzado el ltimo del
recordset, son casos que provocarn una finalizacin anmala del
programa.
El concepto de excepcin permite capturar estas situaciones especiales
antes de que se produzca el error fatal, avisar al usuario y continuar con
la ejecucin del programa dentro de lo posible.
De manera general, una excepcin se puede producir dentro del mbito
de cualquier funcin sin necesidad de que se estn manejando en ella
recordsets o bases de datos. La clase abstracta CException, representa
este concepto. De entre sus clases derivadas destacan:
CMemoryException, para gestin de excepciones producidas
por operaciones directas sobre memoria (new, delete, ).
CFileException, para operaciones sobre ficheros (fichero no
existente o de slo lectura, etc.)
CDBException y CDaoException para operaciones sobre bases
de datos ODBC y DAO respectivamente.
Cada una de estas clases incorpora funcionalidades propias, pero su
utilizacin es muy similar, por lo que nos centraremos sobre
CDBException que nos ocupa ahora.
La forma de utilizar las excepciones es como sigue: tenemos que
encapsular la operacin que pueda producir la excepcin dentro de un
bloque TRY/CATCH, que de manera general tiene el siguiente formato.
TRY
Curso: Visual C++

71

{
Operacin que puede producir
excepcin
}
CATCH(Clase de excepcin a capturar,
objeto asociado)
{
Operaciones de recuperacin de la
excepcin
}
La rama donde se encuentran las operaciones de recuperacin de la
excepcin slo se ejecutarn en el caso de que se produzca una
excepcin de la clase especificada en la sentencia CATCH, entonces el
objeto que le acompaa tomar los valores que identifican dicha
excepcin. Mas en concreto, para el caso de CDBException, el ejemplo
sera algo as:
CEmpleadosSet e;
e.m_strFilter = "DEPARTAMENTO =
VENTAS";
TRY
{
e.Open();
}
CATCH(CDBException, e)
{

Curso: Visual C++

72

}
END_CATCH

Curso: Visual C++

También podría gustarte