Embarcadero Delphi PDF
Embarcadero Delphi PDF
Embarcadero Delphi PDF
#delphi
Table of Contents
About 1
Remarks 2
Versions 2
Examples 3
Hello World 3
Introduction 5
Examples 5
Trivial example 5
Syntax 7
Remarks 7
Examples 7
For in array 9
Chapter 4: Generics 11
Examples 11
Sort a TList 12
Chapter 5: Interfaces 13
Remarks 13
Examples 13
Properties in interfaces 15
Chapter 6: Loops 16
Introduction 16
Syntax 16
Examples 16
Repeat-Until 17
While do 17
Remarks 18
Examples 18
FireDAC example 18
Examples 21
Responsive GUI using threads for background work and PostMessage to report back from the t 21
Thread 21
Form 22
Examples 25
CreateProcess 25
Examples 27
String types 27
Strings 27
Chars 27
Assignment 28
Reference counting 28
Encodings 29
Examples 31
Examples 33
Introduction 33
Key-Value Pairing 33
Syntax 35
Examples 35
Examples 38
Rotating TRectangle 38
Introduction 39
Remarks 39
Examples 39
Credits 41
About
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/ 1
Chapter 1: Getting started with Embarcadero
Delphi
Remarks
Delphi is a general-purpose language based on an Object Pascal dialect with its roots coming
from Borland Turbo Pascal. It comes with its own IDE designed to support rapid application
development (RAD).
It allows cross-platform native (compiled) application development from a single code base.
Currently supported platforms are Windows, OSX, iOS and Android.
• VCL: Visual Component Library specifically designed for Windows development wrapping
Windows native controls and support for creating custom ones.
• FMX: FireMonkey cross-platform framework for all supported platforms
Versions
https://riptutorial.com/ 2
Version Numeric version Product name Release date
Examples
Hello World
This program, saved to a file named HelloWorld.dpr, compiles to a console application that prints
"Hello World" to the console:
program HelloWorld;
{$APPTYPE CONSOLE}
begin
WriteLn('Hello World');
end.
This progam uses VCL, the default UI components library of Delphi, to print "Hello World" into a
message box. The VCL wrapps most of the commonly used WinAPI components. This way, they
can be used much easier, e.g. without the need to work with Window Handles.
To include a dependency (like Vcl.Dialogs in this case), add the uses block including a comma-
separated list of units ending with an semicolon.
https://riptutorial.com/ 3
program HelloWindows;
uses
Vcl.Dialogs;
begin
ShowMessage('Hello Windows');
end.
This program uses the Windows API (WinAPI) to print "Hello World" into a message box.
To include a dependency (like Windows in this case), add the uses block including a comma-
separated list of units ending with an semicolon.
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.
For the platforms that require a GUI (any iOS device and some Android devices), the above
FireMonkey example works well.
https://riptutorial.com/ 4
Chapter 2: Creating easily removable runtime
error checks
Introduction
This shows how a runtime error check routine of your own making can be easily incorporated so
that it doesn't generate any code overhead when it is turned off.
Examples
Trivial example
{$DEFINE MyRuntimeCheck} // Comment out this directive when the check is no-longer required!
// You can also put MyRuntimeCheck in the project defines instead.
The defined symbol is used to turn on the use of the code. It also stops the code being explicitly
in-lined, which means it is easier to put a breakpoint into the check routine.
However, the real beauty of this construction is when you don't want the check anymore. By
commenting out the $DEFINE (put '//' in-front of it) you will not only remove the check code, but
you will also switch on the inline for the routine and thus remove any overheads from all the
places where you invoked the routine! The compiler will remove all traces of your check entirely
(assuming that inlining itself is set to "On" or "Auto", of course).
The example above is essentially similar to the concept of "assertions", and your first line could set
the result to TRUE or FALSE as appropriate to the usage.
But you are now also free to use this manner of construction for code that does trace-logging,
metrics, whatever. For example:
https://riptutorial.com/ 5
MyTrace( SomeString ); // So will this.
https://riptutorial.com/ 6
Chapter 3: For Loops
Syntax
• for OrdinalVariable := LowerOrdinalValue to UpperOrdinalValue do begin {loop-body} end;
• for OrdinalVariable := UpperOrdinalValue downto LowerOrdinalValue do begin {loop-body}
end;
• for EnumerableVariable in Collection do begin {loop-body} end;
Remarks
• Delphi's for-loop syntax does not provide anything to change step amount from 1 to any
other value.
• When looping with variable ordinal values, e.g. local variables of type Integer, the upper and
lower values will be determined only once. Changes to such variables will have no effect on
the loops iteration count.
Examples
Simple for loop
A for loop iterates from the starting value to the ending value inclusive.
program SimpleForLoop;
{$APPTYPE CONSOLE}
var
i : Integer;
begin
for i := 1 to 10 do
WriteLn(i);
end.
Output:
1
2
3
4
5
6
7
8
9
10
https://riptutorial.com/ 7
Looping over characters of a string
2005
The following iterates over the characters of the string s. It works similarly for looping over the
elements of an array or a set, so long as the type of the loop-control variable (c, in this example)
matches the element type of the value being iterated.
program ForLoopOnString;
{$APPTYPE CONSOLE}
var
s : string;
c : Char;
begin
s := 'Example';
for c in s do
WriteLn(c);
end.
Output:
E
x
a
m
p
l
e
A for loop iterates from the starting value down to the ending value inclusive, as a "count-down"
example.
program CountDown;
{$APPTYPE CONSOLE}
var
i : Integer;
begin
for i := 10 downto 0 do
WriteLn(i);
end.
Output:
10
9
8
https://riptutorial.com/ 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.
Output:
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
For in array
program ArrayLoop;
{$APPTYPE CONSOLE}
const a : array[1..3] of real = ( 1.1, 2.2, 3.3 );
var f : real;
begin
for f in a do
WriteLn( f );
end.
https://riptutorial.com/ 9
Output:
1,1
2,2
3,3
https://riptutorial.com/ 10
Chapter 4: Generics
Examples
Sort a dynamic array via generic TArray.Sort
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/ 11
for Item in Self do
Result := Result + Item;
end;
Sort a TList
...
List.Sort(
TComparer<TDateTime>.Construct(
function(const A, B: TDateTime): Integer
begin
Result := CompareDateTime(A, B);
end
)
);
https://riptutorial.com/ 12
Chapter 5: Interfaces
Remarks
Interfaces are used to describe the needed information and the expected output of methods and
classes, without providing information of the explicit implementation.
Classes can implement interfaces, and interfaces can inherit from each other. If a class is
implementing an interface, this means all functions and procedures exposed by the interface
exist in the class.
A special aspect of interfaces in delphi is that instances of interfaces have a lifetime management
based on reference counting. The lifetime of class instances has to be managed manually.
Considering all these aspects, interfaces can be used to achieve different goals:
• Provide multiple different implementations for operations (e.g. saving in a file, database or
sending as E-Mail, all as Interface "SaveData")
• Reduce dependencies, improving the decoupling and thus making the code better
maintainable and testable
• Work with instances in multiple units without getting troubled by lifetime management
(though even here pitfalls exist, beware!)
Examples
Defining and implementing an interface
An interface is declared like a class, but without access modifiers (public, private, ...). Also, no
definitions are allowed, so variables and constants can't be used.
Interfaces should always have an Unique Identifier, which can be generated by pressing Ctrl +
Shift + G.
IRepository = interface
['{AFCFCE96-2EC2-4AE4-8E23-D4C4FF6BBD01}']
function SaveKeyValuePair(aKey: Integer; aValue: string): Boolean;
end;
To implement an interface, the name of the interface must be added behind the base class. Also,
the class should be a descendant of TInterfacedObject (this is important for the lifetime
management).
When a class implements an interface, it must include all methods and functions declared in the
https://riptutorial.com/ 13
interface, else it won't compile.
One thing worth noting is that access modifiers don't have any influence, if the caller works with
the interface. For example all functions of the interface can be implemented as strict private
members, but can still be called from another class if an instance of the interface is used.
Classes can implement more than one interface, as opposed to inheriting from more than one
class (Multiple Inheritance) which isn't possible for Delphi classes. To achieve this, the name of all
interfaces must be added comma-separated behind the base class.
Of course, the implementing class must also define the functions declared by each of the
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
Interfaces can inherit from each other, exactly like classes do, too. An implementing class thus has
to implement functions of the interface and all base interfaces. This way, however, the compiler
doesn't know that the implenting class also implements the base interface, it only knows of the
interfaces that are explicitly listed. That's why using as ISuperInterface on TImplementer wouldn't
work. That also results in the common practice, to explicitly implement all base interfaces, too (in
this case TImplementer = class(TInterfacedObject, IDescendantInterface, ISuperInterface)).
ISuperInterface = interface
['{A2437023-7606-4551-8D5A-1709212254AF}']
procedure Method1();
https://riptutorial.com/ 14
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
Properties in interfaces
Since the declaration of variables in interfaces isn't possible, the "fast" way of defining properites (
property Value: TObject read FValue write FValue;) can't be used. Instead, the Getter and setter
(each only if needed) have to be declared in the interface, too.
IInterface = interface(IInterface)
['{6C47FF48-3943-4B53-8D5D-537F4A0DEC0D}']
procedure SetValue(const aValue: TObject);
function GetValue(): TObject;
One thing worth noting is that the implementing class doesn't have to declare the property. The
compiler would accept this code:
One caveat, however, is that this way the property can only be accessed through an instance of
the interface, noth through the class itself. Also, adding the property to the class increases the
readability.
https://riptutorial.com/ 15
Chapter 6: Loops
Introduction
Delphi language provide 3 types of loop
for - iterator for fixed sequence over integer, string, array or enumeration
repeat-until - quit condition is checking after each turn, loop executing at minimum once tmeeven
while do - do condition is checking before each turn, loop could be never executed
Syntax
• for OrdinalVariable := LowerOrdinalValue to UpperOrdinalValue do begin {loop-body} end;
• for OrdinalVariable := UpperOrdinalValue downto LowerOrdinalValue do begin {loop-body}
end;
• for EnumerableVariable in Collection do begin {loop-body} end;
• repeat {loop-body} until {break-condition};
• while {condition} do begin {loop-body} end;
Examples
Break and Continue in Loops
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.
Output:
1
3
4
5
6
https://riptutorial.com/ 16
7
Finish.
Repeat-Until
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.
This short example print on console Type a words to echo. Enter an empty string to exit., wait for
user type, echo it and waiting input again in infinite loop - until user entering the empty string.
While do
program WhileEOF;
{$APPTYPE CONSOLE}
uses SysUtils;
CloseFile( F );
end
else
WriteLn( 'File ' + cFileName + ' not found!' );
end.
This example print to console the text content of WhileEOF.dpr file using While not(EOF) condition. If
file is empty then ReadLn-WriteLn loop is not executed.
https://riptutorial.com/ 17
Chapter 7: Retrieving updated TDataSet data
in a background thread
Remarks
This FireDAC example, and the others I'm planning to submit, will avoid the use of native calls to
asynchronously open the dataset.
Examples
FireDAC example
The code sample below shows one way to retrieve records from an MSSql Server in a background
thread using FireDAC. Tested for Delphi 10 Seattle
As written:
• The thread retrieves data using its own TFDConnection and TFDQuery and transfers the
data to the form's FDQuery in a call to Sychronize().
• The Execute retrieves the data only once. It could be altered to run the query repeatedly in
response to a message posted from the VCL thread.
Code:
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/ 18
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/ 19
procedure TForm1.Button1Click(Sender: TObject);
begin
if not QueryThread.Finished then
QueryThread.Start
else
ShowMessage('Thread already executed!');
end;
end.
https://riptutorial.com/ 20
Chapter 8: Running a thread while keeping
GUI responsive
Examples
Responsive GUI using threads for background work and PostMessage to
report back from the threads
Keeping a GUI responsive while running a lengthy process requires either some very elaborate
"callbacks" to allow the GUI to process its message queue, or the use of (background) (worker)
threads.
Kicking off any number of threads to do some work usually isn't a problem. The fun starts when
you want to make the GUI show intermediate and final results or report on the progress.
Showing anything in the GUI requires interacting with controls and/or the message queue/pump.
That should always be done in the context of the main thread. Never in the context of any other
thread.
This example shows how you can do it using simple threads, allowing the GUI to access the
thread instance after it is finished by setting FreeOnTerminate to false, and reporting when a thread
is "done" using PostMessage.
Notes on race conditions: References to the worker threads are kept in an array in the form. When
a thread is finished, the corresponding reference in the array gets nil-ed.
This is a potential source of race conditions. As is the use of a "Running" boolean to make it easier
to determine whether there are still any threads that need to finish.
You will need to decide whether you need to protect theses resource using locks or not.
In this example, as it stands, there is no need. They are only modified in two locations: the
StartThreads method and the HandleThreadResults method. Both methods only ever run in the
context of the main thread. As long as you keep it that way and don't start calling these methods
from the context of different threads, there is no way for them to produce race conditions.
Thread
type
TWorker = class(TThread)
private
FFactor: Double;
FResult: Double;
FReportTo: THandle;
https://riptutorial.com/ 21
protected
procedure Execute; override;
public
constructor Create(const aFactor: Double; const aReportTo: THandle);
The constructor just sets the private members and sets FreeOnTerminate to False. This is
essential as it will allow the main thread to query the thread instance for its result.
The execute method does its calculation and then posts a message to the handle it received in its
constructor to say its done:
procedure TWorker.Execute;
const
Max = 100000000;var
i : Integer;
begin
inherited;
FResult := FFactor;
for i := 1 to Max do
FResult := Sqrt(FResult);
The use of PostMessage is essential in this example. PostMessage "just" puts a message on the
queue of the main thread's message pump and doesn't wait for it to be handled. It is asynchronous
in nature. If you were to use SendMessage you'd be coding yourself into a pickle. SendMessage puts the
message on the queue and waits until it has been processed. In short, it is synchronous.
The declarations for the custom UM_WORKERDONE message are declared as:
const
UM_WORKERDONE = WM_APP + 1;
type
TUMWorkerDone = packed record
Msg: Cardinal;
ThreadHandle: Integer;
unused: Integer;
Result: LRESULT;
end;
The UM_WORKERDONE const uses WM_APP as a starting point for its value to ensure that it doesn't
interfere with any values used by Windows or the Delphi VCL (as recommended by MicroSoft).
Form
Any form can be used to start threads. All you need to do is add the following members to it:
https://riptutorial.com/ 22
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;
Oh, and the example code assumes the existence of a Memo1: TMemo; in the form's declarations,
which it uses for "logging and reporting".
The FRunning can be used to prevent the GUI from starting being clicked while the work is going
on. FThreads is used to hold the instance pointer and the handle of the created threads.
The procedure to start the threads has a pretty straightforward implementation. It starts with a
check whether there already is a set of threads being waited on. If so, it just exits. If not, it sets the
flag to true and starts the threads providing each with its own handle so they know where to post
their "done" message.
FRunning := True;
The thread's handle is also put in the array because that is what we receive in the messages that
tell us a thread is done and having it outside the thread's instance makes it slightly easier to
access. Having the handle available outside the thread's instance also allows us to use
FreeOnTerminate set to True if we didn't need the instance to get its results (for example if they had
been stored in a database). In that case there would of course be no need to keep a reference to
the instance.
https://riptutorial.com/ 23
// 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;
This method first looks up the thread using the handle received in the message. If a match was
found, it retrieves and reports the thread's result using the instance (FreeOnTerminate was False,
remember?), and then finishes up: freeing the instance and setting both the instance reference
and the handle to nil, indicating this thread is no longer relevant.
Finally it checks to see if any of the threads is still running. If none is found, "all done" is reported
and the FRunning flag set to False so a new batch of work can be started.
https://riptutorial.com/ 24
Chapter 9: Running other programs
Examples
CreateProcess
Following function encapsulates code for using CreateProcess Windows API for launching other
programs.
It is configurable and can wait until calling process finishes or return immediately.
Parameters:
https://riptutorial.com/ 25
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;
CreateProcess documentation
https://riptutorial.com/ 26
Chapter 10: Strings
Examples
String types
Maximum Minimum
Type Description
length size
Strings
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
Chars
https://riptutorial.com/ 27
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
uses
SysUtils;
var
S1, S2: string;
begin
S1 := 'Foo';
S2 := LowerCase(S1); // S2 := 'foo';
S1 := UpperCase(S2); // S1 := 'FOO';
Assignment
Assigning string to different string types and how the runtime environment behaves regarding
them. Memory allocation, reference counting, indexed access to chars and compiler errors
described briefly where applicable.
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 }
Reference counting
https://riptutorial.com/ 28
Counting references on strings is thread-safe. Locks and exception handlers are used to
safeguard the process. Consider the following code, with comments indicating where the compiler
inserts code at compile time to manage reference counts:
As shown above, introducing temporary local string to hold the modifications to a parameter
involves the same overhead as making modifications directly to that parameter. Declaring a string
const only avoids reference counting when the string parameter is truly read-only. However, to
avoid leaking implementation details outside a function, it is advisable to always use one of const,
var, or out on string parameter.
Encodings
String types like UnicodeString, AnsiString, WideString and UTF8String are stored in a memory
using their respective encoding (see String Types for more details). Assigning one type of string
into another may result in a conversion. Type string is designed to be encoding independent - you
should never use its internal representation.
The class Sysutils.TEncoding provides method GetBytes for converting string to TBytes (array of
bytes) and GetString for converting TBytes to string. The class Sysutils.TEncoding also provides
many predefined encodings as class properties.
One way how to deal with encodings is to use only string type in your application and use
TEncoding every time you need to use specific encoding - typically in I/O operations, DLL calls,
etc...
https://riptutorial.com/ 29
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/ 30
Chapter 11: Time intervals measurement
Examples
Using Windows API GetTickCount
The Windows API GetTickCount function returns the number of milliseconds since the system
(computer) was started. The simplest example follows:
var
Start, Stop, ElapsedMilliseconds: cardinal;
begin
Start := GetTickCount;
// do something that requires measurement
Stop := GetTickCount;
ElapsedMillseconds := Stop - Start;
end;
Note that GetTickCount returns 32-bit DWORD so it wraps every 49.7 days. To avoid wrapping, you
may either use GetTickCount64 (available since Windows Vista) or special routines to calculate tick
difference:
Anyway these routines will return incorrect results if the interval of two subsequent calls of
GetTickCount exceeds the 49.7 day boundary.
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/ 31
Recent versions of Delphi ships with the TStopwatch record which is for time interval
measurement. Example usage:
uses
System.Diagnostics;
var
StopWatch: TStopwatch;
ElapsedMillseconds: Int64;
begin
StopWatch := TStopwatch.StartNew;
// do something that requires measurement
ElapsedMillseconds := StopWatch.ElapsedMilliseconds;
end;
https://riptutorial.com/ 32
Chapter 12: TStringList class
Examples
Introduction
TStringList is a descendant of the TStrings class of the VCL. TStringList can be used for storing
and manipulating of list of Strings. Although originally intended for Strings, any type of objects can
also be manipulated using this class.
TStringList is widely used in VCL when the the purpose is there for maintaining a list of Strings.
TStringList supports a rich set of methods which offer high level of customization and ease of
manipulation.
The following example demonstrates the creation, adding of strings, sorting, retrieving and freeing
of a TStringList object.
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 has a variety of user cases including string manipulation, sorting, indexing, key-value
pairing and delimiter separation among them.
Key-Value Pairing
You can use a TStringList to store Key-Value pairs. This can be useful if you want to store
settings, for example. A settings consists of a Key (The Identifier of the setting) and the value.
https://riptutorial.com/ 33
Each Key-Value pair is stored in one line of the StringList in Key=Value format.
In this example, the Stringlist has the following content before it is destroyed:
1stName=John
LastName=Doe
City=New York
Note on performance
Under the hood TStringList performs key search by straight looping through all items, searching
for separator inside every item and comparing the name part against the given key. No need to
say it does huge impact on performance so this mechanism should only be used in non-critical,
rarely repeated places. In cases where performance matters, one should use
TDictionary<TKey,TValue> from System.Generics.Collections that implements hash table search or to
keep keys in sorted TStringList with values stored as Object-s thus utilizing binary find algorithm.
https://riptutorial.com/ 34
Chapter 13: Use of try, except, and finally
Syntax
1. Try-except: try [statements] except [[[on E:ExceptionType do statement]] [else statement] |
[statements] end;
Examples
Simple try..finally example to avoid memory leaks
Use try-finally to avoid leaking resources (such as memory) in case an exception occurs during
execution.
The procedure below saves a string in a file and prevents the TStringList from leaking.
Regardless of whether an exception occurs while saving the file, SL will be freed. Any exception
will go to the caller.
When a function returns an object (as opposed to using one that's passed in by the caller), be
careful an exception doesn't cause the object to leak.
https://riptutorial.com/ 35
// 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;
Naive programmers might attempt to catch all exception types and return nil from such a function,
but that's just a special case of the general discouraged practice of catching all exception types
without handling them.
try
AcquireResources;
try
UseResource;
finally
ReleaseResource;
end;
except
on E: EResourceUsageError do begin
HandleResourceErrors;
end;
end;
If an exception occurs inside UseResource, then execution will jump to ReleaseResource. If the
exception is an EResourceUsageError, then execution will jump to the exception handler and call
HandleResourceErrors. Exceptions of any other type will skip the exception handler above and
bubble up to the next try-except block up the call stack.
AcquireResource;
try
UseResource1;
try
UseResource2;
except
on E: EResourceUsageError do begin
HandleResourceErrors;
end;
end;
UseResource3;
https://riptutorial.com/ 36
finally
ReleaseResource;
end;
If an EResourceUsageError occurs in UseResource2, then execution will jump to the exception handler
and call HandleResourceError. The exception will be considered handled, so execution will continue
to UseResource3, and then ReleaseResource.
If an exception of any other type occurs in UseResource2, then the exception handler show here will
not apply, so execution will jump over the UseResource3 call and go directly to the finally block,
where ReleaseResource will be called. After that, execution will jump to the next applicable exception
handler as the exception bubbles up the call stack.
If an exception occurs in any other call in the above example, then HandleResourceErrors will not be
called. This is because none of the other calls occur inside the try block corresponding to that
exception handler.
Object1 := nil;
Object2 := nil;
try
Object1 := TMyObject.Create;
Object2 := TMyObject.Create;
finally
Object1.Free;
Object2.Free;
end;
If you do not initialize the objects with nil outside the try-finally block, if one of them fails to be
created an AV will occur on the finally block, because the object won't be nil (as it wasn't
initialized) and will cause an exception.
The Free method checks if the object is nil, so initializing both objects with nil avoids errors when
freeing them if they weren't created.
https://riptutorial.com/ 37
Chapter 14: Using Animations in Firemonkey
Examples
Rotating TRectangle
Now we have our animation set up. All is left is to turn it on: Drop two buttons on form, call first one
"Start", second one - "Stop". in OnClick event of first button write:
FloatAnimation1.Start;
FloatAnimation1.Stop;
If you changed name of your TFloatAnimation - Also change it when calling Start and Stop.
https://riptutorial.com/ 38
Chapter 15: Using RTTI in Delphi
Introduction
Delphi provided Runtime Type Information (RTTI) more than a decade ago. Yet even today many
developers aren't fully aware of its risks and benefits.
In short, Runtime Type Information is information about an object's data type that is set into
memory at run-time.
RTTI provides a way to determine if an object's type is that of a particular class or one of its
descendants.
Remarks
RTTI IN DELPHI - EXPLAINED
The Run-Time Type Information In Delphi - Can It Do Anything For You? article by Brian Long
provides a great introduction to the RTTI capabilities of Delphi. Brian explains that the RTTI
support in Delphi has been added first and foremost to allow the design-time environment to do its
job, but that developers can also take advantage of it to achieve certain code simplifications. This
article also provides a great overview of the RTTI classes along with a few examples.
Examples include: Reading and writing arbitrary properties, common properties with no common
ancestor, copying properties from one component to another, etc.
Examples
Basic Class Information
This example shows how to obtain the ancestry of a component using the ClassType and
ClassParent properties. It uses a button Button1: TButton and a list box ListBox1: TListBox on a
form TForm1.
When the user clicks the button, the name of the button’s class and the names of its parent
classes are added to the list box.
https://riptutorial.com/ 39
end;
end;
The list box contains the following strings after the user clicks the button:
• TButton
• TButtonControl
• TWinControl
• TControl
• TComponent
• TPersistent
• TObject
https://riptutorial.com/ 40
Credits
S.
Chapters Contributors
No
Creating easily
2 removable runtime Alex T
error checks
6 Loops Y.N
Retrieving updated
7 TDataSet data in a MartynA
background thread
Running a thread
8 while keeping GUI Fr0sT, Jerry Dodge, Johan, kami, LU RD, Marjan Venema
responsive
Running other
9 Dalija Prasnikar
programs
Time intervals
11 Fr0sT, John Easley, kludg, Rob Kennedy, Victoria, Wolf
measurement
Use of try, except, EMBarbosa, Fabio Gomes, Johan, MrE, Nick Hodges, Rob
13
and finally Kennedy, Shadow
Using Animations in
14 Alexander Petrosyan
Firemonkey
https://riptutorial.com/ 41
15 Using RTTI in Delphi Petzy, René Hoffmann
https://riptutorial.com/ 42