Programación III - Visual C ++

by M@lonso © 2002

Referencia abreviada Developer Studio de Visual C++ y librería MFC

Visual C++ de Microsoft es un compilador de C++, perteneciente a la línea de herramientas de desarrollo con Windows. El paquete de Visual C++ contiene no solamente ese compilador, sino también todas las bibliotecas, ejemplos y documentación que se necesita para crear aplicaciones en WindowsNT y Windows95.


La parte central del paquete de Visual C++ es Developer Studio (Estudio del Desarrollador), que es el Ambiente Integrado de Desarrollo (IDE, para los anglosajones) que se muestra en la ilustración.

Algunas de las herramientas que incorpora el Developer Studio son:

Developer Studio incluye también tres asistentes que se emplean para simplificar el desarrollo de los programas de Windows:

AppWizard (hechicero de aplicaciones) se usa para crear el esquema básico de un programa de Windows. Los tres tipos de programas que se manejan son: los de simple documento, los de múltiple documento y los basados en cuadro de diálogo.


ClassWizard (hechicero de clases) se usa para definir las clases en un programa creado con AppWizard. Se pueden añadir clases, añadir funciones a esas clases para manejar los mensajes recibidos y también se pueden manejar controles mediante la asociación de variables miembro a esos controles.

ActveX ControlWizard (hechicero de controles OLE) se usa para crear el esqueleto de un control OLE. Un control OLE es un control personalizado que soporta un conjunto definido de interfaces y se utiliza como un componente reutilizable. Sustituyen a los controles de VisualBasic, o VBX, que se usaron en las versiones de 16 bits de Windows.

Bibliotecas MFC versión 4.21

Se trata de una biblioteca de clases que hace que la programación en Windows sea más sencilla. La gran cantidad de código escrito para el programador permite concentrarse en las partes más importante del código sin tener que preocuparse de los detalles de la programación en Windows. La mayor parte de las clases quedan dentro de las siguientes categorías principales:

Diseño orientado a objetos

Uno de los objetivos principales de diseño del lenguaje C++ fue proporcionar un lenguaje que apoyara la programación orientada a objetos. Esta programación no es nueva, ya que Simula apareció a mediados de los años sesenta.

El diseño orientado a objetos comprende la clasificación de objetos y acciones del mundo real como clases que pueden crearse, manejarse y destruirse. Los datos que forman un objeto y las funciones que se realizan sobre ese objeto se combinan para formar una clase, o una descripción de ese objeto. Las clases pueden heredar funcionalidad de otros objetos y se pueden añadir nuevas que se apoyan en clases existentes.

Otra parte importante del diseño orientado a objetos es la idea de que la clase debe proporcionar una interfaz que se usa para manejar los objetos que se crean a partir de la clase. En la medida de lo posible, los detalles de la implementación deben quedar ocultos ante el usuario. Así se puede cambiar la implementación sin tener que variar la interfaz.

En el diseño estructurado tradicional, los datos manejados por un programa y las funciones que manejan los datos están separados. En ocasiones, es difícil volver a utilizar partes de un diseño elaborado con técnicas de diseño estructurado, a menos que el nuevo diseño sea muy similar al antiguo.

Un diseño orientado a objeto puede utilizarse en programas futuros, en forma similar a los componentes de hardware.

Otra de las ventajas del diseño orientado a objeto es la herencia. Las clases identificadas como padre o base contienen datos y funciones que se incluyen en todas las clases hijas o derivadas. Si una operación puede hacerse utilizando una clase base, todas las subclases deben ser capaces de realizar la misma tarea. Esto se conoce como el Principio de Substitución de Liskov.

Cuando los mismos métodos se declaran en las clases padres y en las hijas, pero el compilador debería elegir la función adecuada para cada ocasión, entonces a estas funciones se las declara como virtuales. En el caso de que no tenga sentido esa función en la clase base, se dejará sin implementar y esta clase pasará a ser abstracta. Es decir, sólo se usará para dar origen a otras clases.

Clases base en MFC

Las dos clases base de las MFC son CObject y CWnd, y son las que proporcionan una funcionalidad especial a las derivadas de ellas. CObject es la clase que está en la raíz de la jerarquía de clases MFC. Cualquier clase que representa una ventana o control se deriva de CWnd. Estas dos clases utilizan funciones virtuales, que permiten al programa accesar funciones de propósito general a través de un apuntador base. Esto permite que se use fácilmente cualquier objeto que se deriva de CObject o CWnd cuando se interactúa con el marco de trabajo de MFC.

Clase base CObject

La clase CObject proporciona cuatro tipos de servicios:

Se puede controlar la funcionalidad proporcionada por CObject usando macros de declaración de la clase derivada y en los archivos de definición o encabezamientos. Existen cuatro niveles diferentes de soporte que proporciona CObject a sus clases derivadas:

Clase base CWnd

Se deriva a su vez de CObject, y añade gran funcionalidad que se comparte con todas las ventanas en un programa MFC. Esto también incluye los cuadros de diálogo y controles que simplemente son versiones especializadas de ventanas. Por ejemplo, para poner el título a cualquier ventana se puede usar la función CWnd::SetWindowText.

Plantillas

Se puede pensar en una clase o plantilla de función como un formato de pedido con algunos espacios en blanco que pueden llenarse cuando se hace el pedido. En lugar de crear una clase de lista para arreglos de apuntadores y otra clase de lista para CString, puede usarse una sola plantilla como una clase de lista para ambos tipos. La reutilización como puede verse es absoluta.

La STL, o biblioteca de plantillas estándar, es un conjunto de colecciones, algoritmos y funciones que se han añadido recientemente al borrador estándar del C++. Las clases STL surgieron de la investigación que realizó Hewlett-Packard sobre programación genérica. Las funciones y objetos en la STL se clasifican por lo que hacen y no por la forma como se implementan.

La biblioteca estándar incluye cinco tipos de componentes:

Colecciones en MFC

Las colecciones se implementan como plantillas. Se usan para crear objetos capaces de almacenar otros objetos. Existen tres tipos básicos de colecciones que se proporcionan como parte de la biblioteca de clases MFC:

Los tres tipos están disponibles en versiones de plantilla y de no plantilla. Las versiones que no son de plantilla especifican un tipo de elemento determinado que debe guardarse en la colección. Por ejemplo, la clase CObArray maneja una colección de apuntadores para objetos derivados de CObject y trata la colección como si fuera un arreglo. Por lo general, usar versiones de plantilla es más fácil y moderno que utilizar las de no plantilla.

Mensajes en MFC

Los programas que se escriben para Windows de Microsoft reaccionan a eventos enviados a la ventana principal del programa. Estos eventos se envían a la ventana en forma de mensajes. Cada mensaje tiene un objetivo específico: volver a trazar una ventana, redimensionarla, cerrarla, etc. Para muchos mensajes, la aplicación sólo pasa el mensaje a una función especial llamada "procedimiento de ventana por omisión", que maneja el mensaje si no se requiere un tipo de procesamiento especial.

Un programa Windows también puede enviar mensajes a otras ventanas. Como cada control usado en un programa Windows es también una ventana, en ocasiones los mensajes también se usan para la comunicación con los controles.

Existen dos tipos de mensajes que se manejan en un programa Windows:

Ejemplos de mensajes que se envían desde el sistema operativo incluyen los que se emplean para decirle al programa que debe iniciar o terminar, o para decirle a una ventana que se está redimensionando o moviendo. Los mensajes que se envían a los controles pueden usarse para cambiar el tipo de letra utilizado por una ventana o su título. Los mensajes que se reciben desde un control incluyen las notificaciones de que se ha oprimido un botón o que se ha tecleado un carácter en un control de edición.

Hay dos razones por las que se usan los mensajes intensamente en Windows:

El hecho de que los mensajes sean independientes del lenguaje, permite que Windows crezca a través de los años. Actualmente se pueden escribir programas Windows utilizando diversos lenguajes, como VisualBasic, Delphi, Visual C++ o PowerBuilder.

Menús

Un menú es una lista de mensajes de comando que pueden seleccionarse y enviarse a una ventana. Ante el usuario, un elemento de menú es una cadena que indica una tarea que puede realizar la aplicación. Por lo general, los menús están asociados a una ventana, aunque muchas aplicaciones soportan menús desplegables flotantes que pueden aparecer en cualquier lugar del escritorio.

Se pueden crear menús dinámicamente o como recursos estáticos que se añaden al programa. La biblioteca de clases MFC proporciona una clase CMenu que simplifica el manejo de menús.

AppWizard genera un recurso de menú para los programas que crea. Este recurso puede editarse para añadir elementos de menú adicionales para la aplicación o puede crear nuevos recursos de menú para ésta.

Cuadros de diálogo

Los cuadros de diálogo, en ocasiones nombrados como diálogos, se usan para presentar información y recopilar datos del usuario. Los cuadros de diálogo se proporcionan en todas las formas y tamaños, que van desde cuadros de mensajes sencillos que despliegan una sola línea de texto, hasta grandes cuadros de diálogo que contienen controles complejos.

Normalmente, los cuadros de diálogo se usan para recopilar información y para proporcionar retroalimentación al programa. El tipo de cuadro de diálogo que se usa más es el diálogo modal, que generalmente contienen varios controles para interactuar con el programa. Este tipo de diálogos deben de ser cerrados antes de continuar con el programa.

Los cuadros de diálogo también se usan para la comunicación de una sola vía con el usuario, como las "pantallas de presentación" que se utilizan para la información de los derechos reservados y del arranque cuando se lanza un programa. La pantalla de apertura que despliega el Developer Studio del Visual C++ y la del Word de Microsoft son dos ejemplos de cuadro de diálogo que se usan para comunicación de una sola vía. Algunas veces se usan cuadros de diálogo para notificar al usuario el avance de una operación.

Otro tipo de cuadro de diálogo común es el de mensaje. La mayoría de los cuadros de mensaje se usan para proporcionar mensajes cortos al usuario y algunas veces para tener retroalimentación sencilla.

Un proyecto basado en cuadro de diálogo usa un cuadro de diálogo como ventana principal de un programa sencillo. Por ejemplo, muchas de las utilidades que se encuentran en el panel de control de Windows95 se basan en cuadro de diálogo.

Un programa basado en cuadro de diálogo tiene un menú que se accesa por medio del menú de sistema, en la esquina superior izquierda de la barra de título del cuadro de diálogo. Si el programa requiere menús complejos, no debe basarse en un cuadro de diálogo.

Las rutinas DDV y DDX son funciones de ayuda que auxilian para manejar los datos de los cuadros de diálogo. Las rutinas DDV, o validación de datos de diálogo, se usan para validar datos. Las rutinas DDX, o intercambio de datos de diálogo, se usan para el intercambio desde y hacia los controles en un cuadro de diálogo.

Aunque se pueden emplear las rutinas DDV y DDX en los cuadros de diálogo directamente, ClassWizard añade código con el clic de un botón. Normalmente se añaden con ClassWizard.

Controles de Botón

Un botón es un tipo especial de ventana que contiene una etiqueta de texto o mapa de bits y generalmente se encuentra en un cuadro de diálogo, barra de herramienta u otra ventana que contiene controles. Windows proporciona cinco tipos diferentes de botones:

En general, los botones se usan para indicar una selección del usuario. Los botones se usan en los programas de Windows por ser útiles y fáciles de operar por los usuarios. Éstos esperan que los botones estén presentes en muchos casos, en especial cuando existen los cuadros de diálogo en un programa.

Los botones se crean normalmente como parte de un cuadro de diálogo. Después de añadir un botón a un cuadro de diálogo se puede usar ClassWizard para añadir funciones manejadoras de eventos producidos cuando se oprime, marca o selecciona el botón. ClassWizard también se usa para crear objetos CButton asociados con controles de botón individuales.

Controles de Edición

Un control de edición es una ventana que se usa para guardar texto en formato libre dado por el usuario. Los controles de edición pueden ser de una sola línea, lo que significa que únicamente puede darse una sola línea de texto, o pueden ser de varias líneas, conocidos algunas veces como controles MLE.

Se usan cuando se necesita recopilar texto. Por ejemplo, cuando se necesita dar un nombre o dirección en un cuadro de diálogo, se usa un control de edición para recopilar esa información. Los controles de edición de varias líneas frecuentemente usan barras de desplazamiento que permiten introducir más texto del que puede desplegarse.

Debido a las capacidades de edición integradas del control de edición, es posible crear un editor de texto sencillo usando el control de edición de varias líneas. Aunque un MLE no puede reemplazar un editor de texto real, proporciona una forma sencilla para recopilar varias líneas de texto del usuario.

Una diferencia entre los controles de edición y los controles de botón de acción es que un control de botón se usa generalmente para generar eventos. Un control de edición también puede generar eventos, pero usa con más frecuencia para almacenar datos.

En ocasiones se usa la clase MFC CEdit para interactuar con los controles de edición. Puede usarse ClassWizard para asociar un control de edición con un objeto CEdit específico. Un control de edición también se puede asociar con un objeto CString, lo que puede significar el uso de los controles de edición en los cuadros de diálogo.

Cuadros de lista y cuadros combinados

Los cuadros de lista se usan para contener una lista de elementos disponibles para su selección. El usuario puede seleccionar elementos mediante el teclado o usando el ratón y haciendo clic en un elemento individual. Pueden ser de selección única o de selección múltiple. Si alguno de los elementos no puede desplegarse, se despliega una barra de desplazamiento para ayudar al usuario a navegar por la vista.

Los cuadros de lista son el control más sencillo para desplegar una cantidad arbitraria de elementos ante el usuario. Se usan a menudo para desplegar listas de información que se extraen de bases de datos o reportes.

La clase MFC CListBox puede usarse para manejar e interactuar con los controles de cuadro de lista.

Un control de cuadro combinado es un solo control que combina un control de edición y un cuadro de lista. Un cuadro combinado permite al usuario proporcionar datos, ya sea tecleando texto como en un control de edición o seleccionando un elemento entre varias alternativas como en un cuadro de lista.

Existen tres tipos de cuadros combinados:

Se usa ClassWizard para agregar funciones manejadoras de mensaje y asociar el control con un objeto CComboBox.

Mapas de Bits y Listas de Imágenes

Un mapa de bits es un objeto gráfico que puede usarse para representar una imagen en los programas escritos para Windows. Utilizando un mapa de bits, una imagen puede guardarse, cargarse y desplegarse fácilmente. Otros tipos de objetos gráficos son:

La forma más fácil para crear un mapa de bits es usar un editor de imágenes como el integrado en Developer Studio. Una vez creado el mapa de bits, se puede manejar con la clase MFC CBitmap. Se puede cargar en el programa usando la función LoadBitmap, y después se puede desplegar en cualquier dispositivo de salida usando un contexto de dispositivo.

Una lista de imágenes es similar a un array de mapas de bits, al igual que un rollo de película es un array de imágenes. Cada mapa de bits guardado en una lista de imágenes está asociado con un índice que se puede usar para recuperar una imagen particular.

Las listas de imágenes las usan controles como las vistas de árbol, vistas de lista y barras de herramientas.

Se usa la clase MFC CImageList para crear, desplegar y manejar las listas de imágenes.

Arquitectura Documento/Vista

El documento/vista separa al programa en cuatro clases principales:

Cada una de las clases tiene un papel específico a desempeñar en una aplicación MFC documento/vista. La clase documento es responsable de los datos del programa. La clase de vista maneja la interacción entre documento y usuario. La clase de marco contiene la vista y otros elementos de interfaz de usuario, como el menú y las barras de herramientas. La clase de aplicación es responsable de la inicialización real del programa y maneja algunas interacciones de propósito general con Windows.

Existen dos tipos básicos de programas documento/vista:

La primera razón para usar documento/vista es proporcionar una gran cantidad de código de aplicación gratis. Siempre se debe tratar de escribir la menor cantidad posible de código fuente y, eso significa usar clases MFC y permitir que AppWizard y ClassWizard hagan la mayor parte del trabajo en lugar del usuario. Una gran cantidad de código escrito en forma de clases MFC y código AppWizard usa la arquitectura documento/vista.

Para las clases que se usan en un programa Windows, la arquitectura documento/vista define varias categorías principales. El documento/vista proporciona un marco de trabajo flexible que puede emplearse para crear casi cualquier tipo de programa en Windows. Una de las mayores ventajas de la arquitectura documento/vista es que divide el trabajo de un programa en Windows en categorías bien definidas. La mayor parte de las clases quedan en una de las cuatro categorías de clases principales:

Cambiar la interfaz de usuario para un programa documento/vista afecta solamente a las clases de vista, y no se necesita hacer cambios en las clases de documento, marco o aplicación.

Tanto las aplicaciones SDI como las MDI usan un objeto llamado plantilla de documento para crear una relación entre una vista, un documento y una clase marco, así como un identificador empleado por el menú, icono y otros recursos del programa. La base común de estas plantillas es CDocTemplate.

Contextos de dispositivo

Toda la salida de un programa escrito para Windows debe hacerse utilizando un contexto de dispositivo. Consiste en una estructura que guarda la información necesaria cuando un programa escrito para Windows debe desplegar salida en un dispositivo. El contexto de dispositivo guarda información acerca de la superficie de trazo y sus capacidades. Antes de usar cualquier función de salida de la GDI se debe crear un contexto de dispositivo.

Puede seleccionarse un objeto GDI en un contexto de dispositivo para proporcionar capacidades de trazo.

Debido a la forma como el contexto de dispositivo de un programa escrito para Windows, del hardware del dispositivo real, en ocasiones se dice que la salida se "escribe a un contexto de dispositivo". Esta independencia del hardware facilita el envío de salida a una impresora que tiene una apariencia muy similar a la salida en pantalla.

Existen cuatro tipos de contexto de dispositivo:

La razón primordial de los contextos de dispositivo es que simplemente no hay otra manera de ejecutar una salida, sin éstos, en un programa Windows.

Las cuatro clases de contexto de dispositivo son: CDC, CPaintDC y CClientDC, CWindowDC.

Serialización

La serialización es la forma como las clases de CDocument guardan y recuperan datos de un fichero. La propiedad de un objeto que debe guardarse y cargarse se llama persistencia, que también se define como la capacidad de un objeto para recordar su estado entre ejecuciones.

El uso de la serialización para almacenar objetos es mucho más flexible que la escritura de funciones especializadas que guardan datos en un formato fijo. Los objetos persistentes son capaces de guardarse a sí mismos, en lugar de apoyarse en una función externa para leerlos y escribirlos en disco.

Un objeto serializado puede componerse de muchos objetos más pequeños que también se serializan.

Hay dos clases MFC que se usan para serializar objetos:


Regresar
M@lonso (c) 2002