manual de vc++ completo

90
INTRODUCCIÓN: El entorno de desarrollo de VC++ 6.0 ofrece muchas posibilidades programador, desde crear aplicaciones de diversos formatos y cara pasando además por la creación de librerías DLL, iconos, bitmaps, etc. Todo el IDE, (entorno de desarrollo), en conjunto es una gran "co desarrollar las aplicaciones más versátiles tanto para entorno Wi DOS. Es importante aclarar que cuando se pretende crear una aplicación bajo Windows con VC++ se debe tener en cuenta si la misma estará MFC o si será una aplicación WIN 32 estándar. Microsoft Foundation Class (MFC): Visual C++ se suministra junto con la biblioteca MFC que es un co clases predefinidas de C++. Estas clases han pasado a ser un está desarrollo para aplicaciones Windows y poseen clases que facilita programación en C++, por ejemplo al incluir un tipo de dato CStri declarar cadenas; cosa que no existe en C y siempre es un dolor d También se pueden crear programas Windows que no usen MFC, así se obtendría una aplicación con la cual no haría falta distribuir la "HOLA VISUAL C++": Para introducirse en un nuevo lenguaje no hay como un buen ejempl históricamente fue y es el famoso "Hola Mundo". Para comenzar a desarrollar esta pequeña aplicación ingresamos en luego seleccionamos NEW en el menú FILE y aparecerá la siguiente Esta pantalla muestra los distintos proyectos que uno puede desarrollar con VC++. Como queremos hacer una aplicación basada en MFC seleccionaremos MFC AppWizard (exe). En VC++ como en VB se trabaja con PROYECTOS, a su vez éstos en VC++ se agrupan en WORKSPACES ("espacios de trabajo"). Entonces en Project Name escribimos el nombre de nuestro proyecto, HolaVC, en Locatio defecto se establecerá la ruta de nuestro nuevo WORKSPACE y será ARCHIVOS DE PROGRAMA\Microsoft Visual Studio\MyProjects\HolaVC. opción se puede modificar).

Upload: antonio-mira

Post on 21-Jul-2015

264 views

Category:

Documents


1 download

TRANSCRIPT

INTRODUCCIN: El entorno de desarrollo de VC++ 6.0 ofrece muchas posibilidades al programador, desde crear aplicaciones de diversos formatos y caractersticas, pasando adems por la creacin de libreras DLL, iconos, bitmaps, cursores, etc. Todo el IDE, (entorno de desarrollo), en conjunto es una gran "cocina" para desarrollar las aplicaciones ms verstiles tanto para entorno Windows como DOS. Es importante aclarar que cuando se pretende crear una aplicacin que corra bajo Windows con VC++ se debe tener en cuenta si la misma estar basada en MFC o si ser una aplicacin WIN 32 estndar. Microsoft Foundation Class (MFC): Visual C++ se suministra junto con la biblioteca MFC que es un conjunto de clases predefinidas de C++. Estas clases han pasado a ser un estndar de desarrollo para aplicaciones Windows y poseen clases que facilitan mucho la programacin en C++, por ejemplo al incluir un tipo de dato CString para declarar cadenas; cosa que no existe en C y siempre es un dolor de cabeza. Tambin se pueden crear programas Windows que no usen MFC, as se obtendra una aplicacin con la cual no hara falta distribuir la librera MFC. "HOLA VISUAL C++": Para introducirse en un nuevo lenguaje no hay como un buen ejemplo y ste histricamente fue y es el famoso "Hola Mundo". Para comenzar a desarrollar esta pequea aplicacin ingresamos en VC++, luego seleccionamos NEW en el men FILE y aparecer la siguiente pantalla:

Esta pantalla muestra los distintos proyectos que uno puede desarrollar con VC++. Como queremos hacer una aplicacin basada en MFC seleccionaremos MFC AppWizard (exe). En VC++ como en VB se trabaja con PROYECTOS, a su vez stos en VC++ se agrupan en WORKSPACES ("espacios de trabajo"). Entonces en Project Name escribimos el nombre de nuestro proyecto, HolaVC, en Location por defecto se establecer la ruta de nuestro nuevo WORKSPACE y ser ARCHIVOS DE PROGRAMA\Microsoft Visual Studio\MyProjects\HolaVC. (esta opcin se puede modificar).

Una vez ingresado el nombre del proyecto veremos que el botn OK ya est activo si lo pulsamos damos inicio al ASISTENTE DE APLICACIONES MFC el cual nos crear un armazn de programa que despus habr que adecuar (algo as como la ventana por defecto que trae VB cuando uno crea un proyecto). Nos aparece la siguiente ventana:

Una aplicacin de Windows puede ser SDI (Single Document Interface), MDI (Multiple Document Interface) o Dialog Based (basada en dialogos) . Single Document es muy similar a Dialog Based, salvo que por defecto VC le agrega menes y MDI es una aplicacin como por ejemplo Word, con una ventana principal que puede contener a muchas otras en su interior (como un contenedor). Ahora seleccionaremos Dialog Based y como lenguaje de recursos (recursos es algo que ms adelante se explica en detalle) dejaremos por defecto Spanish, salvo que pretendamos que nuestra aplicacin se use en Alemania entonces seleccionaramos German..., : ) ste no ser nuestro caso. Luego de todo esto presionamos NEXT para pasar a la siguiente pantalla: Esta pantalla nos pregunta que caractersticas le queremos agregar a nuestra aplicacin, About Box, Context Sensitive Help (un botn que llame a un archivo de ayuda), 3D Controls, dejemos todo como est, y pasemos a la siguiente ventana pulsando nuevamente NEXT.

Aqu se nos est diciendo que se crear un proyecto MFC Standard y adems se nos pregunta si deseamos o no que el cdigo fuente generado automticamente por ste asistente est comentado; obviamente dejamos YES, PLEASE porque esos comentarios son muy tiles para no perderse. Tambin debemos especificar como queremos usar la librera MFC con el ejecutable: como DLL compartida (dinmica) o como librera esttica. Dejemos la primer opcin pues es comn en Windows que las aplicaciones funcionen de esta forma, no obstante si seleccionamos como librera esttica, obtendremos un ejecutable ms grande. Si pulsamos NEXT accedemos a la ltima pantalla de este asistente que nos ofrece la posibilidad de cambiar los nombres de las clases que est a punto de crear, esto habitualmente no se modifica. Pulsamos FINISH y se muestra una listado con las caractersticas del armazn de aplicacin que el asistente est por hacer, OK y listo. El asistente nos gener la base de una aplicacin que consta de una ventana con dos botones (aceptar y cancelar) con un texto en el centro y adems otra ventana (ms pequea), el Acerca de.... Este "armazn" es totalmente funcional, podemos ejecutar el programa haciendo click en el icono con el signo de exclamacin ! o precionando Ctrl + F5, nos dir que el subdirectorio DEBUG de nuestra aplicacin no existe y si deseamos crearlo, decimos que YES y tenemos el programa en ejecucin. Nos inform de la falta de la carpeta DEBUG por ser la primera vez en ejecutar el programa y esta carpeta se crea ya que por defecto todas la aplicaciones en desarrollo en VC++ contienen informacin de depuracin, que nos permite depurar el programa poniendo puntos de interrupcin, ejecutando paso a paso, etc., pero cuando terminemos nuestra aplicacin y se la entreguemos al usuario sta no debe contener informacin de depuracin pues har que descienda su performance y el ejecutable sea ms grande. Para quitar la informacin de DEBUG (slo cuando tengamos la aplicacin terminada), vamos a la opcin SET ACTIVE CONFIGURATION.. del men BUILD y seleccionamos RELEASE. En el entorno de desarrollo se nos presenta a la izquierda, una ventana que tiene 3 solapas: Class View, Resource View y File View. Seleccionando la solapa Class View, podremos ver que dice HolaVC classes, si expandimos esta descripcin haciendo click en l +, se desplegarn las clases,

(generadas por el asistente) que forman mi aplicacin: CAboutDlg, la clase de la ventana AboutBox, CHolaVCApp, la clase aplicacin que existe en todas las aplicaciones y CHolaVCDlg, la clase de la ventana principal (la que contiene los botones Aceptar y Cancelar, y donde luego agregaremos un botn ms). Adems hay una carpeta llamada Globals donde se agrupan las variables globales. Las clases a su vez contienen ms cosas: Funciones miembro y variables miembros. Precisamente gran parte del cdigo que uno escribe en VC++ se trata de nuevas funciones miembros que uno agrega a las clases existentes. En todo lenguaje de programacin visual, sea VB o VC++, se tiene un lugar del IDE(Entorno de desarrllo) donde uno puede disear el aspecto visual de la aplicacin y otro donde uno puede escribir el cdigo necesario para los objeto diseados de manera tal que las cosas respondan de acuerdo a lo que uno quera. En VC++ se accede al lugar donde se lleva a cabo el diseo seleccionando la solapa RESOURCE (recursos) de la ventana WORKSPACE, (la de la izquierda donde adems estn todas las clases). Al seleccionar RESOURCE se podr observar varias carpetas Dialog, Icon, String Table y Version. Expandiendo la carpeta Dialog veremos IDD_ABOUTBOX y IDD_HOLAVC_DIALOG estas son las dos ventanas "dilogos" creados automticamente por el Asistente de Aplicaciones. Nosotros modificaremos IDD_HOLAVC_DIALOG, entonces hacemos doble click en el mismo y se nos mostrar la ventana con los dos botones por defecto "Aceptar" y "Cancelar" lista para modificar. La pantalla debera presentar ms o menos lo siguiente:

Primero marcamos con el mouse el texto "A HACER:..." y lo eliminamos presionando la tecla suprimir. Luego de la barra de herramientas seleccionamos un botn y lo colocamos en algn lugar del cuadro de dilogo. (por lo pronto no toque los botones Aceptar y Cancelar que estn por defecto).

Luego que tenemos un nuevo botn, ahora hay que modificar algunas de sus propiedades, por ejemplo la propiedad Caption que por defecto es button1. Para acceder a las propiedades de los controles hacemos click con el derecho sobre el control, en este caso el botn, y seleccionamos del men contextual, "propiedades".

En la solapa General de la pantalla propiedades podremos modificar, entre otras cosas, la propiedad Caption (que es el texto que muestra el botn), y la propiedad ID, la cual es muy importante ya que con ese valor se reconocer al botn al escribir cdigo. Primero modifique la propiedad Caption y escriba "Pulseme"; tambien modificaremos el ID, pues el que tiene por defecto no es muy representativo de lo que el botn realizara. Escriba IDC_PULSEME (por convencin se recomienda dejar el prefijo IDC_ y luego escribir algo que represente la utilidad del control. No altere el resto de las propiedades, pues por ahora no las necesitamos, an as si lo desea puede seleccionar las restantes solapas y observar que otras propiedades puede modificar. Nuestra idea es que, al pulsar el botn "Pulsame", se muestre el mensaje: "HolaVC", por ejemplo a travs de un cuadro de mensaje. Para esto hay que tener en cuenta que se necesita una funcin que maneje la accin de "pulsar el botn", en Windows esta funcin as como muchas otras (mover el mouse, tocar una tecla del teclado, hacer doble click, etc), se denominan "Mensajes", pues estas acciones son precisamente mensajes entre las ventanas, que uno tiene que interceptar de alguna forma. Existen muchas formas de crear un manejador de mensajes, pero habitualmente se hace click con el derecho del mouse sobre el control al cual se quiere crear un manejador y se selecciona la opcin "ClassWizard". Tambin se puede acceder a ClassWizard en cualquier momento presionando Ctrl + W. ClassWizard es un asistente para la creacin de Mapas de Mensajes (manejadores de mensajes), funciones miembros, variables miembros, clases, etc.

En la lista Object Ids del ClassWizard selecciones IDC_PULSAME, pues queremos crear un mapa de mensajes para este control, y en la lista Messages selecciones

BN_CLICKED. Luego pulse Add Function y aparecer un mensaje alertando que est por crear la funcin miembro OnPulsame; si lo desea puede modificar este nombre, pero no es recomendable, entonces slo presione OK. La nueva funcin se habr sumado a la lista de Member Functions, pulse Edit Code para poder escribir el cdigo de esta nueva funcin. Aparecer lo siguiente: void CHolaVCDlg::OnPulseme() { // TODO: Add your control notification handler code here } Entre las llaves tendremos que escribir nuestro cdigo que permita mostrar el mensaje "HolaVC". La lnea en color verde es un comentario que nos indica que en esa seccin tiene que escribir uno el cdigo que actuar al pulsar el botn. Esta funcin, OnPulseme, forma parte de la clase base, CHolaVCDlg. Podemos cerciorarnos de su existencia si en la ventana Workspace seleccionamos la solapa ClassView; all veremos todas las funciones y variables miembros de esta y otras clases. Bien, escribamos entonces el cdigo para mostrar nuestro mensaje: MessageBox("HolaVC", "Mi Mensaje", MB_ICONINFORMATION); Slo esa lnea de cdigo es necesario escribir. Presione Ctrl + F5 y se ejecutar la aplicacin; si pulsa el botn aparecer el mensaje:

Los parmetros de la funcin MessageBox son: Texto a mostrar, Ttulo del mensaje e icono + botones a mostrar (en este caso como no se especifican los botones muestra por defecto OK). Botones posibles MB_ABORTRETRYIGNORE MB_OK MB_OKCANCEL MB_RETRYCANCEL MB_YESNO MB_YESNOCANCEL Iconos posibles MB_ICONEXCLAMATION MB_ICONINFORMATION MB_ICONQUESTION MB_ICONSTOP

CUADROS DE EDICIN: Otro control importante en Windows (adems del botn), son los cuadros de edicin. En estos controles se basa prcticamente el 70% del ingreso de datos

en una aplicacin Windows. Por lo tanto es despus del botn, el control ms comn. Ahora realizaremos un programa que utilizar un cuadro de edicin, y el objetiv ser que, mientras escribimos algo en el cuadro de edicin, simultneamente se escribir lo mismo en el ttulo del dilogo (ventana). Entonces, vaya al men FILE NEW y seleccione, como en el ejemplo anterior, MFC AppWizard (exe) y ponga Edicion como Project Name. Contine con el Asistente de aplicaciones como en el primer ejemplo hasta crear la estructura bsica del programa. Luego que tenga en pantalla el dilogo con los dos botones por defecto Aceptar y Cancelar, agregue, desde la barra de controles, un cuadro de edicin (icono ab| ), y acceda a sus propiedades haciendo click con el derecho del mouse sobre el control. Verifique que la propiedad ID sea IDC_EDIT1 (por defecto tiene que ser esa), no va hacer falta que la modifique. Cierre el cuadro de propiedades.

Bien, como queremos que al momento de estar escribiendo cada carcter del texto que ingresamos en el cuadro de edicin, se muestre adems en la barra de ttulo de la ventana, debemos escribir cdigo para el mensaje EN_CHANGE del cuadro de edicin. Para crear este gestor de mensaje, debemos acceder al ClassWizard, esto se logra haciendo click con el derecho del mouse sobre el control de edicin y seleccionando la opcin ClassWizard del men contextual. En ClassWizard verifique que en la lista Object ID se encuentre seleccionado IDC_EDIT1 y en la lista Messages, EN_CHANGE. Presione Add Function, EN_CHANGE pasar a formar parte de la lista Member Functions, seleccinela y presione Edit Code. Escriba entonces el siguiente cdigo: void CEdicionDlg::OnChangeEdit1() { // TODO: If this is a RICHEDIT control, the control will not // send this notification unless you override the CDialog::OnInitDialog() // function and call CRichEditCtrl().SetEventMask()

// with the ENM_CHANGE flag ORed into the mask. // TODO: Add your control notification handler code here CEdit* edTexto; (1) CString strDato; (2) edTexto = (CEdit*) GetDlgItem(IDC_EDIT1); (3) edTexto->GetWindowText (strDato); (4) SetWindowText(strDato); (5) } Los comentarios que estn al principio (en verde), los coloc ClassWizard automaticamente y hacen referencia en el caso que se tratara de un control de texto enriquecido, que no enva directamente este mensaje. Esto por lo pronto no nos interesa. Antes de continuar analizando las lneas de cdigo enumeradas, conviene destacar lo siguiente: "TODOS LOS CONTROLES (OBJETOS) DE WINDOWS SON UNA VENTANA", esto quiere decir que todos los controles son derivados de la clase CWnd. El control de edicin es un objeto CWnd, y en muchas ocasiones dejaremos esto as, pero a veces es conveniente convertir el tipo de los controles a su clase correspondiente, en nuestro caso CEdit. Por esto en la linea (1) se declara la variables edTexto como un puntero a la clase CEdit, pues la intencin es asociar el cuadro de edicin con esta variable, para as poder hacer uso de las funciones miembro de la clase CEdit. En la lnea (2) se declara un variable de tipo CString (cadena), donde se almacenaran los caracteres que se van ingresando. Luego de las declaraciones de variables, debemos asociar el puntero con el cuadro de edicin. Esto hace la lnea (3) a travs de la funcin GetDlgItem a la cual se le pasa el ID del objeto a asociar con la variable; el problema es que GetDlgItem retorna un puntero a CWnd y yo quiere uno a CEdit, por eso se utiliza el operador: (Cedit*), que permite realizar la conversin al tipo deseado. Una vez que uno tiene la variable asociada con el control se pueden usar las funciones miembro de esa clase. En la lnea (4) se obtiene el texto del cuadro de edicin con GetWindowText a la cual se le pasa como parmetro la variable CString. Note que se llama la funcin por medio del operador: -> pues la variable es un puntero a CEdit y no una variable CEdit. En la ltima lnea, (5), se establece el ttulo del cuadro de dilogo por medio de la funcin SetWindowText a la cual se le pasa la variable CString que desde la lnea anterior viene cargada con el contenido del cuadro de edicin. Se escribe SetWindowText directamente porque por defecto actuar sobre la clase principal que es la que da origen al cuadro de dilogo, tambin se podra haber usado el puntero this que es el que apunta al objeto por defecto, (quedara: this -> SetWindowText(strDato). ) AGREGAR VARIABLES MIEMBROS: Para el caso de los controles que permiten ingreso de datos es muy importante el uso de esa informacin que probablemente se pasarn a diferentes gestores de mensajes que los procesar. Por ejemplo se ingresa una edad y en algn momento hay que validarla. Los datos contenidos en un control se transfieren a variables que luego el cdigo manipula, despus se pueden volver a volcar al control.

Para ejemplificar esto modificaremos la aplicacin anterior agregando un botn en el cuadro de dilogo. Escribiremos el cdigo adecuado para cuando se pulse el botn se invierta el contenido del cuadro de dialogo. En vez de agregar un nuevo botn, utilicemos el botn CANCELAR. Seleccinelo, vaya a Propiedades, modifique la propiedad Caption a Invertir y cambie el ID por IDC_INVERTIR. El Cuadro de dilogo debera quedar ms o menos as:

Primero crearemos una variable miembro para el cuadro de edicin; para esto accedemos a ClassWizard y seleccionamos la solapa Members Variables. Una vez ah se marca de la lista Controls ID, el ID del cuadro de edicin, (IDC_EDIT1), y se pulsa el botn Add Variable. En la ventana que aparece ingrese m_strDato como Member Variable Name, Category Value y Variable Type Cstring (puesto que el valor ingresado ser una cadena). Acepte esta ventana. Y acepte la ventana del ClassWizard. Bien, ya tenemos una variable para almacenar el contenido del cuadro de edicin. ClassWizard relaciona automticamente las variables miembro con sus clases, as que slo debemos escribir el cdigo que invierta lo ingresado y lo deje nuevamente en el mismo cuadro de edicin. Seleccione el botn Invertir y acceda a ClassWizard. Seleccione la solapa Messages Map, IDC_INVERTIR en Objects ID y BN_CLICKED en Messages. Presione Add Function. Acepte el nombre sugerido y la funcin se agregar a la lista Member Functions. Presione Edit Code. Estamos entonces en la funcin OnInvertir de la clase CedicionDlg donde escribiremos el cdigo que invertir lo ingresado. Escriba: void CEdicionDlg::OnInvertir() { // TODO: Add your control notification handler code here UpdateData(TRUE); (1) if (m_strDato.IsEmpty ()== FALSE) (2) { MessageBox("Ahora se invertir: " + m_strDato); (3) m_strDato.MakeReverse (); (4) UpdateData(FALSE); (5) } } Lo primero que hay que hacer es que el contenido del cuadro de edicin pase a la variable miembro. Esto hace la lnea (1) con la funcin UpdateData(TRUE) luego de esta linea la variable m_strDato contiene lo ingresado en el control.

En la lnea (2) se verifica que no est vaca (lo que inplica que el cuadro de edicin se dej en blanco). En caso de haber ingresado algo, entonces hay que darlo vuelta, se muestra un mensaje advirtiendo esto: lnea (3). En (4) se hace uso de la funcin MakeReverse() de la clase Cstring, que invierte la cadena sobre s misma. En lnea (5) se transfiere el contenido de la variable a el control. Resumiendo: Se declaran variables miembro para los controles cuando se necesita pasar el contenido de los mismos a funciones que los procesen. Los contenidos de los controles se transfieren a las variables por medio de la funcin UpdateData(TRUE). Y luego para transferir los valores de las variables a los controles se usa UpdateData(FALSE): CONTROLES: RADIO BUTTON, CHECK BOX Y GROUP BOX. Cree una aplicacin MFC basada en dilogo, tal como se hizo en los ejemplos anteriores y pngale autos como Project Name. La aplicacin har uso de controles de opcin (radio button), controles de veirficacin (check box) y marcos (GROUP BOX). Los controles de opcin son esos "circulitos" que uno selecciona y que automticamente otro queda sin efecto (sin seleccionar). Esto ocurre cuando los controles de opcin se consideran agrupados. En VC se agrupan de acuerdo al orden en que fueron colocados en el cuadro de dilogo, partiendo de un primer control con la propiedad GROUP activada y hasta que encuentre otro objeto con la misma propiedad GROUP activada. Para pasar en claro esto ltimo disee la aplicacin de acuerdo a los siguientes pasos. Seleccione un control GROUP BOX de la barra de herramientas. Escriba Marcas en la propiedad Caption del GROUP BOX. Luego coloque 3 radio buttons dentro del GROUP BOX Las propiedades de los tres botones de opcin sern: El primero: ID = IDC_BMW, CAPTION = BMW y tildar GROUP. El segundo: ID = IDC_AUDI, CAPTION = Audi y no tildar GROUP. El tercero: ID = IDC_OPEL, CAPTION = Opel y no tildar GROUP.

Se tilda GROUP slo en el primero para especificar que a partir de ese control en adelante (de acuerdo al orden de tabulacin), estarn relacionados los botones de opcin hasta encontrar un nuevo control con GROUP tildado. Agregue otro GROUP BOX a la izquierda de Marcas con la propiedad CAPTION = Tipos. Coloque 3 radio buttons dentro del GROUP BOX y especifquele las siguientes propiedades: El primero: ID = IDC_SEDAN, CAPTION = Sedan, tildar GROUP y en STYLE tildar PUSH LIKE. El segundo: ID = IDC_COUPE, CAPTION = Coup, no tildar GROUP y en STYLE tildar PUSH LIKE.

El tercero: ID = IDC_BREAK, CAPTION = Break, no tildar GROUP y en STYLE tildar PUSH LIKE. Aqu el primero como tiene la propiedad GROUP tildada da por finalizado el agrupamiento anterior y comienza el nuevo de los Tipos.

Por ltimo coloque 2 CHECK BOX a la izquierda: El primero ID = IDC_AIRE, Caption = con aire y GROUP tildado (da por finalizado el grupo anterior). El segundo ID = IDC_CD, Caption = con CD y GROUP sin tildar. Ms o menos as quedara el diseo:

Una vez diseada la ventana y los controles con sus respectivas propiedades especificadas; hay que crear las variables asociadas a los controles que manipularn los datos. Aqu los datos son, bsicamente, si un botn de opcin est activado o no. Se necesitar una variable por grupo de botones de opcin: una para el grupo "autos", asociada a la primer opcin: BMW y otra para el grupo "tipos", asociada a la primer opcin: SEDAN. Crear variables miembro: Seleccione el primer radio button del grupo Autos, (BMW) y acceda a ClassWizard. En ClassWizard vaya a la solapa Member Variables y seleccione IDC_BMW. Presione Add Variable; aparecer la ventana Add Member Variable. All ingrese m_Marca como Member Variable Name; seleccione Value en Category y Variable Type = int.

Haga lo mismo para el primer radio button del grupo Tipos (Sedn) y llame a la variable m_Tipo. La idea es que al presionar Aceptar, de acuerdo a las opciones seleccionadas muestre un mensaje informativo. Antes debemos asignarles a las variables recin creadas un valor inicial, para que as, al iniciar la aplicacin, estn seleccionados por defecto los primeros radio buttons de cada grupo. Esto se hace editando el constructor de la clase CAutosDlg: En la ventana WorkSpace, seleccione la solapa ClassView. Expanda la rama de la clase CAutosDlg. Haga doble click en la primer funcin: CAutosDlg(CWnd *pParent = NULL). Ver que las variables creadas tienen el valor 1, cmbielo por 0. Esto establece como seleccionada la primer opcin, (BMW en el primer grupo y Sedan en el segundo). Ahora escribiremos el cdigo del botn Aceptar. Puede acceder al mismo por el ClassWizard o simplemente haciendo doble click sobre el botn. Escriba: void CAutosDlg::OnOK() { // TODO: Add extra validation here CWnd *wndAuto; (1) CWnd *wndTipo; (2) CString strMensa; (3) CString strAuto, strTipo, strExtra; (4) CButton* bAire; (5) CButton* bCD; (6) //Convierto los dos Check que originalmente son de //tipo CWnd a tipo CButton para poder hacer uso de //las funciones de CButton. bAire = (CButton*) GetDlgItem(IDC_AIRE); (7) bCD = (CButton*) GetDlgItem(IDC_CD); (8) strExtra= " -"; (9) if (bAire->GetCheck () && bCD->GetCheck ()) (10) strExtra = " con Aire y CD."; (11) else if (bAire->GetCheck() && !bCD->GetCheck()) (12) strExtra = " con Aire."; (13) else if (!bAire->GetCheck() && bCD->GetCheck()) (14) strExtra = " con CD."; (15) UpdateData(); (16) wndAuto=GetDlgItem(IDC_BMW + m_Marca); (17) wndTipo=GetDlgItem(IDC_SEDAN + m_Tipo); (18) wndAuto->GetWindowText (strAuto); (19) wndTipo->GetWindowText (strTipo); (20) strMensa = "Su auto es un/a: " + strTipo + " " + strAuto + strExtra; (21) MessageBox(strMensa); (22) } Parecer un poco extenso y complejo este cdigo, pero no desespere, veamos lnea por lnea.

En las lneas (1) y (2) se declaran dos punteros a CWnd para luego asociarlos a los primeros radio buttons de cada grupo y poder obtener el texto (ver lneas 17, 18 19 y 20). En las lneas (3) y (4) se declaran algunas variables de cadena donde se almacenarn, por un lado los textos de los radio buttons y check box. Como antes se coment, todos los objetos de Windows son ventanas, o sea de la clase CWnd. La clase CButton posee funciones que vamos a necesitar, por ejemplo GetCheck(), entonces en (5) y (6) se declaran dos punteros a CButton que luego en (7) y (8) se usan para relacionarlos con los checks box. De 10 a 15 se averigua, por medio de GetCheck(), que check box est marcado para as preparar el texto correspondiente. Con UpdateData(TRUE) en (16) se transfieren los datos de los controles a las variables. En (17) y (18) se relacionan los radio buttons con punteros CWnd para despus, por medio de GetWindowText() se obtiene el texto de los controles seleccionados (19 y 20). Nos detenemos un instante en (17) y (18) y vemos que es precisamente en esas lneas donde se determina que radio button est seleccionado, pues el parmetro de GetDlgItem es el ID del primer control del grupo ms el contenido de la variable miembro. En (21) se prepara una variable CString que luego en (22) se muestra por pantalla. Resumiendo: Para saber si un Check Box est marcado o no se debe usar la funcin GetCheck() de la clase Cbutton, por lo tanto de debe convertir el puntero CWnd que retorna GetDLgItem() a CButton. Es bueno tener en cuenta eso de poder convertir de una clase a otra en caso de necesitar alguna funcin en especial. Se conoce un Radio Button seleccionado perteneciente a un grupo a travs de pasar el ID del primer control del grupo ms la variable miembro a GetDlgItem(). CONTROL: LISTBOX. Las listas son otros de los objetos ms importantes en Windows. Existen: listas, listas desplegables, lista de archivos, listas de directorios, etc. Todas funciones y caractersticas propias pero funcionan bsicamente igual. Veamos un ejemplo. - Cree un nuevo proyecto basado en dilogos con el MFC AppWizard y llmelo listas1. Coloque 2 controles ListBox un al lado del otro y dos botones entre ellos.

Acceda a la ventana de propiedades de la lista de la izquierda, (la izquierda suya) (puede dejar visible la ventana de propiedades si presiona el icono "alfiler" del extremo superior izquierdo), y como ID ponga IDC_NUMEROS. En la solapa STYLES desmarque la opcin SORT, pues en este caso no pretendemos que la lista se ordene automticamente.

Para la otra lista escriba IDC_PARES como ID, tambin quite la marca en STYLES a SORT y en EXTENDED STYLES marque MODAL FRAME, (ver como cambian los borde de la lista). Seleccione el botn de arriba, acceda a sus propiedades, como ID escriba IDC_PASAPARES y CAPTIOS = >>. El botn de abajo tendr > como CAPTION e ID = IDC_PASA1. An falta agregar un par ms de objetos, pero antes agregaremos variables miembro a las listas. Seleccione nuevamente la lista de la izquierda, presione Ctrl + W, acceder a ClassWizard. Vaya a la solapa Member Variables, marque IDC_NUMEROS y presione Add Variable. Aparecer la ventana Add Member Variable; como NAME escriba m_lstNumeros, como CATEGORY seleccione Control y TIPO CListBox. Realice los mismo para la otra lista, (la de la derecha), pero como Member Variable Name escriba m_lstPares. Bien, ahora agregaremos unos controles ms para terminar el diseo de la aplicacin. Coloque un pequeo cuadro de edicin abajo a la derecha de IDC_NUMEROS y escriba en la propiedad ID, IDC_CANT. Coloque un botn debajo de IDC_NUMEROS con la propiedad ID = IDC_CARGAR y CAPTION = Cargar. Elimine el botn Cancelar y mueva el botn Aceptar para ubicarlo en el extremo inferior izquierdo del cuadro de dilogo. Coloque un Static Text a la derecha del cuadro de edicin, con el texto (propiedad CAPTION), "Ingrese cantidad de nmeros". Cree una variable miembro para el cuadro de edicin de TIPO int, CATEGORY values y de nombre m_Cant.

El objetivo del programa ser hacer uso de diferentes eventos y propiedades de las listas. Se ingresar un valor numrico mayor a 0 en el cuadro de edicin, luego se presionar el botn Cargar y se cargar la lista IDC_NUMEROS con los nmeros naturales menores al contenido del cuadro de edicin. Tambin ser posible seleccionar un elemento de la lista y mostrarlo en un mensaje. Al presionar el botn >> se pasarn todos los valores pares de IDC_NUMEROS a IDC_PARES y presionando > , se pasar el valor seleccionado siempre y cuando sea par. Finalmente presionando Aceptar se terminar la aplicacin, pero antes preguntando al usuario si es realmente lo que desea.

Primero codificaremos el botn Aceptar; haciendo doble click vamos directamente al mensaje por dedfecto OnOk(), ah escriba: void CListas1Dlg::OnOK() { // TODO: Add extra validation here if (MessageBox("Desea salir?","Salir",MB_ICONQUESTION+MB_YESNO)==IDYES) CDialog::OnOK(); } Lo nico que se agreg fue la lnea if, donde se averigua que botn del MessageBox se ha pulsado; si fue YES se termina el programa, caso contrario contina todo igual. En este caso se hace uso del valor que retorna MessageBox(), que pueden ser varios de acuerdo a los botones usados en el mensaje. Si probamos la aplicacin y pulsamos el botn Aceptar veremos que ahora aparece un mensaje preguntando si efectivamente queremos salir; mensaje tpico de todo programa Windows. Seleccione el botn Cargar y acceda a ClassWizard. All seleccione Message Maps, luego en Objects IDs marque IDC_CARGAR, en MESSAGE marque BN_CLICKED y entonces presione ADD FUNCTION e inmediatamente EDIT CODE. Aparecer la funcin OnCargar(), all escriba: void CListas1Dlg::OnCargar() { // TODO: Add your control notification handler code here CString c; (1) int i; (2) UpdateData(TRUE); (3) m_lstNumeros.ResetContent (); (4) for (i=1; i 0) (4) for (i=0; i< ce; i++) (5) { m_lstNumeros.GetText (i, strC); (6) //obtengo elemento n=atoi(strC); (7) //lo convierto a numrico if(n%2==0) (8) //averiguo si es par m_lstPares.AddString(strC); (9) //lo paso a la otra } } Primero (1) se declaran variables enteras; i ser el ndice del variar, ce la cantidad de elementos de la lista IDC_NUMEROS y n donde se almacenar cada elemento convertido a numrico para poder averiguar si es par o no. En strC se almacenar cada elemento. En (3) por medio de GetCount() se obtiene la cantidad de elementos en IDC_NUMEROS. Si la cantidad de elementos es mayor a 0 (4) comienzan a recorrerse todos los elementos de la lista, desde el primero, 0, hasta el ltimo, ce-1. Por cada

elemento obtengo el contenido a travs de la funcin GetText (5) a la cual se le pasa el ndice i y la variable donde dejar el valor. Como tengo que ver si ese valor es par o no, debo pasarlo a entero, pues es una cadena; esto hace la lnea (7) por medio de la funcin atoi (array to integer), dejando en la variable n el valor en formato integer. Si el resto de dividir n por 2 es 0, es porque es par, entonces, lo paso a IDC_PARES, as sucesivamente, elemento por elemento hasta recorrer toda la lista IDC_NUMEROS. El botn IDC_PASA1 es ms fcil, pues solamente hay que averiguar si es par el que est seleccionado. Cree una funcin de gestin para el mensaje OnPasa1, tal como lo hizo para el botn anterior, y escriba: void CListas1Dlg::OnPasa1() { // TODO: Add your control notification handler code here int n; CString strC; m_lstNumeros.GetText (m_lstNumeros.GetCurSel (), strC); n=atoi(strC); if (n%2==0) m_lstPares.AddString (strC); } Estas lneas de cdigo son exactamente las misma que estn en el botn IDC_PASAPARES, (detalladas anteriormente), slo que aqu no hace falta ningn bucle pues solamente interesa el elemento seleccionado. Se obtiene el valor del elemento seleccionado, se lo convierte a entero, se averigua si es par y en caso positivo se lo pasa a la otra lista. Resumiendo: Las listas, sean ListBox o ComboBox poseen la funcin miembro AddString() con la cual incorporan elementos. Los elementos de una lista tienen una posicin dentro de ella donde el primer elemento es 0. Este ndice se obtiene por medio de la funcin miembro GetCurSel(), la misma retorna la posicin del elemento seleccionado. La cantidad de elementos de una lista se obtiene con la funcin GetCount(). El elemento seleccionado se obtiene por medio de GetText() cuyos parmetros son: el ndice en la lista donde se encuentra el elemento y una variable CString donde se almacenar el valor. A una lista se le asocia una variable de Category Control y Type CListBox..

DIALOGOS MODALES Y NO MODALES: Hasta ahora hemos visto aplicaciones que slo usaban un solo cuadro de dilogo (una sola ventana); a pesar que AppWizard nos genera un AboutBox. Desde ya que una aplicacin no se basa siempre en un solo dilogo sino que a veces necesitaremos incorporar ms ventanas a nuestros programas. Crearemos entonces un proyecto al cual llamaremos Dialogos y como siempre ser Dialog Based. Una vez generada la aplicacin por AppWizard ver el dilogo cotidiano con los botones Aceptar y Cancelar. Antes de incorporar un nuevo dilogo modificaremos nuestra pantalla principal. Coloque el botn Cancelar en el extremo inferior izquierdo del cuadro de dilogo. Acceda a las propiedades de este botn, cambie su ID por IDC_LLAMA y CAPTION por "Llamar al otro dilogo". Ahora agregaremos un nuevo dilogo, para esto en la ventana WorkSpace debe estar activa la solapa ResourceView (seguramente est activa sta pues estuvo modificando el botn). Haga click con el botn derecho del mouse sobre la carpeta Dialog y seleccione Insert Dialog del men contextual. Aparecer un nuevo dilogo con los botones Aceptar, Cancelar y por defecto ID = IDD_DIALOG1. Si lo desea puede modificar las propiedades del dilogo, pero en este caso dejaremos todo como est. Cuando un agrega un dilogo slo se incorpora el recurso (archivo de recurso), que sera el aspecto visual, pero para nada est an vinculado con la aplicacin, pues necesita de una clase la cual traer consigo las funciones miembro y los datos miembro. Por eso cada vez que inserte un cuadro de dilogo cree la clase del mismo, cmo se hace esto?; simplemente presione Ctrl + W y aparecer automticamente antes de entrar a ClassWizard la siguiente ventana:

Se detect que IDD_DIALOG1 es un nuevo recurso y que probablemente necesitaremos una clase para el mismo, entonces no ofrece crear una nueva o seleccionar una existente; elegiremos Create a new class y pulsamos OK. Aparecer una ventana pidiendo que ingresemos un nombre para la clase, all ingresaremos CDialogo1, (por convencin todas las clases comienzan con la letra C).

Automticamente en el campo File Name aparecer Dialogo1.cpp, (aqu se encontrar la definicin de la

clase) y en la lista Base Class verifique que se encuentre seleccionada Cdialog. Presione OK, pasar a ClassWizard, presione nuevamente OK para cerrar el asistente. Ya tenemos entonces un nuevo cuadro de dilogo y una clase para el mismo, obviamente esto no hace que nuestra nueva ventana sea til en nuestro programa, ahora deberemos escribir el cdigo necesario para poder mostrarla. Regresemos a la ventana principal, pues el cdigo que llamar al nuevo dilogo estar al presionar el botn IDC_LLAMA. Pero el dilogo donde est este botn reconocer la clase del nuevo dilogo si agregamos en el archivo de implementacin del dilogo principal el archivo de cabecera del nuevo dilogo que fue generado por ClassWizard, el cual tiene el mismo nombre que el de implementacin pero con extensin .h (en nuestro ejemplo sera dialogo1.h ). No se olvide, entonces, de agregar la lnea #include "Dialogo1.h" en DialogosDlg.cpp. Cuando uno muestra un cuadro de dilogo de forma MODAL, hasta tanto no se cierre el dilogo llamado con su respectivo botn cerrar o desde el men de sistema NO SE PODR ACCEDER AL RESTO DE LA APLICACIN y si se lo muestra NO MODAL en cambio PODRA ACCEDER A OTROS PUNTOS DE LA APLICACIN. Por ejemplo: en VC++ la barra de herramientas, donde estn los controles, es un dilogo NO MODAL, pues uno puede acceder a diferentes secciones de VC sin necesidad de cerrar la barra. Por otro lado ClassWizard es un dilogo, ventana, MODAL porque mientras no pulsemos OK, CANCEL o el botn de cerrar de la ventana no podremos utilizar el resto de VC++. En principio veremos como llamar al cuadro de dilogo IDD_DIALOG1 como MODAL. DIALOGOS MODALES: Haga doble click en el botn IDC_LLAMA, (generar automticamente el evento OnLlama) y escriba: void CDialogosDlg::OnLlama() { // TODO: Add your control notification handler code here int r; (1) CDialogo1 dlgDialogo1(this); (2) r=dlgDialogo1.DoModal (); (3) } Este cdigo simplemente se ajusta a llamar al dilogo de forma modal. En (2) se crea un objeto derivado de la clase CDialogo1 especificando Clase variable(this), this es un puntero que hace referencia al objeto actual, o sea el dilogo principal. Y en (3) a travs de DoModal(), del objeto recin creado, se llama al dilogo, y es ms, se le pasa en este punto el control del programa, de manera tal que cuando se cierre el nuevo cuadro de dilogo el flujo del programa continuar despus de esta lnea. Por eso DoModal() retorna un valor entero que puede ser IDOK si el nuevo dilogo al momento de cerrarlo con EndDialog(), (ver ms adelante), se le pas el parmetro IDOK. Por esto extienda el cdigo de IDC_LLAMA como sigue: void CDialogosDlg::OnLlama() { // TODO: Add your control notification handler code here

int r; CDialogo1 dlgDialogo1(this); r=dlgDialogo1.DoModal (); //al volver verificar como se cerr if (r == IDOK) AfxMessageBox("Usted cerr con Aceptar o Si"); else AfxMessageBox("Usted cerr con Cancelar o NO"); } En el nuevo dilogo agregue un botn con las siguientes propiedades: ID = IDC_CERRAR CAPTION = CERRAR. Y escriba en OnCerrar: void CDialogo1::OnCerrar() { // TODO: Add your control notification handler code here CString Mensa; Mensa="Seleccione para cerrar SI o No"; if (MessageBox(Mensa,MB_YESNO+ MB_ICONINFORMATION)==IDYES) (1) EndDialog(IDOK); else EndDialog(IDCANCEL); } Cuando se presione el botn Cerrar, para cerrar el dilogo, se le informa al usuario que seleccione como quiere salir, presionando OK o CANCEL, de acuerdo a lo que se pulse.

Resumiendo: Para insertar un dilogo, hacer click con el botn derecho del mouse sobre la carpeta Dialog del ResourceView y seleccionar Insert Dialog. Luego de agregar un dilogo hay que crear la clase del mismo, esto se hace accediendo a ClassWizard inmediatamente despus de haber insertado el dilogo. No olvidar agregar la lnea de inclusin de archivo de cabecera para el nuevo dilogo en el archivo de implementacin del dilogo que lo llama.

Un dilogo Modal se llama por medio de la funcin DoModal() perteneciente al objeto derivado de la clase del nuevo dilogo, previamente definido en el mismo evento. DoModal() retorna un valor entero que sirve para verificar como fue cerrado el dilogo con la funcin EndDialog(). DIALOGOS NO MODALES: Ahora veamos como llamar a dilogos NO MODALES. Cree un nuevo proyecto basado en dilogos y llmelo Nomodal. En ResourceView haga click con el botn derecho del mouse sobre la carpeta Dialog y seleccione Inser Dialog. Llame a ClassWizard, (por ejemplo haciendo Ctrl + W), aparecer una ventana detectando que se agreg un nuevo dilogo, deje marcado Create a new class y pulse OK. En la ventana New Class en el cuadro de edicin Name escriba CDialogoNoModal y acepte. Escriba la lnea #include "DialogoNoModal.h" en el archivo de implementacin NoModalDlg.cpp. En el dilogo principal agregue 2 botones y establezca las siguientes propiedades: ID = IDC_LLAMAR y CAPTION = Llamar a dilogo no modal. ID = IDC_CERRAR y CAPTION = Cerrar dilogo no modal. En el evento OnLlamar escriba: CDialogoNoModal* dlgNoModal =NULL; (1) void CNomodalDlg::OnLlamar() { // TODO: Add your control notification handler code here if (dlgNoModal == NULL) (2) dlgNoModal = new CDialogoNoModal(this); (3) } En la lnea (1) antes de comenzar la funcin se declara un puntero a la clase del nuevo dilogo (global) y por defecto se le asigna el valor NULL. Este puntero servir para crear una instancia de la clase que ser la forma por la cual manipularemos luego el dilogo. Precisamente en (2) si el puntero es NULL se crea la instancia por medio del operador new (3) el cual reserva memoria para el objeto descendiente de this o sea el dilogo que lo llama. Con esto la aplicacin no va a funcionar, hace falta llamar a la funcin Create() y ShowWindow() desde el constructor del nuevo formulario. Lo escrito en el constructor ser los primero en ejecutarse al ocurrir la lnea (3). Al constructor del nuevo dilogo se accede por medio de la solapa ClassView de la ventana WorkSpace. Expanda la clase del nuevo dilogo y haga doble click donde dice: CDialogoNoModal(CWnd* pParent =NULL); y escriba: CDialogoNoModal::CDialogoNoModal(CWnd* pParent /*=NULL*/) : CDialog(CDialogoNoModal::IDD, pParent) { //{{AFX_DATA_INIT(CDialogoNoModal) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT

//Crear la ventana del cuadro de dilogo no modal if (Create(CDialogoNoModal::IDD, pParent)) (1) ShowWindow(SW_SHOW); (2) //Si se pudo crear, se muestra } Cuando, en el dilogo principal, se pulsa el botn que llama al nuevo dilogo (usando new ), se ejecuta el cdigo del constructor del objeto dlgNoModal, donde habitualmente se inicializan, por ejemplo variables miembros, pero en este caso se intenta crear el dilogo (1) y de ser posible lo muestra (2). Si ejecuta la aplicacin y pulsa el botn que dice: "Llamar a dilogo no modal" acceder al nuevo dilogo no modal que permite acceder indistintamente a sus controles como a los del dilogo principal.

Faltara escribir el cdigo en el botn que permite cerrar el dilogo no modal desde la ventana que lo llam. Escriba el siguiente cdigo en IDC_CERRAR del dilogo principal:

void CNomodalDlg::OnCerrar() { // TODO: Add your control notification handler code here if (dlgNoModal != NULL) { delete dlgNoModal; dlgNoModal = NULL; } } Ac se averigua si la variable objeto CnomodalDlg no contiene NULL, porque si no es NULL es porque ha sido referenciada ya una vez, lo que implica que se est mostrando an el diologo, entonces elimina la memoria reservada y le vuelve a asignar NULL INTERCAMBIO Y VALIDACIN DE DATOS EN UN CUADRO DE DILOGO: Siempre que se asocien variables miembro a controles mediante ClassWizard se genera automticamente un cdigo para efectuar el intercambio de valores de las variables desde y hacia los controles. Este cdigo se encuentra en la funcin DoDataExchange() del cuadro de dilogo. Esta funcin es responsable de transferir los datos en ambas direcciones, desde y hacia los controles del cuadro de dilogo.

El proceso de transferencia se denomina Data Exchange (Intercambio de datos) y se inicia mediante una llamada a la funcin UpdateData(). A UpdateData() se le puede pasar un parmetro Boolean, (TRUE o FALSE) denominado bSaveAndValidate. Se puede pasar o bien FALSE para dar valor a los controles a partir de las variables miembro, o bien TRUE para transferir a las variables miembro los valores actuales de los controles. UpdateData() es invocada automticamente por la funcin OnInitDialog() de la clase CDialog y la funcin OnOK() del botn Aceptar que AppWizard pone por defecto en nuestras aplicaciones tambin llama de forma automtica a UpdateData(). Cuando uno utiliza UpdateData() pasando TRUE en el parmetro bSaveAndValidate en cualquier funcin de cualquier control; se hace un llamado a DoDataExchange(). Si los datos eran vlidos, UpdateData() valdr TRUE caso contrario se emite el aviso oportuno para el usuario y UpdateData() valdr FALSE. Para ver esto cree un nuevo proyecto MFC basado en dilogos y llmelo ValidarDatos. Objetivo del proyecto: La aplicacin siguiente constar de 2 dilogos, uno es el que crea el AppWizard ms otro que agregaremos. Del principal se llamar al nuevo formulario, all habr dos cuadros de edicin donde se ingresar un Apellido y una edad. Al momento de presionar Aceptar se validar si la edad est entre 0 y 110 y si no es 30; de ser vlida se pasan los parmetros a unas etiquetas (cuadro de texto esttico) del dilogo principal. Ya que conoce el objetivo del programa continuaremos con el diseo de las pantallas: En el dilogo principal agregue un control de texto esttico y uno de edicin con las siguientes propiedade ID= IDC_NOMBRE, CAPTION= en blanco y en STYLE tilde SUNKEN. ID=IDC_ANIOS y en STYLE tilde READ ONLY. Ahora le asociaremos variables a estos textos estticos: Pulse con el derecho sobre IDC_NOMBRE y seleccione la opcin ClassWizard del men contextual. Luego elija la solapa Member Variables, marque IDC_NOMBRE y pulse el botn ADD VARIABLE. Especifique en el campo nombre m_strNombre, CATEGORY value y TYPE CString. Acepte todas al ventanas. Realice la misma operacin para IDC_ANIOS pero como nombre de variable escriba m_nAnios, CATEGORY value y TYPE int. Elimine el botn Cancelar y coloque otro con ID = IDLLAMA y CAPTION = Llama a otra ventana. El dilogo principal debera quedar ms o menos as:

Antes de escribir el cdigo del botn "Llamar a otra ventana" agregaremos el nuevo dilogo. En ResourceView haga click con el derecho sobre la carpeta Dialog y selecciones

Insert Dialog. Esto dar a lugar a un nuevo recurso de dilogo. Pngale como ID, IDD_DATOS. Pulse Ctrl + W para acceder a ClassWizard y crear la clase para este dilogo. Como nombre de clase escriba CdatosDlg y acepte todas las ventanas. Agregue la lnea #include "DatosDlg.h" en el archivo de implementacin ValidarDatosDlg.cpp. Diseemos ahora el dilogo DatosDlg. Abra haciendo doble click en la carpeta Dialog de ResourceView, el dilogo IDD_DATOS. Coloque dos cuadros de edicin con los siguientes ID: IDC_APELLIDO , IDC_EDAD. A un lado de los cuadro de edicin coloque controles de texto esttico que sirvan para identificar lo que hay que ingresar en cada campo: CAPTION: Apellido y Edad. El dilogo IDD_DATOS quedara:

Asciele a los cuadros de edicin variables: para IDC_APELLIDO: m_strApellido, CATEGORY value y TYPE CString. Y especifique en la ventana principal de ClassWizard, Maximum Characters = 20. Para IDC_EDAD: m_Edad, CATEGORY value y TYPE int. Minimum Value = 0 y Maximum Value = 110. Bien, ahora regresemos al dilogo principal para codificar el botn que llama a IDD_DATOS. Vamos a llamar a nuestro nuevo dilogo de manera tal que por defecto los cuadros de edicin tengan valores. Escriba en OnLlama: void CValidarDatosDlg::OnLlama() { // TODO: Add your control notification handler code here CDatosDlg dlgDatos(this); (1) //antes de mostrar el formulario le asigno a las variables //de los cuadros de texto valores iniciales dlgDatos.m_strApellido = "Francescoli"; (2) dlgDatos.m_Edad = 34; (3) dlgDatos.DoModal (); (4) } Llamaremos al dilogo de forma Modal, por lo tanto creamos el objeto dlgDatos derivado de CDatosDlg (1), entonces antes de usar DoModal(), le asignamos a las variables miembro de los cuadros de edicin valores por defecto (2) y (3). La transferencia de los valores desde la variables a los controles se realizar, en este caso, de forma automtica cuando el flujo del programa pase por OnInitDialog() del dilogo que acaba de ser invocado.

Si prueba el programa, ver cuando llama al nuevo dilogo que los controles de edicin muestran los valores por defecto. Nos queda escribir el cdigo que valide la edad y que pase los datos de los cuadros de edicin del dilogo IDD_DATOS a los controles del principal, al presionar Aceptar. Cuando se aaden cierto tipo de variables miembro a un cuadro de dilogo mediante ClassWizard, se especifica adems del nombre, una categora, un tipo y algunas validaciones, como por ejemplo para m_Edad se especific que el valor mnimo sera 0 y el mximo 110. Estas validaciones generan cdigo en la funcin DoDataExchange(), (del dilogo correspondiente, en este caso IDD_DATOS), con lneas como esta: DDV_MinMaxInt(pDX, m_Edad, 0, 110); Ver que esa lnea est escrita en un color gris, pues nos permite saber que fueron generadas por ClassWizard. Esta es una funcin DDV (funcin de validacin de datos) propia de VC++ que en este caso en particular verifica que el contenido de la variable m_Edad se encuentre entre 0 y 110. CMO CREAR FUNCIONES DE VALIDACIN PERSONALIZADAS: Es posible crear nuestras propias funciones de validacin personalizadas para comprobar casos especiales escribiendo una funcin del estilo DDV. Nuestra funcin debera admitir el puntero del objeto CDataExchange (pDX), la variable miembro que se desea validar y otros parmetros adicionales que consideremos necesarios. La primera condicin que tiene que verificar nuestra funcin es que el objeto CDataExchange sea guardar y validar (m_bSaveAndValidate); esto se hace comprobando que pDX->m_bSaveAndValidate sea TRUE, pues esto implica que ocurri una llamada UpdateData(TRUE) que transfiere los datos de los controles a las variables. Luego deberamos validar nuestra variable en s, de acuerdo al criterio elegido. Si es vlida la variable, entonces la funcin puede retornar normalmente; en caso contrario ser preciso visualizar un mensaje aclaratorio para el usuario y llamar a la funcin Fail() de DoDataExchange() para indicarle a la funcin UpdateData() que haya llamado que ha fracasado. Bueno, en nuestro ejemplo queramos comprobar que la edad est entre 0 y 110 pero que no sea 30, entonces haga click con el botn derecho del mouse sobre la clase CdatosDlg y seleccione Add Member Function y en la ventana que aparece escriba en Function Type: void y en Function Declaration: ValidarEdad(CDataExchange *pDX, int& Edad), acepte y se presentar en pantalla la funcin. All escriba: void CDatosDlg::ValidarEdad(CDataExchange *pDX, int& Edad) { //Esta funcin me valida la edad //Si va a guardar los datos validando y Edad == 30...

if (pDX->m_bSaveAndValidate && Edad ==30) { AfxMessageBox("La edad debe estar entre 0 y 110 pero no igual a 30!"); pDX->Fail(); //Reseteo el UpdateData() } } Falta hacer la llamada a esta funcin; que la ubicaremos en DoDataExchange() del dilogo IDD_DATOS. All escriba: void CDatosDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CDatosDlg) DDX_Text(pDX, IDC_APELLIDO, m_strApellido); DDV_MaxChars(pDX, m_strApellido, 20); DDX_Text(pDX, IDC_EDAD, m_Edad); DDV_MinMaxInt(pDX, m_Edad, 0, 110); //}}AFX_DATA_MAP ValidarEdad(pDX, m_Edad); //Llamo a la funcin que valida la edad } Puede probar el programa y comprobar que cuando llama al dilogo IDD_DATOS por defecto trae en los cuadros de dilogos los valores iniciales que habamos especificado Apellido=Francescoli y edad = 34. Adems podr verificar que si ingresa una edad fuera del rango 0 a 110 o igual a 30 mostrar el mensaje: "La edad debe estar entre 0 y 110 pero no igual a 30!". Para terminar la aplicacin debemos escribir el cdigo que permita pasar los datos a los controles del formulario principal. Tericamente sera asignarle a las variables de los controles del dilogo principal, el contenido de las variables de los controles del dilogo IDD_DATOS, luego que hayan sido validados. Bastara agregar un else en el if de la funcin ValidarDatos(), pero el problema consiste en cmo hacer referencia a variables de otro dilogo. La solucin es pasarle un puntero de la clase del dilogo principal al constructor del dilogo IDD_DATOS, para que luego desde cualquier gestor de mensajes del dilogo llamado se pueda acceder a travs del puntero a cualquier funcin o dato miembro del dilogo "llamador". Parece un poco complejo, pero siga estos pasos: En primer lugar declararemos una variable miembro de la clase CDatosDlg de tipo CValidarDatosDlg, pues es la clase del dilogo "llamador". Seleccione entonces en ClassView la clase CDatosDlg y pulse el botn derecho del mouse. Del men contextual elija Add Member Variable; aparecer una ventana pidiendo el tipo de variable (Variable Type) all escriba CValidarDatosDlg*, pues ser un puntero, como nombre escriba m_pPrincipal y marque la opcin Protected. Esto dar a lugar a un icono con una llave en el ClassView, lo que indica que se trata de una variable protegida.

El siguiente paso es cambiar los parmetros del constructor que originalmente es: CDatosDlg::CDatosDlg(CWnd* pParent /*=NULL*/) : CDialog(CDatosDlg::IDD, pParent) El parmetro pParent es un puntero a la clase CWnd (ventana) y efectivamente es una referencia a la ventana predecesora, pero lo que nos interesa a nosotros es pasar un puntero a CValidarDatosDlg entonces donde CWnd escribimos CValidarDatosDlg. Y adems agregamos m_pPrincipal(pParent). El constructor quedara: CDatosDlg::CDatosDlg(CValidarDatosDlg* pParent /*=NULL*/) : CDialog(CDatosDlg::IDD, pParent), m_pPrincipal(pParent) (en azul lo modificado y aadido). Ahora hay que hacer la misma modificacin en la declaracin, el paso anterior era la definicin. Para acceder a la declaracin haga click con el botn derecho del mouse en ClassView sobre el constructor y seleccione Go to Declaration all encontrar lo siguiente: // CDatosDlg dialog class CDatosDlg : public CDialog { // Construction public: void ValidarEdad(CDataExchange* pDX, int &Edad); CdatosDlg(CWnd* pParent = NULL); // standard constructor .... por razones de espacio se omite el resto del cdigo. Aqu hay que hacer la misma modificacin que en la definicin; donde dice CWnd* pParent escriba CValidarDatosDlg* y para que la clase datos reconozca la clase predecesora se agrega antes del comentario //CDatosDlg dialog la lnea #include "ValidarDatosDlg.h" que permite incluir el archivo de cabecera que contiene la definicin de la clase CValidarDatosDlg. Resumiendo: Cada vez que se hace un llamado a la funcin UpdateData() sta llama a la funcin DoDataExchange() que es la encargada de validar los datos de acuerdo a los criterior especificados al crear las variables miembros. Cuando se llama a UpdateData() la variable miembro m_bSaveAndValidate de la clase CDataExhange que se accede a travs del puntero pDX. Para poder acceder a las funciones y variables de un dilogo predecesor se debe agregar una variable miembro puntero a la clase del dilogo, modificar adems la definicin y la declaracin del constructor del dilogo desde el cual se quiere usar el predecesor, cambiando el puntero CWnd por el de la clase dilogo requerida incluyendo adems el archivo de cabecera pertinente. EVENTOS DEL MOUSE: Seguramente necesitar en alguna ocasin saber cundo se ha pulsado o soltado un botn del mouse y dnde se ha pulsado.

Windows maneja tres botones del mouse: los botones izquierdo, central y derecho. Para cada botn el programa recibir dos sucesos: uno para el momento en que el usuario pulsa el botn y otro para el momento en que suelta el botn. Cree un proyecto MCF basado en dilogos con el nombre EventosMouse . Pulse el botn derecho del mouse sobre el texto esttico: "A HACER.." y seleccione del men contextual la opcin Properties. Modifique la propiedad Caption por: "Objetivo: Hacer click donde x e y son iguales". Mueva el texto esttico y reubquelo bien arriba al centro del dilogo:

El objetivo del programa ser ir mostrando en la barra de ttulo del dilogo las coordenadas x e y relativas el puntero del mouse, a medida que uno lo mueve. Adems si justamente se pulsa el botn izquierdo del mouse cuando las coordenadas x e y son iguales, se mostrar un mensaje y se realizar un pequeo circulo con centro en esas cooredenadas. Son dos los mensajes del mouse que deberemos codificar. Uno es el que ocurre con el solo hecho de moverlo y el otro cuando pulsamos el botn izquierdo. Presione Ctrl + W para llamar a ClassWizard. Verifique que en la lista Objects IDs est CEventosMouseDlg marcado y seleccione de la lista Messages el suceso WM_MOUSEMOVE. Presione Add Function y luego Edit Code. Aparecer la definicin del mensaje OnMouseMove(), all escriba: void CEventosMouseDlg::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CString strPos; (1) strPos.Format ("Puntero en: x=%d, y=%d", point.x , point.y); (2) SetWindowText(strPos); (3) CDialog::OnMouseMove(nFlags, point); } En principio ver que la funcin recibe dos parmetros el primero un entero sin signo nFlags indica que otros botones del teclado se han mantenido pulsados, (este parmetro por ahora no nos interesa), y el otro de tipo CPoint son las coordenadas donde anda el puntero, es la estructura point y da a lugar a point.x , point.y.

En (1) se declara un string donde se almacenar la cadena a mostrar en la barra de ttulo, la misma que en (2) formateo a travs de su funcin Format() y como parmetros los valores x e y. Con SetWindowText() en (3) se establece como ttulo del dilogo el texto recin formateado. Con esto ya logramos que a medida que movemos el mouse se van mostrando las coordenadas de la posicin del puntero en la barra de ttulo. Ahora presione Ctrl + W para acceder a ClassWizard; marque en Object IDs CeventosMouseDlg y en Messages selecciones WM_LBUTTONDOWN (este es el suceso para capturar cuando se presion el botn izquierdo del mouse), pulse Add Function y luego Edit Code. Escriba: void CEventosMouseDlg::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CDC* pDC; (1) pDC = GetDC(); (2) if (point.x == point.y ) (3) { MessageBox("Perfecto!", "Acert",MB_ICONEXCLAMATION); pDC->Ellipse (point.x -5 , point.y -5 , point.x + 5, point.y +5); (4) } else MessageBox("Intentelo nuevamente", "Fall", MB_ICONERROR); CDialog::OnLButtonDown(nFlags, point); } Lo que se quiere lograr es que si al presionar el botn izquierdo del mouse sobre el dilogo coinciden el valor de la coordenada x con el de y, se muestre un mensaje y se dibuje un circulo pequeo con centro en x, y. Como hay que dibujar sobre el dilogo habr que hacer uso de un Contexto de dipositios, por eso en (1) se declara un puntero a la clase CDC (ms adelante se detallar el tema de Contextos de Dispositivos). En (2) se obtiene el dispositivo por defecto (el dilogo) y en (3) me fijo si los parmetros x e y son iguales. En caso de ser iguales se muestra el mensaje "Perfecto!" y en (4) se dibuja el crculo por medio de la funcin Ellipse() de la clase CDC, cuyos parmetros son los puntos del rectngulo en el cual est inscripta la elipse. En este caso para que point.x, point.y sea el centro, se rest 5 para obtener el puntos superior izquierdo del rectngulo y se sum 5 para el punto inferior izquierdo. Resumiendo: Los sucesos del mouse que se pueden capturar reciben como parmetros las coordenadas x e y del puntero (el puntero del mouse), en la estructura point de la clase Cpoint y el botn o la combinacin de botones pulsados como una entero sin signo UINT. Lo referente a el Contexto de Dispositivo (clase CDC) se ver ms adelante. TEMPORIZADOR: Quienes programan en Visual Basic habrn usado alguna vez el control Timer. Este control permite estipular un intervalo de tiempo para el cual ejecutar una determinada porcin de cdigo. Digamos por ejemplo que quiero mostrar el

mensaje "Hola" cada 5 segundos; bueno, en VB bastaba con agregar un control Timer en el formulario, especificar la propiedad Interval en 5000 (milsimas de segundos) y escribir el cdigo del mensaje en el evento Timer del Timer. Bien, nada de esto hay en VC++. Mirando la barra de herramientas no encontramos ningn control Timer o Temporizador, pero esto no implica que no exista el concepto de temporizador en VC++. Hay un mensaje para la clase CDialog llamado WM_TIMER, este mensaje es el encargado de ejecutar peridicamente el cdigo que queramos. No funciona solo, sino que primero hay que hacer una llamada a la funcin SetTimer() pasndole como parmetro el intervalo en milsimas de segundos, (esta funcin, se podra decir, activa el Timer), despus hay que usar la funcin KillTimer() para desactivarlo, (hay que recordar que un Timer activo ocupa recursos del sistema). Bien, vamos a realizar una aplicacin que incremente en 1 una variable pblica y en 2 otra, cada un segundo. El programa utilizar el mensaje WM_TIMER y se activar cuando se pulse un botn y desactivar pulsando otro. Cree un nuevo proyecto con el nombre "tempo" basado en dilogos. Coloque dos cuadros de edicin en el centro del dilogo los dos con las propiedades Read Only y Number tildadas y Border sin tildar. Con los ID: IDC_VECES e IDC_VECES2. Coloque dos botones con los siguientes ID: IDC_PONER_TIMER e IDC_TERMINAR_TIMER y como Caption escriba: "Poner timer" y "Terminar timer". Elimine el botn Cancelar. La pantalla debera quedar as:

Ahora vamos a asociarles variables a los cuadro de edicin: Presione Ctrl + W para acceder a ClassWizard. Seleccione la solapa Member Variables. En Control IDs seleccione IDC_VECES y presione el botn Add Variable. Como nombre escriba m_eVeces, Category = Value y Type = UINT. Acepte la ventana. Realice lo mismo para IDC_VECES2 pero la variable con el nombre m_eVeces2. Creamos ahora la variable pblica contador. En ClassView, con el botn derecho del mouse pulse sobre la clase CTempoDlg; del men contextual elija Add Member Variable.

Aparece la ventana Add Member Variable, all, en Variable Type escriba UINT y en nombre m_nVeces y acepte la ventana. Esto declar la variable m_nVeces de tipo entero largo, debemos darle el valor inicial 0; y el lugar correcto para hacer esto es el constructor del dilogo. Haga doble click en CTempoDlg::CTempoDlg(CWnd* pParent = NULL), el constructor. Se editar el cdigo: CTempoDlg::CTempoDlg(CWnd* pParent /*=NULL*/) : CDialog(CTempoDlg::IDD, pParent) { //{{AFX_DATA_INIT(CTempoDlg) m_eVeces = 0; m_eVeces2 = 0; //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); m_nVeces=0; //Esta es la inicializacin de la variable pblica } Ya que tenemos todo preparado, es hora de agregar el mensaje WM_TIMER al dilogo: Presione Ctrl + W para abrir ClassWizard. Seleccione la solapa Message Maps y CTempoDlg en la lista Object IDs. En Messages seleccione WM_TIMER y pulse Add Function. Esto dar lugar al evento OnTimer(). Pulse Edit Function y podr aadir cdigo en el evento. Escriba: void CTempoDlg::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default m_eVeces= m_nVeces; (1) m_eVeces2=m_nVeces*2; (2) UpdateData(FALSE); (3) m_nVeces++; (4) CDialog::OnTimer(nIDEvent); } Simplemente aqu se igualan las variables asociadas a los cuadros de edicin con la variable pblica contador, en (1) para que se vaya mostrando de saltos de a 1 y (2) se lo multiplica por 2 al contenido, entonces va pasando de a 2. En (3) transfiero los datos desde las variables a los contadores por medio de la funcin UpdateData(FALSE), para que se muestren por pantalla; y (4) incremento la variable pblica. Ahora hay que escribir el cdigo, en el botn "Poner Timer", que llame a funcin SetTimer(), que es precisamente la que activa el Temporizador. Entonces haga doble click sobre el botn, se crear automticamente la funcin OnPonerTimer(), all escriba: void CTempoDlg::OnPonerTimer()

{ // TODO: Add your control notification handler code here SetTimer(1,1000, NULL); (1) } A la funcin SetTimer() se le pasa como parmetros, primero un valor distinto de 0 que identificar a ese Timer en particular, en segundo lugar el intervalo de tiempo en milsimas de segundos, (en este caso 1000 equivale a 1 segundo, o sea que cada un segundo se ejecutar el cdigo del evento OnTimer()) y por ltimo se pasa un valor que significa a que objeto pertenece el temporizador, NULL porque se trata del dilogo actual;(por lo general va siempre NULL aqu). Falta el cdigo para terminar el Timer, escriba para el botn "Teminar Timer" lo siguiente: void CTempoDlg::OnTerminarTimer() { CRect recDlg; CString strH, strW; // TODO: Add your control notification handler code here KillTimer(1); (1) } Para terminar el temporizador simplemente hay que llamar a la funcin KillTimer() pasndole como parmetro el mismo valor distinto de 0 que representa el Timer. Resumiendo: Un temporizador, Timer, es un mensaje de Windows que se ejecuta cada vez que se cumple el lapso de tiempo especificado en la llamada SetTimer(). Para utilizar el Timer, hay que agregar la funcin miembro del dilogo, WM_TIMER y luego activarlo, (slo una vez), usando la funcin SetTimer(). CMO TRABAJAR CON MENS: Los mens, (o menes), en las aplicaciones Windows son objetos, prcticamente omnipresentes. El Application Wizard que uno usa para generar la base de la aplicacin permite agregarles a los dilogos mens, siempre y cuando la eleccin nuestra haya sido desarrollar un proyecto SDI o MDI, AppWizard no genera mens para los proyectos basados en dilogos. Pero aqu haremos las cosas ms rebuscadas, crearemos un proyecto basado en dilogo, con el nombre de menu y a "manopla" crearemos el men. El programa constar de un men "Principal" con los submens "Uno", "Dos", "Tres", una separacin y "Salir". Adems estar la opcin "Ayuda" con el submen "Acerca de..." que nos permitir acceder al dilogo Acerca de que AppWizard nos gener. Cuando se seleccione el tem "Uno" se incrementar en 1 un campo de una estructura pblica, si se selecciona "Dos" se incrementar en 2 otro campo de la misma estructura, si se selecciona "Tres" se incrementar en 3 y cuando se pulse el submen "Sumar" se mostrar un mensaje con el resultado de la suma de los tres campos de la estructura. Primero crearemos el men, que se trata de un recurso. Una vez generado el proyecto, seleccione la solapa Resource View de la ventana WorkSpace, all haga click con el botn derecho del mouse sobre la carpeta menu resources, del men contextual seleccione Insert...

De la lista de recursos elija Menu y presione New. En la ventana de la derecha aparecer una barra horizontal donde uno ir diseando el men. Presione el botn derecho del mouse sobre el rea punteada y seleccione properties. Aparecer la ventana de propiedades de ese tem en particular, que en este caso se trata del nivel ms superior del men por lo que no lleva ID, pero como Caption escriba "Principal", ver como automticamente se extiende el men para poder agregar otros tems. Agregue los siguientes elementos al men "Principal": ID= IDC_MUNO, CAPTION=Uno. ID= IDC_MDOS, CAPTION=Dos. ID=IDC_MTRES, CAPTION=Tres. ID= IDC_MSUMAR, CAPTION= Sumar. Marque la opcin SEPARATOR para crear un elemento que divida el men. ID=IDC_MSALIR, CAPTION=Salir. Del mismo nivel que Principal cree "Ayuda" y como submen de ste: IDC_MACERCA, CAPTION=Acerca de...

Solamente esto hace falta para crear el aspecto visual del men; ahora hay que asociarlo al dilogo que lo presentar...algo sumamente complejo!. Seleccione con dos click el dilogo principal y luego dirjase a sus propiedades. Como propiedades del dilogo, adems de su ID y CAPTION, ver una lista desplegable que dice MENU, pues all seleccione IDR_MENU1 que es el men que acabamos de crear. Listo el pollo cocinada la gallina, tenemos nuestra aplicacin con men y todo!. Al fin de cuentas no es para tanto VC++, no?. Puede probar el programa presionando Ctrl + F5, ver que el dilogo tiene ahora el men que creamos, pero hay un problema, todava no hace nada. Habamos quedado que de acuerdo al tem seleccionado del men Principal se iran incrementando campos de una estructura pblica del dilogo. Bueno, lo primero que vamos a hacer es crear la estructura: Seleccione la solapa ClassView y luego presione el botn derecho del mouse sobre la clase CMenuDlg. Elija el tem Go to definition. Se editar en la ventana de la derecha el archivo de cabecera menuDlg.H que contiene la definicin de la clase CMenuDlg, deberemos modificar esta definicin, ya que vamos a agregar un dato miembro a la clase, entonces en la seccin public escriba: // CMenuDlg dialog

class CMenuDlg : public CDialog { // Construction public: struct numeros (1) //Se define la estructura numeros { int m_uno, m_dos, m_tres; (2) }n; (3) //variable n de tipo numeros CMenuDlg(CWnd* pParent = NULL); // standard constructor ......... Se ha abreviado el cdigo especificando slo las lneas agregadas. En (1) se declara una estructura con el nombre de numeros. Que contiene tres campos enteros, muno, m_dos y m_tres (2). Y en tres de declara la variable n de tipo numeros. Ahora le daremos valores iniciales a los campos y el lugar indicado para esto es el constructor de la clase. Pulse dos veces sobre el elemento CMenuDlg::CMenuDlg(CWnd* pParent =NULL) de la clase CMenuDlg. Agregue las ltimas tres lneas: // CMenuDlg dialog CMenuDlg::CMenuDlg(CWnd* pParent /*=NULL*/) : CDialog(CMenuDlg::IDD, pParent) { //{{AFX_DATA_INIT(CMenuDlg) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); n.m_uno =0; (1) n.m_dos =0; (2) n.m_tres =0; (3) } (1), (2) y (3) son las lneas agregadas, las que inicializan en 0 los campos de la estructura. Finalmente hay que escribir el cdigo por cada evento del men, o sea por pulsar cada elemento: Presione Ctrl +W para acceder a ClassWizard. Pulse la solapa Message Maps. Seleccione IDC_MUNO en la lista Object Ids. Seleccione COMMAND en la lista Messages. Pulse Add Function y luego Edit Code. Se editar el mensaje OnMuno() y escriba: void CMenuDlg::OnMuno() { // TODO: Add your command handler code here n.m_uno = n.m_uno +1; (1) }

Simplemente se incrementa en 1 el campo m_uno de la estructura. Realice los mismos pasos anteriores para crear las funciones OnMdos(), OnMtres(), OnMsumar(), OnMsalir y OnMacerca(). Cuyos cdigos son: void CMenuDlg::OnMdos() { // TODO: Add your command handler code here n.m_dos = n.m_dos +2; } void CMenuDlg::OnMtres() { // TODO: Add your command handler code here n.m_tres = n.m_tres +3; } void CMenuDlg::OnMsumar() { // TODO: Add your command handler code here CString strSuma; strSuma.Format ("%s%i", strSuma, n.m_uno + n.m_dos +n.m_tres ); MessageBox(strSuma); n.m_uno =0; n.m_dos =0; n.m_tres =0; } void CMenuDlg::OnMsalir() { // TODO: Add your command handler code here EndDialog(IDOK); } void CMenuDlg::OnMacerca() { // TODO: Add your command handler code here CAboutDlg dlgAcerca; dlgAcerca.DoModal (); } Resumiendo: Para crear un dilogo con un men, primero hay que disear el men insertando un nuevo recurso (men en este caso) en la solapa Resource View de la ventana WorkSpace. Luego en las propiedades del dilogo se especifica que men utilizar. Se deben crear todos los mensajes de los tems del men. Una variable miembro pblica de una clase se puede crear de dos formas: haciendo click con el derecho del mouse sobre la clase y selecconando Add Member Variable o editando la definicin de la clase y escribiendo directamente en ella.

ICONOS Y MAPAS DE BITS: En Visual C++, adems disear y escribir el cdigo de una aplicacin, puede crear los icono y archivos BMP (mapas de bits), que la aplicacin utilice. Tanto los icono como los mapas de bits son recursos. Crearemos una aplicacin que manipular dos controles Picture, que permitirn visualizar los iconos y archivos BMP que crearemos. Cree una nueva aplicacin con el nombre "imgenes" Agregue dos controles Picture con las siguientes propiedades: ID = IDC_ICONOS, TYPE = ICON, deje vaca la lista IMAGE y tilde en la solapa Style la propiedad NOTIFY, (esta propiedad permite que el control acepte la accin de pulsar el botn del mouse). ID= IDC_BMP, TYPE = Bitmap, IMAGE = [vaco], NOTIFY=tildado. Agregue dos cuadros de texto esttico cerca de los controles Picture, para identificarlos: CAPTION= Icono y CAPTION = Imagen BMP. El dilogo debera quedar ms o menos as:

Bien, ahora hay que disear los iconos e imgenes. Vaya a la solapa ResourceView de la ventana WorkSpace y sobre la carpeta ICON pulse con el botn derecho del mouse. Seleccione el tem Insert Icon. Esto da a lugar a un icono en blanco. Dibuje, usando la barra de herramientas de dibujos, un rectngulo rojo. Deje el ID por defecto. Cree otro icono y dibuje un circulo rojo: Deje el ID por defecto. Pulse con el botn derecho del mouse sobre la carpeta "imgenes resource" y seleccione Insert. De la ventana de opciones de recursos seleccione Bitmap. Esto da a lugar a un bitmap en blanco. Dibuje el siguiente bitmap: Deje el ID por defecto. Cree otro bitmap, como el siguiente: Deje el ID por defecto. Una vez creados los iconos y los bitmaps, regresamos al dalogo para asociarle variables a los controles picture: Presione Ctrl+W para acceder a ClassWizard. Pulse la solapa Member Variables. Seleccione en Objects ID , IDC_ICONOS y pulse Add Variable.

En Member Variable Name escriba: m_imgIcono y en Value seleccione Control. Acepte la ventana. Seleccione en Objects ID, IDC_BMP y pulse Add Member Variable. En Member Variable Name escriba: m_imgBmp y en Value seleccione Control. Acepte todas las ventanas. De esta forma se crearon dos variables de tipo CStatic relacionadas a los controles de imagen. El programa consistir en pulsar el icono o imagen que se est visualizando y cambiar al otro icono o imagen. Tendremos que crear dos variables globales para poder saber que icono y/o que imagen se est visualizando al momento de hacer click sobre el control. Pulse la solapa ClassView de la ventana WorkSpace. Haga click con el botn derecho del mouse sobre la clase del dilogo y seleccione Add Member Variable. Escriba en Variable Type: int y en Variable Name: MostrarIcono. Cree otra variable de la misma forma de tipo int y con nombre MostrarBmp. Pulse dos veces sobre el constructor de la clase para escribir en l los valores iniciales de la variables recin creadas. Escriba al final: MostrarIcono = 1; MostrarBmp = 1; Una tercer variable global necesitaremos cuando carguemos los BMP. Entonces, aprovechamos y la creamos ahora. Igual que en los pasos anteriores agregue una nueva variable esta vez de tipo CBitmap y nombre m_bmp. (esta variable no hay que inicializar). Bueno, ahora hay que conectar por cdigo los iconos e imgenes con sus respectivos controles. Al iniciar la aplicacin se cargar por defecto en uno de los controles Picture el icono IDI_ICON1 (el rectngulo) y en el otro la imagen IDB_BITMAP1 (el icono de RIVER). Escriba entonces en el mensaje OnInitDialog(), las siguientes lneas numeradas: BOOL CImagenesDlg::OnInitDialog() { CDialog::OnInitDialog(); HICON hIcono; (1) //Tomo un puntero a la clase CWinApp CWinApp* pApp = AfxGetApp(); (2) // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here //Cargo la imagen por defecto del control imagen VERIFY(m_bmp.LoadBitmap (IDB_BITMAP1)); (3)

m_imgBmp.SetBitmap (m_bmp); (4) //Cargo el icono por defecto del otro control imagen hIcono= pApp->LoadIcon (IDI_ICON1); (5) m_imgIcono.SetIcon (hIcono); (6) return TRUE; // return TRUE unless you set the focus to a control } En (1) se declara una variable de tipo HICON, esto es un manejador para el objeto icono, que ser necesario luego. En (2) se obtiene un puntero a la aplicacin, portadora de la funcin para cargar un icono. Primero cargamos el BitMap de River (IDB_BITMAP1) por medio de la funcin LoadBitmap() (3) del objeto CBitmap, se lo asignamos al manejador. Luego en (4) con la funcin SetBitmap() del control Picture le asignamos la imagen recin cargada. En (5) y en (6) se cargar el icono por defecto y se lo asigna al control. Listo, si ejecuta la aplicacin ver que ahora los controles Picture vienen con una imagen por defecto. Falta escribir el cdigo que permita al pulsar el botn izquierdo del mouse sobre las imgenes cambiar los iconos y BitMaps. Entonces pulse dos veces sobre la primer imagen, (IDC_ICONOS), se crear el mensaje OnIconos(), all escriba: void CImagenesDlg::OnIconos() { // TODO: Add your control notification handler code here HICON hIcono; CWinApp* pApp = AfxGetApp(); if (MostrarIcono==1) { hIcono= pApp->LoadIcon (IDI_ICON2); m_imgIcono.SetIcon (hIcono); MostrarIcono=2; } else { hIcono= pApp->LoadIcon (IDI_ICON1); m_imgIcono.SetIcon (hIcono); MostrarIcono=1; } } Bsicamente se realiza el mismo procedimiento que en InitDialog() con la salvedad que aqu se verifica si la variable global MostrarIcono tiene un 1, porque de ser as se cargar el otro icono y se establece esa variable a 2. En caso de ser 2 se carga la primera y se establece MostrarIcono a 1. Ahora pulse dos veces sobre el otro control Picture para generar el mensaje OnBmp(), all escriba: void CImagenesDlg::OnBmp()

{ // TODO: Add your control notification handler code here m_bmp.DeleteObject (); //Elimino una referencia anterior if (MostrarBmp==1) { VERIFY(m_bmp.LoadBitmap (IDB_BITMAP2)); m_imgBmp.SetBitmap (m_bmp); MostrarBmp=2; } else { VERIFY(m_bmp.LoadBitmap (IDB_BITMAP1)); m_imgBmp.SetBitmap (m_bmp); MostrarBmp=1; } } Tambin aqu es el mismo procedimiento que en InitDialog(), pero con dos salvedades. Una, es la de verificar que BMP se est mostrando, esto se hace en la sentencia IF y la otra salvedad es que lo primero que se hace es eliminar la referencia anterior de la variable CBitmap m_bmp. La misma variable tiene el mtodo DeleteObject() que se encarga de esto. Resumiendo: En ResourceView se pueden insertar nuevos recursos de iconos y mapas de bits. All tambin se le asigna un ID, necesario para usar el recurso por cdigo. A un control Picture se le puede asignar en tiempo de diseo un icono o imagen por defecto, en la ventana Propiedades. Para cargar un icono hay que usar la funcin LoadIcon() de la clase CWinApp, para esto hay que definir un puntero a esta clase y una variable de tipo HICON. Para cargar un mapa de bits hay que, primero declarar una variable pblica de tipo CBitmap con la cual se carga un mapa de bits con la funcin LoadBitmap(). A veces es necesario eliminar referencias anteriores con DeleteObject(). GRFICOS EN VISUAL C++: Existe en Windows un concepto denominado Contexto de dispositivo. Un contexto de dispositivo proporciona el medio sobre el cual se dibujan todos los puntos, lneas, figuras, fuentes y todo lo que se ve. La palabra dispositivo se refiere al lugar donde se dibujar, o sea, la pantalla, impresora, plotter o cualquier otro dispositivo de cualquier fabricante, sin necesidad de tener un excesivo conocimiento del modelo del mismo. Algo positivo que ha hecho Microsoft para la industria del software ha sido estandarizar el soporte para todos los dispositivos en el sistema Windows. TIPOS DE CONTEXTO DE DISPOSITIVOS: Existe un contexto de dispositivo estndar global y adems hay otros para ocasiones especiales y tareas concretas. Todos son objetos GDI (interfaz de dispositivo grfico). El GDI son funciones grficas de la librera GDI32.DLL y proporcionan el enlace con los controladores de dispositivos y el propio hardware. La MFC (Microsoft Foundation Classes) proporciona clases que simplifican la interaccin con los GDI. La clase del contexto de dispositivo global es la CDC.

Esta clase proporciona funciones de dibujo, de correspondencia entre coordenadas y otras para implementar la visualizacin de grficos. Todas las dems clases de contexto de dispositivo, ms especializadas, se basan en sta y la extienden. La clase CDC: Para ejemplificar el uso de CDC vamos a crear una aplicacin que pinte toda la pantalla, para esto entonces, cree un proyecto MFC basado en dilogos, con el nombre graf1. Reduzca las dimensiones del dilogo un poco y al botn por defecto Cancelar cmbiele el ID por IDC_DIBUJAR y Caption= Dibujar. Tiene que quedar un dilogo con slo dos botones: Aceptar y Dibujar. Pulse dos veces sobre el botn Dibujar para crear el manejador de mensajes OnDibujar() all escriba: void CGraf1Dlg::OnDibujar() { // TODO: Add your control notification handler code here CDC* pDC; (1) CWnd* pEscritorio; (2) int x, y; pEscritorio = GetDesktopWindow(); (3) pDC= pEscritorio->GetWindowDC (); (4) for(x=0; xReleaseDC (pDC); (6) } En la primer lnea se declara una variable puntero, pDC, a CDC, por lo general siempre se declara el futuro objeto CDC como un puntero porque el retorno de la funcin que los crea es un puntero. Como se desea utilizar toda la pantalla y no slo la regin ocupada por nuestro dilogo deberemos relacionar el contexto de dispositivo con el escritorio, cosa que en Windows equivale a toda la pantalla, entonces en la lnea (2) se declara un puntero a la clase CWnd y en (3) se toma el manejador, (puntero CWnd), del escritorio por medio de la funcin global GetDesktopWindow(). Una vez que tengo el manejador, que sera la salida de mi contexto de dispositivo, creo el objeto CDC en la lnea (4) por medio de la funcin GetWindowDC() perteneciente a la clase CWnd, que en nuestro caso est apuntando a la ventana que representa el escritorio. Una vez que uno tiene referenciado el objeto CDC, en nuestro caso por medio del puntero pDC, se pueden acceder a todas las funciones GDI disponibles haciendo pDC->funcin, (note que se utiliza el operados -> y no el punto ya que la variable es un puntero). El dibujo que vamos a hacer ser recorrer todo el escritorio dibujando de un color en particular cada pxel, por eso se usan dos ciclos variar para el ancho y el alto, (mi resolucin de video es de 800 x 600, en caso de tener una resolucin diferente hay que cambiar estos valores). En la lnea (5) se usa la funcin GDI SetPixel() cuyos parmetros son los puntos x e y donde se dibujar el pxel y el otro parmetro es el color del mismo. Para el color usamos la funcin RGB() donde los parmetros representan el grado de rojo, verde y azul, entre 0 y 255. La intensidad de verde y azul la dejamos en 0 y el rojo ser

el producto de las coordenadas x e y lo que da un efecto interesante llamado tramas moir. La ltima lnea libera la referencia al objeto CDC del escritorio, esto es importante hacerlo ya que ocupa memoria. Antes de ejecutar la aplicacin, hay que hacer otra cosa importante, que es limpiar la pantalla cuando la aplicacin termine, porque sino todo el escritorio quedar dibujado de forma permanente hasta que se pulse F5 que se encarga en Windows de re-dibujar. Entonces utilizaremos el evento, (mensaje), WM_DESTROY que se ejecuta cuando la aplicacin termina, para re-dibujar el escritorio y dejar todo como antes. Hay que agregar el mensaje WM_DESTROY, para esto pulse CTRL.+ W para acceder a ClassWizard. All en Objects Ids seleccione CGraf1Dlg y en messages WM_DESTROY, luego pulse Add Function y luego Edit Code, se editar el mensaje OnDestroy(), all escriba: void CGraf1Dlg::OnDestroy() { CDialog::OnDestroy(); // TODO: Add your message handler code here // re-dibujar todo lo anterior CWnd* pEscritorio; pEscritorio=GetDesktopWindow(); pEscritorio->RedrawWindow(NULL,NULL, RDW_ERASE+RDW_INVALIDATE+RDW_ALLCHILDREN+RDW_ERASENO W); } Nuevamente se toma el manejador del escritorio con un puntero CWnd y luego se usa la funcin RedrawWindow(). Los dos primer parmetros hacen referencia a la regin a re-dibujar, como en nuestro caso pretendemos redibujar todo el escritorio estos parmetros sern NULL y el tercer parmetro son combinaciones de constantes que indican como se re-dibujar, RDW_ERASE va junto con RDW_INVALIDATE donde est ltima si el segundo parmetro es NULL, (nuestro caso), indica que se re-dibujar todo incluyendo las aplicaciones descendientes tal como lo especifica RDW_ALLCHILDREN. Pruebe escribiendo este cdigo en el mensaje WM_MOUSEMOVE y obtendr un prototipo de salva pantalla. Ahora si ejecute la aplicacin y pulse Dibujar, obtendr el siguiente dibujo en toda la pantalla:

Para cerrar la aplicacin tendr que adivinar donde est el botn Aceptar detrs del dibujo. En caso de querer usar como objeto de salida el dilogo lea el siguiente ejemplo de este captulo. Resumiendo:

Las funciones grficas de Windows forman parte de una librera llamada GDI, a la cual se puede acceder desde Visual C++ haciendo uso de la clase CDC que es la clase principal para el uso de contextos de dispositivos (pantalla, impresora, casco de realidad virtual, etc). Para usar toda la pantalla como lugar donde dibujar, (la pantalla en Windows equivale al escritorio), se debe declarar un puntero a la clase CDC y otro a la clase CWnd. Entonces con la funcin GetDesktopWindow() uno puede almacenar el manejador del escritorio en el puntero CWnd antes declarado y luego tomarlo como dispositivo de contexto con la funcin GetWindowDC() del puntero CWnd declarado. Despues puede hacer uso de muchas funciones de grficos: SetPixel(), LineTo(), Ellipse(), etc. Luego se debe liberar la memoria utilizada para el contexto usando la funcin ReleaseDC() del objeto CWnd pasandole como parmetro el puntero CDC usado. No hay que olvidarse de re-dibujar el escritorio por ejemplo en el evento WN_DESTROY para as tener todo lindo como antes. Dibujar en un dilogo cliente: En el ejemplo anterior dibujamos sobre el escritorio utilizando la clase principal para definir un contexto de dispositivo, CDC. Usando esta misma clase tambin se puede establecer como contexto de dispositivo un dilogo, al cual se le llama cliente. En este caso no hara falta obtener ningn manejador de ventana por medio de una funcin, pues el puntero a un dilogo activo ya se encuentra referenciado con la palabra clave this, por lo que slo hara falta definir el puntero CDC y obtenerlo desde el cliente: CDC* pDC; pDC=this->GetWindowDC(); De esta forma puede uno, luego, usar la funcin SetPixel() o cualquier otra del puntero pDC y el efecto se producir en toda la ventana del dilogo, incluyendo la barra donde est el ttulo de la ventana y los botones de cerrar, maximizar y minimizar, (para que el dibujo se realice slo dentro del dilogo; en lugar de GetWindowDC() habra que utilizar GetDC()). Bien, VC++ nos da otra posibilidad ms de hacer lo mismo usando una clase descendiente de CDC que se llama CClientDC y se dedica pura y exclusivamente a definir como DC el dilogo cliente (sin incluir la barra de ttulo). Para probar esto con un ejemplo cree un proyecto MFC basado en dilogo con el nombre graf2 y realice los cambios en el dilogo de manera tal que quede exactamente igual que el del ejemplo anterior, o sea con un botn Aceptar y el otro Dibujar, con ID=IDC_DIBUJAR. Pulse dos veces el botn dibujar para generar el evento OnDibujar(), all escriba: void CGraf2Dlg::OnDibujar() { // TODO: Add your control notification handler code here //Se construye un DC cliente a partir de la ventana de dilogo CClientDC dlgDC(this); (1)

int x,y; for (x=0; xtop; ybottom; y++) paintDC.SetPixel(x,y,RGB(x*y,0,0)); } Bien, en primero lugar se declara una variable objeto CPaintDC para pintar sobre el dilogo (1). En (2) se declara una variable de tipo RECT, (tambin existe una clase CRect), para almacenar los puntos de la regin a redibujar. RECT es una estructura predefinida en VC cuyos campos son: typedef struct tagRECT { LONG left; LONG top; LONG right; LONG bottom;} RECT; left indica la coordenada x del punto superior izquierdo. top indica la coordenada y del punto superior izquierdo. right indica la coordenada x del punto inferior izquierdo. bottom indica la coordenada y del punto inferior izquierdo. Lo siguiente a hacer es cargar la estructura pRect con los puntos de la regin, (rectngulo), a redibujar; esto se hace en la lnea (3) ya que en el mismo objeto CPaintDC creado existe una variable miembro pblica llamada m_ps de tipo PAINTSTRUCT que contiene informacin que le sirve a la aplicacin para pintar un rea cliente de un dilogo, (ventana), asociado con un objeto CPaintDC. Una estructura PAINTSTRUCT contiene los siguientes campos: typedef struct tagPAINTSTRUCT { HDC hdc; BOOL fErase; RECT rcPaint; BOOL fRestore; BOOL fIncUpdate; BYTE rgbReserved[16];} PAINTSTRUCT

hdc identifica el dispositivo de contexto usado para pintar. fErase especifica si el fondo de la ventana necesita redibujarse. Si es distinto de 0, es porque la aplicacin debera redibujar el fondo. rcPaint especifica las esquinas superior izquierda e inferior derecha del rectngulo que necesita ser redibujado. Este es el campo que usamos en la lnea (3). fRestore campo reservado. Windows lo usa internamente. fIncUpdate campo reservado. Windows lo usa internamente. rgbReserved[16] bloque de memoria reservado que usa Windows internamente. Lo que resta es recorrer el rectngulo pRect por medio de unos bucles y pintarlo nuevamente con la funcin SetPixel(). Esto es todo lo que respecta a la funcin Dibujar, ahora hay que llamarla desde el evento OnDibujar() y desde OnPaint(). Entonces pulse dos veces sobre el botn Dibujar, aparece un aviso indicando que est por crear un manejador de mensajes llamado OnDibujar(), acepte el aviso y escriba: void CGraf3Dlg::OnDibujar() { // TODO: Add your control notification handler code here Dibujar(); //Aqu est la llamada a nuestra funcin. } Para escribir la llamada en OnPaint(), pulse dos veces en dicha funcin en el ClassView. void CGraf3Dlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting //Resumiendo un poco el cdigo .... // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { Dibujar(); //Esta es la llamada. CDialog::OnPaint(); } } Ejecute la aplicacin y obtendr ms o menos la siguiente salida:

Pruebe superponer ciertas zonas de la ventana con otra, (ejemplo la

calculadora), y ver que cuanto ms pequea sea la zona que cubre y descubre ms rpido ser repintada. Resumiendo: La clase CPaintDC es una clase derivada de CDC como contexto de dispositivo para pintar y permite capturar los mensajes BEGIN_PAINT y END_PAINT (de WM_PAINT). Los datos correspondientes a los vrtices de la regin a redibujar se pasan a una variable de tipo RECT igualandol al campo rcPaint de la variable miembro m_ps de tipo PAINTSTRUCT perteneciente a la clase CPaintDC. (pRect=&paintDC.m_ps.rcPaint;) El evento OnPaint(), (mensaje WM_PAINT), es el lugar encargado de manipular todo el cdigo referente a redibujar, repintar una ventana. LPICES Y PINCELES (las clases CPen y CBrush): El GDI de Windows proporciona adems de cientos de funciones grficas para dibujar lneas, crculos, elipses etc., herramientas con las cuales dibujarl