+ All Categories
Home > Documents > PRÁCTICA 2. VISUAL C++ (VC) - IIT | Instituto de … · 2010-09-28 · de desarrollo que se usa en...

PRÁCTICA 2. VISUAL C++ (VC) - IIT | Instituto de … · 2010-09-28 · de desarrollo que se usa en...

Date post: 27-Sep-2018
Category:
Upload: hoangdien
View: 212 times
Download: 0 times
Share this document with a friend
19
PRÁCTICA 2. VISUAL C++ (VC) 1 Introducción y objetivos En la presente práctica se pretender ofrecer la segunda toma de contacto con el entorno de desarrollo que se usa en la asignatura para programar en el lenguaje C/C++. En la primera toma de contacto el alumno aprendió a programar DLLs para implementar comportamientos de robots para el simulador. En esta segunda toma de contacto se pretende que el alumno sea capaz de hacer pequeñas aplicaciones basadas en un entorno gráfico que le servirán para representar gráficamente el estado del robot y su "pensamiento". Evidentemente no se pretenden hacer entornos gráficos sofisticados, ni siquiera perderse en todos los vericuetos que eso supone. La parte gráfica, únicamente debe ser una herramienta que pone en contacto al robot con el alumno de forma visual. De forma no casual, este entorno se utiliza de la misma forma que el Embedded Visual C++ que se usa para programar los dispositivos móviles usados en la asignatura "Sistemas robóticos móviles: sistemas mecatrónicos básicos", continuación de ésta. Los objetivos de esta práctica son: Saber realizar y depurar proyectos sencillos en el Visual C++. Estos proyectos están orientados representar el estado del robot y a practicar programación en C++, aunque en esta práctica no se haga. Estas aplicaciones constan de un interfaz gráfico y de un reloj que manda ejecutar ciertos procedimientos de forma periódica. Por ello, los proyectos se basarán en una aplicación con una ventana (llamada también Dialogo) que servirá de interfaz con el usuario y de un timer que se usará para ejecutar algoritmos de forma periódica. Entender cómo se hacen interfaces gráficos sencillos, de forma que la práctica sea una guía de referencia para futuras prácticas. En esta segunda toma de contacto el procedimiento a seguir es el siguiente: En primer lugar se aprenderá a crear un proyecto basado en una ventana de Dialogo. Es importantísimo realizar todos los pasos exactamente tal y como se indica en la práctica, sino es muy fácil perderse en la misma. Este procedimiento debe seguirse siempre que se quiera crear un nuevo proyecto gráfico en sucesivas prácticas. Posteriormente se irán adquiriendo conocimientos para poder personalizar el interfaz de la aplicación, hasta hacerlo interactivo con el usuario. Un aspecto importante es cómo se usan los timers, para poder mandar ejecutar procesos de forma periódica. Se volverá a hacer hincapié en los conceptos necesarios para poder depurar (buscar errores) un programa. 2 Entregables La práctica se da por concluida con los entregables que serán evaluados. Los entregables consisten en: Realizar demostraciones al profesor de la sección 10 y 11.
Transcript

PRÁCTICA 2. VISUAL C++ (VC)

1 Introducción y objetivos En la presente práctica se pretender ofrecer la segunda toma de contacto con el entorno

de desarrollo que se usa en la asignatura para programar en el lenguaje C/C++. En la

primera toma de contacto el alumno aprendió a programar DLLs para implementar

comportamientos de robots para el simulador. En esta segunda toma de contacto se

pretende que el alumno sea capaz de hacer pequeñas aplicaciones basadas en un entorno

gráfico que le servirán para representar gráficamente el estado del robot y su

"pensamiento". Evidentemente no se pretenden hacer entornos gráficos sofisticados, ni

siquiera perderse en todos los vericuetos que eso supone. La parte gráfica, únicamente

debe ser una herramienta que pone en contacto al robot con el alumno de forma visual.

De forma no casual, este entorno se utiliza de la misma forma que el Embedded Visual

C++ que se usa para programar los dispositivos móviles usados en la asignatura

"Sistemas robóticos móviles: sistemas mecatrónicos básicos", continuación de ésta.

Los objetivos de esta práctica son:

• Saber realizar y depurar proyectos sencillos en el Visual C++. Estos proyectos están

orientados representar el estado del robot y a practicar programación en C++,

aunque en esta práctica no se haga. Estas aplicaciones constan de un interfaz gráfico

y de un reloj que manda ejecutar ciertos procedimientos de forma periódica. Por

ello, los proyectos se basarán en una aplicación con una ventana (llamada también

Dialogo) que servirá de interfaz con el usuario y de un timer que se usará para

ejecutar algoritmos de forma periódica.

• Entender cómo se hacen interfaces gráficos sencillos, de forma que la práctica sea

una guía de referencia para futuras prácticas.

En esta segunda toma de contacto el procedimiento a seguir es el siguiente:

• En primer lugar se aprenderá a crear un proyecto basado en una ventana de Dialogo.

Es importantísimo realizar todos los pasos exactamente tal y como se indica

en la práctica, sino es muy fácil perderse en la misma. Este procedimiento debe

seguirse siempre que se quiera crear un nuevo proyecto gráfico en sucesivas

prácticas.

• Posteriormente se irán adquiriendo conocimientos para poder personalizar el

interfaz de la aplicación, hasta hacerlo interactivo con el usuario.

• Un aspecto importante es cómo se usan los timers, para poder mandar ejecutar

procesos de forma periódica.

• Se volverá a hacer hincapié en los conceptos necesarios para poder depurar (buscar

errores) un programa.

2 Entregables La práctica se da por concluida con los entregables que serán evaluados. Los

entregables consisten en:

• Realizar demostraciones al profesor de la sección 10 y 11.

• Dejar ver al profesor una lista de lo que has aprendido en la práctica que habrás

anotado en tu cuadernillo.

• Dejar ver al profesor una lista de los detalles que estimas importantes para otras

prácticas y que habrás anotado en tu cuadernillo. Por ejemplo, detalles de C++,

de entorno de desarrollo, …

3 Creación de un nuevo proyecto El objetivo es crear un proyecto basado en una ventana de Dialogo. Es

importantísimo realizar todos los pasos exactamente tal y como se indica en la

práctica, sino es muy fácil perderse en la misma. Este procedimiento debe seguirse

siempre que se quiera crear un nuevo proyecto en sucesivas prácticas.

1. Abrir Microsoft Visual Studio C++

1. Ir al menú Archivo->Nuevo->Proyecto.

2. Seleccionar en el cuadro de dialogo “Nuevo Proyecto” las siguientes opciones:

• Asegurarse de elegir ¡¡¡¡Aplicación MFC!!! • Project name: Dlg

• Location (siguiendo el ejemplo de la primera práctica): d:\robots\. Este

directorio tiene que existir; por ello, es necesario crearlo con el Explorador

de Windows.

• Resto de opciones por defecto como en figura

3. Pulsar Aceptar.

4. En el nuevo cuadro de dialogo seleccionar Basada en cuadros de diálogo, el

resto de opciones como se indica a continuación

5. Comprobar en Clases generadas que se van a generar las clases CDlgApp y

CDlgDlg.

6. Pulsar Finalizar.

4 Descripción de la ventana de proyecto En la siguiente figura se muestran los nombres de las diferentes ventanas que hay en el

proyecto.

En la ventana de Workspace hay tres pestañas:

1. Explorador de soluciones: es el lugar donde se encuentran nuestros ficheros de código C/C++.

2. Vista de Clases: no la vamos a usar.

3. Administrador de propiedades: no la vamos a usar

4. Vista de Recursos: es donde vamos a tocar para poder cambiar el interfaz gráfico

de nuestra aplicación.

Una vez creado el proyecto VC crea varios ficheros, ver Ventana workspace-

>Explorador de soluciones->Archivos de código fuente (antes de seguir leer la

sección 13):

• Dlg.cpp/.h: fichero donde se encuentra el código de la aplicación principal; es decir,

el equivalente a main. Este fichero no es necesario tocarlo en ninguna aplicación que

hagamos en el laboratorio.

• Dlg.rc: En este fichero se encuentran almacenados los recursos que usa la

aplicación. Estos recursos son las ventanas, botones, etc. Este fichero no se puede

tocar directamente. De hecho si se hace doble clic sobre él se muestra un entorno

gráfico donde se puede modificar el aspecto de la ventana de Dialogo del proyecto.

• DlgDlg.cpp/.h: Es el código de la ventana de Dialogo creada. Este fichero es el

punto de partida que se tiene que tocar para poder desarrollar el programa que va a ir

en el robot.

• Stdafx.cpp/.h: Es un fichero que siempre existe en todos los proyectos, y que no

hace falta entender pero que es necesario para que todo funcione.

• Targetever.h: Es un fichero que indica la plataforma destino. No vamos a necesitar

modificarlo.

Ventana de

workspace Ventana de código

Ventana de mensajes

Barra de selección

Para ejecutar el programa pulsar F5 o Build->Start Debug->Go.

NOTA IMPORTANTE: el #include <stdafx.h> siempre tiene que existir en todo

fichero *.cpp y debe ser el primero de todos. ¿por qué? sólo Microsoft lo sabe.

5 Cambiar el aspecto del Dialogo 1) Seleccionar el fichero de recursos donde se muestra la ventana de Dialogo.

2) Hacer doble clic sobre “Ventana Workspace->Vista de Recursos->Dlg->Dlg.rc-

>Dialog->IDD_DLG_DIALOG”

3) Borramos la etiqueta que hay por defecto en el Dialogo. Se selecciona y se pulsa

el botón suprimir.

4) Si no se puede ver la ventana de controles, activarla en “Ver->Cuadro de

herramientas”. Añadimos una etiqueta al Dialogo. Elegir “Static Text” de la

ventana de controles que aparece en el punto 2 y arrastrar hasta el lugar que

queramos de la ventana de Dialogo.

5) Escribir “hola mundo”. Hacer clic con el botón derecho del ratón y seleccionar

propiedades. En la pestaña “Apariencia” escribir “hola mundo” en “Caption”.

6) Ejecutar el programa de nuevo.

6 Dialogo interactivo En esta sección es necesario seguir los pasos tal y como se explica. No se pueden añadir

más componentes de los indicados, ni borrarlos. En tal caso, en posteriores apartados se

pueden tener problemas. Para controlar más volver a leer la sección 13.

1) Seleccionar el fichero de recursos donde se muestra la ventana de Dialogo.

2) Hacer doble clic sobre “Ventana Workspace->Vista de Recursos->Dlg->Dlg.rc-

>Dialog->IDD_DLG_DIALOG”

3) Añadimos un cuadro de texto. Elegir “Edit Control” de la ventana de controles

que aparece en el punto 2 y arrastrar hasta el lugar que queramos de la ventana.

4) Añadimos otro cuadro de texto. Elegir “Edit Box” de la ventana de controles

que aparece en el punto 2 y arrastrar hasta el lugar que queramos de la ventana.

5) Añadimos un botón. Elegir “Button” de la ventana de controles que aparece en

el punto 2 y arrastrar hasta el lugar que queramos de la ventana.

6) Escribir “Run” en el botón. Hacer clic con el botón derecho del ratón y

seleccionar propiedades. En la pestaña “Apariencia” escribir “Run” en

“Caption”.

7) Hacer doble click sobre el botón. Aceptar el nombre por defecto. Se creará una

función que se ejecutará cuando se pulse el botón

void CDlgDlg::OnBnClickedButton1()

8) Escribir el siguiente código en la función que se acaba de crear. Pulsar F1 sobre

la función que queráis ayuda. Este código copia el texto del cuadro de texto

primero sobre el segundo. Las funciones vienen explicadas en 13.2.1.

char uText[10]; // variable donde se almacena el t exto unsigned int nelem; // número de caracteres del t exto nelem = GetDlgItemText(IDC_EDIT1,(LPTSTR) uText ,10); // coge el texto SetDlgItemText(IDC_EDIT2, (LPTSTR) uText); // lo copia al otro cuadro de texto SetDlgItemInt(IDC_EDIT1, 12,false); // ejemplo de como se escribe un número UpdateData(false); // actualiza los datos en pant alla

9) Ejecutar el programa

Es necesario hacer notar que el cuadro de texto que se añadió primero se llama por

defecto IDC_EDIT1 y que el segundo cuadro de texto se llama IDC_EDIT2. Si se

quieren modificar esos nombres hacer clic con el botón derecho del ratón sobre el

cuadro de texto y seleccionar “Propiedades->Varios->ID”. Evidentemente si los

nombres cambian, entonces el código que hace referencia a ellos es necesario también

cambiarlos.

7 A golpe de reloj El objetivo es crear un contador que se incremente cada 10 segundos. De esta manera se

aprende a manejar un timer, esencial para programar un robot.

1) Ir a la ventana de recursos

2) Hacer clic en botón derecho del ratón (sobre la ventana de dialogo a la que se

accede mediante "Ventana Workspace->Vista de Recursos->Dlg->Dlg.rc-

>Dialog->IDD_DLG_DIALOG"), botón derecho propiedades y en la ventana de

propiedades, con el botón Mensajes pulsado, ordenar de A..Z y para el evento

WM_TIMER seleccionar <agregar> OnTimer.

3) En DlgDlg.cpp se ha añadido una nueva función, que hay que completar como

sigue (¡¡¡Ojo la función ya existe, no hay que copiarla, sólo rellenarla!)

void CDlgDlg::OnTimer(UINT_PTR nIDEvent) { // La funcion se ejecuta cada vez que el timer ter mina la cuenta, esto después de que pasan los 10 segundos KillTimer(1); // borrado de la cuenta del timer, s e pone a 0 SetDlgItemInt(IDC_EDIT1, i++,false); // aumenta e n 1 el contador, el numero del Edit Box UpdateData(false); // actualiza los datos en pant alla SetTimer(1,10000, NULL); // inicializa el timer; c ada 10 segundos aumenta la cuenta CDialog::OnTimer(nIDEvent); }

4) Añadir la siguiente variable global en DlgDlg.cpp int i = 0;

5) En la función “BOOL CDlgDlg::OnInitDialog()” añadir justo antes del “return”:

SetTimer(1, 10000,NULL); // inicializa el timer par a que cuente 10 segundos

6) Ejecutar el programa. ¿qué hace?

7) ¿Qué crees que hace KillTimer y SetTimer ?

8) ¿Qué crees que pasa si no se hace el paso 5?

8 Debug de programas En esta sección se va a tratar de cómo depurar programas. Un Punto de Interrupción

(Breakpoint) es un lugar del código donde se le dice a VC que pause la ejecución del

programa cuando llegue al mismo. Sirve para ver el estado de las variables en ese

momento o para seguir ejecutando el programa de una línea en una línea.

1) Añadir un Punto de Interrupción en la siguiente línea de la función OnTimer.

Encima de la línea clic botón derecho del ratón y ejecutar “Punto de

interrupción->Insertar punto de interrupción”

SetDlgItemInt(IDC_EDIT1, i++,false); //aumenta e n 1 el contador

2) Ejecutar el programa

3) Cuando el programa se para en el Punto de Interrupción, ver el valor de la

variable i en la ventana de watch. “Depurar->Ventanas->Automático”

4) A partir de ese punto ejecutar línea a línea el código bien pulsando la tecla F10,

o bien “Depurar->Paso a paso por procedimientos”. Observar como cambia el

valor de la variable i en la ventana de watch. El comando “Depurar->Paso a paso

por instrucciones” sirve para que si la ejecución de la línea contiene una función,

poder introducirse en la misma.

5) Investigar el comando de Botón derecho->Ejecutar hasta el cursor”.

9 Gráficos El objetivo de esta sección es aprender a hacer gráficos muy simples con VC. Para

entrar en calor, sustituye el código de la función OnTimer por el siguiente:

void CDlgDlg::OnTimer(UINT nIDEvent) { // Es lo primero que se tiene que hacer. // Desactiva el timer para que no pueda volver a // lanzar el evento OnTimer mientras se atiende KillTimer(1); // coje el objeto gráfico de la ventana para dibuj ar en él CDC *pDC=GetDC( ); // define el color rojo unsigned long rojo = RGB(255,0,0); unsigned long verde = RGB(0,255,0); unsigned long color; // elije la pluma que desea usar en el dibujo CPen pen; // pluma de trazo continuo de anchura 3 y de color rojo pen.CreatePen(PS_SOLID, 3, rojo); pDC->SelectObject(&pen); if (i%2) color = verde; else color = rojo; // elije la brocha con la que se pinta el relleno CBrush brush(color); pDC->SelectObject(&brush);

i++; // dibuja una elipse pDC->Ellipse(50,70,70,90); UpdateData(false); // actualiza los datos en pant alla // reactiva el timer para que vuelva a saltar en // el siguiente ciclo SetTimer(1,5000, NULL); CDialog::OnTimer(nIDEvent); }

¿Qué hace?. Jugad con distintas brochas y plumas.

En el link

http://www.iit.upcomillas.es/~alvaro/teaching/Clases/Programacion/Practicas/P2clases

Dlg.zip

se encuentra una clase llamada CDibuja que se encarga de dibujar figuras geométricas

por pantalla. Para más información sobre cómo dibujar, remitirse a la ayuda de

Microsoft http://msdn.microsoft.com/library/. Para entender la clase CDibuja leer la

sección 14.

10 Ejercicio Hacer un programa usando la clase CDibuja que muestre un círculo en pantalla que en

función de un número introducido por un cuadro de texto se coloree de color rojo si el

número es mayor que 0 y de color verde si el número es menor o igual que 0.

1) Hacerlo con un botón de validación

2) Hacerlo muestreando cada 5 segundos

Para coger un número de un cuadro de texto (Edit Box):

int num; // número donde se va a guardar el result ado num = GetDlgItemInt(IDC_EDIT1, NULL, true); // Cog e un número con signo de IDC_EDIT1

Para usar la clase CDibuja es necesario seguir los siguientes pasos:

1. Instalar la clase CDibuja en el proyecto.

a. Descomprimir el ZIP en el directorio del proyecto.

b. Añadir los ficheros nuevos (Dibuja.cpp, CPunto.cpp, CPunto.h y

Dibuja.h), en la ventana de proyecto, en la pestaña Explorador de

soluciones->Archivos de codigo fuente, pulsar botón derecho y elegir

“Agregar elemento existente”. Seleccionar los cpp. Repetir el proceso

para los .h en Explorador de soluciones->Archivos de encabezado.

2. En el fichero DlgDlg.h añadir la línea dentro de la clase CDlgDlg que define

un puntero a la clase CDibuja denominado m_p_dibuja .

protected : CDibuja* m_p_dibuja; HICON m_hIcon;

3. En el fichero DlgDlg.cpp añadir una línea en la función

CDlgDlg::OnInitDialog que crea la memoria para alojar el objeto al que

apunta el puntero m_p_dibuja . m_p_dibuja = new CDibuja(GetDC());

4. En el fichero DlgDlg.cpp añadir una línea en el destructor de la clase CDlgDlg

que se encarga de eliminar de la memoria el objeto al que apunta m_p_dibuja.

CDlgDlg::~CDlgDlg(){ if (m_p_dibuja != NULL) delete m_p_dibuja; }

5. Declarar el destructor anterior en el fichero “DlgDlg.h”, justo debajo del

constructor.

6. Poner #include “Dibuja.h” en el fichero “DlgDlg.h”.

7. Utilizar el puntero m_p_dibuja dentro de la función CDlgDlg::OnTimer

como se describe en la sección 14.

Hacer demostración al profesor.

11 Posición del robot Se quiere dibujar en una aplicación de supervisión, el trayecto que sigue el robot en el

simulador en tiempo real. Para ello, se deberá partir del programa realizado en la

práctica anterior que escribía en un fichero la posición del robot. Este programa se

encuentra resuelto en la siguiente dirección:

http://www.iit.upcomillas.es/~alvaro/teaching/Clases/Programacion/Practicas/P2clases

Dllsencilla.zip

Simultáneamente ese fichero es leído por la aplicación de supervisión (sólo la posición

calculada a partir de los encoders), la cual dibujará el trayecto seguido por el robot en la

pantalla. Se recomienda usar el mismo sistema de referencia que usa el simulador.

Hacer demostración al profesor.

Pistas:

• Para leer un fichero: se usa el operador >>, tal y como se muestra a

continuación.

• Para repintar la pantalla se puede llamar a la función RedrawWindow() desde

cualquier función de CDlgDlg.

#include <fstream>

...float x,y,z;std::ifstream fin("C:\\posicion.txt");if (!fin.fail()) { // si lo ha podido abrir

// lee x y z hasta que termine el ficherowhile (!fin.eof())

fin >> x >> y >> z;}fin.close();

...

12 Ejercicio opcional para aquellos que les sobre t iempo Dibujar el robot con un aspecto similar al del simulador, moviéndose por la ventana de

la aplicación realizada, según se mueve por el simulador.

13 Introducción a la programación orientada a objet os y a interfaces de Windows

13.1 Clases Una clase es una estructura de datos que contiene variables (también llamadas

propiedades o estados), y funciones (también llamados métodos o comportamientos).

Como estructura de datos que es, cuando se define se crea un nuevo tipo de datos, cuyo

nombre se indica al lado de la palabra clave class . La forma de declarar una clase en

C++ es (las declaraciones en C++ siempre van en los ficheros *.h):

Tanto las variables como las funciones pueden ser públicas o privadas. Aquellas que

son públicas son accesibles desde fuera de la clase; es decir, cualquier función que no se

encuentre dentro de la clase puede acceder a parte pública de la clase. Aquellas que son

privadas sólo son accesibles desde las funciones que pertenecen a la clase.

Cuando se crea una variable del tipo de la clase, se ha creado un objeto; es decir, una

variable es a un tipo de dato como un objeto es a una clase. La creación de un objeto de

una clase se denomina instanciar la clase; es decir, un objeto de una clase es una

instancia de la misma.

El acceso a las variables y funciones públicas de un objeto se hace poniendo el nombre

del objeto seguido de un punto y el nombre de la variable o función. Por ejemplo:

int n = robot.get_numero_sensores(); // guarda en n el número de sensores

En toda clase existen unas funciones miembro muy especiales que son:

• El constructor: es una función que tiene el mismo nombre que el de la clase y no

se puede llamar directamente, sino que se llama en el momento de la creación de

un objeto de la clase.

• El destructor: es una función que tiene el mismo nombre que la clase, pero

precedido de ~. No se puede llamar directamente, sino que se llama de forma

automática en el momento en el que un objeto desaparece.

void main(void) { // llama al constructor de robot ya que se crea CRobot robot(4); // crea un robot con 4 sensores. Instancia un robot int n = robot.get_numero_senosres(); // guarda en n el número de sensores // error!!!! no se puede acceder a la parte priva da de una clase desde fuera n = robot.m_numero_sensores; }; // se llama al destructor de robot ya que se sal e de la función main

class CRobot { public: // Accesible desde fuera de la clase int get_numero_sensores(); // método CRobot(int numero_sensores); // constructor ~CRobot(); // destructor private: // Inaccesible desde fuera de la clase CSensor *vector_sensores; // sensores que tiene e l robot int m_numero_sensores; // propiedad };

Se ha visto que la declaración de una clase se hace en los ficheros *.h. Pues bien, la

definición de una clase se hace en los ficheros *.cpp:

Cada función va precedida del nombre de la clase seguido de ::, para que se sepa que las

funciones son de la clase.

13.2 Programación de interfaces en Windows Las ventanas en Windows son clases específicas que ha desarrollado Microsoft para que

puedan ser manejadas de forma sencilla. Una ventana en Windows está formada por

controles. Los controles son componentes que se sitúan en una ventana y sirven para

interaccionar con el usuario.

Aunque hay muchas clases para gestionar ventanas (CWnd, CWindow, CDialog), en

esta sección sólo se va a explicar CDialog. CDialog es la ventana más básica de

Windows y permite situar controles encima de ella. Cuando se quiere desarrollar una

aplicación basada en una ventana de diálogo, se crea una clase con el nombre de la

aplicación que es una ventana de diálogo. En esta clase se pueden ir incorporando

diferentes tipos de controles, los cuales formarán parte de las propiedades o variables

que tiene la clase. Además se pueden añadir nuevas variables o funciones de forma que

finalmente la clase creada es una ventana de dialogo con un aspecto y características

especiales que son las que el programador ha elegido.

Si por ejemplo se crea una aplicación que se llama “Ejemplos”, la clase de diálogo se

llamará “CEjemplosDlg”. A continuación se muestra un ejemplo de clase ventana de

dialogo que tiene un botón que se llama “BotonRun”.

// constructor de robot CRobot::CRobot(int numero_sensores) { m_numero_sensores = numero_sensores; vector_sensores = new CSensor[m_numero_sensores]; }; // destructor de robot CRobot::~CRobot(){ delete[] vector_sensores; } // función miembro int CRobot::get_numero_sensores(){ return(m_numero_sensores); }

Además las ventanas tienen un conjunto de eventos asociados; es decir, acciones que

pueden suceder en un momento determinado. Desde le punto de vista de la

programación un evento no es más que una función, que se ejecuta cuando se produce el

evento. El evento más importante de una ventana es:

• OnTimer : las ventanas tienen asociado un timer, que es un contador de tiempo.

Gracias a este contador de tiempo se puede hacer que se ejecuten de forma

periódica un conjunto de instrucciones.

13.2.1 Controles Un control es una clase que sirve de interfaz con el usuario y se coloca en una ventana

de diálogo. Los controles dentro de un dialogo pueden tener eventos asociados, que no

son más que funciones que se ejecutan en el momento en que se produce dicho evento.

Dichas funciones tienen un nombre con el prefijo On para indicar que es un evento; por

ejemplo OnChange.

Hay muchos tipos de controles pero los más importantes son:

• CButton : es la clase que permite crear un botón. El evento por defecto es el

OnClic.

• CEdit : es la clase que le permite al usuario introducir datos en un programa. El

evento por defecto asociado es el OnChange.

Windows provee un conjunto de controles para el manejo de controles y son:

• unsigned int GetDlgItemInt(int id_del_control, int* conversion_ok, int

con_signo): función que obtiene el número entero que se ha escrito en el

control. Se usa fundamentalmente con controles CEdit . Se pasa como parámetro

el identificador del control, una variable booleana que indica si el número lo

interpreta con signo o no. Devuelve el número entero que contiene el control y

en el parámetro segundo devuelve si la transformación del texto del control al

número ha sido correcta. Hay que tener en cuenta que todos los interfaces con el

usuario son en modo texto y por lo tanto para poder obtener un número hay que

hacer una conversión de texto a número que puede ser o no correcta.

• int GetDlgItemText( int id_del_control, LPTSTR text o, int

cantidad_de_texto_maxima): función que obtiene el texto que hay escrito en el

control. Se usa fundamentalmente con controles CEdit . Se pasa como parámetro

class CEjemplosDlg : public CDialog { public: CEjemplosDlg(CWnd* pParent = NULL); // constructor // funciones públicas de la clase int get_contador(); // para devolver el valor del contador private: // variables y funciones privadas globales a esta clase

// que quiera usar el programador int contador; // para llevar cuentas void control(); // para controlar un proceso // funciones eventos que se van a asociar a contro les //{{AFX_MSG(CEjemplosDlg)

virtual BOOL OnInitDialog(); // evento de visualiz ación de la ventana

afx_msg void OnBotonRun(); // evento de clic de un botón

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

};

el identificador del control, una cadena de caracteres (que tiene que tener

reservada memoria) donde se va a escribir el texto y el número máximo de

caracteres que puede coger del control (este parámetro debe ser menor que el

número de caracteres que se han reservado para la cadena de caracteres del

parámetro segundo).

• void SetDlgItemText(int id_del_control, LPCTSTR tex to_a_escribir): función que escribe en texto en un control. Se usa fundamentalmente con

controles CEdit . Se pasa como parámetro el identificador del control, y la cadena

de texto que se tiene que escribir en el control.

• void SetDlgItemInt(int id_del_control, unsigned int valor, int

con_signo): escribe un número entero en un control. Se usa fundamentalmente

con controles CEdit . Se pasa como parámetro el identificador del control, el

valor que se tiene que escribir y si se quiere que se escriba con o sin signo. Es

necesario recordar que como todos los interfaces con el usuario son en modo

texto, esta función hace una conversión de número a texto y por lo tanto necesita

información de si debe interpretar el número con o sin signo.

A continuación se muestra un ejemplo de cómo se usan estas funciones:

13.2.2 Gestión de controles desde el entorno de des arrollo Desde la ventana de recursos del entorno de desarrollo, haciendo clic con el botón

derecho sobre un control y accediendo al apartado de propiedades se puede modificar el

identificador (ID) de dicho control, o lo que es lo mismo se puede cambiar su nombre

(no deja de ser el nombre de una “variable” un tanto especial), que por defecto tiene uno

genérico relacionado con el tipo de control que es. Además se pueden modificar sus

propiedades (caption, visible, tipo de letra,…). No se debe confundir el nombre que

tiene un control a la hora de programar (ID), con el texto que aparece por ejemplo sobre

un botón o al lado de un check box (caption).

El nombre que se asigna al control deberá ser intuitivo, ya que a la hora de escribir el

código o de revisarlo será éste el que se tiene que tener en cuenta.

Por defecto los controles tienen asociado un evento, o lo que es lo mismo una acción del

usuario sobre los mismos. Por ejemplo en el caso de un botón el usuario puede apretar

el botón (surge el evento OnButton) y en el caso de un cuadro de texto el usuario puede

cambiar el texto que aparece en el mismo (OnChange). No confundir este último

ejemplo con el texto que aparece grabado sobre un botón.

int i = 10;

unsigned short sout[] = TEXT("hola"); // reserva 5 caracteres de memoria

unsigned char cout[] = "hola";

unsigned short in[MAX]; // reserva MAX caracteres de memoria

CString s = cout;

int ok;

SetDlgItemText(IDC_EDIT1,sout);

SetDlgItemText(IDC_EDIT3,s);

SetDlgItemInt(IDC_EDIT2,i,false);

i = GetDlgItemInt(IDC_EDIT2,&ok,false);

if (ok)

GetDlgItemText(IDC_EDIT1,in,MAX-1);

Cuando se produce dicho evento se pueden ejecutar una serie de acciones, que serán

programadas como una función que se ejecutará cada vez que se realice el evento sobre

el control correspondiente. Se pueden añadir diferentes eventos a cada control, pero por

ahora sólo se va a describir el evento principal o por defecto de cada uno de ellos.

El evento por defecto “aparecerá” si se hace doble clic sobre el control. Entonces se crea

una función en el fichero de código asociado al control donde se pueden programar las

acciones a ejecutar cuando surja el evento. El nombre de esta función puede ser

modificado, pero se aconseja mantener el nombre de la misma para poder relacionarlo

fácilmente con el control correspondiente. Además informa del tipo de evento y el

control asociado al mismo.

A continuación se van a comentar las modificaciones que hay que hacer sobre un

programa si se deciden eliminar o modificar controles:

• Si se decide modificar el nombre de un control se debe tener en cuenta que no solo

hay que hacerlo en la ventana de recursos sino también en todas las zonas de código

que lo referencien; exactamente en el fichero *.cpp en la zona de

BEGIN_MESSAGE_MAP, ver ejemplo a continuación.

• Si se quiere borrar un control, no hará falta eliminar nada en el código, ya que se

mantiene tal cual y esto no generará ningún tipo de error. Siempre y cuando no

añadamos ningún control del mismo tipo, en cuyo caso hay que tomar la solución

del siguiente punto.

• Por último si decidimos borrar un control y crear uno nuevo del mismo tipo que

tenga asociado el mismo evento debemos ponerle el mismo nombre para simplificar.

14 Explicación de clase CDibuja A continuación se muestra el código de una clase que se encarga de dibujar formas

geométricas por pantalla:

// fichero *.h class CEjemplosDlg : public CDialog { public: CEjemplosDlg(CWnd* pParent = NULL); // constructor // funciones públicas de la clase int get_contador(); // para devolver el valor del contador private: // variables y funciones privadas globales a esta clase // que quiera usar el programador int contador; // para llevar cuentas void control(); // para controlar un proceso // funciones eventos que se van a asociar a contro les //{{AFX_MSG(CEjemplosDlg) virtual BOOL OnInitDialog(); // evento de visualiz ación de la ventana afx_msg void OnBotonRun(); // evento de clic de un botón //}}AFX_MSG DECLARE_MESSAGE_MAP() }; // fichero *.cpp // lugar para los includes #include "stdafx.h" // constructor CEjemplosDlg::CEjemplosDlg(CWnd* pParent /*=NULL*/) : CDialog(CEjemplosDlg::IDD, pParent){ .... } // asociación del evento de un control a una funció n BEGIN_MESSAGE_MAP(CEjemplosDlg, CDialog) //{{AFX_MSG_MAP(CEjemplosDlg) // asocia el evento de clic del botón IDC_BOTON_RU N a la función OnBotonRun ON_BN_CLICKED(IDC_BOTON_RUN, OnBotonRun) //}}AFX_MSG_MAP END_MESSAGE_MAP() // función que atiende el evento de arranque de la ventana de diálogo BOOL CEjemplosDlg::OnInitDialog() { ... } // función que atiende el evento de clic del botón IDC_BOTON_RUN void CEjemplosDlg::OnBotonRun() { ... }

class CDibuja { private : CDC* m_pDC; /** Zona donde se puede dibujar*/ public : CDibuja(CDC* dc); ~CDibuja(); /** Dibuja una polilinea * vPuntos vector<CPunto>: vector de puntos de lo s que consta el polilinea * ulColor unsigned long: color del reborde de la polilinea */ void PoliLinea( const std::vector<CPunto>& vPuntos, unsigned long ulColor); /** Dibuja un poligono * vPuntos vector<CPunto>: vector de puntos de lo s que consta el poligono * ulColor unsigned long: color del reborde del p olígono * ulRelleno unsigned long: color del relleno del polígnono */ void Poligono( const std::vector<CPunto>& vPuntos, unsigned long ulColor, unsigned long ulRelleno); /** Dibuja una elipse * p1 CPunto: punto superior izdo del cuadrado en el que está inscrita la elipse * p2 CPunto: punto inferior decho del cuadrado e n el que está inscrita la elipse * ulColor unsigned long: color del reborde de la elipse * ulRelleno unsigned long: color del relleno de la elipse */ void Elipse( const CPunto& p1, const CPunto& p2, unsigned long ulColor, unsigned long ulRelleno); };

La clase tiene tres funciones públicas que se apoyan en la clase CPunto . Aunque se

verá en detalle en clase, esta clase guarda las coordendas x e y de un punto en el

espacio. Cuando se necesita un vector de puntos se usa la clase vector. Esta clase

pertenece a la STL (Estandard Template Library) que no se va a ver en este curso;

simplemente se quiere que se sepa usar aunque no se entienda ya que requiere

conocimientos más avanzados de C++ como son los Templates. A continuación se

explica como se maneja la función PoliLinea :

#include ”CPunto.h”#include <vector>

...unsigned long rojo = RGB(255,0,0);// define un vector de CPunto de tres elementosstd::vector<CPunto> v(3); // define tres puntosCPunto p3(200,200), p4(300,300), p5(200,300);// rellena el vector con los puntosv[0] = p3; v[1] = p4; v[2] = p5;// llama a la funciónm_p_dibuja->PoliLinea(v,rojo);

...

Es importante hacer notar que el acceso a las funciones de una clase cuando se

utiliza un puntero que apunta al objeto, se hace con “->” en vez de “.”.

Las los parámetros de las funciones en C++ pueden variar respecto a la notación en C.

Por ejemplo:

• const std::vector<CPunto>& vPuntos: es un parámetros que se pasa por referencia,

ya que tiene &, cosa que no se puede hacer en C. Acordarse de que en C los

parámetros siempre se pasan por copia. Esto significa que en la función se pasa

el propio vector de puntos y se podría modificar, todo ello sin usar punteros

como se puede ver dentro de la función. Al pasar un parámetro por referencia, se

consigue ganar mucho tiempo ya que el programa no tiene que hacer una copia

del mismo para ser utilizado en una función. Hacer copias implica reserva y

destrucción de memoria, que son procesos muy costosos en tiempo. Para evitar

que un parámetro se pueda modificar dentro de la función se le pone el

calificador const . De esa manera se consiguen las ventajas del paso por copia

que garantiza que una función no modifica una variable pasada por parámetro y

por otro lado se consigue la ventaja del paso por referencia que es la eficiencia.


Recommended