AprendiendoBORLAND Delphi. Marta Sananes. Universidad de Los Andes, Venezuela. Junio 2002.

Ejemplo ConToolBar
 
Este ejemplo muestra el uso de los componentes y controles tipos TMemo (Control que aloja, muestra y actualiza líneas de un Texto), TToolBar (Control Barra de tareas, con botones gráficos),TMenu (Componente que genera el Menú encabezando una Forma o Ventana),  TActionList, TImageList (Componentes para centralizar acciones provenientes de Menu y ToolBar), TOpenDialog, TSaveDialog y TPrintDialog (Ventanas predefinidas de diálogos para abrir, guardar e imprimir archivos, respectivamente). Observe  que algunos componentes no son objetos visibles directamente en la forma. Como no son directamente visibles ni manipulables,  pueden colocarse en cualquier lugar en la forma. Su colocación significa que hay una funcionalidad asociada que se activa por acciones del usuario. El componente TMenu presenta una barra en el borde superior de la forma con las opciones de menú principal creadas por el programador, con formato y funcionamiento al estilo de Windows. Los tres componente de tipo Diálogo se presentan y activan cuando el programador lo ordene,  en respuesta generalmente a alguna opción de menú o de algún botón. Tiene igualmente el estilo de presenación y funcionamiento de Windows.

El contenido de los archivos que confroman la aplicación se muestra en forma de tablas, en la columna izquierda el código en ObjectPascal y en la derecha explicaciones y comentarios. 

En los archivos de programa (.dpr y .pas), las líneas que son generadas automáticamente por Delphi están en color amarillo; en blanco sólo las que el programador tuvo que agregar. Aparecen resaltadas en ambos casos las palabras reservadas de ObjectPascal, tal como lo hace el Editor de Delphi.
Son tres los archivos que conforman la aplicación: ConToolBar.dpr: es el archivo raíz o índice del proyecto, de extensión .dpr (Delphi PRoject); ConToolBarU.pas: es la Unit que contiene la programación correspondiente a la forma de interfaz de usuario; ConToolBarU.dfm: es parte de la visualización en modo texto de la Forma diseñada por el programador como interfaz de usuario. Este archivo de extensión .dfm (Delphi ForM) contiene las declaraciones correspondientes al diseño de la Forma; es generado por Delphi transcribiendo la construcción que hace el usuario en forma visual. No hace falta que el programador vea este archivo ni debe modificar manualmente el texto, Delphi se encarga de su actualización cada vez que visualmente se modifique la apariencia o el contenido de la Forma asociada, ya sea por acciones directas sobre la Forma o modificando propiedades con el Object Inspector .

Dieseņo de la Forma de Intefaz de Usuario

ConToolBar.dpr
 
program ConToolBar; 

uses
  Forms, 
  ConToolBarU in 'ConToolBarU.pas' {Form1};

{$R *.RES}

begin
  Application.Initialize; 
  Application.CreateForm(TForm1, Form1); 
  Application.Run; 
end.

Para proyectos diseñados con formas de interfaz gráfica para usuarios, Delphi genera el archivo  de extensión .dpr. En la sección uses coloca los nombres y las ubicaciones de todas las Units incorporadas al proyecto, además de la referencia a la Delphi-Unit Forms, que contiene la Clase TForm, clase primitiva de todas las formas.

Unit ConToolBarU.pas
 
unit ConToolBarU;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls,
  Forms, Dialogs, ActnList, ImgList, StdActns, ToolWin,
  ComCtrls, Menus, StdCtrls, Printers;
 

En la sección interface se colocan todas las declaraciones o definiciones.

Delphi genera la lista de Units utilizadas en la aplicación,
a la cual se pueden agregar las que el usuario desee, preferiblemente usando la opción de Agregar Unit. También se
puede hacer manualmente, como en este caso ques se agregó la unit Printers.
 

type
  TForm1 = class(TForm)
Tipo de clase de forma generado con todos los componentes y controles colocados por el programador en la forma.
    ImageList1: TImageList; Para que la aplicación muestre las opciones de menú con íconos y una barra de tareas con botones equivalentes a las opciones de menú (ToolBar), es necesario agregar a la forma un componente de clase TImageList, de donde Delphi toma las imágenes. Oprimiendo el segundo botón con el componente de clase TImageList seleccionado en la forma, aparec un menú. Seleccione la primera opción para abrir el diálogo de selección de imágenes. Para agregar imágenes necesita tener una colección de imágenes disponibles. Por ejemplo, tomarlas de .../Borland Shared/Images/Buttons y modificarlas si quiere a su gusto con el Image Editor,accesible desde el menú Tools de Delphi o con cualquier editor gráfico. Delphi numera las imágenes a partir de 0 para referenciarlas en otros componentes o controles.
    ActionList1: TActionList; Componente de clase TActionList para definir una lista de acciones que permite compartir una misma acción entre distintos controles, como botones y opciones de menús. 

    ActionNew: TAction;
    ActionOpen: TAction;
    ActionSave: TAction;
    ActionSaveAs: TAction;
    ActionPrint: TAction;
En este ejemplo se definen las acciones de un editor de texto para: Crear nuevo texto, Abrir archivo de texto, Guardar y Guardar asignando nombre e Imprimir el texto. Relacione la lista de acciones con la lista de imágenes seleccionando el componente de clase TImageList en la casilla Images de las Propiedades en el ObjectInspector

Para definir las acciones de la lista, oprimir el segundo botón con el componente TActionList seleccionado para que se despliegue un menú. Seleccione la primera opción para abrir el diálogo de definición de acciones. Agregue acciones a la lista y defina en el ObjectInspector las propiedades deseadas: Name (del objeto Action en en el programa: ActionNew, ActionOpe, etc., en este caso), Caption (leyenda que aparecerá cuando se asocie la acción a una opción de un menú), Hint (leyenda que aparecerá cuando se asocie la acción a un botón, al pasar el punto del ratón sobre él), y muy importante, ImageIndex que asocia la acción con una de las imágenes, por su número de referencia en la lista de imágenes.
Para programar la acción, seleccione la pestaña Events en el ObjectInspector y allí, seleccione la casilla OnExecute. Coloque el nombre deseado para el método de la acción terminando con tecla Enter. O simplemente haga doble click en la casilla para que Delphi genere el nombre. En cualquier caso, Delphi genera en el texto del programa el esqueleto del método-procedimiento para que el programador agregue el código ObjectPascal deseado.

    MainMenu1: TMainMenu;
    File1: TMenuItem;
    New1: TMenuItem;
    Open1: TMenuItem;
    Save: TMenuItem;
    SaveAs: TMenuItem;
    Exit1: TMenuItem;
    Misc1: TMenuItem;
    Print: TMenuItem;
Desplegando la propiedad Items de un componente TMainMenu; o seleccionando el componente en la forma, oprimiendo el segundo botón y seleccionando la primera opción, Delphi presenta un editor de Menús para definir opciones y subopciones de clase TMenuItem. En este ejemplo se crean dos opciones en el menú principal: File y Misc, File con las subopciones New, Open, Save, Save As y Exit y Misc con la subopción Print, las cuales se asocian a las acciones de la lista de acciones ActionNew, ActionOpen, ActionSave, ActionSaveAs y ActionPrint, respectivamente. Ellas también podrán activarse desde la Barra de Tareas. Esta asociación se establece seleccionando la casilla Action en las Propiedades en el ObjectInspector, desplegando la lista de acciones -ya debe estar definido el componente TActionList- y seleccionando la acción que se quiere hacer corresponder, con lo cual Delphi automáticamente le transfiere las demás propiedades comunes al objeto de clase TAction y le transfiere así mismo el nombre del método de ejecución de la acción al evento OnClick .
La opción Exit en este ejemplo se crea independientemente de las acciones definidas, como puede hacerse también con todo el menú si no se desea tener formas distintas de activación de las acciones y por lo tanto, no es necesario definier una lista de acciones. En ese caso, las propiedades de la opción se asignan manualmente en el ObjectInspector así como la asignación del evento OnClick (ocurre cuando el usuario selecciona la opción) en Events.
    ToolBar1: TToolBar;
    ToolNew1: TToolButton;
    ToolOpen1: TToolButton;
    ToolSaveAs: TToolButton;
    ToolSave: TToolButton;
TToolBar es un tipo de Control que permite colocar botones para que los usuarios puedan activar -generalmente en forma alternativa a las opciones de un menú- acciones en la aplicación. Oprimiendo es segundo botón con el componente de clase TToolBar seleccionado en la forma, aparec un menú. Seleccione la primera opción para agregar un nuevo botón o la segunda para agregar un separador. En este ejemplo se agregaron 4 botones para asociarlos a las acciones definidas en el componente TActionList, tal como se hizo con las opciones de menú. Para asociar cada botón a una acción, seleccione la casilla Action en las Propiedades del ObjectInspector, despliegue la lista de acciones definidas y seleccione la adecuada con lo cual Delphi automáticamente le transfiere las otras propiedades comunes al objeto de clase TAction y le transfiere el nombre del método de la acción al evento OnClick en Events.
    Memo1: TMemo; El componente de clase TMemo se usa para alojar el contenido de un archivo de texto, el cual puede ser editado por el usuario (agregar, borrar, marcar, cortar, copiar, pegar, eliminar). 
    OpenDialog1: TOpenDialog;
    SaveDialog1: TSaveDialog;
    PrintDialog1: TPrintDialog;
Componentes para presentar diálogos de apertura de archivo, de guardado y de impresión, respectivamente.
    procedure ActionNewExecute(Sender: TObject);
    procedure ActionOpenExecute(Sender: TObject);
    procedure ActionSaveExecute(Sender: TObject);
    procedure ActionSaveAsExecute(Sender: TObject);
    procedure ActionPrintExecute(Sender: TObject);
    procedure Exit1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action:
                        TCloseAction);
    procedure FormActivate(Sender: TObject);
Procedimientos de atención a los eventos del usuario: OnClick en las subopciones del Menu o en los botones del ToolBar (asignados por Delphi a los eventos OnExecute en las acciones de la lista definida), al cerrar la forma (OnClose) y al activarse la forma al inicio de la ejecución de la aplicación.
  private
    { Private declarations }
    NombreArchivo: string;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

Se agregó otro atributo, NombreArchivo, para mantener el nombre del archivo mostrado en el Control de clase TMemo
procedure TForm1.ActionNewExecute(Sender: TObject);
begin
   ActionSaveExecute(Sender);
   Memo1.Clear;
   NombreArchivo:='';
end;
En atención al evento OnClick en la opción File/New del menú o en el botón correspondiente de la barra de tareas, se ejecuta el método definido para la acción asociada en el componente de clase TAction definido en el componente de clase TActionList
Primero se invoca el método asociado al evento File/Save para que en caso de que haya un texto en el control Memo1, pueda guardárselo a un archivo antes de limpiar el área de texto. Luego se limpia el área y se asigna el string nulo al nombre del archivo indicando que no hay ninguno definido.
procedure TForm1.ActionOpenExecute(Sender: TObject);
begin
  ActionSaveExecute(Sender);
  if OpenDialog1.Execute then
  begin
     Memo1.Clear;
     NombreArchivo:=OpenDialog1.FileName;
     Memo1.Lines.LoadFromFile(NombreArchivo);
  end 
  else ShowMessage('Cancelado');
end;
En atención al evento OnClick en la opción File/Open del menú o en el botón correspondiente de la barra de tareas, se ejecuta el método definido para la acción asociada en el componente de clase TAction definido en el componente de clase TActionList
Primero se invoca el método asociado al evento File/Save para que en caso de que haya un texto en el control Memo1, se pueda guardarlo a un archivo antes de reemplazar el texto con el contenido del archivo que se vaya a abrir. Luego se hace desplegar la ventana de Diálogo OpenDialog1, directamente,  invocando su método Execute. El método-función devuelve Truesi el usuario elige o suministra un nombre de archivo y sale aceptando, nombre que el Objeto OpenDialog1 guarda en la propiedad FileName. Se limpia el contenido del Memo y luego el contenido del archivo se coloca en la propiedad Lines del componente Memo1, usando el método LoadFromFile. Como aquí no se valida la existencia del archivo, pudiera ocurrir un error fatal en caso de que el archivo no exista.
procedure TForm1.ActionSaveAsExecute(Sender: TObject);
begin
  if not SaveDialog1.Execute then ShowMessage('Cancelado')
  else
  begin
    NombreArchivo:=SaveDialog1.FileName;
    Memo1.Lines.SaveToFile(NombreArchivo);
    Memo1.Modified:=false; 
  end
end;
En atención al evento OnClick en la opción File/SaveAs del menú o en el botón correspondiente de la barra de tareas, se ejecuta el método definido para la acción asociada en el componente de clase TAction definido en el componente de clase TActionList
Primero se hace desplejar la ventana de Diálogo SaveDialog1, directamente, invocando su método Execute. El método-función devuelve True si el usuario elige o suministra un nombre de archivo y sale aceptando, nombre que el Objeto SaveDialog1 guarda en la propiedad FileName. El archivo se crea y guarda con el contenido de la propiedad Linesdel componente Memo1, usando el método SaveToFile. En caso de que el usuario hubiera hecho alguna modificación al contenido del objeto Memo1, el archivo quedará guardado con las modificaciones. Se coloca la propiedad Modified del Memo en falso indicando que  al momento los contenidos del Memo y del archivo son idénticos. (Delphi automáticamante revierte el valor de esta propiedad cuando el usuario hace cualquier modificación al contenido del Memo). 
procedure TForm1.ActionPrintExecute(Sender: TObject);
var i, x, y, h: integer;
begin
  if not PrintDialog1.Execute then ShowMessage('Canceloado')
  else
    with Printer do
    begin
      BeginDoc;
      x:=10;  y:=10;
      h:=Canvas.TextHeight('T')+1;
      for i:=0 to  Memo1.Lines.Count-1 do
      begin
        Canvas.TextOut(x,y,Memo1.Lines[i]);
        Inc(y,h);
      end;
      EndDoc;
    end;
end;
En atención al evento OnClick en la opción File/Print del menú o en el botón correspondiente de la barra de tareas, se ejecuta el método definido para la acción asociada en el componente de clase TAction definido en el componente de clase TActionList
Primero se hace desplegar la caja o ventana de Diálogo PrintDialog1, directamente, invocando su método Execute. El método-función devuelve False si el usuario cancela la impresión. Si no, se procede a usar el objeto global Printer, predefinido en la Unit Printers, utilizando sus métodos BeginDoc y EndDoc, encerrando el código para definir el contenido de la propiedad Canvas de clase TCanvas que representa el área de impresión (Ver las propiedades y métodos de la clase TCanvas en el Help). Al ejecutarse el método EndDoc, Delphi coloca el contenido de la impresión en la cola de impresión de la impresora activa de Windows
procedure TForm1.Exit1Click(Sender: TObject);
begin
  ActionSaveExecute(Sender);
  Close;
end;
En atención a la selección de la opción File/Exit se ejecuta el método asociado al evento OnClick. Primero se invoca el método asociado al evento File/Save para que en caso de que haya un texto en el control Memo1, pueda guardarse a un archivo antes de hace cerrar la Forma, con lo cual termina la ejecución de la aplicación. 
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  ActionSaveExecute(Sender);
  Action:=caFree;
end;
En atención al evento de cerrado de la forma, se ejecuta su método asociado. Delphi genera en en encabezado de este tipo de método la inclusión de un parámetro calificado con la palabra var, lo cual indica que se trata de una referencia a una variable definida en el entorno que invoca al método. En el caso de eventos de usuario, ese entorno es el sistema operativo Windows que es quien recibe y reacciona a cada evento del usuario, invocando el procedimiento que se le haya asociado. Ese parámetro de nombre Action sirve para informarle a Windows si debe terminar la aplicación (valor caFree) o debe dejar que continúe activa (valor caNone).
En este caso, después de invocar el método asociado al evento File/Save para que en caso de que haya un texto en el control Memo1, pueda guardarse a un archivo antes de hace cerrar la Forma. Luego se coloca el valor del parámetro y termina la ejecución del método, con lo cual la variable en el entorno de Windows queda con el valor caFree, para que Windows actúe en consecuencia.
procedure TForm1.ActionSaveExecute(Sender: TObject);
begin
   if (NombreArchivo='') then 
     if (Memo1.Lines.Count>0)
     then ActionSaveAsExecute(Sender) 
     else
   else if Memo1.Modified then
          if MessageDlg('Archivo modificado. ¿Guardarlo?',
                        mtConfirmation,[mbYes,mbNo],0)=mrYes
       then begin
                 Memo1.Lines.SaveToFile(NombreArchivo);
                 Memo1.Modified:=false;
         end;
end;
En atención al evento OnClick en la opción File/Save del menú o en el botón correspondiente de la barra de tareas, se ejecuta el método definido para la acción asociada en el componente de clase TAction definido en el componente de clase TActionList. También es invocada su ejecución desde otros métodos, como desde el método Exit1Click asociado al evento OnClick de la opción de menú Exit.
Primero se revisa si no se ha cargado ningún archivo (NombreArchivo es nulo) y si hay algún contenido en el Memo. Si es así, se invoca la acción de guardar asignando nombre.
Si sí hay un archivo cargado y fué modificado, se pregunta al usuario si desea guardar el texto modificado en el archivo (sobreescribiendo). (Ver sintaxis del procedimiento MessageDlg, de la Unit Dialogs, en el Help). 

En caso afirmativo se guarda y se coloca la propiedad Modified del Memo en falso indicando que al momento los contenidos del Memo y del archivo son idénticos. (Delphi automáticamante revierte el valor de esta propiedad cuando el usuario hace cualquier modificación al contenido del Memo). 

procedure TForm1.FormActivate(Sender: TObject);
begin
  NombreArchivo:='';  Memo1.Clear;
end;

end.

Si el progrmador asocia un método al evento OnActivate de la forma, el método se ejecuta después que Windows ha iniciado la ejecución de la aplicación y creado la forma, en el momento en el que la activa. En este caso, se inicializa el atributo NombreArchivo al string nulo y se limpia el área del control Memo1

Forma ConToolBarU.dfm vista como texto
 

object Form1: TForm1
  Left = 467
  Top = 218
  Width = 417
  Height = 295
  Caption = 'Editor con Menu y ToolBar'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  Menu = MainMenu1
  OldCreateOrder = False
  OnActivate = FormActivate
  OnClose = FormClose
  PixelsPerInch = 96
  TextHeight = 13
  object ToolBar1: TToolBar
    Left = 0
    Top = 0
    Width = 409
    Height = 33
    BorderWidth = 1
    Caption = 'ToolBar1'
    Color = clBtnFace
    EdgeBorders = [ebTop, ebBottom]
    EdgeInner = esLowered
    Images = ImageList1
    ParentColor = False
    TabOrder = 0
    object ToolNew1: TToolButton
      Left = 0
      Top = 2
      Action = ActionNew
      ParentShowHint = False
      ShowHint = True
    end
    object ToolOpen1: TToolButton
      Left = 23
      Top = 2
      Action = ActionOpen
      ParentShowHint = False
      ShowHint = True
    end
    object ToolSaveAs: TToolButton
      Left = 46
      Top = 2
      Action = ActionSaveAs
      ParentShowHint = False
      ShowHint = True
    end
    object ToolSave: TToolButton
      Left = 69
      Top = 2
      Action = ActionSave
      ParentShowHint = False
      ShowHint = True
    end
    object ToolPrinter: TToolButton
      Left = 92
      Top = 2
      Action = ActionPrint
      ParentShowHint = False
      ShowHint = True
    end
  end
  object Memo1: TMemo
    Left = 0
    Top = 33
    Width = 409
    Height = 216
    Align = alClient
    Color = clNavy
    Font.Charset = ANSI_CHARSET
    Font.Color = clYellow
    Font.Height = -11
    Font.Name = 'Courier New'
    Font.Style = []
    Lines.Strings = ( '')
    ParentFont = False
    ScrollBars = ssVertical
    TabOrder = 1
  end
  object MainMenu1: TMainMenu
    Images = ImageList1
    Top = 40
    object File1: TMenuItem
      Caption = '&File'
      object New1: TMenuItem
        Action = ActionNew
      end
      object Open1: TMenuItem
        Action = ActionOpen
      end
      object Save: TMenuItem
        Action = ActionSave
      end
      object SaveAs: TMenuItem
        Action = ActionSaveAs
      end
      object Exit1: TMenuItem
        Caption = '&Exit'
        OnClick = Exit1Click
      end
    end
    object Misc1: TMenuItem
      Caption = '&Misc'
      object Print: TMenuItem
        Action = ActionPrint
      end
    end
  end
  object ActionList1: TActionList
    Images = ImageList1
    Left = 16
    Top = 216
    object ActionNew: TAction
      Category = '(All Categories)'
      Caption = 'New'
      Hint = 'New'
      ImageIndex = 0
      OnExecute = ActionNewExecute
    end
    object ActionOpen: TAction
      Category = '(All Categories)'
      Caption = '&Open'
      Hint = 'Open'
      ImageIndex = 1
      OnExecute = ActionOpenExecute
    end
    object ActionSaveAs: TAction
      Category = '(All Categories)'
      Caption = 'Save &As...'
      Hint = 'Save As'
      ImageIndex = 2
      OnExecute = ActionSaveAsExecute
    end
    object ActionPrint: TAction
      Category = '(All Categories)'
      Caption = '&Print'
      Hint = 'Print'
      ImageIndex = 3
      OnExecute = ActionPrintExecute
    end
    object ActionSave: TAction
      Category = '(All Categories)'
      Caption = '&Save'
      Hint = 'Save'
      ImageIndex = 4
      OnExecute = ActionSaveExecute
    end
  end
  object ImageList1: TImageList
    Left = 64
    Top = 216
    Bitmap = {
      3620000.............Datos de las imágenes..............003E07F}
  end
  object OpenDialog1: TOpenDialog
    Left = 32
    Top = 40
  end
  object SaveDialog1: TSaveDialog
    Left = 64
    Top = 40
  end
  object PrintDialog1: TPrintDialog
    Left = 96
    Top = 40
  end
end