Técnicas de Programación - granabot.es 3.2.2.pdf · La VCL es un marco de trabajo visual y...

102
1 Tema 3.2.2.- Componentes en C++ Builder Técnicas de Programación Introducción Los compiladores C++Builder nos ofrecen definidos una serie de componentes en la paleta de componentes. Los componentes se agrupan en esta paleta en una serie de pestañas o páginas según la funcionalidad de los mismos. Existen tres formas posibles de insertar cualquier componente en un formulario, que son: Hacemos clic sobre el componentes y posteriormente en el formulario. Hacemos un doble click sobre el componente. Hacemos un click sobre el componente y, manteniendo pulsado el botón izquierdo del ratón, arrastramos sobre el formulario hasta dar el tamaño deseado al componente. Mediante el inspector de objetos accedemos a las propiedades y eventos asociados a los componentes. Estos componentes son elementos genéricos con una funcionalidad muy concreta, cuya finalidad es la reutilización. Cada uno de ellos está destinado a realizar una tarea típica en una aplicación. Los componentes se organizan en la denominada VCL (Visual Component Library) que es una jerarquía de clases escritas en Object Pascal y que se asocia al IDE de C++Buider. Un componente de la VCL es una clase que caracteriza a un control de Windows agregando propiedades, métodos y gestores de eventos a cada control. En este tema vamos a analizar las propiedades, métodos y eventos de los componentes más importante y usuales. Tema 3.2.2.- Componentes en C++ Builder 3.2.- Programación C++ con Builder C++

Transcript of Técnicas de Programación - granabot.es 3.2.2.pdf · La VCL es un marco de trabajo visual y...

1Tema 3.2.2.- Componentes en C++ Builder

Técnicas de Programación

IntroducciónLos compiladores C++Builder nos ofrecen definidos una serie de componentes en la paleta de componentes. Los componentes se agrupan en esta paleta en una serie de pestañas o páginas según la funcionalidad de los mismos. Existen tres formas posibles de insertar cualquier componente en un formulario, que son:• Hacemos clic sobre el componentes y posteriormente en el formulario.• Hacemos un doble click sobre el componente.• Hacemos un click sobre el componente y, manteniendo pulsado el botón izquierdo del ratón,

arrastramos sobre el formulario hasta dar el tamaño deseado al componente.Mediante el inspector de objetos accedemos a las propiedades y eventos asociados a los componentes. Estos componentes son elementos genéricos con una funcionalidad muy concreta, cuya finalidad es la reutilización. Cada uno de ellos está destinado a realizar una tarea típica en una aplicación. Los componentes se organizan en la denominada VCL (Visual Component Library) que es una jerarquía de clases escritas en Object Pascal y que se asocia al IDE de C++Buider.Un componente de la VCL es una clase que caracteriza a un control de Windows agregando propiedades, métodos y gestores de eventos a cada control. En este tema vamos a analizar las propiedades, métodos y eventos de los componentes más importante y usuales.

Tema 3.2.2.- Componentes en C++ Builder

3.2.- Programación C++ con Builder C++

2Tema 3.2.2.- Componentes en C++ Builder

La VCL (Visual Components Library) o biblioteca de componentes visualesEn Windows, no son las aplicaciones quienes manejan los recursos del sistema como pueden ser la memoria, los ficheros, las ventanas y hasta los controles gráficos. Es el sistema operativo quién realiza todas estas tareas. Y la aplicación se limita a realizar peticiones de lo que necesita. Estas peticiones se realizan mediante lo que se denomina la API de Windows.Por todo esto los entornos de programación visuales han desarrollado diversos Marcos de Trabajo. Un marco de trabajo es una fase intermedia que se coloca por encima de la API para aportar mayor sencillez a las aplicaciones. Normalmente estos marcos de trabajo son orientados a objetos y se implementan como bibliotecas del lenguaje base, por ello también se suelen denominar bibliotecas de clases. La VCL es un marco de trabajo visual y orientado a objetos.

Aplicación

VCL

S.O. Windows

Tan importantes son los marcos de trabajo, que dominar un entorno de programación visual, suele traducirse en conocer el lenguaje base del entorno, y su marco de trabajo.Los marcos de trabajo se pueden clasificar en dos categorías:1. Los marcos de trabajo C++ (OWL y MFC)2. La VCL.OWL (Object Windows Library o Biblioteca de Objetos para Windows) fue un marco de trabajo desarrollado por Borland e incorporado a los compiladores Borland C++ (versiones 3 y sucesivas) y supuso un importante hito en la programación para Windows por su potencia y facilidad de uso.MFC (Microsoft Foundation Class o Biblioteca Fundamental de Clases de Microsoft) y lo incorporó a los compiladores Microsoft Visual C++ (actualmente incluso en Borland C++ 6). MFC es una biblioteca de clases menos abstracta que el OWL y más cercana a la API. También resulta más sencillo que OWL para los programadores que conocen la API.Aunque MFC se usa más que OWL la arquitectura de OWL es, técnicamente, mejor que MFC.

3Tema 3.2.2.- Componentes en C++ Builder

La VCL (Visual Components Library) o biblioteca de componentes visualesEn 1995, Borland lanzó al mercado Delphi, que supuso la revolución en la programación para Windows e inició el desarrollo rápido y sencillo de aplicaciones visuales (RAD), empleando componentes (objetos que pueden ubicarse en formularios y manipulados por medio de propiedades, métodos y eventos). Delphi se basa en el lenguaje Object Pascal (una ampliación de Pascal que incorpora programación orientada a objetos) y permitía la creación de programas ejecutables independientes que no requerían intérprete, por lo que se ejecutaban mucho más rápido.Lo más relevante desde el punto de vista técnico es que Borland creó la VCL (Visual Class Library o Biblioteca de Componentes Visuales) que es un marco de trabajo para crear aplicaciones Windows diseñada en torno al concepto de componente (propiedades, métodos y eventos). La VCL desarrollada para Delphi es la misma que se emplea como núcleo de C++ Builder, de hecho, está escrita en Object Pascal. TObject

TPersistent

TComponent

Ttimer, Ttable, ...

TControl

TGraphicControl

TpaintBox ...

TWinControl

Tbutton, Tpanel, ...

Componentes visibles

Componentesno visibles

La VCL hace un uso extensivo del concepto de herencia. El objetivo final de la VCL es crear clases que representan a componentes, aunque algunas clases no hagan referencia a componentes concretos: realizan tareas de gestión interna y se emplean como clases bases para derivar mediante herencia otras clases. En la figura mostramos una pequeña parte de la jerarquía de clases que forman la VCL.

4Tema 3.2.2.- Componentes en C++ Builder

La VCL (Visual Components Library) o biblioteca de componentes visualesEs posible construir aplicaciones Windows de gran calidad con C++ Builder sin un conocimiento exhaustivo de la VCL, aunque es conveniente realizar una somera descripción de la jerarquía de clases que conforman la VCL.Las clases que conforman la parte superior (el techo) de la jerarquía de la VCL (Tobject, TPersistent y TComponent) se denominan clases "abstractas" porque sirven para estructurar, y agrupar comportamientos comunes de las clases de la VCL. No se suelen crear objetos directamente a partir de ellas. Rigurosamente hablando, no son clases abstractas, porque no tienen métodos virtuales puros, pero las podemos considerar como tales en la práctica.TobjectEs el ancestro de todas las clases de la VCL. Encapsula el comportamiento común de los objetos en C++ Builder, como puede ser información de la clase, instanciación... Suele ser una buena idea derivar nuestras propias clases de TObject, porque aunque no sea normal que el programador haga uso de los métodos proporcionados por Tobject, si lo es que lo haga C++ Builder en tiempo de ejecución. Directamente de TObject heredan aquellas clases que no son componentes, y no necesitan ser almacenadas en disco.TPersistentEsta clase tiene que ver con la habilidad de un objeto de almacenarse en disco o en memoria, asignarse a otros objetos, así como otros detalles internos de C++ Builder.TComponentÉsta es una de las clases más importantes de la VCL, ya que la mayoría de los objetos que se manejan en una aplicación son componentes. Esta clase proporciona toda la funcionalidad que requiere un componente básico. La funcionalidad de TComponent permite que los objetos aparezcan en la paleta de componentes y que sean manipulados por el diseñador de formularios, además de otras capacidades comunes a los componentes.Los componentes no visibles derivan directamente de TComponent mientras que los componentes visibles derivan de TControl, que a su vez deriva de TComponent. Por esta razón se suelen denominar controles a los componentes visibles.

5Tema 3.2.2.- Componentes en C++ Builder

La VCL (Visual Components Library) o biblioteca de componentes visualesTControlProporciona la funcionalidad de los componentes visibles (controles). Esta funcionalidad es principalmente el aspecto visual que deben ofrecer los componentes en tiempo de ejecución. TControl proporciona mayor funcionalidad que la que requieren los componentes visibles: los componentes individuales derivan de TGraphicControl o de TWinControl, clases derivadas de Tcontrol.TGraphicControlGeneraliza a los controles que tienen una representación visual, pero no pueden recibir el foco: el usuario podrá verlos pero no interactuar con ellos. Suelen ser controles para visualizar texto (no editable en tiempo de ejecución), gráficos o dibujos. Poseen una propiedad Canvas que permite acceder a su área de dibujo.TWinControlSon los controles típicos de Windows, que pueden recibir el foco, contener otros controles, y además poseen un manejador de ventana. Un manejador de ventana es un identificador que proporciona Windows para el control, por lo que podemos decir que Windows tiene un conocimiento directo de la existencia del mismo. Dicho identificador es un número que Windows incorpora a su base de datos de controladores y periódicamente comprueba si ha realizado alguna solicitud.Clases de Formularios y AplicacionesSon controles en si mismos, pero no se presentan en la paleta de componentes.TApplicationLa clase TApplication encapsula una aplicación Windows por lo que caracteriza las operaciones fundamentales de un programa en Windows. TApplication simplifica el interface entre el programador y el sistema operativo, ocupándose de tareas como gestionar el paso de mensajes, proporcionar la ayuda contextual, establecer los textos de sugerencia de los botones y barras de estado, procesamiento de "teclas rápidas", gestión de excepciones, ejecutar cuadros de mensajes, etc.Todas las aplicaciones de C++ Builder tienen un puntero a un objeto Tapplication denominado Application, que se crea automáticamente. Cuando un programa empieza a ejecutarse, C++ Builder invoca a la variable Application, llama a sus métodos Initialize(), CreateForm() y Run().

6Tema 3.2.2.- Componentes en C++ Builder

Clases de Formularios y AplicacionesTApplicationPor ejemplo, si retomamos el ejemplo 3 podemos abrir el fichero Ejemplo3.cpp o bien abrir el proyecto y seleccionar Proyect/View Source para observar el contenido del fichero que C++ Builder crea como fichero principal de la aplicación.{ try { Application->Initialize(); Application->Title = "Primera aplicación"; Application->CreateForm(__classid(TFormPrincipal), &FormPrincipal); Application->Run(); } catch (Exception &exception) { Application->ShowException(&exception); } catch (...) { try { throw Exception(""); } catch (Exception &exception) { Application->ShowException(&exception); } } return 0;}

Métodos Initialize(), CreateForm() y Run().Además aparece el método Title por haber puesto un título a nuestra aplicación

Como Application se crea automáticamente no aparece en la paleta de componentes ni está disponible en el inspector de objetos para manipular "visualmente" sus propiedades.En cualquier caso, algunas propiedades pueden establecerse en tiempo de diseño seleccionando las páginas Forms o Applicaction en Project/Options.

7Tema 3.2.2.- Componentes en C++ Builder

Clases de Formularios y AplicacionesPropiedades de TApplication

Propiedad DescripciónActive Especifica si la aplicación está activa y tiene el foco.

Hint

Hint especifica el texto que debe aparecer en el cuadro de ayuda o texto de sugerencia asociadoa la aplicación. Este cuadro aparece cuando ocurre el evento OnHint. Por defecto se muestraúnicamente el cuadro asociado al componente sobre el que está el ratón por lo que usualmentese emplea esta propiedad para mostrar la información extensa de este componente en una barrade estado, por ejemplo.

ShowHintShowHint determina si los cuadros de sugerencia estarán activados o desactivados para toda laaplicación.Pueden emplearse las funciones GetShortHint() y GetLongHint() para obtener las dos partes dela propiedad Hint.

MainForm MainForm especifica qué formulario actúa como ventana principal de la aplicación.

ShowMainFormShowMainForm especifica si la aplicación debe mostrar la ventana principal al iniciar suejecución. Para ocultarla, establecer esta propiedad a false antes de la llamada a Application->Run y asegurarse de que la propiedad Visible del formulario esté también a false.

Icon y TitleEspecifican el icono y el texto, respectivamente, que aparecen en la barra de tareas de Windowscuando se minimiza la aplicación. Pueden establecerse en tiempo de diseño seleccionandoProject/Options/Application.

HelpFile yCurrentHelpFile Para especificar el fichero de ayuda asociado a la aplicación.

Ejemplo 93.- Propiedades de TApplicationVamos a realizar paso a paso una aplicación visual que muestra el uso de la propiedad

Application.

8Tema 3.2.2.- Componentes en C++ Builder

Clases de Formularios y AplicacionesPropiedades de TApplicationCreamos una aplicación y archivamos el trabajo, no es necesario cambiar el nombre a ningún archivos.Declaramos el método DisplayHint como un procedimiento público del Formulario

Escribimos en el Unit, debajo de lo creado automáticamente, el método DisplayHint y lo asignamos a Application para que lo maneje el evento OnCreate del Form. void __fastcall TForm1::DisplayHint(TObject *Sender){ StatusBar1->SimpleText = GetLongHint(Application->Hint);}Situamos sobre el formulario un componente OpenPictureDialog de la pestaña Dialog y un botón al que modificamos su propiedad Caption a Seleccionar un Icono.

9Tema 3.2.2.- Componentes en C++ Builder

Clases de Formularios y AplicacionesPropiedades de TApplicationSituamos sobre el formulario un componente StatusBar de la pestaña Win32 y hacemos doble clic sobre el formulario para crear el gestor de evento y teclear las líneas siguientes.

void __fastcall TForm1::FormCreate(TObject *Sender){ Form1->Hint="Mostrar la propiedad Hint"; Application->OnHint = DisplayHint; Application->Title="Uso de Application";}

Hacemos doble clic sobre el botón para crear el gestor de evento y teclear las líneas siguientes.void __fastcall TForm1::Button1Click(TObject *Sender){ OpenPictureDialog1->DefaultExt = GraphicExtension(__classid(TIcon)); OpenPictureDialog1->FileName = GraphicFileMask(__classid(TIcon)); OpenPictureDialog1->Filter = GraphicFilter(__classid(TIcon)); OpenPictureDialog1->Options.Clear(); OpenPictureDialog1->Options << ofFileMustExist << ofHideReadOnly << ofNoChangeDir; while (true) { if (OpenPictureDialog1->Execute()) { if (!OpenPictureDialog1->Options.Contains(ofExtensionDifferent)) { Application->Icon->LoadFromFile(OpenPictureDialog1->FileName); break; } else { OpenPictureDialog1->Options.Clear(); OpenPictureDialog1->Options << ofFileMustExist << ofHideReadOnly << ofNoChangeDir; } } else break; }}

10Tema 3.2.2.- Componentes en C++ Builder

Clases de Formularios y AplicacionesPropiedades de TApplicationEjecutando el programa y seleccionando un icono al pulsar el botón obtenemos el siguiente resultado. Observar minimizando la aplicación como aparece el título de la misma.El ejemplo lo hemos realizado a efectos de demostración de Application, ya que mostrar una pista en la barra de estado se puede hacer con su propiedad Autohint sin necesidad de escribir el evento OnHint.Métodos de TApplication

Método DescripciónBringToFront() Establece la última ventana activa como la que se muestra por encima de todas las demás.

CreateForm() Crea un nuevo formulario. Generalmente, el programador no usa este método ya que las líneas decódigo para la creación de formularios las añade automáticamente C++ Builder.

HelpCommand()HelpContext()HelpJump()

Se emplean para gestionar la ayuda asociada a una aplicación. Generan un evento OnHelp, y si nohay un gestor para este evento, se gestiona a través de WinHelp.

MessageBox() Muestra un mensaje al usuario en cuadro de diálogo que puede incorporar botones. Devuelve unvalor que depende del botón seleccionado para cerrar el cuadro de diálogo.

Minimize() Minimiza una aplicación y la aloja en la barra de tareas de Windows.Restore() Reestablece el tamaño que tenía la aplicación antes de ser minimizada.Run() Ejecuta la aplicación.Terminate() Finaliza laejecución de una aplicación.

ShowException()Muestra un cuadro de diálogo cuando se produce una excepción que no es gestionada por laaplicación. Para especificar qué excepciones pueden gestionarse en la aplicación, debemosconstruir un gestor para el evento OnException.

HandleException() Proporciona una manera de gestionar excepciones por defecto en la aplicación.

11Tema 3.2.2.- Componentes en C++ Builder

Clases de Formularios y AplicacionesEventos de TApplication

Evento Descripción

OnActivateOnDeactivate

Ocurren respectivamente cuando se activa o desactiva la aplicación.Una aplicación se activa cuando se genera la aplicación (empieza a ejecutarse) o cuandoestaba activa otra aplicación y una ventana de la aplicación a la que se refiere recibe el foco.Una aplicación se desactiva cuando el usuario selecciona otra aplicación.

OnHintOnHint ocurre cuando el cursor se coloca sobre un control o una opción de un menú quepuede mostrar un cuadro de sugerencia.Se suele escribir un gestor para este evento cuando se quiere mostrar un texto largo desugerencia en una barra de estado.

OnShowHintOnShowHint ocurre cuando la aplicación va a mostar un cuadro de sugerencia. Se sueleusar para modificar la apariencia del cuadro.Pueden emplearse las funciones GetShortHint() y GetLongHint() para obtener las dos partesde la propiedad Hint

OnMinimizeOnRestore

Ocurren cuando la aplicación se minimiza o se reestablece al tamaño normal,respectivamente.

OnHelp Ocurre cuando la aplicación recibe una petición de ayuda. Los métodos HelpContext() yHelpJump() gestionan de forma automática este evento.

OnException Se emplea cuando se desea modificar el comportamiento por defecto de una aplicacióncuando se manifiesta alguna excepción que no es tratada por el programa.

OnShortCutSe emplea este gestor para realizar acciones antes de que el formulario o los controles delformulario gestionen los eventos oportunos a la pulsación de teclas.Cuando se pulsa una tecla se desencadenan los siguientes eventos, por este orden:OnKeyDown, OnKeyPress, y OnKeyUp.

12Tema 3.2.2.- Componentes en C++ Builder

Clases de Formularios y AplicacionesMétodos y eventos de TApplicationEjemplo 94.- Métodos y eventos de TApplication

Muestra de un programa totalmente comentado para ver algunos métodos y eventos de Tapplication. Situando en un Form un componente Timer y dos botones para tener algo similar a:

void __fastcall TForm1::Button1Click(TObject *Sender){ /* Hacemos doble clic sobre el botón al que hemos puesto en Caption Mostrar Mensaje. Las siguientes líneas harán que la ventana con el mensaje se muestre en primer plano y una vez cerrada esta que el formulario desde el que la hemos llamado se restaure en primer plano. */ Application->NormalizeTopMosts(); Application->MessageBox("Esto se muestra en primer plano", "Observese", MB_OK); Application->RestoreTopMosts();}//---------------------------------------------------------------------------void __fastcall TForm1::AppDeactivate(TObject *Sender){ /* El código siguiente minimiza la aplicación cuando esta se desactiva. Debemos declarar el método como público en el header con lo siguiente: void __fastcall AppDeactivate(TObject *Sender); */ Application->Minimize();}//--------------------------------------------------------------------------- /* Las siguientes líneas van a provocar el siguiente efecto: cuando minimizamos la aplicación el Timer comienza a contar y tras el tiempo especificado la ventana vuelve a su estado anterior debido al evento OnTimer. El temporizador no estará activo hasta la próxima vez que minimicemos la ventana. */

13Tema 3.2.2.- Componentes en C++ Builder

Clases de Formularios y AplicacionesMétodos y eventos de TApplication// Creamos el eventovoid __fastcall TForm1::IniciarTimer(TObject *Sender){ /* Implementamos el método IniciarTimer sin olvidarnos de declararlo como público con: void __fastcall IniciarTimer(TObject *Sender); */ Timer1->Enabled = true;}// Creamos el eventovoid __fastcall TForm1::FormCreate(TObject *Sender){ Application->OnDeactivate = AppDeactivate; Application->OnMinimize = IniciarTimer; Timer1->Interval = 1000;}// Creamos el eventovoid __fastcall TForm1::Timer1Timer(TObject *Sender){ Application->Restore(); Timer1->Enabled = false;}// Creamos el eventovoid __fastcall TForm1::Button2Click(TObject *Sender){ Application->Terminate();}//---------------------------------------------------------------------------

14Tema 3.2.2.- Componentes en C++ Builder

Clases de Formularios y AplicacionesTformLa clase TForm caracteriza a los formularios en la VCL. Los formularios se emplean como ventanas principales, cuadros de diálogo, ventanas secundarias o cualquier otro tipo de ventana que se pueda imaginar. A continuación veremos las propiedades, métodos y eventos principales de los formularios de forma resumida.Propiedades de los formularios en tiempo de diseño y ejecución

Propiedad DescripciónActiveControl Establece qué componente tiene el foco cuando se abre el formulario.Enabled Indica si el formulario está activo (si puede recibir el foco).AutoScroll,HorzScrollBarVertScrollBar

Controlan conjuntamente las barras de desplazamiento de un formulario.

BorderIcons Indica qué iconos aparecen en la barra de título de un formulario.BorderStyle Indica qué tipo de borde debe tener el formulario.Caption Indica la cadena que aparece en la barra de título del formulario mientras que NameName Indica con qué nombre se refiere al formulario en la aplicación (en el código).Color Color de fondo del formulario.Cursor Especifica qué cursor se muestra cuando está sobre el formulario.

Font Permite especificar las propiedades de la fuente de letra que se usará en el formulario. Se aplica a todoslos componentes ubicados en el formulario o componentes hijo.

Icon Establece el icono que se verá en la barra de título cuando se muestre el formulario en tiempo de ejecucióny cuando se minimice.

Height y Width Altura y anchura (en píxels) del formulario.

ClientWidthClientHeight

Altura y anchura (en píxels) del área de cliente del formulario (el área de cliente es la que queda dentro delos bordes del formulario y por debajo de la barra de título y de la barra de menú). Al modificar estaspropiedades se actualizan Width y Height.

15Tema 3.2.2.- Componentes en C++ Builder

Clases de Formularios y AplicacionesPropiedades de los formularios en tiempo de diseño y ejecución

Propiedad DescripciónLeft y Top Coordenadas X e Y del formulario (esquina superior izquierda) en la pantalla.Position Determina el tamaño y la posición del formulario.FormStyle Para especificar si un formulario es o no parte de una aplicación multiformulario.HelpFileHelpContext Para especificar el fichero de ayuda asociado a la aplicación y gestionar la ayuda contextual.

HintEspecifica el texto que debe aparecer en el cuadro de ayuda o texto de sugerencia asociado al formulario.Este cuadro aparece cuando ocurre el evento OnHint. Por defecto se muestra únicamente el cuadro asociadoal componente sobre el que está el ratón por lo que usualmente se emplea esta propiedad para mostrar lainformación extensa de este componente en una barra de estado, por ejemplo.

ShowHint Determina si los cuadros de sugerencia estarán activados o desactivados para el formulario.

Visible Indica si el formulario es visible o no. Los métodos Show() y ShowModal() hacen que un formulario seavisible y lo colocan por encima de todos.

WindowState Para establecer el estado inicial del formulario (normal, minimizado o maximizado) o consultar su estado.

Propiedades de los formularios en tiempo de ejecución

Propiedad DescripciónActive Indica si el formulario está activo (si tiene el foco).

CanvasEl lienzo es la superficie del formulario sobre la que se puede dibujar. La propiedad Canvas da acceso aesta superficie para dibujar líneas, mapas de bits, texto, ... en el área de cliente. Suele usarse con el gestordel evento OnPaint

ClientRect Coordenadas de los cuatro puntos que delimitan el área de cliente del formulario.ModalResult El valor devuelto cuando se cierra un formulario modal (abierto con el método ShowModal()).

FormState Proporciona información acerca del estado en que se encuentra un formulario (si se está creando, si esvisible, si es modal, etc.).

16Tema 3.2.2.- Componentes en C++ Builder

Clases de Formularios y AplicacionesMétodos de los formularios

Método DescripciónBringToFront() SendToBack() Coloca al formulario en primer plano o en último, respectivamente.

Hide() Oculta el formulario (establece la propiedad Visible a falso).Print() Imprime el contenido del formulario.Show()ShowModal()

Para mostrar formularios. ShowModal() ejecuta (abre) el formulario modalmente: debe cerrarse paraque el usuario pueda seguir trabajando con la aplicación.

Close()CloseQuery()

Close() cierra el formulario tras llamar a CloseQuery() para asegurarse de que es correcto cerrarlo.Esta última llama al manipulador del evento OnCloseQuery.

SetFocus() Activa el formulario y lo coloca en primer plano, poniendo a true la propiedad Active. Además, elcomponente especificado en la propiedad ActiveControl recibe el foco.

CanFocus() Devuelve true si el formulario puede recibir el foco (si las propiedades Visible y Enabled están a true).SetBounds() Establece simultáneamente los valores de las propiedades Top, Left, Width y Height.ClientToScreen()ScreenToClient() Convierte las coordenadas del área de cliente en coordenadas de pantalla y viceversa.

Invalidate()Refresh()Repaint()Update()

Para redibujar un formulario.

Release() Destruye un formulario y libera toda la memoria asociada.

Eventos de los formulariosUna acción puede desencadenar varios eventos y el orden en que ocurren puede ser muy importante.Cuando se crea un formulario se generan los siguientes eventos, que enumeramos ordenadamente:1. OnCreate.2. OnShow.3. OnActivate.4. OnPaint.

17Tema 3.2.2.- Componentes en C++ Builder

Clases de Formularios y AplicacionesEventos de los formulariosDe la misma manera, cuando se destruye el formulario se generan los siguientes eventos, que enumeramos ordenadamente:1. OnCloseQuery.2. OnClose.3. OnDestroy.4. Destructor del formulario (si existe).

Evento DescripciónOnActivateOnDeactivate

Ocurren cuando se activa o desactiva un formulario, respectivamente. Un formulario se activa cuandose recibe el foco y se desactiva cuando el foco pasa a otro formulario de la misma aplicación.

OnCreateOnDestroy

OnCreate ocurre cuando se crea inicialmente el formulario (sólo ocurre un evento de este tipo porformulario) y OnDestroy cuando se destruye.

OnCloseOnCloseQuery

El evento OnClose ocurre cuando se cierra un formulario. Hace una llamada a OnCloseQuery paraasegurarse de que es correcto cerrarlo.

OnMouseDownOnMouseMoveOnMouseUpOnClickOnDblClick

Para responder a los eventos que suceden al mover el ratón o cuando se pincha con él sobre elformulario.

OnKeyDownOnKeyUpOnKeyPress

Para responder a los eventos que suceden al pulsar alguna tecla sobre el formulario.

OnHelp Ocurre cuando se recibe una petición de ayuda en el formulario.

OnHideOnShow

Ocurren cuando se oculta o se muestra el formulario, respectivamente (cuando su propiedad Visible seestablece a false o true, respectivamente). OnShow ocurre justo antes de que el formulario se hagavisible.

OnPaintOcurre cuando el formulario necesita ser redibujado (refrescado). Esto ocurre muy frecuentemente, yaunque los componentes del formulario se redibujan generalmente por sí mismos, a veces es precisoredibujar "manualmente" el formulario.

OnResize Ocurre cuando se modifica el tamaño del formulario, justo después de redimensionar el formulario.

18Tema 3.2.2.- Componentes en C++ Builder

Resumen sobre la VCLLa VCL (Visual Component Library) la forman un conjunto de componentes u objetos visuales prefabricados. Cuando incluimos un componente en una aplicación este pasa a formar parte de su ejecutable. Podemos decir que un componente es un elemento de nuestro programa que posee características (propiedades) y acciones (métodos) asociadas y que reaccionará o no ante una situación producida en el entorno (evento). Un componente, por tanto, está asociado a métodos (código de programa correspondiente a un procedimiento al que se puede acceder desde el programa), y en muchos casos a propiedades y eventos.

Las propiedades representan los datos contenidos en el objeto. Los métodos son las acciones que el objeto puede realizar. Los eventos son condicionantes ante los cuales el objeto puede reaccionar.

Todo componente posee un nombre (Name) que lo diferencia del resto de componentes de una aplicación. Por defecto, C++ Builder asigna un valor que tiene relación con el tipo de componente y un número que los diferencie del resto de componentes.Una propiedad la podemos considerar como una variable ligada al componente que posee un valor que condicionará su funcionamiento. Algunas propiedades están disponibles en fase de diseño y otras no, es decir, que podremos modificar su contenido mediante el Inspector de Objetos o lo deberemos hacer en tiempo de ejecución. Por ejemplo, para modificar el título de un formulario podemos asignar el valor directamente a la propiedad Caption desde el Inspector de Objetos o modificarla desde código cuando ocurra un evento o cuando se inicie la aplicación. El código asociado se incluiría en el código del programa como muestra la figura:

19Tema 3.2.2.- Componentes en C++ Builder

Resumen sobre la VCLEn la figura anterior aparece la línea de código Caption = "Modificación del título o Caption"; que modificará el contenido de la propiedad en tiempo de ejecución. Si queremos hacer referencia a una propiedad de un componente desde un procedimiento no asociado a ese componente debemos referenciar la propiedad con el operador -> de la siguiente forma:

Form1->Caption = "Modificación del título o Caption";Un evento es una situación que se produce durante la ejecución de un programa. Los eventos pueden provenir del sistema, del ratón, desde teclado, etc.... Un componente podrá reaccionar ante un evento si el tipo de componente lo tiene así predefinido, dependiendo del objetivo para el que está diseñado. Por ejemplo, un componente TForm (formulario o ficha) tiene, por supuesto, un evento asociado a la acción de cerrar (Sistema), en cambio, el componente TButton (botón) no lo tendrá. Cuando ocurre un suceso durante la ejecución de nuestro programa, los componentes sobre los que se produzca reaccionarán o no a este suceso si disponen de un evento que lo detecte. Cuando queramos incluir un conjunto de sentencias que se ejecuten cuando se produzca un determinado suceso deberemos asociar un conjunto de instrucciones al evento correspondiente del componente. Este grupo de acciones se expresará en el código del programa. C++ Builder generará automáticamente la base principal del código que se va asociar al evento, pudiendo escribir como bloque de instrucciones las sentencias que deseemos. Por ejemplo, si pulsamos en el Inspector de Objetos del componente formulario (Form1) sobre el evento OnClose (que se produce cuando se cierra el formulario) aparecerá el editor de código con las líneas:

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action){

ShowMessage(“Cierre de la aplicación”);}

Creándose una línea en blanco donde se sitúa el cursor y donde podemos escribir una línea de código como la destacada en rojo. Esto nos mostrará una ventana de diálogo con el mensaje entrecomillado y un botón OK.

20Tema 3.2.2.- Componentes en C++ Builder

Resumen sobre la VCLEjemplo 95.- Propiedades, métodos y eventos sobre un formulario

Se trata de realizar un programa visual que trabaje con propiedades, métodos y eventos de un formulario para realizar las operaciones que iremos describiendo paso a paso. En el inspector de objetos (Object Inspector) hacemos los siguientes cambios de propiedades del formulario:1.- Ponemos en false los valores de biMinimize y biMaximize de BorderIcons, lo que eliminará las

opciones de maximizar y minimizar en tiempo de ejecución.2.- A la propiedad BorderStyle le damos el valor bsSingle, impidiendo que la ventana sea

dimensionable en la fase de ejecución.3.- Asignamos a la propiedad Position el valor psScreenCenter, con lo que la ventana siempre

aparezca centrada en pantalla. 4.- Establecemos la propiedad Cursor con el valor crHandPoint y cuando el puntero del ratón esté

situado sobre el formulario aparezca el cursor como una mano.5.- Establecemos unas dimensiones del formulario de 150x300 pixels.

Accedemos a la ventana de código con F12, o con el botón de acceso rápido Toggle Form/Unit o bien desde menú view y escribimos justo debajo de la línea Tform *Form1; la sentencia int ncolor; con la que definiremos una variable global de tipo entero que, en nuestro programa podrá tomar los valores 1, 2, 3 ó 4.Entre las llaves que definen el constructor del formulario (líneas que siguen en gris) tecleamos la línea que vemos destacada en negro .

__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner){Caption = "Modificación del título o Caption";}

21Tema 3.2.2.- Componentes en C++ Builder

Resumen sobre la VCLEjemplo 95.- Propiedades, métodos y eventos sobre un formularioHacemos doble clic sobre el evento OnClose del Inspector de Objetos teniendo seleccionado el componente Form1 y sobre el gestor de evento que se genera (gris) tecleamos la línea de código en negro.void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action){ ShowMessage("Cierre de la aplicación");}Hacemos doble clic en el evento OnCreate y escribimos el siguiente código:void __fastcall TForm1::FormCreate(TObject *Sender){ ncolor=1; Form1->Color=clRed;}En este caso no sería necesario anteponer a la propiedad Color el componente al que corresponde porque la función corresponde al propio formulario. También podríamos usar el puntero this escribiendo this->Color=clRed; , aunque tampoco es necesario en este caso.Generamos el evento OnCloseQuery, que se producirá cuando se solicite el cierre del formulario, y escribimos el siguiente código:void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose){ if (Application->MessageBox("¿Esta seguro?","Va a cerrar la aplicación",MB_YESNO) == ID_YES) CanClose=true; else CanClose=false;}Conseguimos que se pregunte al usuario si quiere o no abandonar el programa, evitándolo si su respuesta es no.

22Tema 3.2.2.- Componentes en C++ Builder

Resumen sobre la VCLEjemplo 95.- Propiedades, métodos y eventos sobre un formularioFinalmente, hacemos doble clic sobre el evento OnClick de forma que cada vez que se pulse el ratón aparezca el fondo del formulario de uno de los 4 colores que escogemos con el código siguiente.void __fastcall TForm1::FormClick(TObject *Sender){ switch (ncolor) { case 1:Color=clMaroon; break; case 2:Color=clPurple; break; case 3:Color=clGreen; break; default:Color=clRed; ncolor=0; } ncolor++;}Guardamos el programa, depuramos los posibles errores de compilación, linkado y ejecución hasta ejecutar el programa y la ventana tendrá la siguiente apariencia al solicitar su cierre:

23Tema 3.2.2.- Componentes en C++ Builder

ComponentesYa hemos visto que los componentes que podemos insertar en nuestros formularios están organizados en carpetas (pestañas o páginas) en la Paleta de Componentes del IDE. Los componentes pueden ser visibles y no visibles. Pestaña Standar. Estos componentes son los elementos de control más comunes de Windows.

Componente ¿Visible? Descripción breveMainMenu No Diseño de barras de menús junto con sus correspondientes menús desplegables.

PopUpMenu No Diseño de menús contextuales o emergentes que se muestras al hacer clic con el botónderecho del ratón.

Label Si Para mostrar texto no accesible por el usuario, como son los títulos. Edit Si Presenta un área donde el usuario puede introducir o modificar texto en una sola línea.Memo Si Presenta un área donde el usuario puede introducir o modificar varias líneas de texto. Button Si Un botón permite que los usuarios lo seleccionen para realizar una operación.

CheckBox SiCasilla de verificación, para alternativas tipo Sí/No, Verdadero/Falso o Activado/Desactivado.Los CheckBox son independientes entre sí, ya que las opciones que representan no sonexcluyentes entre ellas.

RadioButton Si Para representar opciones donde sólo está disponible una de ellas. ListBox Si Lista de opciones para que el usuario seleccione una o varias de ellas.ComboBox Si Conjunta la funcionalidad del Edit y del ListBox para presentar una lista de opciones.

ScrollBar Si Barra de desplazamiento para poder desplazar en pantalla la parte visible de una lista o ficha,o trasladarse por un rango en incrementos.

GroupBox Si Agrupar componentes relacionados en una ficha.RadioGroup Si Agrupar RadioButton en una ficha.Panel Si Agrupar componentes y creación de barras de estado.

24Tema 3.2.2.- Componentes en C++ Builder

ComponentesPestaña Standar

Componente ¿Visible? Descripción breveFrames Si Contenedor de componentes que puede anidarse en otros frames o formularios.

ActionList No Mantiene una lista de las acciones que pueden ser usadas por componentes y controles,como opciones de menú y botones.

Ejemplo 96.- Modificación y consulta de propiedades en tiempo de ejecuciónSe trata de retomar el ejemplo 3 donde diseñamos un formulario con varios campos y establecer

el código necesario sobre los gestores de eventos para realizar las operaciones que citamos.Sobre el evento OnCreate:

▫ Modificamos la propiedad Caption para que aparezca Ejemplo 96▫ Si el color del Form es clBtnFace lo cambiamos a clWhite▫ Establecemos la propiedad Checked del CheckBox a false▫ Hacemos que se oculten los dos RadioButtom▫ Crear y trabajar con otros gestores de eventos que describiremos una vez realizadas las

operaciones anteriores. En primer lugar creamos un nuevo directorio denominado ejemplo 96 y abrimos el ejemplo 3 tal y como lo dejamos anteriormente. Clicamos en File/Save As... y guardamos en nuestro nuevo directorio y también File/Save Project As ... para archivar el proyecto cambiando el nombre de Ejemplo3 a Ejemplo96. Con esto tendremos los archivos necesarios mínimos para el proyecto. El código asociado al evento OnCreate será: FormPrincipal->Caption = "Ejemplo 96"; if (FormPrincipal->Color == clBtnFace) // Lectura FormPrincipal->Color = clWhite; // Escritura CheckBoxOpciones->Checked = false; // Escritura RadioButtonOp1->Hide(); RadioButtonOp2->Hide(); /* Hide() es el método que oculta el componente sobre el que se aplica. */

25Tema 3.2.2.- Componentes en C++ Builder

ComponentesEjemplo 96.- Modificación y consulta de propiedades en tiempo de ejecución

Hasta este momento el aspecto de la aplicación en tiempo de ejecución será

if (CheckBoxOpciones->Checked == true) { RadioButtonOp1->Show(); RadioButtonOp2->Show(); RadioButtonOp1->Checked = true; ButtonOK->Enabled = true; } else { RadioButtonOp1->Hide(); RadioButtonOp2->Hide(); ButtonOK->Enabled = false; LabelSalida->Caption = ""; }

Una vez llegados a este punto vamos a dar sentidos a los botones, a la casilla de selección, a las opciones de selección (ahora no visibles) y a la etiqueta que por ahora no es visible (propiedad Caption vacía). Procedemos a:Construir el gestor del evento asociado a modificar el componente de selección CheckBox de forma que cuando se active (inicialmente está desactivado) se muestren los dos RadioButtom y se active el botón de OK. Cuando se desactive, los RadioButtom se volverán a ocultar y el botón de OK se desactivará. Para ello, escribiremos el gestor asociado al evento OnClick del componente CheckBox:

26Tema 3.2.2.- Componentes en C++ Builder

ComponentesEjemplo 96.- Modificación y consulta de propiedades en tiempo de ejecuciónFinalmente, escribiremos el gestor del evento asociado a hacer clic sobre el botón OK, que está operativo (propiedad Enabled) únicamente cuando el CheckBox está activado, y en consecuencia, cuando pueden emplearse los RadioButtom. Haremos además que en la etiqueta vacía se muestre un texto alusivo al texto introducido (o no) en el Edit y a la opción elegida. Este evento será: if (RadioButtonOp1->Checked) { if (EditNombre->Text=="") LabelSalida->Caption="Ha escogido la Opción 1, D./Dª. sin identificar"; else LabelSalida->Caption="Ha escogido la Opción 1, D./Dª. " + EditNombre->Text; } else { if (EditNombre->Text == "") LabelSalida->Caption = "Ha escogido la Opción 2, D./Dª. sin identificar"; else LabelSalida->Caption = "Ha escogido la Opción 2, D./Dª. " + EditNombre->Text; }

27Tema 3.2.2.- Componentes en C++ Builder

Conversión entre tiposCuando estudiamos la clase AnsiString vimos que resultaba especialmente útil la conversión entre tipos, por lo que vamos a analizar algunas de las rutinas de conversión entre tipos.StrToIntConvierte un AnsiString que representa un número entero (en notación decimal o hexadecimal) a un número. Su sintaxis es la siguiente: StrToInt(const AnsiString S);. StrToInt convierte la cadena S de tipo AnsiString, que representa un número de tipo entero en notación decimal o hexadecimal, en un número. Si la S no representa número válido, StrToInt ejecuta una excepción EconvertError.Ejemplo 97.- Uso de StrToInt

Situamos en un formulario dos elementos Edit y un elemento Button. Cuando pulsemos el botón, el código convierte los valores introducidos en los Edit a números enteros, los suma, y muestra un mensaje que indica la suma. El fichero .cpp quedaría en los gestores de eventos de la siguiente forma:

void __fastcall TForm1::Button1Click(TObject *Sender){ int i1, i2; //Declara i1 e i2 como enteros i1 = StrToInt(Edit1->Text); //Convierte a entero el Text que introducimos en Edit1, que deberá ser // un número entero, y asigna el valor a i1 i2 = StrToInt(Edit2->Text); //Convierte a entero el Text que introducimos en Edit2, que deberá ser // un número entero, y asigna el valor a i2 ShowMessage("Suma: " + IntToStr(i1 + i2)); // Suma los valores i1 e i2 (un entero) y convierte el resultado en un // string que se muestra como mensaje emergente.}//---------------------------------------------------------------------------void __fastcall TForm1::FormCreate(TObject *Sender){ Edit1->Text=""; Edit2->Text="";}

28Tema 3.2.2.- Componentes en C++ Builder

Conversión entre tipos

Efectivamente, el número introducido no es un valor entero válido, por lo que se ejecuta una excepción EconvertError antes de efectuar la operación señalada. Dicho de otra forma, la suma se realiza en complemento a 1 y, mientras los datos introducidos sean enteros válidos, el procesador efectuará la suma dentro de rango sin lanzar una excepción EconvertError. De esta forma se evita que el procesador realice operaciones no válidas mediante comandos de programación, pero en cambio surge un error en la programación que debemos tener especialmente presente.

Recordemos lo que pasaba con la suma de enteros con números dentro del rango del tipo int.En cambio cuando tecleamos un número fuera de rango lo que ocurre es:

29Tema 3.2.2.- Componentes en C++ Builder

Conversión entre tiposEl problema lo podemos resolver utilizando el siguiente procedimiento, del que vemos el resultado:Ejemplo 97b.- Uso de StrToInt

Situamos en un formulario tres elementos Edit, dos label y un elemento Button. Cuando pulsemos el botón, el código convierte los valores introducidos en los Edit a números enteros de 64 bits, los suma, y muestra en el tercer Edit la suma. El fichero .cpp quedaría en los gestores de eventos de la siguiente forma:

void __fastcall TForm1::Button1Click(TObject *Sender){ __int64 i1, i2; i1 = StrToInt64(Edit1->Text); i2 = StrToInt64(Edit2->Text); Edit3->Text = i1+ i2;}//---------------------------------------------------------------------------void __fastcall TForm1::FormCreate(TObject *Sender){ Edit1->Text=""; Edit2->Text=""; Edit3->Text="";}

30Tema 3.2.2.- Componentes en C++ Builder

Conversión entre tiposStrToIntDefConvierte un AnsiString que representa un número entero a un número. Su sintaxis es la siguiente:

StrToIntDef(const System::AnsiString S, int Default);StrToIntDef convierte la cadena S de tipo AnsiString, que representa un número de tipo entero en un número. Si la S no representa número válido, StrToIntDef devuelve el entero introducido por defecto en int Default, evitando así la excepción EconvertError que se produce en StrToInt.Ejemplo 98.- Uso de StrToIntDef

Veamos un ejemplo que utiliza dos elementos Label, dos Edit y un Button de forma que el usuario introduce en dato de entrada un número entero, clica sobre el botón de ejecución y en el campo correspondiente a dato de salida aparece el número tecleado si es un entero válido, en caso contrario aparecerá el número 0 introducido por defecto. El código para el OnClick del botón será el siguiente:

void __fastcall TForm1::Button1Click(TObject *Sender){ int Numero = StrToIntDef(Edit1->Text, 0); Edit2->Text = IntToStr(Numero);}

Los resultados son:

31Tema 3.2.2.- Componentes en C++ Builder

Conversión entre tiposIntToStrConvierte un número entero en un AnsiString. Su sintaxis, cuando trabajamos con tipo int, es la siguiente:

IntToStr(int Value);Su sintaxis, cuando trabajamos con tipo __int64, es la siguiente:

IntToStr(__int64 Value);Es decir puede trabajar con cualquier dato de tipo int.

En el ejemplo de StrToInt hemos puesto la línea siguiente: Edit3->Text = i1+i2;. El texto del Edit3 era la suma i1+i2 , que es un número entero (también es una cadena) puesto que lo son i1 e i2, pero lo más correcto es convertir de forma efectiva el número entero en un AnsiString que es lo que “en realidad” puede mostrar un Edit. Lo más correcto en el ejemplo citado será:

Para tipo int:int i1, i2; // 1i1 = StrToInt(Edit1->Text);i2 = StrToInt(Edit2->Text);Edit3->Text = IntToStr(i1+i2); //2// 1: Datos de tipo int// 2: Como i1 e i2 son tipo int, IntToStr trabajo con tipo int

Para tipo __int64:__int64 i1, i2; // 1i1 = StrToInt64(Edit1->Text);i2 = StrToInt64(Edit2->Text);Edit3->Text = IntToStr(i1+i2); //2// 1: Datos de tipo int64// 2: Como i1 e i2 son tipo int64, IntToStr trabajo con tipo int64

32Tema 3.2.2.- Componentes en C++ Builder

Conversión entre tiposStrToFloatConvierte un AnsiString a un valor de coma flotante. Su sintaxis es la siguiente:

StrToFloat(const AnsiString S);StrToFloat convierte la cadena AnsiString S a un valor de coma flotante. La cadena S puede contener opcionalmente un signo + o -, una cadena de dígitos con un punto decimal, una ‘E' o ‘e' seguida por un número entero con signo. Los espacios en blanco son ignorados.La variable global DecimalSeparator define el carácter usado como punto decimal. En la cadena no se pueden usar separadores de miles ni símbolos de moneda. Si la S no contiene un valor válido, StrToFloat lanza una excepción ECONVERTERROR.FloatToStrConvierte un valor en coma flotante a un AnsiString. Su sintaxis es la siguiente:

FloatToStr(Extended Valor);FloatToStr convierte el valor en coma flotante dado por Valor a una cadena. En general, el formato de conversión numérica emplea 15 dígitos significativos.Extended hace referencia a los tipos reales descritos anteriormente.FloatToStrFConvierte un valor en coma flotante a un AnsiString usando un formato que debemos especificar en cuanto a precisión y número de dígitos. Su sintaxis es la siguiente:

FloatToStrF(Extended Valor, TfloatFormat Formato, int Precision, int Digitos);FloatToStrF convierte el valor en coma flotante especificado por Valor a su representación como cadena de caracteres (string). El parámetro Valor es el valor a convertir. El parámetro precisión especifica la precisión de valor. Debería ser inferior o igual a 7 para valores sencillos, menor o igual a 15 para valores de tipo Doble, y menor o igual a 18 para los valores de tipo real descritos. El número de dígitos y los parámetros de formato controlan la forma de conversión en cadena. Para todos los formatos, los caracteres usados como coma decimal y separador de miles se definen en las variables globales DecimalSeparator y ThousandSeparator respectivamente.Si el valor dado es una cadena YO (no un número), la cadena resultante es 'YO'. Si el valor dado es el infinito positivo, la cadena resultante es 'INF'. Si el valor dado es el infinito negativo, la cadena resultante es '-INF '.

33Tema 3.2.2.- Componentes en C++ Builder

Conversión entre tiposStrToCurrConvierte un AnsiString en un objeto tipo Currency. Su sintaxis es la siguiente:

StrToCurr(const AnsiString S);CurrToStr y CurrToStrFConvierte un currency en representación de tipo cadena sin y con formato respectivamente. Su sintaxis es la siguiente:

CurrToStr(Currency value);CurrToStrF(System:: Currency Value, TFloatFormat Format, int Digits);

StrToDateConvierte una cadena AnsiString a un objeto TdateTime con la siguiente sintaxis:

StrToDate(const AnsiString S);Llama a StrToDate para analizar una cadena que especifica una fecha. Si la S no contiene una fecha válida, StrToDate lanza una excepción ECONVERTERRORTDateTime es una clase de C++ basada en el tipo de datos de fecha y hora de Delphi. La clase TDateTime es un miembro heredado de datos val declarado como double que contiene los valores de fecha y hora. La parte entera de un TDateTime es el número de días que han pasado desde 12/30/1899. La parte fraccionaria de un valor TDateTime es la hora de ese día.DateToStrConvierte un objeto TdateTime a un AnsiString con la siguiente sintaxis:

DateToStr(System::TDateTime Date);

Ejemplo 99.- ¿Que día de la semana es?Sobre un formulario situamos varios Label, un Edit y un Button. Cuando introduzcamos en el edit

un dato con el formato DD-MM-YY, la cadena será convertida a un valor TdateTime que será usado para calcular el día de la semana que representa, mostrándonos además la fecha actual.

34Tema 3.2.2.- Componentes en C++ Builder

Conversión entre tiposEjemplo 99.- ¿Que día de la semana es?void __fastcall TForm1::Button1Click(TObject *Sender){ DateSeparator = '-'; //Cambia el separador / por - ShortDateFormat = "d/m/yyyy"; //Cambia el formato de m/d/yyyy a d/m/yyyy Label2->Caption = DateToStr(Date()); //Fecha actual del sistema char dias[7][10]={"Domingo","Lunes","Martes","Miércoles","Jueves","Viernes","Sabado" }; TDateTime dia = StrToDate(Edit1->Text); //1 Label4->Caption = dias[dia.DayOfWeek() - 1]; //Mostramos el resultado obtenido//1 Convertimos de String a Date almacenandolo en dia del tipo TDateTime}

StrToTimeConvierte una cadena AnsiString a un objeto TdateTime con la siguiente sintaxis:

StrToTime(const AnsiString S);El parámetro S se forma con dos o tres numeros, separados por un caracter definido en la variable global TimeSeparator, y seguidos opcionalmente del indicador AM o PM. Los números representan las horas, minutos y, opcionalmente, los segundos. Si la hora va seguida de AM o PM se asume un formato de reloj de 12 horas y si no se incluye el indicador el formato es de 24 horas.TimeToStrConvierte un objeto TdateTime a un AnsiString con la siguiente sintaxis:

TimeToStr(System::TDateTime Time);

35Tema 3.2.2.- Componentes en C++ Builder

Conversión entre tipos

Ejemplo 100.- Buenos días o buenas tardesVeamos un programa que salude con buenos días o buenas tardes según la hora introducida.

Además vamos a mostrar la fecha y la hora con las conversiones vistas.El código es:void __fastcall TForm1::Button1Click(TObject *Sender){ DateSeparator = '-'; //Cambia el separador / por - ShortDateFormat = "d/m/yyyy"; //Cambia el formato de m/d/yyyy a d/m/yyyy TDateTime hora = StrToTime(Edit1->Text); //1 if (hora < (TDateTime) 0.50 ) //2 Edit2->Text="Buenos días"; else Edit2->Text="Buenas tardes";// 1 Convertimos el texto de Edit1 (dado en formato HH:MM:SS) a formato Tdate Time// asignado el valor a la variable hora//2 Según sea antes de las 12 o después de las salude se emite uno u otro saludo TimeSeparator = '_'; Label3->Caption = TimeToStr(Time()); Label5->Caption = DateToStr(Date()); //Fecha actual del sistema Label7->Caption = DateTimeToStr(Now());}

DateTimeToStrConvierte un objeto TdateTime a un AnsiString con la siguiente sintaxis:

DateTimeToStr(const System::TDateTime DateTime);

36Tema 3.2.2.- Componentes en C++ Builder

Conversión entre tiposEjemplo 100.- Buenos días o buenas tardes

Algunos resultados.

IntToHexConvierte a notación hexadecimal un entero. Su sintaxis es la siguiente:

IntToHex(int Valor, int Digitos);IntToHex(__int64 Valor, int Digitos);

Antes de ver un ejemplo de conversión a hexadecimal diremos que la conversión se realiza carácter a carácter dando como resultado un carácter UNICODE. UNICODE es un juego de caracteres que emplea dos bytes para representar cada carácter.

37Tema 3.2.2.- Componentes en C++ Builder

Conversión entre tiposIntToHexCódigos UNICODE de los números:

0030 - 0039 -> 0 - 9 ISO - LATIN-1Códigos UNICODE de las letras y otros caracteres:

0024 Signo de $0041 - 005A Mayusculas A a Z005F _(guión bajo)0061 - 007A Minusculas a a z00C0 - 00D6 À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ñ Ò Ó Ô Õ Ö00D8 - 00F6 Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï õ ñ ò ó ô õ ö00F8 - 00FF ø ù ú û ü ý þ ÿ

Ejemplo 101.- Conversión a HexadecimalSobre un formulario situaremos, entre otros, un Edit, un Button y un Label de forma que en el

Label aparezca la conversión a hexadecimal de la cadena introducida en el Edit.void __fastcall TForm1::Button1Click(TObject *Sender){ AnsiString EditText = Edit1->Text; Label2->Caption = ""; for (int i=1;i<=EditText.Length();i++) { Label2->Caption = Label2->Caption + IntToHex(EditText[i],4) + " "; }}

38Tema 3.2.2.- Componentes en C++ Builder

ComponentesLabelEste componente se utiliza para desplegar textos o mensajes estáticos dentro de los formularios, textos tales como encabezados, solicitud al usuario del programa para que proporcione algún dato o información (edad, sueldo, etc.), en cierta forma hace las funciones de printf, cout, etc., pero solo cuando se considera el aspecto de mensajes.También es un objeto en C++Builder y por tanto tiene asociados sus propias propiedades, métodos y eventos. Como su uso normal es dentro de un objeto Form, muchas propiedades que se definan para el objeto Form1, el objeto Label1 las va a heredar.La propiedad Caption es la que contiene el mensaje a mostrar en la pantalla, que por defecto es su nombre inicial, pero se puede cambiar haciendo clic en la propiedad Caption del Inspector de Objetos, teniendo seleccionado Label en el formulario y escribir el texto que deseemos. También podemos cambiar la propiedad Caption en tiempo de ejecución mediante una línea de programa como la siguiente: Label1->Caption = ”Hola mundo...”;Su uso se limita a mostrar resultados e información al usuario, debido a que este no puede editarlo. No puede contener el foco en una aplicación.Su principales propiedades son:

Name: Es el nombre lógico con el que se referencia al componente.Caption: Permite modificar el texto que se muestra.Font: Modifica la fuente, estilo de fuente, tamaño, etc. del caption.Alignment: Especifica la alineación del texto (derecha, izquierda o centro).

Button, BitBtn y SpeedButtonButton es un botón estándar de Windows, mientras los que los otros dos (pestaña Additional) amplían sus funcionalidades como permitir incluir un bitmap.Button es el componente más empleado, ya que normalmente contiene el código principal del programa y su activación por el usuario provoca que se realicen los principales procesos del problema planteado (aquí es donde se va a capturar datos, realizar operaciones, etc.).

39Tema 3.2.2.- Componentes en C++ Builder

ComponentesButton, BitBtn y SpeedButtonDe este componente manejaremos su propiedad Caption para indicar acciones, etiquetándolo con palabras como Ok, Aceptar, Exe, ejecutar, etc. , y su evento OnClick para activarlo, siendo en dicho evento donde se construye el código del programa.Lo dicho anteriormente no significa que sea un componente necesario en los programas, ya que el código se puede asociar a cualquier evento de cualquier formulario u otro componente del programa, pero el manejo de Windows nos tiene acostumbrados al empleo del botón OK o Aceptar.Este botón puede activar su evento OnClick, cuando el usuario presione la tecla Enter poniendo su propiedad Default en true. Igualmente puede activar su evento OnClick cuando el usuario, presione la tecla ESC tan solo con poner la propiedad Cancel en true. Estas opciones no están disponibles para SpeedButton. Sus principales propiedades son:

Name: Nombre lógico con el que se referencia al componente.Caption: Texto del botón.Font: Modifica la fuente, estilo de fuente, tamaño, etc. del caption.Height y Width: Alto y ancho del botón en pixels.Left y Top: Posición superior izquierda del extremo superior izquierdo del botón relativa al del formulario en pixels.Enabled: Habilita o deshabilita la respuesta del botón a eventos.Hint: Texto de ayuda a pista rápida. Para podamos ver el Hint debe colocarse la propiedad ShowHint en true. Estas propiedades se encuentran en la mayoría de los componentes visuales.Visible: Determina cuando aparece el botón en el formulario.Glyph (sólo en BitBtn y SpeedButton): permite especificar el bitmap que aparece en el botón.Kind (sólo en BitBtn): determina el tipo de algunos bitmap predefinidos.Flat (sólo en SpeedButton): hace desaparecer el efecto 3D de los botones.Down (sólo en SpeedButton): especifica cuando el botón está presionado. Para quedar presionado la propiedad GroupIndex debe ser distinta de cero.TabOrder: especifica el orden en el que los componentes tendrán el foco.

40Tema 3.2.2.- Componentes en C++ Builder

ComponentesButton, BitBtn y SpeedButtonSus principales eventos son:

OnClick: ocurre cuando se hace click sobre el botón.OnMouseMove: ocurre cuando se mueve el mouse sobre el botón.

Un método muy empleado es:SetFocus: coloca el foco en el botón.

EditLa función principal de este componente visual es manejar todos los procesos de entrada y salida (input/output) del programa. El componente Edit, es el equivalente a las variables en cualquier lenguaje de programación, mas la instrucción de captura o despliegue correspondiente, es decir;

a) En PASCAL: Read (Ciudad) -> Edit1b) En C: printf("%d", sueldo) -> Edit2c) En C++, cin.get(nombre,30) -> Edit3

Es decir, que este componente permite capturar datos y también, como en el caso del componente Label, desplegar datos, textos, mensajes o resultados de operaciones, usando su propiedad Text. Esta propiedad, así como la propiedad Caption en Label, permiten igualarse a muchos procesos básicos, es decir es fácil igualar Text o Caption a un dato, una variable, otro Text o Caption, o una expresión algebraica normal, como en los siguientes ejemplos:

Edit1->Text = 5;Label2->Caption = "Palabra";

Edit3->Text = 87/ 6.2 ;Su valor por defecto es Edit1 y es en su propiedad Text donde se modifica, generalmente al principio de un programa se deja en blanco, y al ejecutarse el programa, el usuario lo llena con los datos solicitados o el programa lo llena con el resultado de las operaciones. Cuando un usuario lo carga con un dato, este es almacenado como tipo texto, independientemente de lo que haya escrito el usuario.Para resolver el problema de usar datos numéricos dentro de Text de un componente Edit, en operaciones matemáticas, basta agregarle a la propiedad Text, las funciones de conversión vistas, como .ToInt() o .ToDouble(), como se muestra en los siguientes ejemplos.

Edit3->Text= Edit2->Text.ToInt() * 5;Edit5->Text= 3 * pow( Edit2->Text.ToDouble(), double (4) );

41Tema 3.2.2.- Componentes en C++ Builder

ComponentesEditSi, por ejemplo, se pide resolver el problema de multiplicar dos números cualesquiera, se utilizarán tres componentes Edit (multiplicando, multiplicador, producto) como si fuesen tres variables simples directamente.El problema puede resolver de la siguiente manera:

void __fastcall TForm1::Button1Click(TObject *Sender){ Edit3->Text=Edit1->Text.ToInt()* Edit2->Text.ToInt();}

Y un posible resultado puede ser:

Observamos como el componente Edit permite capturar datos por parte del usuario del programa.Si se realizan divisiones con componentes Edit debemos recordar que al menos uno de ellos sea double, porque de lo contrario se trunca la parte fraccionaria. Para resolver el problema de conversión de datos o variables numéricas a Texto de un componente Edit, donde se tiene una variable numérica cargada, con un resultado o dato numérico y se pretende mandarla a un componente Edit o Label para su despliegue, existen dos manera sencillas, que son:

•Usando la clase AnsiString, que puede recibir como argumentos o parámetros una variable de tipo entera o double y convertirla directamente a una string, que es el tipo de dato que espera el componente Edit o el componente Label para su despliegue, por ejemplo:

42Tema 3.2.2.- Componentes en C++ Builder

ComponentesEdit

int a; // área de declaración de variablesdouble b;a = Edit1->Text.ToInt(); // área de captura de datosb = Edit2->Text.ToDouble();a = a+3; // área de operacionesb = b *5.1; // área de despliegue y conversión de números a strings o EditsLabel3->Caption = AnsiString(a);Edit4->Text = AnsiString(b);

Como se observa se puede transferir variables numéricas tanto a Label como a Edit mediante la clase AnsiString, sin embargo es mas sencillo usar el método que se usa en el programa dado de ejemplo para la multiplicación, es decir considerar los componentes Edit como variables normales.

•Para el caso de resultados decimales , la salida incluye todo el conjunto de decimales asociados a un tipo double (muchos ceros), para resolver este problema se pueden usar directamente algunos de los métodos asociados a la clase AnsiString, por ejemplo uno de esos métodos es; FormatFloat("string de formato", var double);

La string de formato contiene una serie de símbolos literales que se utilizan para darle el formato de salida deseado, esto símbolos o constantes literales junto con algunos ejemplos de salida con el formato que producen son:

0 1234 -1234 1 00.00 1234.00 -1234.00 0.50 0.00#.## 1234 -1234 .5#,##0.00 1,234.00 -1,234.00 0.50 0.00#,##0.00;(#,##0.00) 1,234.00 (1,234.00) 0.50 0.00#,##0.00;;Zero 1,234.00 -1,234.00 0.50 Zero0.000E+00 1.234E+03 -1.234E+03 5.000E-01 0.000E+00#.###E-0 1.234E3 -1.234E3 5E-1 0E0

43Tema 3.2.2.- Componentes en C++ Builder

ComponentesEditPor ejemplo:

double a; // área de declaración de variablesa = Edit1->Text.ToDouble(); // captura y conversión de datosa = a/3.1416 ; // operacionesEdit2->Text= FormatFloat("###,###.##", a); // conversión y despliegue de datos con formato

Veamos un ejemplo muy similar al de multiplicar asociando a Button1 la siguiente línea de comandos:Edit3->Text= FormatFloat("###,###.##",Edit1->Text.ToDouble()/ Edit2->Text.ToDouble());

En la figura vemos algunos posibles resultados:

Ejemplo 102.- Calcular el área de un triánguloVamos a construir un programa que nos facilite el modelo de solución del área del triángulo

conocidas la base y la altura. Construimos un formulario similar a:

44Tema 3.2.2.- Componentes en C++ Builder

ComponentesEjemplo 102.- Calcular el área de un triánguloEl código asociado al evento OnClick del componente Button quedará como sigue:

Edit3->Text=FormatFloat("###.##",Edit1->Text.ToDouble()*Edit2->Text.ToDouble()/2);

MaskEditEste componente de la pestaña Adittional es muy similar en su uso al componente Edit, excepto que proporciona una mascara especializada para el formato de datos, es decir se puede usar para que el usuario proporcione datos con formatos bien definidos, como son valores numéricos que incluyan puntos y comas por ejemplo 3,345.87, o que incluyan símbolos, o para el caso de fechas que lleven su propio separador como por ejemplo 16/06/2003.

También se puede usar, para asegurar que el dato proporcionado por el usuario, solo incluya números, o solo contenga letras, etc. Para dar formato al dato que el usuario debe proporcionar basta con hacer doble clic en la propiedad EditMask en (Inspector de Objetos), para desplegar la ventana que vemos. Observamos en la parte derecha de la ventana algunos ejemplos de mascaras de edición.

45Tema 3.2.2.- Componentes en C++ Builder

ComponentesMaskEditEn la ventanilla superior izquierda se colocan los caracteres especiales de edición y en la ventanilla inferior izquierda se muestra el formato que adquiere y se pueden proporcionar datos para probar el formato diseñado. Los principales caracteres especiales de edición son:

Carácter Significado! Los carácteres opcionales aparecen en blanco

> Todos los caracteres que le siguen se pasan a mayúsculas hasta el final de la máscara o hasta que seencuentra el carácter <.

< Todos los caracteres que le siguen se pasan a minúsculas hasta el final de la máscara o hasta que seencuentra el carácter >.

<> Los caracteres que siguen aparecen en mayúsculas o minúsculas según sean tecleados por el usuario.\ El carácter siguiente es un carácter literal. L Requiere una letra mayúscula o minúscula en esta posiciónl Permite una letra es esta posición pero no la requiereA Requiere un carácter alfanumérico (letras y/o números) en esta posicióna Permite un carácter alfanumérico en esta posición pero no lo requiereC Requiere un carácter arbitrario en esta posición.c Permite un carácter arbitrario en esta posición pero no lo requiere0 Requiere un numero en esta posición9 Permite un numero pero no lo requiere# Permite un numero y signos mas y menos en esta posición pero no lo requiere: Separador de horas, minutos y segundos para funciones horarias. / Separador de meses, días y años para funciones de fecha. ; Se utiliza para separar los tres campos o partes de que consta una mascara_ Para insertar espacios en blanco en el texto de la mascara

46Tema 3.2.2.- Componentes en C++ Builder

ComponentesMaskEditCualquier carácter que no aparezca en la tabla anterior puede aparecer en una máscara, pero se tomara como un literal cualquiera, es decir se insertará automáticamente y el cursor saltará a una posición posterior. El segundo campo de una mascara es un carácter simple que indica que carácter literal debe ser incluido como parte del texto del componente MaskEdit, por ejemplo (000)_000-000;0;*. Un 0 en el segundo campo indica que solo deben capturarse los nueve dígitos marcados con 0, en lugar de los 13 que tiene la mascara. El tercer campo de la mascara es el carácter que queremos que aparezca en lugar de espacios en blancos.Para procesar MaskEdit deberemos usar solo Text y no Text.ToDouble() y recuérdese que este formato es para capturar datos, no para mostrarlos, puesto que para este caso se usa FormatFloat().

ComboBoxExisten multitud de ocasiones en donde el usuario del programa tiene que proporcionar datos que provienen de un conjunto finito y muy pequeño de posibles respuestas, lo que significa que cada vez que se ejecute el programa, el usuario deberá proporcionar las mismas respuestas. Por ejemplo capitales de provincia en Andalucía, donde las posibles respuestas son: Almería, Cádiz, Córdoba, Granada, Huelva, Jaén, Málaga o Sevilla; o en la situación de preguntar por el sexo (Hombre, Mujer), etc. Para situaciones como esta, existen componentes que permiten programar por adelantado las posibles respuestas, y el usuario solo debe seleccionar la respuesta apropiada, en lugar de tener que escribirla. Este componente es el ComboBox, que nos permite definir en primera instancia un conjunto de datos, valores o respuestas asociados a un componente de edición cualquiera, de forma que el usuario tendrá la oportunidad de seleccionar un dato del conjunto de datos o respuestas ya definido. El componente ComboBox tiene dos partes:– Una parte de encabezado, para poner el nombre del grupo de respuestas (por ejemplo capitales de

provincia, sexo, etc.), que se carga usando la propiedad Text del componente; y– Una segunda parte que es la lista de opciones o respuestas que se debe cargar cuando se diseña la

ventana. Para la inclusión de datos debemos hacer doble clic en la propiedad Items en el Inspector de objetos y nos saldrá el siguiente editor de strings o cadenas:

47Tema 3.2.2.- Componentes en C++ Builder

ComponentesComboBox

En tiempo de ejecución del programa, toda la lista de respuestas, estará a la vista del usuario, para que seleccione la deseada. Basta que este pulse sobre la flechita que esta al lado del encabezado. Para procesar este componente debemos usar su propiedad Text de manera normal, es decir si la respuesta se desea de tipo string usaremos ComboBox1->Text, y si la respuesta se quiere numérica debemos convertir Text a ToInt() o ToDouble(). Por ejemplo, ComboBox1->Text.ToDouble().PanelPara poder organizar correctamente todos los datos e información que aparecen en las aplicaciones disponemos de dos métodos, bien trabajar con dos o más ventanas o bien utilizar alguno de los componentes de agrupamiento disponibles. El componente Panel es el más sencillo y común de los componentes de agrupamiento y se utiliza para poner un panel, cuadro o marco dentro de una ventana.El componente Panel puede contener toda una serie lógica de otros componentes. Tan solo se debe recordar que primero debemos colocar todos los paneles en el formulario y encima de ellos los componentes que contendrán.

48Tema 3.2.2.- Componentes en C++ Builder

ComponentesPanelEste componente también tiene una serie de propiedades que le dan una mejor presentación usando las propiedades BevelInner, BevelOuter, BevelWidth, y BorderWidth. Es decir, podemos dividir una ventana en varias partes, por ejemplo en un panel se ponen los componentes donde se capturan los datos de un problema y en otro panel se ponen los datos de salida.Para modificar programas construidos sin paneles, el procedimiento para agregarlos es:0. Mover todos los componentes a alguna parte de la ventana en la que no molesten. Si es necesario se amplía la ventana.1. Colocar los componentes panel en su posición.2. Seleccionamos con un clic el Componente a relocalizar.3. Seleccionamos del menú Edit la entrada Copy o mejor Cut (CTRL+C o CRTL+X)4. Clic dentro del panel, donde queremos el componente.5. Seleccionamos del menú Edit la entrada Paste (CTRL+V).6. Readaptamos la ventana al tamaño adecuado.GroupBoxEste componente es muy similar al componente panel, excepto que incluye una pestaña que permite dejar mas claro el propósito del grupo. El texto que identifica el propósito general del grupo se escribe dentro de la propiedad Caption en el Inspector de Objetos, teniendo seleccionado este componente GroupBox.Además de sus propiedades, métodos y eventos propios, como todos los componentes de este tipo, hereda las propiedades, métodos y eventos de todos los controles generales de tipo Windows.

Ejemplo 103.- Componentes de agrupamientoVamos a reconstruir el ejemplo de cálculo del área de un triángulo utilizando un componente

panel y un groupbox.

49Tema 3.2.2.- Componentes en C++ Builder

ComponentesMúltiples ventanasUn problema muy común en programación visual es el de poder crear, controlar y administrar dos o más formularios o ventanas desde una misma aplicación o proyecto.Lo primero que hay que entender para poder resolver este problema es que en C++Builder, cada formulario o ventana tiene asociados ciertos recursos especiales, ademas de los componentes que contiene relacionados todos ellos en un archivo, que por defecto, toma el nombre de Unit1.cpp. Es decir, si se crea un segundo formulario o ventana, dicho formulario, junto con sus recursos, componentes, etc., se encontraría contenido en el archivo llamado "Unit2.cpp" y así sucesivamente.Para crear un segundo formulario (Form2), se puede usar el icono de New Form de la barra de herramientas, o bien la entrada New Form del menú File.El segundo formulario se construye normalmente, pero queda el problema de donde situar el botón de ordenes, y la respuesta es que se pone en el primer formulario o ventana principal del programa. El proceso en este botón es similar al de los programas anteriores, es decir primero se capturan los datos (pantalla o ventana de captura), luego se resuelve las operaciones y finalmente se traspasan los datos a los componentes de la segunda ventana. Para poder realizar este proceso la sintaxis general es ahora:

Nombre_formulario -> Nombre_componente -> Nombre_propiedad

Los siguientes ejemplos aclararán estos conceptos:

Form5->Edit3->Text=Form1->Edit2->Text; //1int alfa = Form3->Edit4->Text.ToInt(); //2// 1. El contenido de la propiedad Text del Edit2 de Form1 se pasa a la propiedad Text del Edit3 del Form5.// 2. La variable tipo int alfa toma como valor el contenido, convertido a tipo int, del Edit4 del formulario Form3.Observamos que procesar elementos de distintas ventanas, es, inicialmente, sencillo, pero además existen ciertas condiciones que deberán cuidarse para que estos procesos funcionen, y estas condiciones son:

50Tema 3.2.2.- Componentes en C++ Builder

ComponentesMúltiples ventanas0. Crear y diseñar todas las ventanas junto con sus componentes y programas.1. Cualquier ventana que mencione o contenga una referencia dentro de su código a otra ventana,

deberá incluir en su Unit respectiva, la unidad (Unit) de la otra forma o ventana.2. Para incluir la unidad (Unit) de la otra ventana debemos tener seleccionada la ventana que llama y

usar la orden Include Unit del menú File, que mostrará una lista con todas las unidades (Unit) que se han diseñado, y debemos seleccionar la apropiada que se incluirá automáticamente en la ventana actual.

3. Si una ventana referencia dos o más ventanas diferentes debemos usar la orden File/Include Unit, tantas veces como sea necesario.

Este procedimiento permite construir programas con dos o más ventanas, pero el problema es que todas ellas estarán a la vista del usuario, para resolver este problema, el procedimiento más sencillo es poner en False la propiedad visible de la ventana que se quiera tener oculta y poner cualquiera de las siguientes instrucciones en el código del programa para que aparezcan o desaparezcan a voluntad:

Form2->Visible = true;Form2->Show(); // similar a la anterior, pero mas cortaForm2->ShowModal(); // no permite acceder a la primera ventana hasta que se cierra la segunda ventana

Si tenemos formularios de mas, o que ya no se quieren usar, o que están mal construidas se pueden quitar del proyecto usando el icono Remove File from Project de la barra de herramientas, y seleccionando la unidad que contiene el formulario a eliminar.

Ejemplo 104.- Múltiples ventanasVamos a realizar una aplicación que contenga en la ventana principal los siguientes

componentes: BitBtn, SpeedButton, MaskEdit y ComboBox. Respondiendo a distintos eventos se deben mostrar ventanas para cada componentes bien con Show o bien con ShowModal que expliquen de forma visible la principal utilidad de cada componente y sus principales propiedades.

51Tema 3.2.2.- Componentes en C++ Builder

Asignación de memoriaEn tiempo de ejecución de un programa toda la información que necesite manipular deberá estar, en un momento u otro, en la memoria RAM del ordenador. Sabemos que la memoria se divide en celdas de 8 bits (1 byte) y que a cada una de las cuales le corresponde una dirección.Ejemplo 105.- Direcciones de memoria.

Realizar una serie de declaraciones de variables y punteros para posteriormente mostrar el valor de dichas variables y su correspondiente dirección de memoria utilizando para ello componentes Label.

Tiempo de diseño

Tiempo de ejecución

52Tema 3.2.2.- Componentes en C++ Builder

Asignación de memoriaOperadores new y deleteInicialmente, un puntero no apunta a ningún sitio y, para poder usarlo, tendremos que asignarle un bloque de memoria y obtener su dirección. La cantidad de memoria asignada puede determinarlo el tipo propio del puntero, que se indica detrás de new, encargándose este de localizar un bloque de memoria adecuado en tamaño, reservarlo para el programa, almacenar la dirección del puntero y permitirnos el acceso al valor apuntado por él.A diferencia de la asignación de memoria estática, la memoria asignada por new está libre al comienzo del programa reservándose solamente cuando se llama a este operador. Cuando la memoria asignada con new no nos sea útil tendremos que liberarla, ya que a diferencia de lo que ocurre con una variable, la liberación no es automática. Para liberar la memoria se emplea el operador delete, al que pasaremos como parámetro el puntero que contiene la dirección de memoria del bloque a liberar y que es habitualmente el mismo que el de new. Un código cómo el siguiente origina el resultado que vemos.

void __fastcall TForm1::FormCreate(TObject *Sender){ int *Pnumero; Pnumero = new int; Edit1->Text= AnsiString(*Pnumero); *Pnumero = 125; Edit2->Text = AnsiString(*Pnumero); delete Pnumero;}

Cuando asignamos memoria con el operador new es posible especificar un valor inicial dándolo entre paréntesis detrás del tipo, por ejemplo Pnumero = new int(125) asigna memoria e inicializa.A veces es necesario asignar memoria no solamente para un número o un carácter, lo que podemos hacer es especificar el tamaño en el tipo de puntero. Supongamos por ejemplo que queremos reservar memoria para almacenar 25000 enteros. Es evidente que no vamos a crear 25000 identificadores, aunque si podríamos tener como recurso crear una matriz con 25000 elementos.

53Tema 3.2.2.- Componentes en C++ Builder

Asignación de memoriaOperadores new y deleteLa solución de la matriz solamente es valida si se conoce de antemano el número exacto de elementos, porque si dicho número se determina externamente, será difícil crear una matriz del tamaño adecuado sin que resulte, a veces pequeña, o a veces grande, desperdiciando memoria.Para este tipo de casos es posible asignar un bloque de memoria del tamaño que nosotros deseemos mediante los operadores new y delete, indicando dicho tamaño entre corchetes. Al utilizar delete dispondremos detrás del operador unos corchetes vacíos, indicando que lo que se libera es una matriz.Ejemplo 106.- Punteros y matrices

Ejemplo en el que empleamos la asignación de memoria dinámica mediante matrices, inicializamos los elementos y mostramos resultados tanto de direcciones de memoria como del contenido de las mismas. Diseñamos un formulario con un aspecto como el de la figura:

54Tema 3.2.2.- Componentes en C++ Builder

Asignación de memoriaEjemplo 106.- Punteros y matrices

El código es:

void __fastcall TForm1::Button1Click(TObject *Sender){ int *PunteroNumero; //Puntero a entero PunteroNumero = new int[5]; //Asignamos memoria para 5 int //Inicializamos los 5 elementos PunteroNumero[0] = 100; PunteroNumero[1] = 200; PunteroNumero[2] = 300; PunteroNumero[3] = 400; PunteroNumero[4] = 500; //Mostramos en los Edit el contenido y la dirección de memoria Edit1->Text = AnsiString(PunteroNumero[0]); Edit2->Text = AnsiString(PunteroNumero[1]); Edit3->Text = AnsiString(PunteroNumero[2]); Edit4->Text = AnsiString(PunteroNumero[3]); Edit5->Text = AnsiString(PunteroNumero[4]); Edit6->Text = AnsiString((unsigned int) &PunteroNumero[0]); Edit7->Text = AnsiString((unsigned int) &PunteroNumero[1]); Edit8->Text = AnsiString((unsigned int) &PunteroNumero[2]); Edit9->Text = AnsiString((unsigned int) &PunteroNumero[3]); Edit10->Text = AnsiString((unsigned int) &PunteroNumero[4]); delete [] PunteroNumero; //Liberamos la memoria asignada}

55Tema 3.2.2.- Componentes en C++ Builder

ComponentesEjemplo 107.- Sentencias if anidadas, ¿Cuál es el menor de tres números? Con componentes

Sobre un formulario vamos a situar dos componentes GroupBox de la pestaña Standard, a uno de ellos le vamos a llamar Entrada de datos y al otro El menor es. Sobre el primero situamos tres componentes Label y tres Edit (cambiando la propiedad name como A, B y C respectivamente), y sobre el segundo un componente Edit con la propiedad name establecida a Menor, además de un BitBtn en el que seleccionamos bkOK para la propiedad Kind. El aspecto inicial del proyecto lo vemos en la figura siguiente:

void __fastcall TForm1::BitBtn1Click(TObject *Sender){ float datoA, datoB, datoC, Resultado; datoA = StrToFloat(A->Text); datoB = StrToFloat(B->Text); datoC = StrToFloat(C->Text); if (datoA < datoB) if (datoA < datoC) Resultado = datoA; else Resultado = datoC; else if (datoB < datoC) Resultado = datoB; else Resultado = datoC; Menor->Text = FloatToStr(Resultado);}

56Tema 3.2.2.- Componentes en C++ Builder

Componentes

Ejemplo 108.- Decisiones con CheckBox y componente SpeedButtonVamos a crear un nuevo proyecto y sobre el formulario principal situamos cuatro componentes

SpeedButton (pestaña Additional) y cuatro componentes CheckBox (pestaña Standard). Distribuimos y modificamos la propiedad Caption de forma que quede algo similar a la figura siguiente. Hacemos doble clic sobre cada uno de los botones e incluimos el siguiente código:

CheckBoxEste componente permite al usuario seleccionar una opción o tomar una decisión directamente en pantalla, es decir en tiempo de ejecución. Es en la propiedad Text del componente donde se debe escribir el sentido que queremos dar a la selección.

SpeedButton1 CheckBox1->Checked=true; CheckBox2->Checked=false; CheckBox3->Checked=false; CheckBox4->Checked=false;SpeedButton2 CheckBox2->Checked=true; CheckBox1->Checked=false; CheckBox3->Checked=false; CheckBox4->Checked=false;

Hemos utilizado la propiedad booleana Checked de los componentes CheckBox para hacer que trabaje con una sola selección. Naturalmente los CheckBox pueden seleccionarse todos, aunque en el programa del ejemplo no parezca lo más apropiado.

SpeedButton3 CheckBox3->Checked=true; CheckBox1->Checked=false; CheckBox2->Checked=false; CheckBox4->Checked=false;SpeedButton4 CheckBox4->Checked=true; CheckBox1->Checked=false; CheckBox2->Checked=false; CheckBox3->Checked=false;

57Tema 3.2.2.- Componentes en C++ Builder

ComponentesRadioButton y RadioGroupEl componente RadioButton se utiliza para presentar al usuario un conjunto de opciones mutuamente excluyentes entre si, es decir si el usuario selecciona un componente RadioButton todos los demás componentes RadioButton en el formulario, se desmarcan o deseleccionan solos.En la propiedad Caption se pone el texto que identifica el propósito del botón y su propiedad Checked refleja el cambio (True o False). También su evento onclick se activa automáticamente cada vez que el usuario selecciona el RadioButton.La situación de que sean excluyentes entre si deberá resolverse por parte del programador, es decir si se supone un programa donde el usuario debe seleccionar uno de entre dos sexos y uno de entre cinco municipios, en este caso se ocupan ocho RadioButton, pero como todos son mutuamente excluyentes entre si, cuando el usuario seleccione uno de ellos, todos los demás se desmarcaran automáticamente. Para resolver este problema se deberán usar componentes de agrupamiento, como son el componente Panel y el componente GroupBox. Es decir se deberán encerrar en su propio panel o GroupBox todos los RadioButton lógicos, es decir en un Panel los de sexo, en otro Panel los de municipios, etc. De esta manera C++Builder los evalúa por separado y se puede tener seleccionado un RadioButton en cada Panel. En la figura vemos un ejemplo de lo dicho:

58Tema 3.2.2.- Componentes en C++ Builder

ComponentesRadioButton y RadioGroupEl componente RadioGroup es un componente especializado en la agrupación de RadioButton. Un componente u objeto RadioGroup es una caja especial que solo contiene componentes RadioButton, también cuando el usuario marca o selecciona uno de ellos, todos los demás se desmarcan o deseleccionan.Para añadir los RadioButton al componente RadioGroup debemos editar la propiedad Items en el Inspector de Objetos, que nos muestra el minieditor de strings. Debemos recordar que cada línea en el editor corresponderá a un RadioButton dentro del RadioGroup.Para procesar o programar un determinado RadioButton usareremos la propiedad ItemIndex que queda cargada con el numero de RadioButton seleccionado por el usuario. Por ejemplo:

if(Form1->RadioGroup1->ItemIndex==4){código a ejecutar si el usuario seleccionael RadioButton4 del RadioGroup1};

También se pueden desplegar los botones en una o más columnas, usando la propiedad Columns en el Inspector de Objetos, para indicarle cuantas columnas de RadioButton se quieren manejar.El ejemplo anterior resuelto con este componente podría tener un aspecto como el siguiente:

59Tema 3.2.2.- Componentes en C++ Builder

ComponentesListBoxComponente que permite procesar un conjunto de elementos de tipo string. Se puede añadir, eliminar e insertar ítems en la lista usando los métodos Add, Delete e Insert respectivamente de la propiedad Items. La propiedad Columns permite que ListBox tenga varias columnas y los items se pueden clasificar u ordenar usando la propiedad Sorted. Las propiedades MultiSelect y ExtendedSelect permiten al usuario hacer selecciones múltiples. Para determinar que ítem en particular esta seleccionado debemos validar la propiedad Selected y para conocer cuantos ítems se han seleccionado consultar los valores de la propiedad SelCount. La propiedad ItemIndex se utiliza para seleccionar la posición o índice de un ítem o elemento en la lista. La propiedad Style establece los estilos de ListBox, que son: lbStandard; LbOwnerDrawFixed; LbOwnerDrawVariable; LbVirtual y LbVirtualOwnerDraw. Ejemplo 109.- Números, su cuadrado y su raíz cuadrada.

Vamos a desplegar los números enteros comprendidos entre 15 y 25, su cuadrado y su raíz cuadrada utilizando componentes ListBox y su método Add de la propiedad Items. Para este problema situaremos sobre el formulario principal Form1, tres componentes label con su font seleccionado en color rojo, tres componentes ListBox y un componente Button que en su evento OnClick contendrá los bucles o ciclos for y la carga de los componentes ListBox.

60Tema 3.2.2.- Componentes en C++ Builder

ComponentesEjemplo 110.- Tablas de multiplicar.

Vamos a implementar un programa que muestre las tablas de multiplicar hasta el 15 de la forma en que estamos acostumbrados a verlas. Para ello vamos a emplear dos componentes ya conocidos, el componente RadioGroup y el componente ListBox. Emplearemos el método Add(valor) en la propiedad Items de ListBox para cargar todos sus elementos o valores en tiempo de ejecución del programa y la propiedad ItemIndex del componente RadioGroup; con código asociado al evento OnClick del elemento RadioGroup y sentencias condicionales y bucles.Para este problema situaremos sobre el formulario principal Form1 los elementos necesarios para que el aspecto inicial del formulario en tiempo de diseño es el siguiente:

El código del programa adecuando el resto de ItemIndex podría ser el siguiente:void __fastcall TForm1::RadioGroup1Click(TObject *Sender){int x;if(Form1->RadioGroup1->ItemIndex==0){ListBox1->Items->Clear();for (x=0 ; x<=15 ; x++){ListBox1->Items->Add(AnsiString("1 x ")+(x)+AnsiString(" = ")+(1*x));};};

...Sentencias similares para resto de ItemIndex...

}

61Tema 3.2.2.- Componentes en C++ Builder

ComponentesEjemplo 110.- Tablas de multiplicar.El programa en ejecución es:

Ejemplo 111.- Más tablas de multiplicar.Vamos a mejorar el ejemplo anterior permitiendo al usuario entrar el número del que desea

obtener la tabla y el número de items que quiere obtener de la misma. Para ello vamos a emplear el componente ListBox y el método Add(valor) en la propiedad Items de ListBox para cargar todos sus elementos o valores en tiempo de ejecución del programa.Para esto situaremos sobre el formulario principal Form1 los elementos necesarios para que el aspecto inicial del formulario en tiempo de diseño sea similar al siguiente:

62Tema 3.2.2.- Componentes en C++ Builder

ComponentesEjemplo 111.- Más tablas de multiplicar.

Observese el cambio de nombre y de icono en el formulario.A continuación vemos el código completo del programa ya comentado.void __fastcall TForm1::Button1Click(TObject *Sender){/* Declaramos e inicializamos las variables enteras x, y, z x será el número del que queremos obtener la tabla asociado a Edit1 z será el número de items que queramos obtener asociado a Edit2 y será la variable empleada en el bucle */int x=0, y=0, z=0;ListBox1->Items->Clear(); /* Borramos el contenido de ListBox para cada ejecucióny Cambiamos el contenido de los Edit a entero y asignamos su valor a la variable correspondiente*/x = StrToInt(Edit1->Text);z = StrToInt(Edit2->Text);

// Ejecutamos el bucle hasta alcanzar el número de items indicado por zwhile(y<=z){// Añadimos contenido a ListBox{ListBox1->Items->Add(AnsiString(" ")+ (x)+AnsiString(" x ")+(y)+AnsiString(" = ")+(x*y));};y++;};}

63Tema 3.2.2.- Componentes en C++ Builder

ComponentesEjemplo 111.- Más tablas de multiplicar.void __fastcall TForm1::FormCreate(TObject *Sender){/* Asociado al evento OnCreate del Form borramos el contenido de los Edit*/Edit1->Text="";Edit2->Text="";}//---------------------------------------------------------------------------void __fastcall TForm1::Edit1MouseMove(TObject *Sender, TShiftState Shift,int X, int Y){/* Establecemos el foco en Edit1 asociado al evento OnMouseMove */Edit1->SetFocus();}//---------------------------------------------------------------------------

64Tema 3.2.2.- Componentes en C++ Builder

ComponentesTrabajo con componentes Edit, Buttom y LabelEditLa principal finalidad de un Edit es permitir la entrada de un texto por parte del usuario que se almacena en su propiedad Text, a la que podemos dar un valor inicial en tiempo de diseño. Este componente no cuenta con la propiedad Caption, por lo que se suele disponer una etiqueta de texto adjunta que sirve como título.Existe un componente en la pestaña Additional que se compone de un Label y de un Edit, el LabeledEdit, que resulta sencillo de manejar cuando se conocen los dos componentes de forma individual. Cuando en tiempo de ejecución el usuario modifica el contenido de un Edit, su propiedad Modified se establece como true. Nosotros podemos, mediante código, comprobar el valor de esta propiedad y, en caso de que proceda, recuperar la entrada realizada por el usuario leyendo la propiedad Text. Longitud del Texto Por defecto el control Edit no pone ningún límite a la cantidad de texto que el usuario puede introducir y, en caso de que sea necesario, desplazará el contenido actual a medida que se introducen nuevos caracteres. Si es necesario, podemos limitar el número de caracteres que es posible introducir mediante la propiedad MaxLength. El valor 0 indica que no hay un límite establecido y cualquier otro número entero fija la longitud máxima de la propiedad Text. Selección de texto Mientras se edita el contenido de un control Edit, el usuario puede marcar una porción del texto, mediante la combinación de la tecla Shitf y los cursores o bien con el ratón, con el fin de realizar alguna operación que le afecte, como puede ser eliminarlo o copiarlo al portapapeles. En cualquier momento podemos saber qué texto es el que hay seleccionado en el control, para lo que disponemos de las propiedades SelStart, SelLength y SelText. La primera contiene el carácter a partir del cual se ha seleccionado, sabiendo que el primero de los existentes es el carácter 0. La segunda propiedad contiene el número de caracteres que hay marcados y la tercera contiene el texto.El valor de estas propiedades también puede ser establecido por el código de nuestro programa, seleccionando automáticamente el texto que nos interese. Si deseamos marcar todo el texto contenido en el control podemos realizar una simple llamada al método SelectAll().

65Tema 3.2.2.- Componentes en C++ Builder

ComponentesTrabajo con componentes Edit, Buttom y LabelLas operaciones de copiar, cortar y pegar con el portapapeles (clipboard), pueden ser también realizadas mediante código usando los métodos adecuados. Método ClearSelection() elimina el texto que hay seleccionado. Método CopyToClipboard() copia el texto al portapapeles.Método CutToClipboard() copia el texto al portapapeles y lo elimina del campo de edición. PasteFromClipboard() permite recuperar el texto que hay en el portapapeles insertándolo en Edit en la posición actual del cursor.Texto de sólo lectura y oculto Si lo que queremos es solamente mostrar un valor en un componente Edit e impedir que el usuario pueda modificarlo basta con establecer la propiedad ReadOnly a true. Si lo que queremos es que al solicitar cualquier tipo de dato éste no sea visible por terceras personas (caso típico de las contraseñas o password) podemos conseguirlo con la propiedad PasswordChar haciendo que el Edit vaya representando cada uno de los caracteres introducidos mediante un cierto símbolo, como puede ser un asterisco o el carácter que asignemos a la propiedad.Controles de entrada Hay ocasiones en las que es necesario garantizar que todas las letras sean facilitadas en mayúsculas o en minúsculas con el fin de evitar posteriores fallos de comparación. Mediante la propiedad CharCasepodemos forzar estas situaciones asignándole los valores ecNormal, ecUpperCase o ecLowerCase. ButtomPara dotar a un botón de una tecla de acceso rápido utilizable con la tecla Alt (Alternate) basta con anteponer el carácter & a la letra que queremos que lo active, que aparecerá subrayada. Es normal que en un formulario existan varios botones pudiendo dos de ellos ser activados pulsando la tecla Enter o la tecla Esc. Si la propiedad Default tiene el valor true el botón actuará como botón por defecto, es decir, que se activará cuando se pulse la tecla Enter. Si Cancel está a true, el botón será el botón de cancelación o tecla Esc. Podemos pulsar el botón utilizando el cursor del ratón, la tecla de acceso rápido, desplazándonos hasta él con la tecla Tab y pulsando la barra espaciadora, con la tecla Enter si es el botón por defecto, o con la tecla Esc si es el botón de cancelación.

66Tema 3.2.2.- Componentes en C++ Builder

ComponentesTrabajo con componentes Edit, Buttom y LabelLabelUna etiqueta Label es un componente que presenta un texto en el formulario (propiedad Caption) pero que no puede tomar el foco de entrada ni podemos acceder a él con la tecla Tab. Sólo recibe eventos de ratón.

Propiedad Uso ValoresAutoSize El tamaño de la etiqueta se ajusta automáticamente al contenido de ésta o no. true o false

Alignment Alineación del textoIzquierda: taLeftJustify Derecha: taRightJustify Centro: taCenter

FocusControlTiene sentido cuando la etiqueta se usa como título de otro control. Sirve paraque la etiqueta de texto sepa a qué control debe pasar el foco de entrada cuandose pulse la tecla de acceso rápido (&).

Nombre del control querecibe el foco.

Ejemplo 112.- Componentes Edit, Buttom y LabelResolveremos el ejemplo paso a pasoPor un lado vamos a colocar sobre un Form con Caption = Trabajo con componentes Edit, Buttom

y Label un componente Panel del que eliminamos el Caption y establecemos propiedad Color en clAqua y Width = 480.

Insertamos en el Panel una etiqueta estableciendo a false la propiedad AutoSize y redimensionamos su tamaño de forma que ocupe prácticamente todo el ancho del panel. Asignamos a la etiqueta el Color clYellow y comprobamos que la propiedad Alignment tiene el valor taLeftJustify. El valor de Caption va a ser Esto es una etiqueta.

Insertar en panel tres botones de la forma siguiente: Buttom1: Caption = Izquierda Buttom2 : Caption = Centro y Buttom3: Caption = Derecha

Establecemos a true propiedad Default de Buttom1 (Izquierda) y a la propiedad Cancel de Buttom3 (Derecha).

Generamos el evento OnClick de Buttom1 y asignamos, mediante código, el valor taLeftJustify a la propiedad Alignment de la etiqueta. Repetimos para los otros botones asignando los valores taCenter y taRightJustify.

67Tema 3.2.2.- Componentes en C++ Builder

ComponentesTrabajo con componentes Edit, Buttom y LabelEjemplo 112.- Componentes Edit, Buttom y Label

Modificar lo necesario para permitir el acceso mediante teclas rápidas a cada uno de los botones y establecer el color de fondo de la etiqueta al que actualmente tenga el panel cuando el ratón esté situado sobre la misma.

Insertamos en el formulario tres Edit, que estarán encabezados por tres Label y tres botones para que tenga el aspecto siguiente:

El primer Edit, que recibirá el foco desde su etiqueta (propiedad FocusControl) lo utilizaremos para comprobar el funcionamiento de las propiedades MaxLength, a la que asignaremos el valor 10, y PasswordChar, a la que asignaremos el valor *.

El segundo Edit, que recibirá el foco desde su Label lo usaremos para ver cómo podemos controlar la entrada de caracteres, permitiendo tan sólo la introducción de dígitos numéricos. Para ello vamos a generar el siguiente gestor de eventos OnKeyPress.

68Tema 3.2.2.- Componentes en C++ Builder

ComponentesTrabajo con componentes Edit, Buttom y LabelEjemplo 112.- Componentes Edit, Buttom y Label

void __fastcall TForm1::Edit2KeyPress(TObject *Sender, char &Key){ if ((Key < '0' || Key > '9') && Key != 8) Key=0;/* Se comprueba que el carácter sea un dígito o la tecla de borrado.Los caracteres se encierran entre comillas simples porque estamos comparando un carácter tipo char.Asignar a Key el valor 0 es anular la pulsación. */}

El último Edit (recibe el foco de su Label) lo vamos a usar para probar los métodos de copiar, borrar y pegar el texto seleccionado. Será al pulsar cualquiera de los tres botones que hemos dispuesto debajo cuando se realice la acción de copiado, borrado o pegado, gracias al código que asociaremos al evento OnClick de cada uno de los botones de la forma que se muestra a continuación.

void __fastcall TForm1::Button4Click(TObject *Sender){ Edit3->SelectAll(); Edit3->CopyToClipboard(); Edit3->SetFocus(); }void __fastcall TForm1::Button5Click(TObject *Sender){ Edit3->ClearSelection(); Edit3->SetFocus(); }void __fastcall TForm1::Button6Click(TObject *Sender){ Edit3->PasteFromClipboard(); Edit3->SetFocus(); }

69Tema 3.2.2.- Componentes en C++ Builder

ComponentesTipos de propiedadesLas propiedades de los componentes de la VCL tienen asignado un tipo de dato que determina los valores que esta puede tomar. Hay propiedades de tipo bool (Visible), otras de tipo string (Caption) y otras de tipo enumerado (BorderIcons) que solamente pueden tomar valores de una lista prefijada. A continuación vemos lo que muestra la ayuda de BorderIcons.

Indica que la propiedad BorderIcons de un formulario es del tipo TborderIcon es de tipo enumerado, y que, por tanto, sólo puede tomar los valores preestablecidos.

70Tema 3.2.2.- Componentes en C++ Builder

ComponentesTipos de propiedades

Asociamos a los botones de minimizar el código siguiente. Para botón Desactivarvoid __fastcall TForm1::Button1Click(TObject *Sender){ TBorderIcons VarBorderIcon = BorderIcons; VarBorderIcon >> biMinimize; BorderIcons = VarBorderIcon;}Para botón Activarvoid __fastcall TForm1::Button2Click(TObject *Sender){ TBorderIcons VarBorderIcon = BorderIcons; VarBorderIcon << biMinimize; BorderIcons = VarBorderIcon;}El resto de botones es similar trabajando con el valor enumerado correspondiente.

Ejemplo 113.- Propiedad BorderIconsRealizar una aplicación para trabajar con esta propiedad en

tiempo de ejecución.Partimos de un diseño similar al siguiente, en el que al botón Salir le hemos establecido su propiedad Visible a false.

71Tema 3.2.2.- Componentes en C++ Builder

ComponentesTrabajo con componentes Memo, CheckBox, RadioButton y RadioGroupMemoYa hemos visto el uso del componente Edit para solicitar al usuario alguna entrada, pero esta no puede tener mas que una línea. Cuando necesitemos una entrada de texto que ocupe varias líneas podemos usar un componente Memo que posee muchas propiedades de las vistas para el Edit (ReadOnly, MaxLength, Text, ...), así como con los métodos relacionados con las operaciones del portapapeles. Un Memo puede tener barras de desplazamiento o ScrollBars, permitiendo trabajar con líneas más largas que el espacio horizontal disponible y con más líneas de las que es posible mostrar de forma simultánea. La propiedad de tipo enumerado TScrollBars permite el uso de estas barras de desplazamiento. Esta propiedad puede tomar los valores:

0 ssNone //Ninguna1 ssVertical //Sólo la vertical2 ssHorizontal //Sólo la horizontal3 ssBoth //Las dos

El texto que contiene un Memo es accesible mediante la propiedad Text, al igual que en un Edit. Pero resulta más útil y conveniente acceder a ese texto línea a línea, para lo que el componente dispone de la propiedad Lines que es de tipo Strings. Sus dos métodos más interesantes tienen relación con guardar o recuperar el texto en un archivo en disco y son SaveToFile() y LoadFromFile(), que tienen como único parámetro el nombre del fichero donde se va a guardar o del que se va a recuperar la información del Memo. Otra propiedad muy interesante es Count con la que podemos averiguar en cada momento cuántas líneas tiene simplemente haciendo: Memo1->Lines->Count.Un componente Memo tiene la posibilidad de trabajar con las teclas Enter y Tab como parte de la edición del texto siempre que él esté activo. Pero, por defecto, estas teclas tienen su función propia en un formulario. Para que al pulsar la tecla Enter el componente Memo la reconozca como salto de línea y no como activación de, por ejemplo, el botón por defecto, debemos asignar el valor true a la propiedad WantReturns. Lo mismo ocurre con la propiedad WantTabs, que si está activada permitirá insertar tabulaciones en el texto en lugar de pasar el foco de entrada al siguiente componente del formulario.

72Tema 3.2.2.- Componentes en C++ Builder

ComponentesTrabajo con componentes Memo, CheckBox, RadioButton y RadioGroup

CheckBox Este componente permite mostrar y seleccionar información de tipo bool, representándose los dos estados posibles visualmente mediante una casilla, que puede contener o no en su interior una marca. La propiedad Checked nos permite saber el estado actual del componente y, como no, modificarlo; estando a true cuando esté marcado y a false en caso contrario. Podemos poner todos los componentes CheckBox que necesitemos en un formulario, no afecto el hecho de que alguno de ellos esté activo al resto, es decir no son opciones excluyente entre sí. Para que varias opciones sean excluyentes se usan componentes RadioButton. Lo más común es agrupar los componentes CheckBox en un contenedor denominado GroupBox que tiene la posibilidad de asignar un título común a los componentes CheckBox que lo componen.

RadioButton y RadioGroup El componente RadioButton también cuenta con una propiedad Checked en la que se almacena su estado. Si tenemos que usar varios RadioButton en un formulario y que se destinen a solicitar datos diferentes que tengan, a su vez, opciones exclusivas entre sí, debemos usar componentes RadioGroup.Para establecer las opciones de un RadioGroup tendremos que editar el contenido de la propiedad Items, que es de tipo Strings. En modo diseño haremos doble clic sobre la propiedad Items para abrir el editor específico, añadiendo los títulos de las opciones que deseemos mostrar. En tiempo de ejecución podremos usar los métodos Add(), Append(), Insert() y Clear() para añadir o eliminar elementos. Los elementos RadioButton existentes en un RadioGroup se numeran con un índice que comienza en 0. Este índice nos servirá para saber qué opción es la que está activa o bien para establecerla, mediante la propiedad ItemIndex. De esta forma no es necesario comprobar la propiedad Checked de cada uno de los RadioButton que aparece en el RadioGroup.

73Tema 3.2.2.- Componentes en C++ Builder

ComponentesTrabajo con componentes Memo, CheckBox, RadioButton y RadioGroupEjemplo 114.- Trabajo con componentes Memo, CheckBox, RadioButton y RadioGroup

Vamos a realizar una aplicación para mostrar el uso de estos componentes, sus propiedades y los métodos descritos en este apartado.Comenzamos una nueva aplicación e incluimos en el Form los siguientes componentes: Tres Label, un Memo, un GroupBox, dos CheckBox dentro de un GroupBox, un RadioGroup y dos Button, de forma que inicialmente tengamos un aspecto como el que vemos a continuación:

Continuamos dando los pasos necesarios para conseguir como código fuente del Unit asociado al Form el que vemos seguidamente:

74Tema 3.2.2.- Componentes en C++ Builder

Componentes

75Tema 3.2.2.- Componentes en C++ Builder

Componentes

76Tema 3.2.2.- Componentes en C++ Builder

Componentes

77Tema 3.2.2.- Componentes en C++ Builder

ComponentesTrabajo con ListBoxSe trata de un componente que nos permite mostrar listas de elementos de las que es posible seleccionar uno o varios. Tiene un funcionamiento parecido al del RadioGroup, aunque visualmente su aspecto es diferente. Los elementos del ListBox están contenidos en la propiedad Items, que, como sabemos, es un objeto de tipo Strings. En tiempo de diseño podemos usar el editor de código asociado para incluir los elementos que queramos en la lista simplemente haciendo doble clic sobre la propiedad Items. En cambio, en tiempo de ejecución, podemos usar los métodos siguientes:

Método Descripción

Add() Una cadena de texto es el parámetro que la añade como un nuevo elemento al final de la lista, salvo quela propiedad Sorted del ListBox esté a true, en cuyo caso se insertará en la posición que le corresponda.

Insert() Toma dos parámetros, de los que el primero es la posición en la que se desea insertar el elemento y elsegundo el texto a añadir.

Delete() Método que nos permite eliminar el elemento de la lista del que facilitamos su índice.Clear() Elimina todas las cadenas existentes sin necesidad de suministrarle parámetros.

IndexOf() Devuelve el índice de la cadena dada como parámetro. Si retorna -1 la cadena no se encuentra.

Move() Damos el índice en que se encuentra actualmente y el índice correspondiente al punto al que se deseamover.

Exchange() Similar a Move() lo que hace es intercambiar las posiciones de los elementos correspondientes.SaveToFile() Guarda el contenido en un archivo en disco, debiendo facilitar el nombre.

LoadFromFile() Recupera la lista de elementos de un archivo cuyo nombre se facilita como parámetro.

La propiedad ItemIndex del ListBox indica en cada momento qué elemento hay seleccionado. Un valor -1 indica que no hay ninguno seleccionado. Cuando contiene más elementos de los que puede mostrar de forma simultánea aparece una barra de desplazamiento vertical.

78Tema 3.2.2.- Componentes en C++ Builder

ComponentesTrabajo con ListBoxEjemplo 115.- Trabajo con ListBox

Realizar un programa que nos permitirá añadir elementos a un ListBox en tiempo de ejecución con el texto que se facilite en un Edit. También se podrá añadir antes y después de la selección, eliminar el elemento seleccionado o eliminar todos los elementos del ListBox. Mediante un componente CheckBox habilitaremos la ordenación de los elementos.Comenzamos por diseñar un formulario como el siguiente:

Al botón Añadir le establecemos la propiedad Default a true para permitir la inserción mediante la tecla Enter del texto introducido en el Edit y al botón Borrar le establecemos la propiedad Enabled a false para que este no esté activo si no tenemos ningún elemento seleccionado. El resto del proceso es ir creando los gestores de eventos que vemos seguidamente con el código que debemos insertar en los mismos.

79Tema 3.2.2.- Componentes en C++ Builder

ComponentesTrabajo con ListBoxvoid __fastcall TForm1::Button1Click(TObject *Sender){ ListBox1->Items->Add(Edit1->Text); Edit1->SelectAll(); // Selecciona el contenido del Edit}//---------------------------------------------------------------------------void __fastcall TForm1::ListBox1Click(TObject *Sender){/* Activación o desactivación del botón borrar según haya o noseleccionado algún elemento del ListBox */ Button6->Enabled=ListBox1->ItemIndex != -1;}//---------------------------------------------------------------------------void __fastcall TForm1::Button6Click(TObject *Sender){ // Eliminamos el texto seleccionado ListBox1->Items->Delete(ListBox1->ItemIndex); // Desactivamos el botón de Eliminar Button6->Enabled=false; }//---------------------------------------------------------------------------void __fastcall TForm1::Button7Click(TObject *Sender){ // Borramos todo ListBox1->Items->Clear();}//---------------------------------------------------------------------------

80Tema 3.2.2.- Componentes en C++ Builder

ComponentesTrabajo con ListBoxvoid __fastcall TForm1::CheckBox1Click(TObject *Sender){ // Activamos o desactivamos la ordenación ListBox1->Sorted=CheckBox1->Checked;}//---------------------------------------------------------------------------void __fastcall TForm1::Button2Click(TObject *Sender){ // Insertamos delante del elemento seleccionado ListBox1->Items->Insert(ListBox1->ItemIndex,Edit1->Text);}//---------------------------------------------------------------------------void __fastcall TForm1::Button3Click(TObject *Sender){ // Insertamos detrás del elemento seleccionado ListBox1->Items->Insert(ListBox1->ItemIndex+1,Edit1->Text);}//---------------------------------------------------------------------------void __fastcall TForm1::Button4Click(TObject *Sender){ // Movemos arriba la selección if (ListBox1->ItemIndex != -1) ListBox1->Items->Move(ListBox1->ItemIndex,ListBox1->ItemIndex-1); else ShowMessage("No hay nada seleccionado");}//---------------------------------------------------------------------------

81Tema 3.2.2.- Componentes en C++ Builder

ComponentesTrabajo con ListBoxvoid __fastcall TForm1::Button5Click(TObject *Sender){ // Cambiamos la selección con el primer elemento de la lista if (ListBox1->ItemIndex != -1) ListBox1->Items->Exchange(ListBox1->ItemIndex,0); else ShowMessage("No hay nada seleccionado");}Trabajo con ComboBox o listas combinadasEn el apartado anterior hemos usado un ListBox para guardar una lista de elementos procedentes de un Edit. El componente ComboBox es la unión de un Edit y un ListBox incorporando las funciones de ambos componentes y, por tanto, las propiedades Text, MaxLenggth, Items, ItemIndex, etc. El funcionamiento y aspecto de un ComboBox dependen de su propiedad Style que es de tipo TComboBoxStyle, pudiendo tomar, entre otros, los valores siguientes:

Valor Descripción

csDropDown Se trata del estilo establecido por defecto y presenta un Edit en el que es posible introducir texto. Elbotón del extremos derecho despliega una lista con los elementos que contiene.

csSimple El ComboBox aparece como un Edit sin botón ni lista desplegable adjunta. Para recorrer los elementosde ésta debemos usar las teclas de cursor arriba y abajo.

csDropDownList Con este valor se permite al usuario seleccionar uno de los valores de la lista pero no puede introducirtexto alguno.

Ejemplo 116.- Trabajo con ComboBoxRealizar un programa para controlar la propiedad Style de un ComboBox mediante las tres

opciones suministradas por un componente RadioGroup.

82Tema 3.2.2.- Componentes en C++ Builder

ComponentesTrabajo con ListBoxAntes de comenzar con el ejemplo vamos a describir el operador static_cast que se usa en las propiedades tipo enumerado para referirse a los valores con su nombre mediante una conversión de la posición que ocupa el valor dentro de los posibles (comenzando por la posición 0). EstSu sintaxis básica es:

static_cast <tipo_enumerado> (posición del valor)Diseñamos un formulario similar al siguiente:

Situamos un ComboBox al que establecemos como valor csDropDown para la propiedad Style y eliminamos el contenido de su propiedad Text.También situamos un RadioGroup con las tres opciones que vemos y que nos van a permitir cambiar el estilo del ComboBox en tiempo de ejecución.Veamos en dos fases el código necesario para nuestros propósitos:Por un lado deberemos controlar cada pulsación de tecla sobre el ComboBox, mediante el evento OnKeyPress, para que en el momento en que se detecte la pulsación de la tecla Enter se almacene el texto en el ComboBox pero ignorando la pulsación de dicha tecla. El código que deberemos escribir es el siguiente:

83Tema 3.2.2.- Componentes en C++ Builder

ComponentesTrabajo con ListBoxvoid __fastcall TForm1::ComboBox1KeyPress(TObject *Sender, char &Key){ if (Key == 13) // Tecla Enter { ComboBox1->Items->Add(ComboBox1->Text); ComboBox1->SelectAll(); Key=0; }}Por otro lado debemos hacer la propiedad ItemIndex=0 para el componente RadioGroup y controlar su evento OnClick para establecer el estilo adecuado para el ComboBox según la opción que seleccionemos. Esta asignación se realizará de forma directa llevando a cabo una conversión de tipo de la forma siguiente:void __fastcall TForm1::RadioGroup1Click(TObject *Sender){ ComboBox1->Style= static_cast <TcomboBoxStyle> (RadioGroup1->ItemIndex);}Ejemplo 117.- Raíces con funciones

Vamos a establecer una función con asignación de un valor por defecto a uno de sus parámetros con el fin de que, por defecto, calcule la raíz cuadrada del número especificado.Recordemos que si en la declaración de una función asignamos valores por defecto a los parámetros no será indispensable facilitar el valor en la llamada a la función en aquel o aquellos que hayamos especificado por defecto. Para asignar un valor por defecto a un parámetro basta con utilizar el operador de asignación detrás del nombre del parámetro facilitando a continuación el valor, todo ello naturalmente en la cabecera de la función, entre los paréntesis, y estando de acuerdo el valor con el tipo especificado.

84Tema 3.2.2.- Componentes en C++ Builder

ComponentesEjemplo 117.- Raíces con funcionesComenzamos por situar un formulario con las siguientes propiedades:

Height = 150 y Width = 350Caption = RaícesBorderIcon: biMinimize = false, biMaximize = false y biSystemMenu = false. Esto hará que la

ventana no presente los iconos ni de maximizar, ni de minimizar ni de cerrar. Tampoco presentará el icono ni el menú contextual asociado.

BorderStyle = bsSingle. Hará que se presente un borde de una línea sencilla y el tamaño de la ventana no será escalable.

Position = poScreenCenter. La ventana de la aplicación aparecerá centrada en la pantalla.

Sobre el formulario situamos:Un componente ListBox con Height = 70 y Width = 330 Un botón con Caption = &Salir.

Ambos componentes los alineamos Center in windows.El aspecto en tiempo de diseño será:

85Tema 3.2.2.- Componentes en C++ Builder

ComponentesEjemplo 117.- Raíces con funcionesEl código completo del programa es:#include <vcl.h>#pragma hdrstop#include <math.h> //Para usar pow()#include "Codigo.h"//---------------------------------------------------------------------------#pragma package(smart_init)#pragma resource "*.dfm"TForm1 *Form1;//---------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner){}//---------------------------------------------------------------------------AnsiString AlmacenDatos; /*Declaracion global de un AnsiString para ir guardando los resultados obtenidos con los datos que se pasen *///---------------------------------------------------------------------------/* Declaramos la función Raiz con los parámetros: Argumento de tipo __int64 para trabajo con números grandes Indice de tipo int con valor por defecto 2 */void Raiz(__int64 Argumento, int Indice=2){/* En Almacen de Datos vamos guardando las cadenas y los valores pasados o por defecto de los parámetros. El cálcula de la raiz lo realizamos con la función pow() */

86Tema 3.2.2.- Componentes en C++ Builder

ComponentesEjemplo 117.- Raices con funciones AlmacenDatos = "La raiz de Indice " + AnsiString(Indice) + " del número " + AnsiString(Argumento)+ " es: " + AnsiString(pow(Argumento,1.0/Indice));}//MOSTRMOS LOS RESULTADOS ASOCIADOS A: TForm1::FormCreatevoid __fastcall TForm1::FormCreate(TObject *Sender){ Raiz(16); //Pasamos un parámetro (se calcula la raiz cuadrada) ListBox1->Items->Add(AlmacenDatos); //Añadimos los resultados Raiz(27,3); //Pasamos los dos argumentos (se calcula la raiz cúbica) ListBox1->Items->Add(AlmacenDatos); //Añadimos los resultados Raiz(30517578125,5); //Pasamos los dos argumentos (se calcula la raiz quinta) ListBox1->Items->Add(AlmacenDatos); //Añadimos los resultados Raiz(999,15); //Pasamos los dos argumentos (se calcula la raiz 15) ListBox1->Items->Add(AlmacenDatos); //Añadimos los resultados Raiz(3); //Pasamos un parámetro (se calcula de nuevo la raiz cuadrada) ListBox1->Items->Add(AlmacenDatos); //Añadimos los resultados}//---------------------------------------------------------------------------//NECESITAMOS UN BOTON PORQUE HEMOS DESABILITADO LOS ICONOS PARA CERRARvoid __fastcall TForm1::Button1Click(TObject *Sender){ Application->Terminate(); }

87Tema 3.2.2.- Componentes en C++ Builder

ComponentesTrabajo con FormStyleLas opciones de FormStyle son: fsNormal, fsMDIChild, fsMDIForm y fsStayOnTop y se emplea si queremos que en una aplicación un formulario contenga a otros. Este tratamiento de formularios se denomina Multiple Document Interface (Interface de Documento Múltiple) y hace muy fácil este tipo de aplicaciones.

Valor SignificadofsNormal El formulario no es ni ventana MDI padre ni ventana MDI hijo.

fsMDIChild El formulario es una ventana MDI hijo. fsMDIForm El formulario es una ventana MDI padre.

fsStayOnTopEl formulario permanece sobre todo en el escritorio y sobre otros formularios del proyecto, excepto sobre los quetambién tiene la propiedad FormStyle a fsStayOnTop. Si un formulario fsStayOnTop lanza otro del mismo tipo,ninguno permanecerá coherentemente sobre el otro.

Si el formulario es el principal su propiedad FormStyle debe ser fsMDIForm. No es aconsejable cambiar FormStyle en tiempo de ejecución.Ejemplo 118.- Uso de FormStyle0.- Se trata de realizar un programa multiventana para trabajar con esta propiedad y aprender su comportamiento en tiempo de ejecución. Seguimos el siguiente proceso:1.- Creamos una nueva aplicación con File/New Application y, con el inspector de objetos, cambiamos, la propiedad FormStyle a fsMDIForm, el Caption a “Formulario Principal”, Height = 200, Widht = 430 y fijamos Position a poScreenCenter.2.- Añadimos un segundo formulario al proyecto con File/New Form. A este formulario le cambiamos la propiedad Caption a “Formulario secundario Hijo” (podemos tener varias ventanas secundarias), la propiedad FormStyle la cambiamos a la opción fsMDIChild, Height = 100, Widht = 400 y fijamos Position a poScreenCenter.3.- Añadimos un tercer formulario al proyecto con File/New Form. A este formulario le cambiamos la propiedad Caption a “Formulario secundario StayOnTop”, la propiedad FormStyle la cambiamos a la opción fsStayOnTop, Height = 95, Widht = 360 y fijamos Position a poScreenCenter.4.- Añadimos un botón y obtenemos una situación similar a:

88Tema 3.2.2.- Componentes en C++ Builder

ComponentesTrabajo con FormStyle

El formulario hijo solo se puede mover, minimizar o maximizar dentro del principal en cambio el StayOnTop se mueve independientemente.

89Tema 3.2.2.- Componentes en C++ Builder

ComponentesPropiedad IconPor defecto, si no se selecciona ninguno, Builder presenta el icono propio de las aplicaciones C++ Builder. Se puede cambiar haciendo doble clic en el botón Load, para seleccionar el archivo del icono deseado. Esta propiedad busca archivos con extensión .ico. C++ Builder tiene una biblioteca de archivos .ico en la carpeta:

\\Archivos de programa\Archivos comunes\Borland Shared\Images\Icons\El compilador dispone de un editor de iconos que se puede seleccionar en el menú principal: Tools/Image Editor para experimentar con él. En la figura vemos su aspecto con el icono chip cargado.

90Tema 3.2.2.- Componentes en C++ Builder

ComponentesPropiedad PositionDetermina donde se desplegará el formulario en la pantalla del PC en el momento de la ejecución.

Propiedad WindowStateEsta propiedad muestra las características del formulario en tiempo de ejecución.

Valor Efecto en tiempo de ejecución

wsNormal El formulario aparece de la manera en que se definió en el momento de crearse(dimensiones y posición).

wsMinimized El formulario aparece minimizado en pantalla en tiempo de ejecución.wsMaximized El formulario aparece maximizado en pantalla en tiempo de ejecución.

Ejemplo 119.- Propiedades y eventosSe trata de un ejemplo de uso de algunas de las propiedades de las citadas y de algunos eventos

tanto de teclado como de ratón.Debemos disponer un formulario similar a:

Valor Efecto en tiempo de ejecución

poDesigned El formulario aparece en tiempo de ejecución con el tamaño y la posición que tenía dediseño

poDefaultEl formulario aparece en una posición de la pantalla con una altura y una anchuradeterminadas por Windows. Cada vez que ejecutemos la aplicación, el formulario semoverá levemente abajo y a la derecha.

poDefaultPosOnlyEl formulario se muestra con el tamaño con que se creó en tiempo del diseño, peroWindows elige su posición respecto a la pantalla. Cada vez que ejecutemos la aplicación,el formulario se moverá levemente abajo y a la derecha.

poDefaultSizeOnly El formulario aparece en el lugar donde estaba en tiempo de diseño, pero Windows eligesu tamaño.

poScreenCenter El formulario aparece en el lugar donde estaba en tiempo de diseño, pero posicionado enel centro de la pantalla.

91Tema 3.2.2.- Componentes en C++ Builder

ComponentesEjemplo 119.- Propiedades y eventos

Los efectos de los botones Maximizar, Minimizar y Salir los vamos a asociar a los eventos OnClick para efectuar esas operaciones.

Para botón Maximizar: WindowState=wsMaximized; Para botón Maximizar: WindowState=wsMinimized;Para botón Maximizar: Application->Terminate();

El efecto del botón Normal va a ser devolver la ventana a su estado normal asociándolo al evento OnMouseMove del ratón.

Para botón Normal: WindowState=wsNormal;Para el botón ¿Mantenemos pulsada una tecla del ratón? y la etiequeta que tiene a la derecha vamos a trabajar con los eventos OnMouseDown y OnMouseUp de forma que mientras tengamos pulsada la tecla izquierda del ratón sobre el botón la etiqueta muestre SI y en caso contrario NO.void __fastcall TForm1::Button5MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y){ Label1->Caption="SI";}//---------------------------------------------------------------------------void __fastcall TForm1::Button5MouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y){ Label1->Caption="NO";}

92Tema 3.2.2.- Componentes en C++ Builder

ComponentesEjemplo 119.- Propiedades y eventosPara el botón Tecla pulsada y su etiqueta de la derecha vamos a generar un evento OnKeyPress de forma que cuando el botón tenga el foco la etiqueta nos muestre la tecla que hemos pulsado. void __fastcall TForm1::Button6KeyPress(TObject *Sender, char &Key){ char keyString[2]; keyString[0] = Key; strcpy(&keyString[1], ""); Label2->Caption= keyString;}Ahora añadimos un nuevo formulario con un Label y hacemos que tenga algo parecido a:

No debemos olvidar File/Include Unit ... para tener en Unit1 #include "Unit2.h". Para este Form vamos a generar un evento OnResize al que asociamos el código:void __fastcall TForm2::FormResize(TObject *Sender){ Label1->Left = (ClientWidth/2) - (Label1->Width/2); Label1->Top = (ClientHeight/2) - (Label1->Height/2);}Finalmente para el botón Otro Form generamos su evento OnClick y hacemos que muestre el segundo formulario de forma modal. void __fastcall TForm1::Button7Click(TObject *Sender){ Form2->ShowModal();}

93Tema 3.2.2.- Componentes en C++ Builder

ComponentesEjemplo 120.- Eventos DragOver y DragDrop

Creamos una aplicación para trabajar con estos eventos y el formulario tendrá un componente ListBox y tres Label, cada uno con la fuente que se especifica.

Label 1: Britannic Bold - Negrita - Cursiva - 10 Puntos – AzulLabel 2: Arial - Normal - 12 Puntos - RojoLabel 3: Courier New - Negrita - Subrayado - 8 Puntos - Verde

Para probar el funcionamiento seleccionamos un Label, arrastramos hasta el ListBox y soltamos, cambiando el texto del mismo al aspecto del Label seleccionado.El formulario debe tener un aspecto similar a:

La propiedad DragMode de los Label debe ser dmAutomatic de lo que nos aseguramos asociando la propiedad al evento OnCreate del formulario.El código del programa es:void __fastcall TForm1::FormCreate(TObject *Sender){ Label1->DragMode = dmAutomatic; Label2->DragMode = dmAutomatic; Label3->DragMode = dmAutomatic;}

94Tema 3.2.2.- Componentes en C++ Builder

ComponentesEjemplo 120.- Eventos DragOver y DragDropvoid __fastcall TForm1::ListBox1DragOver(TObject *Sender, TObject *Source, int X, int Y, TDragState State, bool &Accept){ Accept = Source->ClassNameIs("TLabel"); }//---------------------------------------------------------------------------void __fastcall TForm1::ListBox1DragDrop(TObject *Sender, TObject *Source, int X, int Y){ if (Sender->ClassNameIs("TListBox") && Source->ClassNameIs("TLabel")) { TListBox *Puntero = (TListBox *)Sender; Puntero->Font = ((TLabel *)Source)->Font; Puntero->Color = ((TLabel *)Source)->Color; } }

Eventos OnHide y OnPaint. Trabajo con la propiedad Canvas del FormLa propiedad TCanvas de un formulario permite dibujar en su área de cliente. Canvas se usa en el evento OnPaint del formulario. El método Draw de Canvas tienen una sintaxis como:

Draw(int X, int Y, TGraphic* Grafico);Dibujándo el gráfico especificado por el parámetro Grafico en el canvas y la localización que indican las coordenadas X e Y. Tendremos por tanto que facilitar un ámbito global de acceso del tipo:

Graphics::TBitmap *Grafico;El evento OnHide ocurre cuando el formulario se oculta, es decir cuando su propiedad Visible se pone en false.

95Tema 3.2.2.- Componentes en C++ Builder

ComponentesEjemplo 121.- Eventos OnHide y OnPaint. Trabajo con la propiedad Canvas del Form

Vamos a implementar una aplicación con dos formularios que permita mediante la pulsación de un botón mostrar el otro formulario dibujando en cada uno de ellos una imagen diferente mediante la propiedad Canvas del formulario. Debemos también permitir que la aplicación se cierre desde cualquiera de los formularios.Comenzamos por construir dos formularios con un Label y un Button con el aspecto que mostramos, estando los Label con su propiedad Caption vacía y situados a la izquierda de los botones. Ambos formularios tienen su propiedad Height = 250 y Width a 190 y 240 respectivamente.

El código del primer Form es://---------------------------------------------------------------------------#include <vcl.h>#pragma hdrstop#include "Unit1.h"#include "Unit2.h" //File/Incude Unit ...//---------------------------------------------------------------------------#pragma package(smart_init)#pragma resource "*.dfm"

96Tema 3.2.2.- Componentes en C++ Builder

Componentes

TForm1 *Form1;Graphics::TBitmap *Grafico; //Ambito global de acceso__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner){}void __fastcall TForm1::Button1Click(TObject *Sender){ Form2->Show(); this->Hide();}void __fastcall TForm1::FormHide(TObject *Sender){ Form2->Label1->Caption = "Athenea oculta";}void __fastcall TForm1::FormPaint(TObject *Sender){ Form1->Canvas->Draw(0, 0, Grafico); //Dibuja el grafico en Canvas}void __fastcall TForm1::FormCreate(TObject *Sender){ Grafico = new Graphics::TBitmap(); //Crea objeto bitmap //Carga bitmapGrafico->LoadFromFile("C:\\ARCHIVOS DE PROGRAMA\\ARCHIVOS COMUNES\\BORLAND SHARED\\IMAGES\\SPLASH\\16COLOR\\ATHENA.BMP");}

97Tema 3.2.2.- Componentes en C++ Builder

ComponentesEl código del segundo Form es:#include <vcl.h>#pragma hdrstop#include "Unit2.h"#include "Unit1.h" //File/Incude Unit ...#pragma package(smart_init)#pragma resource "*.dfm"TForm2 *Form2;Graphics::TBitmap *Grafico1; //Ambito global de acceso__fastcall TForm2::TForm2(TComponent* Owner) : Tform(Owner) { }void __fastcall TForm2::Button1Click(TObject *Sender){ Form1->Show(); this->Hide(); }void __fastcall TForm2::FormHide(TObject *Sender){ Form1->Label1->Caption = "Tierra oculta"; }void __fastcall TForm2::FormPaint(TObject *Sender){ Form2->Canvas->Draw(0, 0, ElGrafico1); //Dibuja el grafico en Canvas }void __fastcall TForm2::FormCreate(TObject *Sender){ Grafico1 = new Graphics::TBitmap(); //Crea objeto bitmap //Carga bitmap Grafico1->LoadFromFile("C:\\ARCHIVOS DE PROGRAMA\\ARCHIVOS COMUNES\\BORLAND SHARED\\IMAGES\\SPLASH\\16COLOR\\EARTH.BMP");}void __fastcall TForm2::FormClose(TObject *Sender, TCloseAction &Action){ Form1->Close(); //Cerramos el Form principal}

98Tema 3.2.2.- Componentes en C++ Builder

ComponentesTrabajo con ficheros: la clase ofstreamEn el fichero Fstream.h se define la clase ofstream que permite trabajar con ficheros. Para esto debemos declarar una variable debiendo ser el tipo de dicha variable cualquiera de las tres clases siguientes:

Clase de objeto Especializaciónifstream Entrada de datos desde un archivoofstream Salida de datos a un archivofstream Lectura y escritura en un archivo abierto

Para declarar el fichero de salida lo haremos con algo similar a:ofstream Fichero("Archivo de Prueba.txt",ios::trunc).

El constructor de la clase toma como primer parámetro el nombre del archivo a asociar al objeto y como segundo el modo de apertura, que está formado por uno o más de los indicadores definidos en la clase ios siguientes:

Indicador Modo Ejemplos de códigoin Apertura para entrada out Apertura para salidaapp Apertura para añadirate Puntero final archivo tras aperturatrunc Eliminar contenido actual del archivonoreplace Fallo en apertura si el archivo existenocreate Fallo en apertura si el archivo no existebinary Apertura en modo binario, no de texto

//Trabajar con archivos de salida sin ninguna asociación ofstream F; //Abrir fichero existente para lectura ifstream F(“Fichero”); //Abrir fichero para escritura creandolo ofstream F(“Fichero”); //Abrir fichero para lectura y escritura fstream F(“Fichero”,ios::int |ios::out); //Abrir fichero para escritura y generar error si existe ofstream F(“Fichero”,ios::noreplace); //Abrir fichero existente y si no existe no lo crea. fstream F(“Fichero”,ios::nocreate); //Abrir fichero en modo binario truncando el contenido actual. fstreamF(“Fichero”,ios::trunc|ios::binary);

El constructor de la clase ifstream tiene como valor por defecto para el segundo parámetro ios::in y elconstructor de ofstream ios::out.

99Tema 3.2.2.- Componentes en C++ Builder

ComponentesProgressBar, StaticText y AnimateVamos a usar el ejemplo para describir estos componentes.Ejemplo 122.- Uso de ProgressBar, StaticText y Animate

Se trata de realizar un ejercicio que almacene los 15000 primeros números en un fichero txt, que una barra de progreso nos muestre el avance que se produce, nos aparezca un número indicativo del progreso sobre la barra y que se muestre un objeto animado tipo folio volando entre carpetas.Vamos a diseñar un formulario con altura 165, anchura 315 y centrado en pantalla sobre el que situamos un objeto ProgressBar (Pestaña Win32) con alineación alBotton, Max=15000 y Step=1; un objeto Animate (Pestaña Win32) con Active = false, CommonAVI = aviCopyFile, Repetitions = 1, StarFrame = 1, StopFrame = 20 y Visible = false.; un objeto StaticText con su Caption vacío y centrado sobre ProgressBar en vertical y en horizontal estableciendoles una fuente color rojo de 10 puntos y en negrita; y finalmente colocamos un botón y un CheckBox para tener un diseño similar a:

Seguidamente vemos el código comentado completo de esta aplicación.

100Tema 3.2.2.- Componentes en C++ Builder

ComponentesProgressBar, StaticText y Animate#include <vcl.h>#pragma hdrstop#include "Unit1.h"#include <FStream.h> // la clase ofstream está definida en este fichero#pragma package(smart_init)#pragma resource "*.dfm"TForm1 *Form1;__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner){}void __fastcall TForm1::Button1Click(TObject *Sender){/* Con el CheckBox vamos a conmutar la propiedad Smooth de la barra de progresoSmooth=false hace que la barra sea segmentada y Smooth=true que sea continua */ if(CheckBox1->Checked==false) ProgressBar1->Smooth=false; else ProgressBar1->Smooth=true;// Creamos el fichero borrando su contenido cuando se crea si ya existe ofstream Fichero("Archivo de Prueba.txt",ios::trunc); Cursor = crHourGlass; Button1->Enabled = false;

101Tema 3.2.2.- Componentes en C++ Builder

ComponentesProgressBar, StaticText y Animate// Recorremos un bucle para los 15000 valores for (int N=0; N<15000; N++) { Animate1->Active=true; Animate1->Visible=true; Animate1->Repetitions = 3; Animate1->Timers=ProgressBar1->Position;// Texto a mostrar en la etiqueta StaticText StaticText1->Caption=AnsiString(ProgressBar1->Position*100/15000+1) + " %";// Método de Application que interrumpe la ejecución de una solicitud a fin // de que pueda procesar la cola de mensajes Application->ProcessMessages();// Desplazamiento a la izquierda de forma que Fichero se va completando sin dejar espacios en blanco. Fichero << N;// Método StepIt para avanzar (actualizar) según lo establecido en la propiedad Step de ProgressBar. ProgressBar1->StepIt(); } Fichero.close(); // Método para cerrar el archivo// Establecimiento de las condiciones iniciales ProgressBar1->Position=0; Button1->Enabled = true; Cursor = crDefault; StaticText1->Caption=""; Animate1->Visible=false;}

102Tema 3.2.2.- Componentes en C++ Builder

Fin de la presentación