Delphi Xe
Delphi Xe
#delphi
Tabla de contenido
Acerca de 1
Observaciones 2
Versiones 2
Examples 3
Hola Mundo 3
Capítulo 2: Bucles 6
Introducción 6
Sintaxis 6
Examples 6
Repetir hasta 7
Mientras hace 7
Examples 9
Introducción 9
Emparejamiento clave-valor 9
Introducción 12
Examples 12
Ejemplo trivial 12
Examples 14
Proceso de creación 14
Examples 16
Interfaz gráfica de usuario receptiva que usa hilos para trabajos en segundo plano y PostM 16
Hilo 16
Formar 18
Capítulo 7: Genéricos 20
Examples 20
Examples 22
Tipos de cuerdas 22
Instrumentos de cuerda 22
Los caracteres 23
SUPERIOR y minúscula 23
Asignación 23
Recuento de referencias 24
Codificaciones 24
Capítulo 9: Interfaces 26
Observaciones 26
Examples 26
Propiedades en interfaces 28
Examples 30
Sintaxis 32
Observaciones 32
Examples 32
Simple para bucle 32
Para en la matriz 34
Observaciones 36
Examples 36
Ejemplo de FireDAC 36
Examples 39
Trectangle giratorio 39
Introducción 40
Observaciones 40
Examples 40
Sintaxis 42
Examples 42
Creditos 45
Acerca de
You can share this PDF with anyone you feel could benefit from it, downloaded the latest version
from: embarcadero-delphi
It is an unofficial and free Embarcadero Delphi ebook created for educational purposes. All the
content is extracted from Stack Overflow Documentation, which is written by many hardworking
individuals at Stack Overflow. It is neither affiliated with Stack Overflow nor official Embarcadero
Delphi.
The content is released under Creative Commons BY-SA, and the list of contributors to each
chapter are provided in the credits section at the end of this book. Images may be copyright of
their respective owners unless otherwise specified. All trademarks and registered trademarks are
the property of their respective company owners.
Use the content presented in this book at your own risk; it is not guaranteed to be correct nor
accurate, please send your feedback and corrections to [email protected]
https://riptutorial.com/es/home 1
Capítulo 1: Comenzando con Embarcadero
Delphi
Observaciones
Delphi es un lenguaje de propósito general basado en un dialecto Object Pascal con sus raíces
que proviene de Borland Turbo Pascal. Viene con su propio IDE diseñado para soportar el rápido
desarrollo de aplicaciones (RAD).
Versiones
Version Fecha de
Versión Nombre del producto
numerica lanzamiento
https://riptutorial.com/es/home 2
Version Fecha de
Versión Nombre del producto
numerica lanzamiento
Examples
Hola Mundo
program HelloWorld;
{$APPTYPE CONSOLE}
begin
WriteLn('Hello World');
end.
https://riptutorial.com/es/home 3
los componentes WinAPI utilizados comúnmente. De esta manera, se pueden usar mucho más
fácilmente, por ejemplo, sin la necesidad de trabajar con los controladores de ventana.
Para incluir una dependencia (como Vcl.Dialogs en este caso), agregue el bloque de uses que
incluye una lista de unidades separadas por comas que terminan con un punto y coma.
program HelloWindows;
uses
Vcl.Dialogs;
begin
ShowMessage('Hello Windows');
end.
Este programa utiliza la API de Windows (WinAPI) para imprimir "Hello World" en un cuadro de
mensaje.
Para incluir una dependencia (como Windows en este caso), agregue el bloque de usos que incluye
una lista de unidades separadas por comas que terminan con un punto y coma.
program HelloWorld;
uses
Windows;
begin
MessageBox(0, 'Hello World!', 'Hello World!', 0);
end.
XE2
program CrossPlatformHelloWorld;
uses
FMX.Dialogs;
{$R *.res}
begin
ShowMessage('Hello world!');
end.
La mayoría de las plataformas compatibles con Delphi (Win32 / Win64 / OSX32 / Android32 /
iOS32 / iOS64) también son compatibles con una consola, por lo que el ejemplo de WriteLn les
queda bien.
Para las plataformas que requieren una GUI (cualquier dispositivo iOS y algunos dispositivos
Android), el ejemplo anterior de FireMonkey funciona bien.
https://riptutorial.com/es/home 4
Lea Comenzando con Embarcadero Delphi en línea:
https://riptutorial.com/es/delphi/topic/599/comenzando-con-embarcadero-delphi
https://riptutorial.com/es/home 5
Capítulo 2: Bucles
Introducción
El lenguaje Delphi proporciona 3 tipos de bucle
for - iterator para secuencia fija sobre entero, cadena, matriz o enumeración
while do condición while do - do se verifica antes de cada turno, el bucle nunca podría ejecutarse
Sintaxis
• para OrdinalVariable: = LowerOrdinalValue to UpperOrdinalValue comience {loop-body}
end;
• para OrdinalVariable: = UpperOrdinalValue down to LowerOrdinalValue do comienza {loop-
body} end;
• para EnumerableVariable in Collection, comience {loop-body} end;
• repita {loop-body} hasta que {break-condition};
• mientras que {condición} comienza {bucle-cuerpo} termina;
Examples
Romper y continuar en bucles
program ForLoopWithContinueAndBreaks;
{$APPTYPE CONSOLE}
var
var i : integer;
begin
for i := 1 to 10 do
begin
if i = 2 then continue; (* Skip this turn *)
if i = 8 then break; (* Break the loop *)
WriteLn( i );
end;
WriteLn('Finish.');
end.
Salida:
1
3
4
https://riptutorial.com/es/home 6
5
6
7
Terminar.
Repetir hasta
program repeat_test;
{$APPTYPE CONSOLE}
var s : string;
begin
WriteLn( 'Type a words to echo. Enter an empty string to exit.' );
repeat
ReadLn( s );
WriteLn( s );
until s = '';
end.
Este ejemplo corto se imprime en la consola Type a words to echo. Enter an empty string to exit.
, espere el tipo de usuario, haga eco y vuelva a esperar la entrada en un bucle infinito, hasta que
el usuario ingrese la cadena vacía.
Mientras hace
program WhileEOF;
{$APPTYPE CONSOLE}
uses SysUtils;
CloseFile( F );
end
else
WriteLn( 'File ' + cFileName + ' not found!' );
end.
Este ejemplo imprime para consolar el contenido de texto del archivo WhileEOF.dpr usando la
condición While not(EOF) . Si el archivo está vacío, entonces no se ejecuta el ciclo ReadLn-WriteLn .
https://riptutorial.com/es/home 7
Lea Bucles en línea: https://riptutorial.com/es/delphi/topic/9931/bucles
https://riptutorial.com/es/home 8
Capítulo 3: Clase TStringList
Examples
Introducción
TStringList es un descendiente de la clase TStrings del VCL. TStringList se puede utilizar para
almacenar y manipular la lista de cadenas. Aunque originalmente estaba destinado a cadenas,
cualquier tipo de objetos también se pueden manipular usando esta clase.
TStringList se usa ampliamente en VCL cuando el propósito es mantener una lista de cadenas.
TStringList admite un amplio conjunto de métodos que ofrecen un alto nivel de personalización y
facilidad de manipulación.
procedure StringListDemo;
var
MyStringList: TStringList;
i: Integer;
Begin
//Output
for i:=0 to MyStringList.Count - 1 do
WriteLn(MyStringList[i]);
finally
//Destroy the object
MyStringList.Free;
end;
end;
TStringList tiene una variedad de casos de usuarios que incluyen manipulación de cadenas,
clasificación, indexación, emparejamiento clave-valor y separación de delimitadores entre ellos.
Emparejamiento clave-valor
Puede usar una TStringList para almacenar pares clave-valor. Esto puede ser útil si desea
almacenar configuraciones, por ejemplo. Una configuración consiste en una clave (el identificador
https://riptutorial.com/es/home 9
de la configuración) y el valor. Cada par clave-valor se almacena en una línea de StringList en el
formato clave = valor.
En este ejemplo, la lista de cadenas tiene el siguiente contenido antes de que se destruya:
1stName=John
LastName=Doe
City=New York
Bajo el capó, TStringList realiza una búsqueda de claves haciendo un bucle directo a través de
todos los elementos, buscando un separador dentro de cada elemento y comparando la parte del
nombre con la clave dada. No es necesario decir que tiene un gran impacto en el rendimiento, por
lo que este mecanismo solo debe utilizarse en lugares no críticos, que rara vez se repiten. En los
casos en los que el rendimiento es importante, se debe usar TDictionary<TKey,TValue> de
System.Generics.Collections que implementa la búsqueda de tablas hash o para mantener las
claves ordenadas en TStringList con los valores almacenados como Object , utilizando el
algoritmo de búsqueda binaria.
https://riptutorial.com/es/home 10
Lea Clase TStringList en línea: https://riptutorial.com/es/delphi/topic/6045/clase-tstringlist
https://riptutorial.com/es/home 11
Capítulo 4: Creación de cheques de error de
tiempo de ejecución fácilmente extraíbles
Introducción
Esto muestra cómo una rutina de verificación de errores de tiempo de ejecución de su propia
creación se puede incorporar fácilmente para que no genere ninguna sobrecarga de código
cuando se apaga.
Examples
Ejemplo trivial
{$DEFINE MyRuntimeCheck} // Comment out this directive when the check is no-longer required!
// You can also put MyRuntimeCheck in the project defines instead.
El símbolo definido se utiliza para activar el uso del código. También evita que el código esté
explícitamente en línea, lo que significa que es más fácil poner un punto de interrupción en la
rutina de verificación.
Pero ahora también es libre de utilizar esta forma de construcción para el código que realiza el
registro de seguimiento, las métricas, lo que sea. Por ejemplo:
https://riptutorial.com/es/home 12
{$ENDIF}
end;
...
MyTrace('I was here'); // This code overhead will vanish if 'MyTrace' is not defined.
MyTrace( SomeString ); // So will this.
https://riptutorial.com/es/home 13
Capítulo 5: Ejecutando otros programas
Examples
Proceso de creación
La siguiente función encapsula el código para usar la API de Windows CreateProcess para iniciar
otros programas.
Parámetros:
https://riptutorial.com/es/home 14
end;
with ProcessInfo do
begin
CloseHandle(hThread);
if WaitUntilIdle then WaitForInputIdle(hProcess, INFINITE);
if WaitUntilTerminated then
repeat
Application.ProcessMessages;
until MsgWaitForMultipleObjects(1, hProcess, false, INFINITE, QS_ALLINPUT) <>
WAIT_OBJECT_0 + 1;
CloseHandle(hProcess);
end;
end;
var
FileName, Parameters, WorkingFolder: string;
Error: integer;
OK: boolean;
begin
FileName := 'C:\FullPath\myapp.exe';
WorkingFolder := ''; // if empty function will extract path from FileName
Parameters := '-p'; // can be empty
OK := ExecuteProcess(FileName, Parameters, WorkingFolder, false, false, false, Error);
if not OK then ShowMessage('Error: ' + IntToStr(Error));
end;
Documentación de CreateProcess
https://riptutorial.com/es/home 15
Capítulo 6: Ejecutar un hilo manteniendo GUI
sensible
Examples
Interfaz gráfica de usuario receptiva que usa hilos para trabajos en segundo
plano y PostMessage para informar sobre los hilos
Mantener una interfaz gráfica de usuario receptiva mientras se ejecuta un proceso largo requiere
o bien algunas "devoluciones de llamada" muy elaboradas para permitir que la interfaz gráfica de
usuario procese su cola de mensajes, o el uso de subprocesos (de fondo) (trabajador).
Iniciar cualquier cantidad de subprocesos para hacer algún trabajo por lo general no es un
problema. La diversión comienza cuando desea que la GUI muestre resultados intermedios y
finales o informe sobre el progreso.
Mostrar cualquier cosa en la GUI requiere interactuar con los controles y / o la cola / bomba de
mensajes. Eso siempre debe hacerse en el contexto del hilo principal. Nunca en el contexto de
cualquier otro hilo.
Este ejemplo muestra cómo puede hacerlo utilizando subprocesos simples, permitiendo que la
GUI acceda a la instancia del subproceso después de que termine configurando FreeOnTerminate
en false e informando cuando un subproceso se "hace" con PostMessage .
Notas sobre las condiciones de carrera: las referencias a los subprocesos de trabajo se
mantienen en una matriz en el formulario. Cuando se termina un hilo, la referencia
correspondiente en la matriz se anula.
Esta es una fuente potencial de condiciones de carrera. Como es el uso de un booleano "En
ejecución" para que sea más fácil determinar si todavía hay algún hilo que necesita terminar.
Tendrá que decidir si necesita proteger estos recursos utilizando bloqueos o no.
En este ejemplo, tal como está, no hay necesidad. Solo se modifican en dos ubicaciones: el
método StartThreads y el método HandleThreadResults . Ambos métodos solo se ejecutan en el
contexto del hilo principal. Mientras lo mantengas así y no comiences a llamar estos métodos
desde el contexto de diferentes hilos, no hay forma de que produzcan condiciones de carrera.
Hilo
type
TWorker = class(TThread)
private
https://riptutorial.com/es/home 16
FFactor: Double;
FResult: Double;
FReportTo: THandle;
protected
procedure Execute; override;
public
constructor Create(const aFactor: Double; const aReportTo: THandle);
procedure TWorker.Execute;
const
Max = 100000000;var
i : Integer;
begin
inherited;
FResult := FFactor;
for i := 1 to Max do
FResult := Sqrt(FResult);
El uso de PostMessage es esencial en este ejemplo. PostMessage "solo" pone un mensaje en la cola
de la bomba de mensajes del hilo principal y no espera a que se maneje. Es de naturaleza
asíncrona. Si fueras a usar SendMessage , estarías codificándote en un encurtido. SendMessage pone
el mensaje en la cola y espera hasta que se haya procesado. En resumen, es síncrono.
const
UM_WORKERDONE = WM_APP + 1;
type
TUMWorkerDone = packed record
Msg: Cardinal;
ThreadHandle: Integer;
unused: Integer;
Result: LRESULT;
end;
La const. UM_WORKERDONE usa WM_APP como punto de partida para su valor para garantizar que no
interfiera con ningún valor usado por Windows o Delphi VCL (según lo recomendado por
MicroSoft).
https://riptutorial.com/es/home 17
Formar
Cualquier forma se puede utilizar para iniciar hilos. Todo lo que necesitas hacer es agregar los
siguientes miembros:
private
FRunning: Boolean;
FThreads: array of record
Instance: TThread;
Handle: THandle;
end;
procedure StartThreads(const aNumber: Integer);
procedure HandleThreadResult(var Message: TUMWorkerDone); message UM_WORKERDONE;
Ah, y el código de ejemplo supone la existencia de un Memo1: TMemo; en las declaraciones del
formulario, que utiliza para "registro e informes".
Se puede utilizar FRunning para evitar que se FRunning clic en la GUI mientras se está realizando el
trabajo. FThreads se utiliza para mantener el puntero de instancia y el identificador de los
subprocesos creados.
El procedimiento para iniciar los hilos tiene una implementación bastante sencilla. Comienza con
una verificación de si ya hay un conjunto de subprocesos en espera. Si es así, simplemente sale.
Si no, establece el indicador en verdadero e inicia los subprocesos proporcionando a cada uno su
propio identificador para que sepan dónde publicar su mensaje "terminado".
FRunning := True;
El identificador del subproceso también se coloca en la matriz porque eso es lo que recibimos en
los mensajes que nos dicen que se ha realizado un subproceso y tenerlo fuera de la instancia del
subproceso hace que sea un poco más fácil acceder. Tener el identificador disponible fuera de la
instancia del hilo también nos permite usar FreeOnTerminate en True si no necesitamos la instancia
para obtener sus resultados (por ejemplo, si se han almacenado en una base de datos). En ese
caso, por supuesto, no habría necesidad de mantener una referencia a la instancia.
https://riptutorial.com/es/home 18
procedure TForm1.HandleThreadResult(var Message: TUMWorkerDone);
var
i: Integer;
ThreadIdx: Integer;
Thread: TWorker;
Done: Boolean;
begin
// Find thread in array
ThreadIdx := -1;
for i := Low(FThreads) to High(FThreads) do
if FThreads[i].Handle = Cardinal(Message.ThreadHandle) then
begin
ThreadIdx := i;
Break;
end;
// Report results and free the thread, nilling its pointer and handle
// so we can detect when all threads are done.
if ThreadIdx > -1 then
begin
Thread := TWorker(FThreads[i].Instance);
Memo1.Lines.Add(Format('Thread %d returned %f', [ThreadIdx, Thread.Result]));
FreeAndNil(FThreads[i].Instance);
FThreads[i].Handle := nil;
end;
Este método primero busca el hilo usando el identificador recibido en el mensaje. Si se encontró
una coincidencia, recupera e informa el resultado del hilo usando la instancia ( FreeOnTerminate era
False , ¿recuerdas?), Y luego finaliza: libera la instancia y configura la referencia de la instancia y
el identificador a cero, lo que indica que este hilo no es ya relevante
https://riptutorial.com/es/home 19
Capítulo 7: Genéricos
Examples
Ordenar una matriz dinámica a través de TArray genérico.
uses
System.Generics.Collections, { TArray }
System.Generics.Defaults; { TComparer<T> }
...
...
WriteLn(List[1]); { 200 }
finally
List.Free;
end;
type
TIntegerList = class(TList<Integer>)
public
function Sum: Integer;
end;
...
https://riptutorial.com/es/home 20
for Item in Self do
Result := Result + Item;
end;
...
List.Sort(
TComparer<TDateTime>.Construct(
function(const A, B: TDateTime): Integer
begin
Result := CompareDateTime(A, B);
end
)
);
https://riptutorial.com/es/home 21
Capítulo 8: Instrumentos de cuerda
Examples
Tipos de cuerdas
Longitud Talla
Tipo Descripción
maxima minima
Instrumentos de cuerda
uses
System.Character;
var
S1, S2: string;
begin
S1 := 'Foo';
S2 := ToLower(S1); // Convert the string to lower-case
S1 := ToUpper(S2); // Convert the string to upper-case
https://riptutorial.com/es/home 22
Los caracteres
2009
uses
Character;
var
C1, C2: Char;
begin
C1 := 'F';
C2 := ToLower(C1); // Convert the char to lower-case
C1 := ToUpper(C2); // Convert the char to upper-case
SUPERIOR y minúscula
uses
SysUtils;
var
S1, S2: string;
begin
S1 := 'Foo';
S2 := LowerCase(S1); // S2 := 'foo';
S1 := UpperCase(S2); // S1 := 'FOO';
Asignación
var
SS5: string[5]; {a shortstring of 5 chars + 1 length byte, no trailing `0`}
WS: Widestring; {managed pointer, with a bit of compiler support}
AS: ansistring; {ansistring with the default codepage of the system}
US: unicodestring; {default string type}
U8: UTF8string;//same as AnsiString(65001)
A1251: ansistring(1251); {ansistring with codepage 1251: Cryllic set}
RB: RawbyteString; {ansistring with codepage 0: no conversion set}
begin
SS5:= 'test'; {S[0] = Length(SS254) = 4, S[1] = 't'...S[5] = undefined}
SS5:= 'test1'; {S[0] = 5, S[5] = '1', S[6] is out of bounds}
SS5:= 'test12'; {compile time error}
WS:= 'test'; {WS now points to a constant unicodestring hard compiled into the data segment}
US:= 'test'+IntToStr(1); {New unicode string is created with reference count = 1}
WS:= US; {SysAllocateStr with datacopied to dest, US refcount = 1 !}
AS:= US; {the UTF16 in US is converted to "extended" ascii taking into account the codepage
in AS possibly losing data in the process}
U8:= US; {safe copy of US to U8, all data is converted from UTF16 into UTF8}
RB:= US; {RB = 'test1'#0 i.e. conversion into RawByteString uses system default codepage}
A1251:= RB; {no conversion takes place, only reference copied. Ref count incremented }
https://riptutorial.com/es/home 23
Recuento de referencias
Como se muestra arriba, la introducción de una cadena local temporal para contener las
modificaciones a un parámetro implica la misma sobrecarga que hacer modificaciones
directamente a ese parámetro. La declaración de una cadena const solo evita el conteo de
referencias cuando el parámetro de cadena es realmente de solo lectura. Sin embargo, para
evitar filtrar detalles de implementación fuera de una función, es recomendable utilizar siempre
uno de const , var o out en el parámetro de cadena.
Codificaciones
La clase Sysutils.TEncoding proporciona el método GetBytes para convertir string a TBytes (matriz
de bytes) y GetString para convertir TBytes a string . La clase Sysutils.TEncoding también
proporciona muchas codificaciones predefinidas como propiedades de clase.
https://riptutorial.com/es/home 24
Una forma de lidiar con las codificaciones es usar solo el tipo de string en su aplicación y usar la
TEncoding cada vez que necesite usar una codificación específica, generalmente en operaciones
de E / S, llamadas a DLL, etc.
procedure EncodingExample;
var hello,response:string;
dataout,datain:TBytes;
expectedLength:integer;
stringStream:TStringStream;
stringList:TStringList;
begin
hello := 'Hello World!Привет мир!';
dataout := SysUtils.TEncoding.UTF8.GetBytes(hello); //Conversion to UTF8
datain := SomeIOFunction(dataout); //This function expects input as TBytes in UTF8 and
returns output as UTF8 encoded TBytes.
response := SysUtils.TEncoding.UTF8.GetString(datain); //Convertsion from UTF8
//In case you need to send text via pointer and length using specific encoding (used mostly
for DLL calls)
dataout := SysUtils.TEncoding.GetEncoding('ISO-8859-2').GetBytes(hello); //Conversion to ISO
8859-2
DLLCall(addr(dataout[0]),length(dataout));
//The same is for cases when you get text via pointer and length
expectedLength := DLLCallToGetDataLength();
setLength(datain,expectedLength);
DLLCall(addr(datain[0]),length(datain));
response := Sysutils.TEncoding.GetEncoding(1250).getString(datain);
https://riptutorial.com/es/home 25
Capítulo 9: Interfaces
Observaciones
Las interfaces se utilizan para describir la información necesaria y el resultado esperado de los
métodos y clases, sin proporcionar información de la implementación explícita.
Las clases pueden implementar interfaces, y las interfaces pueden heredarse unas de otras. Si
una clase está implementando una interfaz, esto significa que todas las funciones y
procedimientos expuestos por la interfaz existen en la clase.
Un aspecto especial de las interfaces en delphi es que las instancias de las interfaces tienen una
administración de por vida basada en el conteo de referencias. El tiempo de vida de las instancias
de clase debe gestionarse manualmente.
Teniendo en cuenta todos estos aspectos, las interfaces se pueden utilizar para lograr diferentes
objetivos:
Examples
Definir e implementar una interfaz.
Una interfaz se declara como una clase, pero sin modificadores de acceso ( public , private , ...).
Además, no se permiten definiciones, por lo que no se pueden usar variables y constantes.
Las interfaces siempre deben tener un identificador único , que se puede generar presionando
Ctrl + Shift + G.
IRepository = interface
['{AFCFCE96-2EC2-4AE4-8E23-D4C4FF6BBD01}']
function SaveKeyValuePair(aKey: Integer; aValue: string): Boolean;
end;
Para implementar una interfaz, el nombre de la interfaz debe agregarse detrás de la clase base.
Además, la clase debe ser descendiente de TInterfacedObject (esto es importante para la
administración de por vida ).
https://riptutorial.com/es/home 26
function SaveKeyValuePair(aKey: Integer; aValue: string): Boolean;
end;
Cuando una clase implementa una interfaz, debe incluir todos los métodos y funciones declarados
en la interfaz, de lo contrario no compilará.
Una cosa que vale la pena mencionar es que los modificadores de acceso no tienen ninguna
influencia, si la persona que llama trabaja con la interfaz. Por ejemplo, todas las funciones de la
interfaz se pueden implementar como miembros strict private , pero aún se pueden llamar
desde otra clase si se utiliza una instancia de la interfaz.
Las clases pueden implementar más de una interfaz, en lugar de heredar de más de una clase (
herencia múltiple ) que no es posible para las clases de Delphi. Para lograr esto, el nombre de
todas las interfaces se debe agregar separados por comas detrás de la clase base.
Por supuesto, la clase implementadora también debe definir las funciones declaradas por cada
una de las interfaces.
IInterface1 = interface
['{A2437023-7606-4551-8D5A-1709212254AF}']
procedure Method1();
function Method2(): Boolean;
end;
IInterface2 = interface
['{6C47FF48-3943-4B53-8D5D-537F4A0DEC0D}']
procedure SetValue(const aValue: TObject);
function GetValue(): TObject;
// IInterface2
procedure SetValue(const aValue: TObject);
function GetValue(): TObject
Las interfaces pueden heredarse unas de otras, exactamente igual que las clases. Por lo tanto,
una clase implementadora tiene que implementar funciones de la interfaz y todas las interfaces
base. De esta manera, sin embargo, el compilador no sabe que la clase implementadora también
implementa la interfaz base, solo conoce las interfaces que se enumeran explícitamente. Es por
eso que el uso as ISuperInterface en TImplementer no funcionaría. Eso también resulta en la
https://riptutorial.com/es/home 27
práctica común, implementar explícitamente todas las interfaces base, también (en este caso
TImplementer = class(TInterfacedObject, IDescendantInterface, ISuperInterface) ).
ISuperInterface = interface
['{A2437023-7606-4551-8D5A-1709212254AF}']
procedure Method1();
function Method2(): Boolean;
end;
IDescendantInterface = interface(ISuperInterface)
['{6C47FF48-3943-4B53-8D5D-537F4A0DEC0D}']
procedure SetValue(const aValue: TObject);
function GetValue(): TObject;
// IDescendantInterface
procedure SetValue(const aValue: TObject);
function GetValue(): TObject
Propiedades en interfaces
IInterface = interface(IInterface)
['{6C47FF48-3943-4B53-8D5D-537F4A0DEC0D}']
procedure SetValue(const aValue: TObject);
function GetValue(): TObject;
Una cosa que vale la pena mencionar es que la clase implementadora no tiene que declarar la
propiedad. El compilador aceptaría este código:
Una advertencia, sin embargo, es que de esta manera solo se puede acceder a la propiedad a
través de una instancia de la interfaz, y no a través de la propia clase. Además, agregar la
propiedad a la clase aumenta la legibilidad.
https://riptutorial.com/es/home 28
Lea Interfaces en línea: https://riptutorial.com/es/delphi/topic/4885/interfaces
https://riptutorial.com/es/home 29
Capítulo 10: Medición de intervalos de tiempo
Examples
Usando la API de Windows GetTickCount
La función GetTickCount API de Windows devuelve el número de milisegundos desde que se inició
el sistema (computadora). El ejemplo más simple sigue:
var
Start, Stop, ElapsedMilliseconds: cardinal;
begin
Start := GetTickCount;
// do something that requires measurement
Stop := GetTickCount;
ElapsedMillseconds := Stop - Start;
end;
Tenga en cuenta que GetTickCount devuelve DWORD 32 bits por lo que se ajusta cada 49.7 días.
Para evitar el GetTickCount64 , puede usar GetTickCount64 (disponible desde Windows Vista) o
rutinas especiales para calcular la diferencia de ticks:
De todos modos, estas rutinas devolverán resultados incorrectos si el intervalo de dos llamadas
subsiguientes de GetTickCount excede el límite de 49.7 días.
var
Start, Stop, ElapsedMilliseconds: cardinal;
begin
Start := GetTickCount;
sleep(4000); // sleep for 4 seconds
Stop := GetTickCount;
ElapsedMillseconds := Stop - Start;
ShowMessage('Total Seconds: '
+IntToStr(round(ElapsedMilliseconds/SysUtils.MSecsPerSec))); // 4 seconds
end;
https://riptutorial.com/es/home 30
Las versiones recientes de Delphi se envían con el registro TStopwatch que es para la medición
del intervalo de tiempo. Ejemplo de uso:
uses
System.Diagnostics;
var
StopWatch: TStopwatch;
ElapsedMillseconds: Int64;
begin
StopWatch := TStopwatch.StartNew;
// do something that requires measurement
ElapsedMillseconds := StopWatch.ElapsedMilliseconds;
end;
https://riptutorial.com/es/home 31
Capítulo 11: Para loops
Sintaxis
• para OrdinalVariable: = LowerOrdinalValue to UpperOrdinalValue comience {loop-body}
end;
• para OrdinalVariable: = UpperOrdinalValue down to LowerOrdinalValue do comienza {loop-
body} end;
• para EnumerableVariable in Collection, comience {loop-body} end;
Observaciones
• La sintaxis de Delphi for bucle no proporciona nada para cambiar la cantidad del paso de 1
a cualquier otro valor.
• Cuando se realiza un bucle con valores ordinales variables, por ejemplo, variables locales
de tipo Integer , los valores superiores e inferiores se determinarán solo una vez. Los
cambios en dichas variables no tendrán ningún efecto en el recuento de iteraciones de los
bucles.
Examples
Simple para bucle
Un bucle for repite desde el valor inicial hasta el valor final incluido.
program SimpleForLoop;
{$APPTYPE CONSOLE}
var
i : Integer;
begin
for i := 1 to 10 do
WriteLn(i);
end.
Salida:
1
2
3
4
5
6
7
8
https://riptutorial.com/es/home 32
9
10
2005
Lo siguiente itera sobre los caracteres de la cadena s . Funciona de manera similar para el bucle
sobre los elementos de una matriz o un conjunto, siempre que el tipo de la variable de control de
bucle ( c , en este ejemplo) coincida con el tipo de elemento del valor que se está iterando.
program ForLoopOnString;
{$APPTYPE CONSOLE}
var
s : string;
c : Char;
begin
s := 'Example';
for c in s do
WriteLn(c);
end.
Salida:
mi
X
una
metro
pag
l
mi
Un bucle for repite desde el valor inicial hasta el valor final incluido, como un ejemplo de "cuenta
atrás".
program CountDown;
{$APPTYPE CONSOLE}
var
i : Integer;
begin
for i := 10 downto 0 do
WriteLn(i);
end.
Salida:
https://riptutorial.com/es/home 33
10
9
8
7
6
5
4
3
2
1
0
program EnumLoop;
uses
TypInfo;
type
TWeekdays = (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday);
var
wd : TWeekdays;
begin
for wd in TWeekdays do
WriteLn(GetEnumName(TypeInfo(TWeekdays), Ord(wd)));
end.
Salida:
domingo
lunes
martes
miércoles
jueves
viernes
sábado
Para en la matriz
program ArrayLoop;
{$APPTYPE CONSOLE}
const a : array[1..3] of real = ( 1.1, 2.2, 3.3 );
var f : real;
https://riptutorial.com/es/home 34
begin
for f in a do
WriteLn( f );
end.
Salida:
1,1
2,2
3,3
https://riptutorial.com/es/home 35
Capítulo 12: Recuperar datos actualizados de
TDataSet en un hilo de fondo
Observaciones
Este ejemplo de FireDAC, y los otros que planeo enviar, evitarán el uso de llamadas nativas para
abrir el conjunto de datos de forma asíncrona.
Examples
Ejemplo de FireDAC
• El hilo recupera los datos utilizando su propia TFDConnection y TFDQuery y transfiere los
datos a la FDQuery del formulario en una llamada a Sychronize ().
• El Ejecutar recupera los datos solo una vez. Podría modificarse para ejecutar la consulta
repetidamente en respuesta a un mensaje publicado desde el hilo de VCL.
Código:
type
TForm1 = class;
TFDQueryThread = class(TThread)
private
FConnection: TFDConnection;
FQuery: TFDQuery;
FForm: TForm1;
published
constructor Create(AForm : TForm1);
destructor Destroy; override;
procedure Execute; override;
procedure TransferData;
property Query : TFDQuery read FQuery;
property Connection : TFDConnection read FConnection;
property Form : TForm1 read FForm;
end;
TForm1 = class(TForm)
FDConnection1: TFDConnection;
FDQuery1: TFDQuery;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
DBNavigator1: TDBNavigator;
Button1: TButton;
https://riptutorial.com/es/home 36
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
public
QueryThread : TFDQueryThread;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TFDQueryThread }
FQuery := TFDQuery.Create(Nil);
FQuery.Connection := Connection;
FQuery.SQL.Text := Form.FDQuery1.SQL.Text;
end;
destructor TFDQueryThread.Destroy;
begin
FQuery.Free;
FConnection.Free;
inherited;
end;
procedure TFDQueryThread.Execute;
begin
Query.Open;
Synchronize(TransferData);
end;
procedure TFDQueryThread.TransferData;
begin
Form.FDQuery1.DisableControls;
try
if Form.FDQuery1.Active then
Form.FDQuery1.Close;
Form.FDQuery1.Data := Query.Data;
finally
Form.FDQuery1.EnableControls;
end;
end;
https://riptutorial.com/es/home 37
procedure TForm1.Button1Click(Sender: TObject);
begin
if not QueryThread.Finished then
QueryThread.Start
else
ShowMessage('Thread already executed!');
end;
end.
https://riptutorial.com/es/home 38
Capítulo 13: Usando animaciones en
firemonkey
Examples
Trectangle giratorio
Ahora tenemos nuestra animación configurada. Todo lo que queda es encenderlo: soltar dos
botones en el formulario, llamar primero "Inicio", segundo - "Detener". en el evento OnClick del
primer botón escribe:
FloatAnimation1.Start;
FloatAnimation1.Stop;
https://riptutorial.com/es/home 39
Capítulo 14: Usando RTTI en Delphi
Introducción
Delphi proporcionó información de tipo de tiempo de ejecución (RTTI) hace más de una década.
Sin embargo, incluso hoy en día, muchos desarrolladores no son plenamente conscientes de sus
riesgos y beneficios.
Observaciones
RTTI EN DELPHI - EXPLICADO
La información de tipo de tiempo de ejecución en Delphi: ¿puede hacer algo por usted? El artículo
de Brian Long proporciona una excelente introducción a las capacidades RTTI de Delphi. Brian
explica que el soporte RTTI en Delphi se agregó primero y principalmente para permitir que el
entorno de tiempo de diseño haga su trabajo, pero que los desarrolladores también pueden
aprovecharlo para lograr ciertas simplificaciones de código. Este artículo también proporciona una
gran visión general de las clases RTTI junto con algunos ejemplos.
Los ejemplos incluyen: leer y escribir propiedades arbitrarias, propiedades comunes sin ancestros
comunes, copiar propiedades de un componente a otro, etc.
Examples
Información básica de la clase
Este ejemplo muestra cómo obtener la ascendencia de un componente utilizando las propiedades
ClassType y ClassParent . Utiliza un botón Button1: TButton y un cuadro de lista ListBox1: TListBox
en un formulario TForm1 .
Cuando el usuario hace clic en el botón, el nombre de la clase del botón y los nombres de las
clases principales se agregan al cuadro de lista.
https://riptutorial.com/es/home 40
ListBox1.Items.Add(ClassRef.ClassName) ;
ClassRef := ClassRef.ClassParent;
end;
end;
El cuadro de lista contiene las siguientes cadenas después de que el usuario haga clic en el
botón:
• TButton
• Control de TButton
• TWinControl
• TControl
• TComponente
• TPersistente
• Objeto
https://riptutorial.com/es/home 41
Capítulo 15: Uso de try, except, y finalmente.
Sintaxis
1. Try-except: try [sentencias] excepto [[[en E: ExceptionType do statement]] [else statement] |
[declaraciones] terminan;
Examples
Simple intento ... finalmente ejemplo para evitar pérdidas de memoria
Utilice try - finally para evitar pérdidas de recursos (como la memoria) en caso de que ocurra
una excepción durante la ejecución.
El siguiente procedimiento guarda una cadena en un archivo y evita que la TStringList fugas.
Cuando una función devuelve un objeto (en lugar de usar uno que ha pasado la persona que
llama), tenga cuidado de que una excepción no provoque la fuga del objeto.
https://riptutorial.com/es/home 42
// allocated by this function and then re-raise the exception so the caller can
// choose what to do with it.
Result.Free;
raise;
end;
// If execution reaches this point, then no exception has occurred, so the
// function will return Result normally.
end;
Los programadores ingenuos pueden intentar capturar todos los tipos de excepción y devolver nil
partir de esa función, pero eso es solo un caso especial de la práctica general desalentada de
capturar todos los tipos de excepción sin manejarlos.
Un bloque try - finally puede estar anidado dentro de un try - except bloque.
try
AcquireResources;
try
UseResource;
finally
ReleaseResource;
end;
except
on E: EResourceUsageError do begin
HandleResourceErrors;
end;
end;
Un bloque try - except que puede estar anidado dentro de un bloque try - finally .
AcquireResource;
try
UseResource1;
try
UseResource2;
except
on E: EResourceUsageError do begin
HandleResourceErrors;
end;
end;
UseResource3;
https://riptutorial.com/es/home 43
finally
ReleaseResource;
end;
Object1 := nil;
Object2 := nil;
try
Object1 := TMyObject.Create;
Object2 := TMyObject.Create;
finally
Object1.Free;
Object2.Free;
end;
Si no inicializa los objetos con nil fuera del bloque try-finally , si uno de ellos no se crea, se
producirá un AV en el bloque finally, porque el objeto no será nulo (ya que no se inicializó) y
causará una excepción
El método Free comprueba si el objeto es nulo, por lo que al inicializar ambos objetos con nil
evitan errores al liberarlos si no se crearon.
https://riptutorial.com/es/home 44
Creditos
S.
Capítulos Contributors
No
2 Bucles Y.N
Creación de cheques
de error de tiempo
4 Alex T
de ejecución
fácilmente extraíbles
Ejecutando otros
5 Dalija Prasnikar
programas
Ejecutar un hilo
6 manteniendo GUI Fr0sT, Jerry Dodge, Johan, kami, LU RD, Marjan Venema
sensible
Medición de
10 Fr0sT, John Easley, kludg, Rob Kennedy, Victoria, Wolf
intervalos de tiempo
Recuperar datos
actualizados de
12 MartynA
TDataSet en un hilo
de fondo
Usando animaciones
13 Alexander Petrosyan
en firemonkey
https://riptutorial.com/es/home 45
Delphi
Uso de try, except, y EMBarbosa, Fabio Gomes, Johan, MrE, Nick Hodges, Rob
15
finalmente. Kennedy, Shadow
https://riptutorial.com/es/home 46