Delphi: conceptos basicos, trucos y apuntes de interés

En este artículo es una especie de chuleta / quick reference card / resumen / recopilación de información básica y necesaría en día a día de la programación en Delphi.

Conforme lo voy elaborando intentaré mantener un estilo resumido poniendo únicamente la información más relevante (los detalles siempre se pueden consultar en la ayuda, que es bastante extensa).

Estructura de una clase

unit nombreUnit

interface

[uses UnitA, UnitB...;

declaraciones de la clase

exports rutinaA,rutinaB...;  //para exportar rutinas de una libreria con su unit en la cláusula uses

type Tipos_de_variable;  //declaración de tipos de variables

var Variables]  //visible en todas las unit que usen ésta

implementation

[{$R *.dfm}  //si tiene formulario asociado
{$R WindowsXP.res}  //para efectos visuales tipo XP
{$R nombreRecurso.res}

exports rutinaA,rutinaB...;

uses UnitAA,UnitBB...;

var Variables;]

código...
código...
código...
código...

[initialization código_de_inicialización;]
[initialization código_de_inicialización;
finalization código_de_finalización;]

end.

Notas:

  • Las variables declaradas en la sección interface son visibles en la unit y allí donde la unit esté en la cláusula uses.
  • Las variables declaradas en la sección implementation son visibles sólo en la unit.

Constantes especiales

false, true, nil, MAXWORD, MAXINT, MAXDOUBLE, MINDOUBLE, etc.

Tipos de datos

Resumen de los tipos de datos más utilizados.

Rango / descripción Formato
Boolean false / true unsigned 8-bit
Byte 0..255 unsigned 8-bit
Integer -2147483648..2147483648 signed 32-bit
Word 0 a 65535 unsigned 16-bit
Double 5E-324..1.7E308 signed 64-bit
Currency ±9.22E14 scaled 64-bit integer
Char Extended ASCII unsigned 8-bit
WideChar Unicode Character unsigned 16-bit
String string of char 4 bytes to 2GB
WideString string of Unicode characters 4 bytes to 2GB
TDateTime Entero que representa los días desde el 12/30/1899 a las 12.00am. Una fracción representa tiempo del día (pe. 0,25 = 6.00am) signed 64-bit

Números

Funciones más importantes para la manipulación de números.

abs(N) devuelve el valor absoluto N
int(N) la parte entera de N
Random número aleatorio entre 0 y 1
Randomize inicializa el generador de números aleatorios
Round(N,d) redondea N al número más cercano con d decimales de precisión.

Texto

Funciones más importantes para la manipulación de cadenas de texto:

chr(arg) devuelve el caracter ASCII que corresponde a arg
SysUtils.CompareStr(s1,s2)
SysUtils.CompareText(s1,s2)
comparación sensible a mayúsculas. s1 s2 devuelve 1
Copy(s,i,n) extrae de s y devuelve una cadena de n carácteres comenzando por el índice i
Delete(s,i,n) borra n carácteres de s comenzando por el índice i
StrUtils.LeftStr(s,n)
StrUtils.RightStr(s,n)
devuelve cadena de n carácteres comenzando por la izquierda / derecha
StrUtils.MidStr(s,i,n) devuelve cadena de n carácteres comenzando por el índice i
Length(s) devuelve nº de caracteres en s
SysUtils.LowerCase(s)
SysUtils.UpperCase(s)
devuelve s en manúsculas / minúsculas
SysUtils.SameText(s1,s2) comparación no sensible a mayúsculas entre s1 y s2. s1 = s2 devuelve true
SetLength(s,len) fija la longitud de s a len
StringOfChar(c,n) devuelve una cadena que contiene n carácteres c
UpCase(c) devuelve el carácter c en mayúsculas
StuffString(s1; ini, len; s2) Devuelve una cadena resultado de insertar en s1 la cadena s2 en la posición ini y eliminando los caracteres a lo largo de la longitud len (o sea, dependiendo de len puede ser una sustitución o una inserción)
StrScan(unPChar; unChr) Devuelve un puntero PChar al primer carácter unChr que encuentre dentro de la cadena unPChar
StrPCopy(arr, s); Copia sen una cadena terminada en null (array of char) y devuelve un puntero a arr. Esta función no realiza ninguna comprobación de longitud. El array de destino debe tener espacio para al menos Length(s) + 1 caracteres
SetString(s, PChar(Addr(arr)), 3); Copia el contenido del array arr a s

Funciones para realizar conversiones de texto a otros formatos:

StrToCurrDef(s,def) s a Currency. def si error
StrToInt[64]Def(s,def) s a Integer. def si error
StrToFloatDef(s,def) s a real. def si error
StrToDateTime(s,def) s a TDateTime. def si error
val(S,V,Code) S es convertido a número y almacenado en V . Code > 0 indica la posición del primer error en s.
S es convertido a número y almacenado en V . Code > 0 indica la posición del primer error en s.

Funciones para realizar conversiones a texto:

FloatToStr(value) convierte value a cadena de texto
Format(pattern,[arg1,arg2...]) usa pattern para construir una cadena de texto. %d, %f, etc. en pattern son reemplazados por los valores en args
FormatDateTime(pattern,datetime) devuelve datetime como una cadena formateada utilizando pattern. Si pattern está vacío utiliza formato de fecha corta.
FormatFloat(pattern,value) devuelve value como una cadena formateada utilizando pattern.
IntToHex(value,N) devuelve value en hexadecimal con N dígitos.
IntToStr(value) devuelve value como entero.

Fechas

Funciones para la manipulación de la fecha y la hora.

Time y GetTime devuelve la hora actual en formato TDateTime (fracción de tiempo entre 0 y 1)
Date y GetDate devuelve la fecha actual en formato TDateTime
DateTimeToStr(d) convierte d a cadena utilizando el formato local
StrToDateTime(s) convierte la cadena s a fecha TDateTime utilizando el formato local
DecodeDate(fecha,Y,M,D) extrae el año, mes y día de Date en Y, M y D
DecodeTime(fecha,H,M,S,N) extrae la hora, minutos, segundos y milisegundos de fecha en H, M, S y N
EncodeDate(Y,M,D) devuelve una fecha (TDateTime) compuesta por Y, M y D
EncodeTime(H,M,S,N) devuelve una hora -o fracción de tiempo entre 0 y 1- (TDateTime) compuesta por H, M, S y N
FormatDateTime(format,fecha) devuelve fecha en cadena de texto y formateada con format

Arrays

Cómo declarar, inicializar y utilizar los arrays.

sin inicializar
letras : array of Char;
de longitud establecida
palabras : array[1..7] of String;
inicializados
numeros : array[0..5] of Shortint = (0,1,2,3,4,5);
constantes
const diasSemana : array[1..7] of string = ('lunes','martes','miércoles','jueves','jueves','viernes','sábado', 'domingo');
multidimensional
quiniela: array[1..15, 1..3] of Boolean;
dinámicos
SetLength(palabras, 14);
SetLength(quiniela, 16, 5);

Nota: SetLength crea un array mayor (o menor) y copia los valores existentes al nuevo array

cómo recorrerlos
for k := Low(palabras) to High(palabras) do
  palabras[k] := 0;
for i := Low(diasHoras) to High(diasHoras) do
  for j := Low(diasHoras[i]) to High(diasHoras[i]) do
diasHoras[i,j] := 0;

Sets

declaración tipo
type TDigitos = set of '0..9';
declaración variable
var digitos : TDigitos;
inicialización al principio todos los valores están off

digitos := ['2','4'..'7'];  //ponemos algunos a on 
utilización
Include(digitos, '1'); //pone '1' a onExclude(digitos, '3'); //pone '3' a on
if char In digits
...  //comprueba si los valores en chars están en digitos

Enumerations

declaración tipo
type TDia = (lun=1, mar, mie, jue, vie, sab, dom);
declaración variable
var hoy : TDia;
utilización
hoy := mie;  //asignacion directa
hoy := 7;  //asignacion por número
for day := Mon to Fri do
begin
  // dia hará 5 iteraciones (desde lun hasta vie)
end;

SubRanges

declaración tipo
type TNumeros = 0..9;
declaración variable
var num : TNumeros;
utilización
num := 5;    // permitido
num := 10;   // no permitido
num := -1;   // no permitido

Records

Ficheros

Funciones para el manejo de ficheros

ChangeFileExt(AFile,AExt) devuelve el nombre del fichero con nueva extensión. AExt debe incluir el caracter ‘.
System.ChDir(dir) cambia el directorio actual a dir
SysUtils.DirectoryExists(dir) devuelve true si dir existe
SysUtils.DiskFree(drive) devuelve los bytes libres en drive (0 = current, 1 = A, etc.)
ExtractFileExt(AFile) devuelve la extensión de AFile
ExtractFileName(AFile) devuelve el nombre de AFile
ExtractFilePath(AFile) devuelve la ruta de AFile
ForceDirectories(path) crea el directorio de la ruta path. Si no existe intenta crear todos los directorios necesarios. Devuelve false si no pudo.
System.GetDir devuelve el directorio actual
RemoveDir(dir) elimina el directorio dir

Control de flujo

SysUtils.abort lanza una excepción silenciosa
break sale del bucle (for, repeat o while)
continue continúa con la siguiente iteración del bucle (for, repeat o while)
exit sale del procedimiento actual
halt finaliza el programa en ejecución

Combinaciones de teclado

Estas son algunas combinaciones muy útiles de teclado:

Combinación
de teclado
Acciones realizadas
Alt + seleccionar bloque Selección de bloque determinada verticalmente
Ctrl + Shift + i Indentación del bloque seleccionado
Ctrl + Shit + u Desindentación del bloque seleccionado
Ctrl + Shift
+ UpArrow
Alternar la posición del cursor entre la definición de la función / procedimiento y su implementación
Ctrl + Barra espaciadora Completado del código
Ctrl + j Escritura automática de esqueletos de bloques de código (clases, bucles, función, procedimiento, etc.)
Ctrl + Shift + r Grabación de macro. Termina realizando otra vez la misma combinación de teclado.
Ctrl + Shift + p Ejecuta la última macro guardada
Ctrl + e Búsqueda incremental
Ctrl + / Comentar / descomentar una línea o un bloque

El ciclo de vida de un formulario

Nacimiento

Secuencia de creación de un formulario: OnCreate » OnShow » OnActivate » OnPaint

OnCreate Evento llamado cuando se crea por primera vez el TForm (solo una vez). Cuando se está creando un formulario y su propiedad Visible es True, ocurren la siguiente secuencia de eventos:.
Cualquier objeto creado en el evento OnCreate debe ser destruido en OnDestroy
OnShow Evento llamado justo antes de que el formulario se haga visible. Exceptuando los formularios principales, este evento ocurre cuando hacemos Visible a True, o al llamar a Show o ShowModal.
OnActivate Evento llamado cuando el formulario recibe el foco
OnPaint, OnResize Eventos llamados repetidamente. OnPaint es llamado antes de que ningún control sea pintado en el formulario.

Muerte

Secuencia de destrucción: OnCloseQuery » OnClose » OnDeactivate » OnHide » OnDestroy

OnCloseQuery Evento llamado cuando tratamos de crear el formulario (por cualquier método). La propiedad CanClose determina si permitimos el cierre del formulario o no
OnClose Si OnCloseQuery indica que puede cerrarse, se llama a este método. Última oportunidad de abortar el cierre. El parámetro Action tiene cuatro valores:

  • caNone. El formulario no puede cerrarse (como poner CanClose a False en OnCloseQuery)
  • caHide. En lugar de cerrarlo, lo ocultamos.
  • caFree. El formulario se cierra y la memoria que ocupaba es liberada.
  • caMinimize. En lugar de cerrarlo, lo minimizamos.
OnDestroy Evento llamado cuando el formulario va a ser cerrado. Usarlo para destruir objetos previamente creados y para liberar memoria

Gestión dinámica de la vida de un formulario

  1. Quitarlo de la lista Auto-create forms para que no se cree al inicio
  2. Crearlo con un código similiar a este:
    if (frmProductos = nil) then
      frmProductos := TfrmProductos.Create(Application);
    
  3. Mostrarlo cuando convenga con Show o ShowModal
  4. Destruirlo con caFree() en el método OnClose del formulario

Mensajes y diálogos

Veamos unos ejemplos de mensajes y diálogos básicos. Para ello se utilizan las funciones MessageDlg y MessageBox (la segunda da más versatilidad). Ambas devuelven un valor para saber qué botón ha pulsado el usuario.

  • un mensaje informativo
    ShowMessage('mensaje a mostrar');
  • un mensaje de confirmación:
    var
    buttonSelected : Integer;
    begin
    // Show a confirmation dialog
    buttonSelected := MessageDlg('Confirmation', mtError, mbOKCancel, 0);
    // Show the button type selected
    if buttonSelected = mrOK     then //código para OK
    if buttonSelected = mrCancel then //código para Cancelar
    end;
  • una pregunta si / no (utilizando MessageDlg)
    MessageDlg('¿Desea guardar los cambios?', mtConfirmation, [mbYes, mbNo, mbCancel], 0)

    En caso de que necesitemos saber el botón pulsado (este caso y el anterior) podemos usar una estructura if o también una case como el ejemplo:

    Respuesta := MessageDlg('¿Guardar los cambios?', mtConfirmation, [mbYes, mbNo, mbCancel], 0);
    case Respuesta of
      mrYes: (*GuardarCambios*);
      mrNo: (*SalirSinGuardar*);
      mrCancel: (*NoSalir*);
    end;
    
  • otra pregunta si / no (utilizando MessageBox)
    MessageBox(handle, '¿Desea guardar los cambios?'+#10+#13+'(Cancelar para omitir)', 'Pregunta', MB_YESNOCANCEL OR MB_ICONQUESTION);
  • Otra forma interesante de crear un mensaje es con la función CreateMessageDialog:
    procedure Mensaje();
    var
      mensaje:TForm;
    begin
    	if mensaje  nil then begin
      	mensaje := CreateMessageDialog('Este es el mensaje de error!', mtError, mbOKCancel);
        mensaje.Position := poScreenCenter;
        mensaje.Color := clwhite;
        mensaje.Caption := 'Titulo!';
      end;
      mensaje.ShowModal;
    end;
    

Trabajar con archivos

AssignFile(miArchivo, rutaArchivo) Enlaza la variable miArchivo (del tipo TextFile) al archivo rutaArchivo (pe. c:dirarchivo.txt)
Memo1.Lines.LoadFromFile(miArchivo) Carga el contenido de miArchivo en el control Memo1
ReWrite(miArchivo) Abre miArchivo como nuevo (descarta contenido, si es que existía)
Reset(miArchivo) Abre miArchivo con acceso de lectura y escritura
Append(miArchivo) Abre miArchivo para añadir contenido al final (como los archivos log)
CloseFile(miArchivo); Al terminar siempre hay que cerrar el archivo
FileMode := fmOpenRead; Variable que define el modo de acceso al fichero. Usar antes de Read(miArchivo) para abrir en modo solo lectura (necesario si el archivo es de solo lectura, pues sino daría error). Muchas veces no se usa porque por defecto FileMode vale fmOpenReadWrit

Aqui puedes ver algunos ejemplos.

Trucos varios

  • Funciones para convertir fechas a Unix timestamp y viceversa:
    const
      // Sets UnixStartDate to TDateTime of 01/01/1970
      UnixStartDate: TDateTime = 25569.0; 
    
    function DateTimeToUnix(ConvDate: TDateTime): Longint;
    begin
      Result := Round((ConvDate - UnixStartDate) * 86400);
    end; 
    
    function UnixToDateTime(USec: Longint): TDateTime;
    begin
      Result := (Usec / 86400) + UnixStartDate;
    end;
  • Funciones para convertir fechas a Unix timestamp y viceversa:
    const
      // Sets UnixStartDate to TDateTime of 01/01/1970
      UnixStartDate: TDateTime = 25569.0; 
    
    function DateTimeToUnix(ConvDate: TDateTime): Longint;
    begin
      Result := Round((ConvDate - UnixStartDate) * 86400);
    end; 
    
    function UnixToDateTime(USec: Longint): TDateTime;
    begin
      Result := (Usec / 86400) + UnixStartDate;
    end;
  • Funciones dinámicas: funciones como parámetro de otras funciones

Enlaces de interés

Otros artículos de esta serie:

[seriesposts show_date=0 order=asc]

Publicar un Comentario

Si es la primera vez que escribes, tu comentario será moderado por un administrador.

Con el fin de garantizar un ambiente de debate respetuoso, no se permitirán comentarios:

  • insultantes, difamatorios, racistas, sexistas, y/o discriminatorios
  • excesivamente críticos con otros participanes
  • que no aporten nada, sin sentido o repetidos
  • con enlaces considerados publicidad o spam
  • con material protegido por derechos de autor
*
*