Blaise 93 UK

Download as pdf or txt
Download as pdf or txt
You are on page 1of 102
At a glance
Powered by AI
The magazine discusses new features in Delphi 10.4.2, components for developers, tools for building applications, and issues threatening bumblebee populations.

New features discussed include a new number component, control list component, and differences between the new and previous versions of FastReport.

The kbmMW application development framework and kbmMemTable in-memory table are highlighted. Other topics include Lazarus, TMS WEB Core, code snippets, and web services.

Delphi 10.4.

2 / new features By Detlef Overbeek


Max Box RSS Feeds of BBC News By Max Kleiner
New Number Component inside Delphi 10.4.2 By Detlef Overbeek & Marco Cantu (Embarcadero)
New ControlList Component inside Delphi 10.4.2 By Detlef Overbeek & Marco Cantu (Embarcadero)
How differs the new FastReport VCL 2021.0 from the previous versions?
Fastreport VCL 2021 Working with the ReportDesigner By Detlef Overbeek
InstallAware By Detlef Overbeek
What's coming in TMS WEB Core v1.7 Ancona By Bruno Fierens
Lazarus: Webform inside Lazarus By Michael van Canneyt
Code Snippets 11By Detlef Overbeek / project by Michael van Canneyt
Web Service Part 2 Storage By Danny Wind
ORM in kbmMW #3 Copying a table from one database to another By Kim Bo Madsen
BLAISE PASCAL MAGAZINE 93
Multi platform /Object Pascal / Internet / JavaScript / WebAssembly / Pas2Js / Databases
CSS Styles / Progressive Web Apps
Android / IOS / Mac / Windows & Linux

ARTICLES
From Your Editor page 4
Cartoon
By Jerry king page 5
Delphi 10.4.2 / new features
By Detlef Overbeek page 7
Max Box RSS Feeds of BBC News
By Max Kleiner page 26
New Number Component inside Delphi 10.4.2
By Detlef Overbeek & Marco Cantu (Embarcadero) page 11
New ControlList Component inside Delphi 10.4.2
By Detlef Overbeek & Marco Cantu (Embarcadero) page 15
How differs the new FastReport VCL 2021.0
from the previous versions? page 32
Fastreport VCL 2021 Working with the ReportDesigner
By Detlef Overbeek page 34
InstallAware
By Detlef Overbeek page 52
What's coming in TMS WEB Core v1.7 Ancona
By Bruno Fierens page 60
Lazarus: Webform inside Lazarus
By Michael van Canneyt page 65
Code Snippets 11
By Detlef Overbeek / project by Michael van Canneyt page 78
Web Service Part 2 Storage
By Danny Wind page 84
ORM in kbmMW #3
Copying a table from one database to another
By Kim Bo Madsen page 97
The Bumble bee page 101
Delphinium
ADVERTISERS
The new LibStick page 6
Super Offer Bundle page 24
Subsription +Lazarus Handbook - hardcover page 25
Fastreport page 31
Delphi 10.4.2 available page 30
Barnsten page 59
Lazarus Handbook - Pocket (softcover) page 76
Lazarus Handbook - Hardcover page 77
Delphi Company page 83
Subscription + Library USB Stick page 96
Componnets4Developers page 102

Pascal is an imperative and procedural programming language, which Niklaus Wirth designed (left below) in 1968–69
and published in 1970, as a small, efficient language intended to encourage good programming practices using
structured programming and data structuring. A derivative known as Object Pascal designed for object-oriented
programming was developed in 1985. The language name was chosen to honour the Mathematician, Inventor of the
first calculator: Blaise Pascal (see top right).
Niklaus Wirth Publisher: PRO PASCAL FOUNDATION in collaboration © Stichting Ondersteuning Programmeertaal Pascal - Netherlands
Blaise Pascal Magazine 93 2021 2
Contributors
Stephen Ball Peter Bijlsma -Editor
http://delphiaball.co.uk peter @ blaisepascal.eu
@DelphiABall
Dmitry Boyarintsev Michaël Van Canneyt, Marco Cantù
dmitry.living @ gmail.com michael @ freepascal.org www.marcocantu.com
marco.cantu @ gmail.com
David Dirkse Benno Evers Bruno Fierens
www.davdata.nl b.evers @ everscustomtechnology.nl www.tmssoftware.com
E-mail: David @ davdata.nl bruno.fierens @ tmssoftware.com

Holger Flick
holger @ flixments.com

Primož Gabrijelčič Mattias Gärtner Peter Johnson


primoz @ gabrijelcic.org [email protected] http://delphidabbler.com
delphidabbler @ gmail.com
Max Kleiner John Kuiper Wagner R. Landgraf
www.softwareschule.ch john_kuiper @ kpnmail.nl wagner @ tmssoftware.com
max @ kleiner.com
Vsevolod Leonov Andrea Magni www.andreamagni.eu
[email protected] andrea.magni @ gmail.com
www.andreamagni.eu/wp
Paul Nauta PLM Solution Architect Kim Madsen
CyberNautics www.component4developers.com
paul.nauta @ cybernautics.nl

Boian Mitov Jeremy North


mitov @ mitov.com jeremy.north @ gmail.com

Detlef Overbeek - Editor in Chief Howard Page Clark Heiko Rompel


www.blaisepascal.eu hdpc @ talktalk.net info @ rompelsoft.de
editor @ blaisepascal.eu

Wim Van Ingen Schenau -Editor Peter van der Sman Rik Smit
wisone @ xs4all.nl sman @ prisman.nl rik @ blaisepascal.eu

Bob Swart B.J. Rao Daniele Teti


www.eBob42.com contact @ intricad.com www.danieleteti.it
Bob @ eBob42.com d.teti @ bittime.it

Anton Vogelaar Danny Wind Siegfried Zuhr


ajv @ vogelaar-electronics.com dwind @ delphicompany.nl siegfried @ zuhr.nl

Editor - in - chief
Detlef D. Overbeek, Netherlands Tel.: Mobile: +31 (0)6 21.23.62.68
News and Press Releases email only to [email protected]
Editors Correctors
Peter Bijlsma, W. (Wim) van Ingen Schenau, Rik Smit Howard Page-Clark, Peter Bijlsma
Trademarks All trademarks used are acknowledged as the property of their respective owners.
Caveat Whilst we endeavour to ensure that what is published in the magazine is correct, we cannot accept responsibility for any errors or omissions.
If you notice something which may be incorrect, please contact the Editor and we will publish a correction where relevant.
Subscriptions ( 2019 prices ) Internat. Internat.
excl. VAT incl. 9% VAT Shipment
Printed Issue
€ 155,96 € 250 € 80,00
±60 pages
Electronic Download Issue
€ 64,20 € 70
60 pages
Printed Issue inside Holland (Netherlands)
Member and donator of IKIPEDI W A
€ 250,00 € 70,00 Member of the Royal Dutch Library
60 pages
Subscriptions can be taken out online at www.blaisepascal.eu or by written order, or by sending an email to [email protected]
Subscriptions can start at any date. All issues published in the calendar year of the subscription will be sent as well.
Subscriptions run 365 days. Subscriptions will not be prolonged without notice. Receipt of payment will be sent by email.
Subscriptions can be paid by sending the payment to:
ABN AMRO Bank Account no. 44 19 60 863 or by credit card or Paypal
Name: Pro Pascal Foundation-Foundation for Supporting the Pascal Programming Language (Stichting Ondersteuning Programeertaal Pascal)
IBAN: NL82 ABNA 0441960863 BIC ABNANL2A VAT no.: 81 42 54 147 (Stichting Programmeertaal Pascal)
Subscription department
Edelstenenbaan 21 / 3402 XA IJsselstein, The Netherlands
Mobile: + 31 (0) 6 21.23.62.68 [email protected]
Copyright notice
All material published in Blaise Pascal is copyright © SOPP Stichting Ondersteuning Programeertaal Pascal unless otherwise noted and may not be copied, distributed
or republished without written permission. Authors agree that code associated with their articles will be made available to subscribers after publication by placing it
on the website of the PGG for download, and that articles and code will be placed on distributable data storage media. Use of program listings by subscribers for
research and study purposes is allowed, but not for commercial purposes. Commercial use of program listings and code is prohibited without the written permission
of the author.

Blaise Pascal Magazine 93 2021 3


From your editor
Spring is in the air and I found something very I had asked Danny Wind of the Delphi
nice: Delphinium, a flower that is beautiful as Company to write a series of articles to explain
you can see on the cover and I think might be very low level how to make use of a web Client
an ode to Delphi and to spring. and Server with the help of a REST service.
I thought it to be so nice that everybody whom He made it very easy and understandable:
subscribes or re-subscribes will get a little bag break the problem into pieces, solve each part
of seed which should be sown at once in this separately and then start with the total
time of the year directly into a spot in your structure. He did it. It’s that simple. It will also
garden. Splendid flower for a summer show you for once how to setup a server under
bouquet. Delphi.

And now for something completely different - FastReport had also some great news:
as you know the phrase: they created their newest version, to have a
during last month the news accumulated look at that I wrote a starters article.
enormously. This issue has now 102 pages! Blaise Pascal Magazine is going to create -
A new version of Delphi was announced. This with the help of FastReport of course – a book
time with only small news: two new about the use of reporting. We will try to
components and of course a lot of bug fixes. publish that by the end of the year.
Happily Bruno Fierens and his TMS team
created again and again new items for Delphi. For some reason I never took a look at various
He displays his new plans in this issue. install programs: only InnoSetup.
He is the only one that really keeps Delphi InstallAware surprised me very much: you
connected to the Internet, I know there are a need to evaluate and consider that installer
few others but they are not quite so program absolutely. Value for money and for
sophisticated as WEBCore. the Delphi users there is a free version. Jason
I will however investigate those suppliers as Strathmore of InstallAware told me they are
soon as possible, and write about their working on a version for Lazarus, and because
products. It is necessary to overlook the entire of that plan: they are working on a version that
range…I think the Internet is the main future is capable of handling instalments on Linux as
platform. well as macOS - and of course Windows.

Lazarus has some big news: The Lazarus and So all together that is why this issue is over a
Free Pascal foundation had asked Martin Friebe hundred pages.
to create a form that will be able to store a
form inside the IDE which is capable of using a Hope you’ll enjoy it. Let’s have fun
browser (Chromium) where almost all the programming!
browsers are built on (even Microsoft's Edge).
So we hope to achieve that the form will be Detlef
connected to the ObjectInspector and all other
technologies that Pas2JS uses, to make
happen what we want: a form that is actually
the browser it self and has one special ability:
WYSIWYG (What You See Is What You Get),
respond to the debugging necessities,
has an underlying help and code completion
and CSS styles. In this issue Michael van
Canneyt has written an explanation that will
show you for the first time how this can work
and even wrote some code that will show the
result of this. Try it!
Yet there is till a lot to be done!

Blaise Pascal Magazine 93 2021 4


From our Technical advisor: Cartoons from Jerry King

Blaise Pascal Magazine 93 2021 5


ADVERTISEMENT
Advertisement

L I B R A R Y 2 0 2 0

89
90
87
88
86
85 51 52 53
84 50 54
55 49 26 27 28
83 29 25
48 56
81 30 24
82 47 9 10 11 57
12 31
80 46 23 8 1
2 13 32 58
78 22 7 3
79 45 14 33
21 4 59
77 44 6
20 5 15 34
75 60
76 43 19 16 35
18 17 61
73 42 36
74
41 37 62
72 40 39 38
71 69 63
70 67 64
68 66 65

ALL CODE ABOUT THE USE

BLAISE PASCAL MAGAZINE


ALL ISSUES IN ONE FILE

Editor in Chief: Detlef Overbeek


BLAISE PASCAL MAGAZINE Edelstenenbaan 21 3402 XA
IJsselstein Netherlands
BLAISE PASCAL MAGAZINE

procedure procedure
var var
begin begin
for I := 1 to 9 do for I := 1 to 9 do
begin Prof Dr.Wirth, Creator of Pascal Programming language begin
... ...
end end
end; end;
Prof Dr.Wirth, Creator of Pascal Programming language Blaise Pascal, Mathematician
[email protected] Prof Dr.Wirth, Creator of Pascal Programming language Blaise Pascal, Mathematician

The new LibStick (1)


(on USB Card - 90 Issues)
€ 60,--
ex vat / including shipment
Delphi 10.4.2 / UPDATE: New features / New Components Page 1/17
By Detlef Overbeek

² The updated Parallel Programming Library


offers a modern style for writing
multi-threaded applications that can take
advantage of modern multi-core CPUs.

² You can now easily see the data stored


in generic collections in the debugger
with the introduction of a new specific
debug visualizer.

² Database and remote data access


technologies have also been improved for
FireDAC InterBase, SQLite,
INTRODUCTION PostgresQL, and Oracle integrated
In this very long article I’ll talk about the drivers, the REST Client Library,
enhancements of Delphi and two new AWS and Azure support.
components that really are interesting. I have
tried to give as much info as possible, but
² RAD Studio’s 10.4.2 release resolves a
they're not (yet) very well documented. To
huge number of reported issues.
understand them I tried to use them and
especially the Binding mechanisms are
interesting.

PRODUCTIVITY ENHANCEMENTS *1 SOAP (acronym for Simple


² RAD Studio 10.4.2 includes new tooling to Object Access Protocol)
help developers build apps quickly, ² is a messaging protocol specification
WIKIPEDIA
for exchanging structured information in the
implementation of web services in computer
² enhanced migration tooling for fast networks. Its purpose is to provide
upgrades, and a new automatic silent extensibility, neutrality, verbosity and
installer. independence.
It uses XML Information Set for its message
² A new progress dialog shows what the IDE format, and relies on application layer
is doing during lengthy operations. protocols, most often Hypertext Transfer
Protocol (HTTP), although some legacy
² RAD Studio’s Code Insight support systems communicate over Simple Mail
(using LSP) has been significantly Transfer Protocol (SMTP), for message
expanded to offer better, faster. negotiation and transmission.

SOAP allows developers to invoke processes


² improved Migration Tool helps you running on disparate operating systems
upgrade easily and copy your IDE (such as Windows, macOS, and Linux) to
configurations. authenticate, authorize, and communicate
using Extensible Markup Language (XML).
Since Web protocols like HTTP are installed
PERFORMANCE AND QUALITY IMPROVEMENTS and running on all operating systems, SOAP
² 10.4.2 includes improved integration with allows clients to invoke web services and
SOAP web services, receive responses independent of language
and platforms.
² improving the WSDL import tool and the
SOAP client invocations.

Blaise Pascal Magazine 93 2021 7


Delphi 10.4.2 / UPDATE: New feature / New Components Page 2/17

*2 WSDL EXPANDED DELPHI SUPPORT


Web Services Description Delphi sees over 20 significant compiler
Language performance improvements that substantially
WIKIPEDIA
is an XML-based interface description reduce compilation time.
language that is used for describing the Delphi also has enhanced Code Insight
functionality offered by a web service. The
support, highlighting warnings and hints in the
acronym is also used for any specific WSDL
description of a web service (also referred to code editor, new improvements to rendering
as a WSDL file), which provides a machine- to enhance visibility, and better support for
readable description of how the service can packages, ctrl-click navigation, and much
be called, what parameters it expects, and more.
what data structures it returns. Therefore,
EXPANDED WINDOWS SUPPORT
its purpose is roughly similar to that of a
type signature in a programming language. RAD Studio 10.4.2 delivers best-in-class
Windows app support, library for native
The current version of WSDL is WSDL 2.0. Windows app development, the Visual
The meaning of the acronym has changed Component Library.
from version 1.1 where the "D" stood for These include the new TControlList VCL
"Definition". control, a virtual and high-performance control
for very long lists, and a new VCL TNumberBox
*3 PPL Parallel Programming Library control that supports integer, floating point
The RTL provides the Parallel Programming and currency values. See issue page 9 and 3/17
Library (PPL), giving your applications the
ability to have tasks running in parallel Windows Store packaging is made easier
taking advantage of working across multiple through support for MSIX, Microsoft’s newly
CPU devices and computers. The PPL recommended Windows application packaging
includes a number of advanced features for format.
running tasks, joining tasks, waiting on
groups of tasks, etc. to process. For all this, There is improved styles support for the
there is a thread pool that self tunes itself Konopka Components suite of over 200
automatically (based on the load on the
Windows UI controls and designers for your
CPU’s) so you do not have to care about
creating or managing threads for this Delphi and C++ Builder VCL applications.
purpose.
The TEdgeBrowser VCL component has been
You can use this library by including updated with support for the GA version of
System.Threading in your apps. This unit is Microsoft's WebView2 control and its SDK.
made up of several features that can be
included into new and existing projects.
The unit also includes a number of
overloaded arguments to make it suitable for
C++ as well as Delphi.

Using the PPL, your applications can easily:


Make looping faster with TParallel.For.
Run multiple tasks in parallel using TTask
and Itask. Leave a process running
focusing on other tasks and then get the
result of that process at the point you want.
IFuture allows you to establish a priority for
the running code blocks and still return the
results when needed.
Platform Support
The PPL works on Windows, MacOSX,
Android, and iOS devices.

Blaise
BlaisePascal
PascalMagazine
Magazine93
912021
2021 8
Delphi 10.4.2 / UPDATE: New Component TNumberBox Page 3/17

starter expert
On these pages we show several aspects of
theproject Marco build:
The TNumberBox On the next pages you see the way of letting
The TNumberBox is a special kind of box that the customer choose from Styles that are
mainly does three things: available.
It can receive Integers
It can receive floats
and currency (can’t we all).
Figure 1: the numberbox in the palette
What makes this component very attractive is
its flexibility: Just enter a simple expression into
it and enter you'll have the answer instantly
actually you could use it as calculator.

By the time I saw it there was no description or


help yet or any explanation.
The new VCL TNumberBox control is a normal
looking numeric input control and is designed
after the Windows platform WinUI NumberBox
control.

The component also allows simple expression


evaluation;
through the dropdownbox you can add an
expression like 12+2 +20*(1234) or anything
else you would like to enter.
After using the enter key with the keyboard the
control will replace it with the result. Figure 2: integers, currency and floats

The control supports


computing inline
calculations of basic
equations such as
multiplication, division,
addition, and
subtraction (allowing
the use of brackets).

Notice that you can use


the symbols + and -
both as binary and
unary operations,
so you can type
-73 or + 73,
you can write 57+13
and 59-23, and even
combine them as in
53++23 or 53--23,
which is evaluated as 53
- (-23). thus adds the
two values.

Blaise Pascal Magazine 93 2021 9


Delphi 10.4.2 / UPDATE: New Component TNumberBox Page 4/17

Figure 3: the example expressions

Figure 4: the executed expression

In figure 3 you see the listbox with example


expressions you can use (make your own as
well and on the fly). Below you can see what
the outcome is of the chosen expression.
Almost all of the properties are shown over
here and might be changed if necessary".

Blaise
BlaisePascal
PascalMagazine
Magazine93
912021
2021 10
10
Delphi 10.4.2 / UPDATE: New Component TNumberBox Page 5/17

Figure 5: choosing your style

If you run the project, which is of course


available for you in your download area,
you can choose between quite some
styles, There must be something of your
choice.
Eventually you could create your own.
The Cobalt XEMedia style from
Embarcadero has a beautiful corner
gradient and shows much better than
most styles where you are...

Blaise Pascal Magazine 93 2021 11


11
Delphi 10.4.2 / UPDATE: New Component TNumberBox Page 6/17

Figure 6: Windows Tablet light

Figure 7: Windows 10 Blue

Figure 8: Windows 10

Blaise
BlaisePascal
PascalMagazine
Magazine93
912021
2021 12
12
Delphi 10.4.2 / UPDATE: New Component TNumberBox Page 7/17

Figure 9: The executed program

procedure TNumBoxDemo.ComboBox2Change(Sender: TObject); On the next page the complete code of the
begin onCreate. The inline variables are non of
NumberBox1.AcceptExpressions := True;
NumberBox1.SetFocus;
my taste. This is Pascal. Not C# or whatever.
NumberBox1.Text := ComboBox2.Text; This form of frivolous novelties should not be
end; used. It confuses and in this way it loses the
procedure TNumBoxDemo.Exit1Click(Sender: TObject); the strength of Pascal: clear view and clear
begin structure. Know what is where. The benefit is
Application.Terminate; only a few lines of typing, and actually that
end;
makes you aware of the construction of
Pascal.
procedure TNumBoxDemo.rdoAlignClick(Sender: TObject);
begin
NumberBox1.Alignment := TAlignment(rdoAlign.ItemIndex);
end;

procedure TNumBoxDemo.rdoCurrencyFormatClick(Sender: TObject);


begin
NumberBox1.CurrencyFormat := rdoCurrencyFormat.ItemIndex;
end;

procedure TNumBoxDemo.rdoModeClick(Sender: TObject);


begin
NumberBox1.Mode := TNumberBoxMode(rdoMode.ItemIndex);
end;

procedure TNumBoxDemo.rdoPlacementClick(Sender: TObject);


begin
NumberBox1.SpinButtonOptions.Placement :=
TNumberBoxSpinButtonPlacement(rdoPlacement.ItemIndex);
end;

procedure TNumBoxDemo.StyleMenuItemClick(Sender: TObject);


begin
TStyleManager.TrySetStyle(TMenuItem(Sender).Caption.Replace('&','',[rfReplaceAll]));
end;

Blaise
BlaisePascal
PascalMagazine
Magazine93
912021
2021 13
13
Delphi 10.4.2 / UPDATE: New Component TNumberBox Page 8/17

procedure TNumBoxDemo.FormCreate(Sender: TObject);


begin
for var nbsp := Low(TNumberBoxSpinButtonPlacement)
to High(TNumberBoxSpinButtonPlacement)
do rdoPlacement.Items.Add( TRttiEnumerationType.GetName(nbsp) );

rdoPlacement.ItemIndex := Ord(NumberBox1.SpinButtonOptions.Placement);

for var nbm := Low(TNumberBoxMode) to High(TNumberBoxMode)


do rdoMode.Items.Add( TRttiEnumerationType.GetName(nbm) );

rdoMode.ItemIndex := Ord(NumberBox1.Mode);

for var algn := Low(TAlignment) to High(TAlignment)


do rdoAlign.Items.Add( TRttiEnumerationType.GetName(algn) );

rdoAlign.ItemIndex := Ord(NumberBox1.Alignment);

for var sname in TStyleManager.StyleNames do


begin
var styleItem := TMenuItem.Create(mnuStyle);
styleItem.Caption := sName;
styleItem.OnClick := StyleMenuItemClick;
mnuStyle.Add(styleItem);
end;

var Authors := TStringList.Create;


for var fname in TDirectory.GetFiles('C:\Users\Public\Documents\Embarcadero\Studio\21.0\Styles','*.vsf')
do begin
var info: TStyleInfo;
if TStyleManager.IsValidStyle(fname, info)
then
begin
var Author: string;
if info.Author.StartsWith('Embarcadero')
then Author := 'Embarcadero'
else
Author := info.Author;

if info.Name.StartsWith('Metro')
or info.Name.StartsWith('Tablet')
or info.Name.StartsWith('Windows')
then
Author := 'Windows';
authors.AddPair(Author, info.Name);
try
TStyleManager.LoadFromFile(fname);
except on EDuplicateStyleException do
end;
end;
end;
authors.Sort;
var authorItem: TMenuItem := nil;
for var i := 0 to pred(authors.Count) do
begin
if not Assigned(authorItem) or (authorItem.Caption <> authors.Names[i]) then
begin
authorItem := TMenuItem.Create(mnuStyle);
authorItem.AutoHotkeys := TMenuItemAutoFlag.maManual;
authorItem.Caption := authors.Names[i];
mnuStyle.Add(authorItem);
end;
var styleItem := TMenuItem.Create(mnuStyle);
styleItem.AutoHotkeys := TMenuItemAutoFlag.maManual;
styleItem.Caption := Authors.ValueFromIndex[i];
styleItem.OnClick := StyleMenuItemClick;
authorItem.Add(styleItem);
end;
end;

Blaise Pascal Magazine 93 2021 14


14
Delphi 10.4.2 / UPDATE: New Component TControlList Pag 9/17
LIVE BINDING
starter expert

NEW VCL TCONTROLLIST CONTROL


Embarcadero is introducing in the VCL library a
new flexible and virtualized list control.
The idea behind this control is to offer a new
modern looking VCL control offering custom UI
configuration and a high performance control,
which can be used with very long lists. This list
represents a single selection list and all items
are visually of the same height and width. Figure 11: The projectof the vcl demo
This list doesn’t include a collection of items
The new control allows the developer to define with specific information. The data might be
the content by designing one of the elements of provided either via live bindings (including
the list using graphical controls (that is, binding to a dataset or a collection of
TGraphicControl descendants) and provide objects) or via an event to query for the data of
data to the control to display individual an individual item (so that the direct storage
elements, without creating all of the controls for and mapping would be completely up to the
all of the elements in the list, but only those developer). For each item to display the
needed to display the data. control calls an event handler you can use to
Being totally virtual, the list can handle customize each item appearance, in this case
thousands and even millions of items, offering just modifying the Caption of the label:
extremely fast scrolling. Beside calculating and
procedure TForm2.ControlList1BeforeDrawItem(AIndex:
displaying only the items that fit on screen, the Integer; ACanvas: TCanvas; ARect: TRect;
list caches the content of the items using in- Astate: TOwnerDrawState);
memory bitmaps. begin
Label1.Caption := 'Label' + AIndex.ToString;
end;

Figure 10: The example of the layout

The new control resembles the classic


TDBCtrlGrid control -- there is a panel for
controls, you put controls on it and have
virtual items created at run time. Unlike
DBCtrlGrid we can put only
TGraphicControl on it and all items are Figure 12: Overview of all compoents
virtual. Below you can see the control at
design time (with the surface of a single
item available for editing) and at runtime
(with the same content multiplied many
times).

Blaise Pascal Magazine 93 2021 15


Delphi 10.4.2 / UPDATE: New Component TControlList Pag 10/17

With the previous design, 10,000 items and


multiple columns, this trivial code produces an
output like below:
In general terms, you can use the
OnClick event for any control on
the control list.
The control supports High-DPI
options and VCL Styles and it is
fully Live Bindings enabled.

THE NEW
TCONTROLLISTBUTTON
COMPONENT
We can't use TSpeedButton
directly on the panel, because
the control doesn’t handle
special interactions like button
changed state.
Figure 13: Overview of the form
At design time, there is special dialog with a For controls, which can have different states,
collection of preset configurations, which we added a special TControlListControl
include adjustment for TControlList class (inherited from TGraphicControl).
properties and control collections with You can create new controls that inherit from
specific properties. You use the arrows at the TControlListControl class and can use
top to pick the core configuration and you can mouse events for their items.
fine tune it with some of the other checkbox This is the approach used by
options at the bottom. The wizard overrides TControlListButton - the analogue of a
the control list setting. TSpeedButton that can be used with
TControlList. This button has 3 styles - push
The item you design is replicated (virtually) for
button, tool button and link.
each of the items requested with the
ItemCount property. The visible
surface of the control generally
allows for a number of items, all
with the same width and height.
The control has 3 different layouts:

Figure 13: The running application

Blaise
BlaisePascal
PascalMagazine
Magazine93
912021
2021 16
16
Delphi 10.4.2 / UPDATE: New Component TControlList Pag11/17
LIVE BINDING
starter expert

This new VCL TcontrolList is nothing but a


very fats itself repeating control (with different
images or labels) which has the ability to repeat
itself and graphically render up to 10.000 times
in milliseconds.
The refresh time is fantastic and this opens a
possibility to create grids about subjects with
various items which has never before been
possible.
Yet there is no project description in the Helpfile.
I suppose that soon will be arranged for. On their
website is no real help-text available. So I suggest
you simply have a look at our explanation and
make use of the trial project.
Figure 1: The running project

First we start the project normally as


seen in Figure 2, that is the way the
project starts with. A number of labels
are put on a panel, but that is not what
it is all about. The shaded square
containing in the upper left corner a
white area with some text label on it
and a number and something like a
label with an idx#. We need to find out
what's going on here. Since there is no
help we simply do several things:
take a look at the code, that might
help finding out what does what?The
first two procedures are obvious.
procedure TfrmCtrlListDemo3.btnFirstClick(Sender: TObject); Figure 2: The project
begin
ControlList1.ItemIndex := 0; The third procedure
end;
TfrmCtrlListDemo3.ControlL
procedure TfrmCtrlListDemo3.btnLastClick(Sender: TObject); ist1BeforeDrawItem reacts to
begin the Acanvas.Brush.Color :=
ControlList1.ItemIndex := ControlList1.ItemCount;
StrToInt(lblColorValue.
end;
Caption);
procedure TfrmCtrlListDemo3.ControlList1BeforeDrawItem(AIndex: Integer; So here is a label involved.
ACanvas: TCanvas; ARect: TRect; AState: TOwnerDrawState);
begin
Maybe it would be best to have
ACanvas.Brush.Color := StrToInt(lblColorValue.Caption); alook at the objects and see
ACanvas.Pen.Width := 5; what their properties are:
if odSelected in AState
then ACanvas.Pen.Color := clBlack
On the next page you will find
else an overview of using the right
ACanvas.Pen.Color := clWhite; clicking method.
ACanvas.Rectangle(ARect); If there is any hint of use by that
lblIndex.Caption := Format('#%d',[AIndex]);
end; way we will find out.
procedure TfrmCtrlListDemo3.ControlList1ItemClick(Sender: TObject);
begin
numIndex.Value := ControlList1.ItemIndex;
end;

Blaise Pascal Magazine 93 2021 17


Delphi 10.4.2 / UPDATE: New Component TControlList Pag12/17
LIVE BINDING

Figure 3: Binding
Components
There is a Binding Components item. If we choose that A new Window pops up: The Editing
frmCtrlListDemo3.Bindinglist . It shows all the links created by binding. See figure 4.

Figure 4 Editing frmCtrlListDemo3.Bindinglist

Blaise
BlaisePascal
PascalMagazine
Magazine93
912021
2021 18
18
Delphi 10.4.2 / UPDATE: New Component TControlList Pag13/17
LIVE BINDING

If you click on the form itself and click


bind visually you see the binding of the
objects, the LiveBindings Designer will
come forward. Its very good to see all
the connections of what is necessary.

You can move replace or add items and


connect them. I added the
LabelLoremIpsum
to find out what can be done. In the
next pages I will show. The label itself
could be replaced by other objects, we
will have a look a that too.

Figure 5: Here you get a true overview of what you just added and connected

Blaise
BlaisePascal
PascalMagazine
Magazine93
912021
2021 19
19
Delphi 10.4.2 / UPDATE: New Component TControlList Pag14/17
LIVE BINDING

Figure:6

If you select the LabelLoremIpsum (I named it after its


field value) and again right-click this too, you have the
next form available: Bindable Members. Figure 6 ).

Figure: 7

Figure: 9

In figure 8 you see the result of right-clicking on


the PrototypeBindSource1 component. A list
of actions appears: (figure 9)
Editing ProtoTypeBindSource1 click on the
“add” item at the top and you will be able to
add a field value to the label by connecting this
via the Binding Editor. (See figure 12 on the
next page). It is complex but not difficult,
in the next version I will also show how to
add more special fields like a bitmap.

Figure: 10
Figure: 8

Blaise
BlaisePascal
PascalMagazine
Magazine93
912021
2021 20
20
Figure: 11
Delphi 10.4.2 / UPDATE: New Component TControlList Pag15/17
LIVE BINDING

Figure12: See the structure of the fields

Blaise
BlaisePascal
PascalMagazine
Magazine93
912021
2021 21
21
Delphi 10.4.2 / UPDATE: New Component TControlList Pag16/17
LIVE BINDING

Figure13:
Figure16:

Figure17:
Figure14:

Figure15: Figure18:

Blaise Pascal Magazine 93 2021 22


22
Delphi 10.4.2 / UPDATE: New Component TControlList Pag17/17
LIVE BINDING

The Preset Configurations are very interesting


Because they have the ability to let you have a
single line configuration. (Figure14 ).
The next one is to automatically add controls of
an item with multi- line text (Figure 15 ) and an
other one is to create an item with a
TGraphicControl and arrange settings for that
case. (Figure 16 ).
Figure 17 is similar and Figure 18 with a Url-Link
Button. All figures are available on page:
article 17/17.

Blaise Pascal Magazine 93 2021 23


23
Advertisement

Editor in Chief: Detlef Overbeek


BLAISE PASCAL MAGAZINE Edelstenenbaan 21 3402 XA BLAISE PASCAL MAGAZINE
IJsselstein Netherlands

procedure procedure
var var
begin begin
for I := 1 to 9 do for I := 1 to 9 do
begin Prof Dr.Wirth, Creator of Pascal Programming language begin
... ...
end end
end; end;
[email protected]
Prof Dr.Wirth, Creator of Pascal Programming language Blaise Pascal, Mathematician Prof Dr.Wirth, Creator of Pascal Programming language Blaise Pascal, Mathematician
https://www.blaisepascalmagazine.eu

BLAISE PASCAL MAGAZINE 92


Multi Platform / Object Pascal / Internet / JavaScript / WebAssembly / Pas2Js / Databases
CSS Styles / Progressive Web Apps
Android / IOS / Mac / Windows & Linux

L I B R A R Y 2 0 2 0
90
85
86
87
88

50
89

51 52 53
VIDEO
84 54
49 55
26 27 28
83 25 29
48 56
81 24
10 30
82 47 9 11
31 57
23 8 1 12
80 46

SUPER
2 13 32 58
78 22 7 3
79 45 14 33
21 4 59
77 44 6
5 15 34

OFFER (5)
20 60
75 19 16
76 43 18 17 35
73 61
74 42 36
41 37 62
72

€ 150 ex Vat
40 39 38 Quantum Computing / By Detlef Overbeek
71 69 63 Max Box / Max Kleiner
Fastreport / By Detlef Overbeek
70 67 64 MMX / By Detlef Overbeek and Dennis Zubov
68 66 65 Code Examples / By Detlef Overbeek
New Lazarus PJU Files for Mac By Mattias
Gaertner

free shipping
Installing a package on MacOs
RegEx / By Michael van Canneyt
Sample Project: Lazarus & Delphi Easter
ALL CODE ABOUT THE USE Holidays
Multi Tier a series for the web / By Danny Wind
Chess / By Detlef Overbeek
BLAISE PASCAL MAGAZINE
ALL ISSUES IN ONE FILE
PAGE-CLARK

LAZARUS DAVID DIRKSE


LEARN TO PROGRAM
HOWARD

HANDBOOK
FOR PROGRAMMING WITH FREE PASCAL AND LAZARUS
USING LAZARUS

procedure ;
var
including begin
30 example for i := 1
projects to 9 do
begin

end;
end;

BLAISE PASCAL MAGAZINE


www.blaisepascal.eu

COMPUTER (GRAPHICS)
MATH & GAMES IN
934 PAGES PASCAL

1. One year Subscription 4. Book Learn To Program using Lazarus PDF


2. The newest LIB Stick including 19 lessons and projects
- including Credit Card USB stick 5. Book Computer Graphics Math & Games
3. Lazarus Handbook - Personalized book + PDF including ±50 projects
-PDF including Code
24
ADVERTISEMENT

R USOK S
ZADBOARU OK
AL
SC
PA

A
L N AZ BO H
FR
EE
AL
LAZARUS HANDBOOK 1

IT SC
W PA

HA L AND
G EE
IN FR
MM
LAZARUS HANDBOOK 2
H
RA IT
ROG G
W
R
P IN
MM
FO
H FO
R
PR
OGRA

el us
n
va sa eek
ha Ino verb
t,
ey ng
nn dra
Ca Oue
o,
2 Bla
ise
Pa
sca
l

: Micner ef O
tl
ors Gärt De
th ,
Au ttias inig
e
Ma n H
e
Sv

Subscription
Combi(4)
Subscription + Lazarus Handbook
(hardcover)

€ 100
Ex Vat 9%
Including shipment!
BBC News
Sentiment Analysis Page1/4 maXbox
maXbox Because of the nature
Author: Max Kleiner of the text and its categories, the classification
„Yesterday I was clever, we will be doing is a form of sentiment analysis
so I wanted to change the world.
or opinion mining. If the classifier returns pos,
Today I am wise,
so I am changing myself." - Rumi then the text expresses a positive sentiment,
whereas if we get neg, then the text expresses
As you way know, we went through the a negative sentiment.
last magazine report on the BBC News
feed, line by line; now we want to equip and This procedure of discovering and classifying
enlarge these texts with a sentiment analysis opinions expressed in a piece of text (like
comments/feedback text/news feed in our
like the following:
case ) is called the sentiment analysis. The
11: French MP and billionaire Olivier intended output of this analysis would be to
Dassault dies in helicopter crash: determine whether the producers mindset
Sun, 07 Mar 2021 20:04:17 GMT toward a topic, product, headline or service
{"probability": {"neg": etc., is in most cases neutral, positive, or
0.46705201547833042, "neutral": negative.
0.81510771060379195, "pos":
0.53294798452166958}, "label":
Let’s get started with the use of an API:
"neutral"}
Const
URLSentimentAPI2=
So the label shows neutral in the middle of 'http://text-processing.com/
possibilities. The english sentiment uses api/sentiment/';
classifiers trained on both twitter sentiment
as well as movie reviews from the data sets.
The dutch and french sentiment is based on
book reviews.

Blaise Pascal Magazine 93 2021 26


BBC News
Sentiment Analysis Page2/4 maXbox
Our text lines are based on the
BBC-News Feed:
The send() method (XMLhttp.Send();) needs
BCFeed =
'http://feeds.bbci.co.uk/ more explanation: send() accepts an optional
news/world/rss.xml'; parameter which lets you specify the requests
body; this is primarily used for requests such
To call the API we use a late binding
as PUT or POST. If the request method is GET
OLE Automation from
or HEAD, the body parameter is ignored and
<msxml2.xmlhttp> .
the request body is set to null. Im not sure if
The text-processing.com API is a simple the content-type is the right (text or
JSON over HTTP web service for text mining application), the MIME media type for JSON
and natural language processing. It is currently text is application/json and the default
free and open for public use without encoding is UTF-8. (Source: RFC 4627).
authentication or login, but could be changed {content-type: application/json; charset=utf-
in the future. As of JSON we use the 8}
delphi4json library to parse the return.
To analyze some text, we do an HTTP POST to
The script you can find at:
http://www.softwareschule.ch/ our API with form encoded data containg the
examples/newssentiment2.txt text we want to analyze. We get back a JSON
XMLhttp:= CreateOleObject('msxml2.xmlhttp')
object response with 2 attributes label and
XMLhttp.Open('POST', URLSentimentAPI2, False) //False: async probability which we parse with a JSON object
XMLhttp.setRequestHeader('Content-Type','application/json'); (more of that in the next number):
XMLhttp.Send('text='+'"'+textin+'"'+CRLF+'language=english');
response:= XMLhttp.responseText; //assign data
writeln(response) with TJson.create() do begin
writeln('statuscode: '+itoa(XMLhttp.status;)) clear;
XMLhttp:= unassigned; parse(response);
cnode:= JsonObject.items[0].name; //'probability'
writeln(itoa(JsonObject.count));
On success, a 200 OK response will be writeln('prob: '+values[cnode].asObject.values['neutral'].asstring);
writeln('result: '+(values['label'].asstring));
returned containing a JSON object that free;
looks like: end;
{"probability":
{"neg": 0.37517484595971884,
"neutral": 0.091034274541377691, >>> 2
"pos": 0.62482515404028116}, >>> prob: 0.854074272795421
"label": "pos"} >>> result: neutral

A 503 Throttled response will be returned if As you may see many of the most commonly
you exceed the daily request limit. Using used words or phrases are insignificant when it
async = false in Open() is not always comes to discerning the meaning of a phrase.
recommended, but for a few small requests For example, in the phrase the movie was
this can be ok. Remember that the script will terrible, the most significant words are movie
NOT continue to execute, until the server and terrible, while the and was are almost
response is ready. If the server is busy or slow, useless. You could get the same meaning if you
the application will hang or stop. took them out, that is, movie terrible or terrible
Anyway we open our XMLhttpObject (which is movie. Either way, the sentiment is the same.
late binding) as not asynchronous, that is to Another approach is to measure the sentiment
say, synchronous because we just post a of face feelings with 3 flavours: Joy, Sadness
single block of data with send(). and Anger or Disbelief, but that’s kind of
research.

Blaise Pascal Magazine 93 2021 27


BBC News
Sentiment Analysis Page3/4 maXbox
Our
quote from above results in: XMLhttp.Send('text='+'"'+textin+'"'+C
Sentiment of: "Yesterday I RLF+'language=dutch');
was clever, so I wanted to Trump's false election fraud claims
change the world. Today I am face a dead end
wise, so I am changing myself". {"probability":
{"probability": {"neg": 0.52,
{"neg": 0.37517484595971884, "neutral": 0.64,
"neutral": 0.091034274541377691, "pos": 0.47},
"pos": 0.62482515404028116}, „label": "neutral"}
"label": "pos"} statuscode: 200 Trumps falsche Wahlbetrugsansprüche
The NLTK (Natural Language Toolkit) is a leading stehen vor einer Sackgasse
platform for building Python or API programs to
Trump's valse verkiezingsfraude claims
work with human language data. It provides easy- lopen dood
to-use interfaces to over 50 corpora and lexical
resources such as WordNet and many others. Les fausses allégations de fraude électorale
de Trump font face à une impasse
CONCLUSION:
This is a demonstration of sentiment analysis {"probability":
{"neg": 0.33,
using a NLTK 2.0.4 powered text classification "neutral": 0.46,
process with msxml2.xmlhttp and TJson objects. "pos": 0.66},
It can tell you whether it thinks the text you enter "label": "pos"}
below expresses positive sentiment, negative Trump's valse verkiezingsfraudeclaims
sentiment, or if it is neutral. lopen dood
{"probability":
The feedback results will be more accurate on {"neg": 0.48,
"neutral": 0.72,
text that is similar to original training data. If you "pos": 0.51},
get an odd result, it could be the words you have „label": "neutral"}
used are unrecognized. Try entering more words
or blocks to improve accuracy. Note that the Ref:
http://www.softwareschule.ch/examples/
public API is for non-commercial purposes, and newssentiment2.txt
each method is throttled to 1000 calls per day http://text-processing.com/docs/
per IP. sentiment.html
https://www.nltk.org/
You may also test the same context with
Script:
different languages, the default language is 1017_RSSDatacampSSLStreamSentiment2.pas
english, but this API also supports dutch and Doc:
french, but don’t forget to change the language in https://maxbox4.wordpress.com
the API call:
Appendix: Alternate HTTPPost-Routine:

function GetBlogStream8Sentiment(const S_API, pData: string; astrm: TStringStream): TStringStream;


begin
sr:='text='+HTTPEncode(pData)+CRLF;
sr:= sr+'language=english';
if HttpPostURL(S_API, sr, astrm)
then result:= astrm;
end;

Blaise Pascal Magazine 93 2021 28


RSS FEEDS of
BBC NEWS Page4/4 maXbox

29
Advertisement maXbox

Fun maXbox Is An All-In-One Script Engine Application: Powered By Delphi. maXbox is an open source script studio with an Object
Pascal scripting language. According to the developer, “it is an open-source script tool engine, compiler, and source library, all in
one. Use it to design and code your scripts! Pure Code for Object Pascal Scripting. The guiding principles are simplicity and the
reduction of complexity to the max. The app is self-containment “out of the box” with no need for installation or registration.”

https://blogs.embarcadero.com/
fun-maxbox-is-an-all-in-one-script-engine-application-powered-by-delphi/
How differs the new FastReport VCL 2021.0 Page 1 / 20
from the previous versions?
Significantly improved work with images -
as in image editors: Improved transparency support for images inside
- High-quality vector SVG images in reports a report. Now FastReport VCL supports not only
- Improved image transparency in different color mask but also an alpha channel in the
formats report preview, on the printout, and exports
which supports transparent images.
New objects widen the concept of a
"report":
Two-Track Pharmacode for designing and
printing medication and vaccine packages
Report safety and security:
Now reports in PDF are protected with a
digital signature. It guarantees its
uniqueness, allows to clearly establish the
authorship, and protects it from editing.
Your reports now correspond with the
docflow standards.
Resource optimization:
- Page miniatures are formed faster Added experimental picture cache with the
- Less memory required for work ability to generate thumbnails and control
New licensing model: overall image quality. New picture cache saves
Starting March 2021 all FastReport VCL memory usage and GDI descriptors. It loads
editions are subscription-based. It means only one instance of duplicated image (can be
that you will always have an up-to-date turned on with
version as long as your subscription is Report.PictureCacheOptions.CachedImagesBu
valid. ildType=tbtOriginal property).
In detail:
Loading and output images in vector SVG
format through standard “Picture” object (only
for Delphi). Enhance the look of your reports!

Added new barcode type Two-Track Pharmacode.

Blaise Pascal Magazine 93 2021 32


How differs the new FastReport VCL 2021.0 Page 2 / 20
from the previous versions?
The picture cache can be set up for thumbnail
generation which’s using for a fast load of
images in the preview window (can be turned
on with Report.PictureCacheOptions.
CachedImagesBuildType=tbtAtPrepare ).
The thumbnail quality controls by
Report.PictureCacheOptions.
ThumbnailQualityReducer properties
and allows setting the percentage of
compression and conditions. In addition, it is
possible to control the overall quality of
compression for all pictures through
Report.PictureCacheOptions.OriginalQualityRed
ucer property. Those images using for preview,
printout, and export of a report.

Added support of Digital signature in PDF select type of signature (hidden, visible,
export with pfx and p12 certificates support. image), and sign up documents with your
Sign up your PDF documents just in 3 simple certificate.
steps: Add the “Digital signature” object
(TfrxDigitalSignatureView),

Blaise Pascal Magazine 93 2021 33


Fast Reports Reporting must be Fast! Page 3 / 20
By Detlef overbeek / Fastreport

WORKING WITH THE


REPORT DESIGNER
INTRODUCTION
FastReport is a reporting tool, that has one big
advantage: It is so easy to understand that
even with very little knowledge you can find out
how to create a report. To be precise: Put some
components on the form (or possibly a
DataModule) and simply start.
To make it even more easy FastReport has
prepared a complete running project that you
could start with. Its called the Embedded
designer: it is located over here:
c:\Program Files (x86)\FastReport VCL
Enterprise\Demos\EmbedDesigner.

START
But to make it even more practical – everyone
wants to use a database- I updated the project
to collaborate with a database: One of the
example databases that come with Delphi:
Employee.

So first let’s find out where that is hiding: Figure 2: The project
c:\ProgramData\Embarcadero\InterBase\g
ds_db\examples\database\employee.gdb Let’s start with the more problematic part of the
So now we found out where the necessary files project: getting the database connected.
are residing we can start Delphi. I have done this We have to do that in Delphi itself – you should
with Delphi 10.4.2 but an older version will not be sure InterBase is running on your computer.
be any problem. (In the next issue I will do the Let’s find out…
same Project In Lazarus). So there is no reason
for you not to try and I must say the price of the 1. DELPHI CONNECTING TO DATABASE
program is very affordable. (See the next page figure 3 of the Data
If you want to know details please go to: Explorer Tab ) Go to the Data Explorer Tab at the
https://www.fast-report.com/en/buy/#!/ right side of your Delphi IDE. Choose “Firedac.”
VCL%20(Embarcadero%20RAD%20Studio|Delp Freedom of choice! Not because you need to, but
hi|C++%20Builder)/FastReport%20VCL/
this is the one I used for this simple trial. You
But for now we need to start Delphi. might also choose for dbExpress where there is
Open the project EmbeddedDesigner. This also a database available. All this explanation is
project will be made available for you with your done to make it understandable for you if you
sources on the website downloads address: have to engage your own database. (See figure 4
https://www.blaisepascalmagazine.eu/ of dbExpress on the next page). There are
your-downloads/ small x-crosses and that means it is not
Figure 1: The project form with components needed connected.

Blaise Pascal Magazine 93 2021 34


Fast Reports Reporting must be Fast! Page 4 / 20

You can click on the InterBase Item and the


EMPLOYEE table will show up: (See figure 3 )

Figure 5: The dbExpress list of databases


2. EXTENDING THE PROJECT
Now we have the database, we need to extend
the project a little:
Normally this project starts without the
database connection so we have only three
components on the form:

Figure 3: Interbase with EMPLOYEE


You need to fill out the form that pops up if
you want make changes after having chosen Figure 6: The Form
Modify; right clicking allows you to either u the main menu
Close /Refresh /Modify /Rename or Delete. v the frxReport
w the frxDesigner
these are to be found on the Palette.
Now as an extra we need:
x a DataSource from the Data Acces Tab
DataSource1
Figure 4: Refreshing?
y an frxDBDataset from the Fastreport VCL Tab
If you have given the right path and settled for frxDBDaset1
you username “Sysdba” and Password
“masterkey” the connection will become z an IBDatbase component from the IB Tab
available.
No more red x-cross there, if still, refresh. IBDatabase1
See figure 5 { and finally an IBTable from the IB Tab

IBTable1

Blaise Pascal Magazine 93 2021 35


Fast Reports Reporting must be Fast! Page 5 / 20

3. CREATING THE RIGHT SETTINGS


Let’s do it per component

IBDatabase1 IBTable1 DataSource1 frxDBDaset1


IBDatabase1

Figure 7: The basis IBDatabase,


Connected has to be set to true.
Note the path to the database.
See the Database Editor by clicking on the item.

Figure 8: Clicking the Database Editor

Figure 9: Check the settings

Blaise Pascal Magazine 93 2021 36


Fast Reports Reporting must be Fast! Page 6 / 20

IBTable1 IBDatabase1 IBTable1 DataSource1 frxDBDaset1

Figure 10: Fields editor


shows the fields

Figure 11: Fields list

Figure 9: the table needs to be set to active

DataSource1

Figure 12: Connection with IBTable

Blaise Pascal Magazine 93 2021 37


Fast Reports Reporting must be Fast! Page 7 / 20

frxDBDaset1
IBDatabase1 IBTable1 DataSource1 frxDBDaset1

Figure 13: The frxDBDataset1

Figure 14: If so desired you can rename the fields


After all these settings there is one more item to be named:
If your connection fails: check the Data Explorer tab and double click on the Employee table item.
If all is settled you can see the table views procedures and generators (see figure 16 next page)

Figure 15: Right click on the Employee table and choose Modify

Blaise Pascal Magazine 93 2021 38


Fast Reports Reporting must be Fast! Page 8 / 20

So now on the side of Delphi everything is set and


should be working. Let’s prepare the Designer.
Run the program and you will see the Designer for the
first time. (See figure 17).
Now you can see a separated program, with this you
can create your new forms etc., even coupled to a
database of your choice. For those of you that want to
create forms like in Adobe Acrobat, here is an other
option.
It’s saved in the directory of the project, so you can
easily find it: ( it’s in your download area)
...\DelphiProjects\
_history\
_recovery\
EmbeddeDesigner.identcache
EmbeddeDesigner.exe
EmbeddeDesigner.dproj.local
EmbeddeDesigner.res
EmbeddeDesigner.dproj
UMain.dfm
UMain.pas
UMain.dcu
Detlef_FastreportTest.fr3
EmbeddeDesigner.dpr
Project1_Icon.ico
EmbeddeDesigner_Icon.ico

Figure 16: The content of the table

Figure 17: The Designer at the beginning

Blaise Pascal Magazine 93 2021 39


Fast Reports Reporting must be Fast! Page 9 / 20

v
INTRODUCTION

y
}

x u

Figure 18: Overview of the Designer IDE

~
Fast Reports Reporting must be Fast! Page 10 / 20

The numbers on the picture are marked: Key Description


INTRODUCTION
Ctrl+O Menu command is "File|Open..."
u designer's working field;
Ctrl+S Menu command "File|Save"
v menu bar;
Ctrl+P Menu command "File|View"
w toolbars; Ctrl+Z Menu command "Edit|Discard"
x object panel; Ctrl+C Menu command "Edit|Copy"
y bookmarks the report pages and Ctrl+V Menu command "Edit|Paste"
the code editor; Ctrl+X Menu command "Edit|Cut"
z report tree window; Ctrl+A Menu command "Edit|Select all"
{ "Object Inspector" window; Arrows, Tab Select active object
| Data Tree window. Del Deletion of selected objects
From this window you can drag Enter Calling the editor of the selected object
and drop items to the report sheet; Shift+ arrows Size change of selected objects
} rulers. Ctrl+ arrows Moving selected objects
At dragging of a ruler on the report Alt+arrows The selected object sticks to the nearest
sheet the external line to which one in the selected direction.
objects can stick is formed; Table 1 - FastReport Designer Control Keys
~ status line.
Like all modern programs, FastReport
Designer has "hot" keys to quickly call
the necessary functions (Table 1.1):

Figure 18: Overview of the Designer IDE

Blaise Pascal Magazine 93 2021 41


Fast Reports Reporting must be Fast! Page 11 / 20

Once you start a new project: Figure 21: The outline of the memo text
File Ú New etc . to be drawn
You can start designing it.
(see the large Figure 18 at the top number
INTRODUCTION v
For this I have prepared a form where you can
see the final coupling to a database.
Let’s describe the necessary steps to make
contact with the database:

Select ÚReport and a small window pops up


and your database is mentioned. So check it
and immediately you will see at the right side
Data and fields of your database.

Figure 22: The Memo text selector

Figure 19: Open Report Data and then select the Dataset of your choice

You now can under FileÚ New Report


create your first form or if you want
to, do it with just a blank form.

To add data and show them you can


use the TMemo (figure 18)
if you click the icon you’ll see a tool
which enables you to set the place
and size of this memo.
There is something special to this
memo:
It holds the ability to simply set text,
or couple a field from your database
and on top of that create a formula.

Figure 20: Here you can even alter the properties

Blaise Pascal Magazine 93 2021 42


Fast Reports Reporting must be Fast! Page 12 / 20

INTRODUCTION

Figure 23: Create Conditions

Figure 24: Click add to show this window


and create Expressions

These are the first steps to create a form and


connect to data.
Have Fun!

In the rest of this article you will find some


detailed information about FastReports and
the functionality.

Blaise Pascal Magazine 93 2021 43


Fast Reports Reporting must be Fast! Page 13 / 20

The control of the mouse manipulator is described.


Action Description
Left Mouse Button Selecting an object; inserting a new object;
moving and resizing the object(s). You can scale the selected objects by
pulling the red quare at the bottom right corner of the selected
group of objects.
Right Mouse Button Context menu of the object(s) above which
the mouse pointer is placed.
Double-click the left Call the object editor. If you double-click on an empty page,
Mouse button the "Page Options" dialog box will be called.
Mouse Wheel Scrolling through the report page.
Ctrl + Mouse Wheel Scope
Shift + left Mouse button If an object is already selected, it removes the selection from it,
otherwise the object is selected. The selection of other objects does
not change.
Ctrl + left Mouse button A frame is drawn as soon as you press and move the mouse;
after releasing the mouse button, all the objects included in the frame
are highlighted. The same effect can be achieved by clicking with the left
mouse button on an empty area of the page and dragging the mouse to
the desired position without releasing the button.
Alt + left Mouse button If the object "Text" is selected, it edits its content inside.
Table 1.2 - Mouse control modes

By learning the "hotkeys" and mouse techniques, you can significantly accelerate the work in the
designer in the future.

Let's look at the toolbars. In the designer it is possible to allocate five panels:
u Designer mode panel (object panel);
v The "Standard" toolbar;
w The Text toolbar;
x Rectangle toolbar;
y Alignment toolbar.
The Designer Mode Panel is combined with the Object Panel.
Icon Title Description
Object selection Normal operation mode, where the mouse pointer allows selecting
objects, changing their size, etc.
Hand pointer If you click with the left mouse button, you can drag the report sheet.

Magnifying Glass A single left mouse click zooms in 100%, the right mouse button zooms
out 100%. If you press the left mouse button and drag the
mouse without releasing it, it zooms the selected area.
Text Editor By clicking on the Text object, you can edit its content right on the report
sheet. If you press the left button and drag the mouse without
releasing it, the "Text" object will be created on the selected place and
its editor will start.
Format copying The button becomes active if the "Text” object is selected. If you
press with the left mouse button on the "Text" object, it copies to the
object the formatting that has the previously selected object "Text".
Table 1.3 - Designer Mode Panel

Blaise Pascal Magazine 93 2021 44


Fast Reports Reporting must be Fast! Page 14 / 20

The "Standard" toolbar is placed at the top of the program window (Figure 1.2).

Figure 25 - "Standard" toolbar left under item on the overview at page 40


v
The "Standard" toolbar has the following icons:
Icon Title
INTRODUCTION Description
New report Creates a new blank report.

Open report Opens an existing report from a file. The keyboard analogue is Ctrl+O.

Save the report Saves the report as a file. The keyboard analogue is Ctrl+S.

Preview Performs report generation and preview.


The keyboard analogue is Ctrl+P.
New Page Adds a new page to the report.

New dialog form Adds a new dialog form to the report.

Delete Page Deletes the current page.

Page Properties Calls up a dialog with page properties.

Cut out Cuts the selected objects into the clipboard.


The keyboard analogue is Ctrl+X.
Copy Copies the selected objects to the clipboard.
The keyboard analogue is Ctrl+C.
Insert Inserts objects from the clipboard. The keyboard analogue is Ctrl+V.

Cancel Cancels the last operation. The keyboard analogue is Ctrl+Z.

Repeat Repeats the last operation that was cancelled.


The keyboard analogue is Ctrl+Y.
Group Groups the selected objects.

Ungroup Ungroups the selected objects.

Zoom level Defines the report page scale.

Table 1.4 - Contents of the "Standard" toolbar

Blaise Pascal Magazine 93 2021 45


Fast Reports Reporting must be Fast! Page 15 / 20

The Text toolbar is also placed by default at the top of the program window,
slightly below the Standard toolbar (Figure 26).

INTRODUCTION
Figure 26 - Toolbar "Text” see item w
The "Text" toolbar has the following icons:
Icon Title
INTRODUCTION Description
No Style Allows you to choose a style. To define the liststyle.
Style of styles, call the menu item "Report|Styles...".
Arial Font Allows you to select a font name from the
drop-down list. Remembers the last five fonts used.
10 Font Size Allows you to select the font size from the drop-down list.
The size can also be entered manually.
Bold Sets/removes font thickening.
Italic Sets/removes the cursive of the font.

Underlining Sets/releases font underscore.

Font Properties Allows you to specify font properties using the


standard font selection dialog box.
Font Colour Selects the font color from the drop-down list.

Conditional allocation Shows a dialog with selection attributes for the


selected Text object.

Rotate text Allows you to select text rotation.

Alignment to the left Sets text alignment to the left.

Center alignment Sets the text to centerline.

Alignment to the right Sets the text alignment to the right.

Width Alignment Sets the alignment of text evenly across the width.

Upperedge alignment Sets the alignment of text at the top edge.

Height alignment Sets the text height alignment.

Lower edge alignment Sets the alignment of text at the bottom edge.

Table 1. 5 - Contents of the "Text" toolbar

Blaise Pascal Magazine 93 2021 46


Fast Reports Reporting must be Fast! Page 16 / 20

By default, the Rectangle toolbar is placed on


the right side of the Text toolbar.

Figure 27 - Rectangle toolbar see item w on page 9/20


Icon Title Description
Upper line Turns on/off the top line of the frame.

Lower Line Enables/disables the frame bottom line.

Left Line Switches on/off the left frame line.

Right Line Switches on/off the right frame line.

All Lines Includes all frame lines.

No Lines Turns off all frame lines.

Frame Editor Calling the frame editor.

Back Ground Color Selects the font color from the drop-down list.

Line Color Selects the line color from the drop-down list.

Fill Editor Calling the fill editor.

Line style Selects a line style from a drop-down list.

1 Line thickness Selects the thickness of the line from the drop-down list.

Table 1. 6 - Contents of the "Rectangle" toolbar

Blaise Pascal Magazine 93 2021 47


Fast Reports Reporting must be Fast! Page 17 / 20

The "Alignment Palette" toolbar is not displayed


by default, but can be easily added from the
"View"Ú"Toolbars"Ú"Alignment Palette" menu
w
(Figure 28 see item ).
INTRODUCTION

Icon Description
INTRODUCTION
Show the grid.

Align objects with the grid.

Arrange in the nodes of the grid.

Align the left edges.

Horizontal center.

Align right edges

Align the upper edges.

Centralize vertically.

Align the lower edges.

Arrange evenly across the width.

Arrange evenly in height.

Center horizontally in the window.

Center vertically in the window.

Set the same width as the first selected object.

Set the same height as the first selected object.


Table 1.7 - Contents of the "Alignment" toolbar

Now let us move on to the settings of the


designer (Figure 29).
To set the options of the designer, use the menu
command "View"Ú "Settings...".

Blaise Pascal Magazine 93 2021 48


Fast Reports Reporting must be Fast! Page 18 / 20

If the "Use object font" option is enabled, the


font in the text editor window will correspond
to the font of the edited object.
INTRODUCTION
If you are not satisfied with the white
background of the designer's work field and
service windows, you can change it using the
"Work field" and "Windows" buttons. The "Mesh
Color for LCD Monitor" option slightly
increases the contrast of the mesh lines, which
allows them to be better seen on LCD displays.

The "Call editor after inserting" option controls


the process of inserting new objects. If this
option is enabled, its editor will be shown each
time an object is inserted. When inserting a
large number of empty objects, it is better to
disable this option.

By disabling the "Show band headers" option,


you can disable band headers to save space on
the page. In this case, the name of the band is
written inside it.

If you disable the "Show drop-down list of


fields" option, you can disable showing the
drop-down list when pointing the mouse
cursor over the object "Text" connected to the
data. It can be necessary if there are many
small objects in the report.

The "Free band placement" option disables


band binding to the sheet. By default, this
option is disabled, and bands are automatically
Figure 30 - Designer settings form
grouped on the page according to their
In this form you can specify the used units of purpose. The gap between bands is set in the
measurement (centimeters, inches, pixels), "Band gap" field.
specify the grid spacing for each unit. You can
also switch the units of measure in the 1.2 REPORT OPTIONS
designer by double-clicking on the left side of The report also has its own settings (Figure
the status bar where the current units of 31). The window with report parameters is
measure are displayed. available from the menu "Report" ->
"Settings...". The form of settings has three
You can immediately set up grid display and tabs: Basic, Inheritance, Description.
alignment of objects to the grid.
You can also do it using the buttons on the
"Standard" toolbar in the designer.

In addition, there is an option to configure the


font for the code editor window and for the
editor of the "Text" object.

Blaise Pascal Magazine 93 2021 49


Fast Reports Reporting must be Fast! Page 19 / 20

The total number of pages is counted on the


first pass and can be accessed via the system
variable TOTALPAGES. The most common error
INTRODUCTION is an attempt to apply this variable in a single-
pass report, in which case it returns 0.

Another area of application is to perform any


calculations on the first pass and display the
results on the second pass. For example, when
you want to display an amount in the group
header, which is usually calculated and
displayed in the group basement. Such
calculations are connected with the use of the
built-in FR language.

The "Print if empty" checkbox allows you to build


a report that does not contain any data lines. If
this option is disabled, no empty reports will be
generated.
Figure 31 - Report settings window. Tab "General”
The "Password" field allows you to specify a
On the "Basic" tab, you can attach the report password that will be requested from the user
to one of the printers installed in the system. when opening the report.
This means that the report will be printed to
the selected printer by default. If there are The controls on the "Inheritance" tab (Figure 32)
several printers in the system, this function allow you to set the report inheritance options.
allows, for example, to attach text documents
to monochrome printers, and documents with
graphics - to color printers. As you can see on
Figure 31 there is a "Default" printer in the list
of printers. When it is selected, the report will
be displayed on the current active printer.

Here you can specify the number of copies of


the report to be printed and the parse
function. The values specified in this window
will be displayed in the "Print" window.

If the "Two passes" checkbox is checked, the


report will be generated in two stages. On the
first pass, the report is generated, it is divided
into pages, but the result is not saved
anywhere. On the second pass, the normal
report generation is performed with saving the
result in the flow.

Why do you have to do two passes for? This


Figure 32 - "Inheritance" tab
option is most often used when there is a
mention of the total number of pages in a
report, i.e. information like "Page 1 of 15".

Blaise Pascal Magazine 93 2021 50


Fast Reports Reporting must be Fast! Page 20 / 20

Here you can find out from which report the


current report is inherited, disconnect the basic
report (in this case the report ceases to be
inherited and becomes independent ), and also
INTRODUCTION
inherit the report from one of the selected ones.
For more information about inheritance, see
chapter "Report Inheritance".
The controls on the "Description" tab (Figure 33)
allow you to set the description of the report.

Figure 34 - Page settings. Tab "Other Options”

The "Print on front page" checkbox allows you


to start printing the page starting from the free
space on the previous sheet. This option can
be used if the report template consists of
several sheets or when printing batch
(composite) reports.
The "Mirror Fields" option allows you to swap
Figure 33 - "Description" tab
the right and left margins of a page for even
In this tab, you can specify the name of the
pages when viewing or printing a report.
report (it is displayed in the preview window
and is assigned to the print job), author,
Options "Infinite Width", "Infinite Height" allow
description, picture and version of the report.
you to enable the mode in which the page size
All these parameters are optional and serve for
increases depending on the output data. In
information purposes.
this case, in the preview window you see one
dimensionless page containing all data (unlike
1.3 PAGE PARAMETERS the normal mode, when a new page is formed
Like in text editors, in FR Studio you can set when reaching the end of the page).
page parameters, namely size, margins, paper
orientation and so on. Page parameters are The option "Greater height in designer" allows
available through "File"->"Page Parameters..." you to increase the height of the page by
menu or by double-clicking on an empty page. several times. This can be useful if there are
The window has two tabs: many bands on the page. The actual page
height does not change when building a
report.
In the next issue we will extend the learning
session,.

Blaise Pascal Magazine 93 2021 51


Install Aware Installer soon not only for Windows
by Detlef Overbeek
Page 1/7
There is of course a financial factor in this:
ABSTRACT: Inno Setup is free, so costs nothing at all.
InstallAware is a program that started as a
specific Windows installer for Visual Studio. INSTALLAWARE also has a free version:
It has grown to something very professional InstallAware can be found in Delphi in the GetIt
and is now even going to gain ground on other Package Manager , located at the Welcome -
OS’s. There is a free version that I will present Page at the subject Promoted , I found it by
to you here. setting the filter to All / Name / Trial.
Simply typing the name in the search box
INTRODUCTION didn’t help. Maybe because the Embarcadero
In several occurrences I have used Install GetIt server could not be reached, which
programs like Inno Setup. Problem with this happens quite a lot.
program was that you need to find out by trial There is of course an other way: go to their
and error how it works. And that consumes a website, but I found that they explicitly say the
lot of time. free installer is a VisualStudio Extension.
For testing reasons I took the simplest version So I simply installed the version from Get it.
of Install Aware and found that I could install a
program almost instantly within a few minutes. Now for testing reasons I had a look at the
AND working. other options for downloading a free or trial
version: I ran into
https://www.installaware.com/landing/
code-gear.html which confused me a little.
I thought Code Gear didn’t exist any more?
What I found wasn't exactly a free trial.
Again I tried to find the free version download
at their site:
https://www.installaware.com/download
s-product-downloads.htm
Here I get a warning that you will need Visual
Studio. That’s not what I want.
So I’ll go back to the version I installed by
choosing install through the GetIt Package
Figure 1: The starting screen
Manager.
Take into consideration that
they later this year will have
these extra options Ú

Figure 2: The enlarged text of the Trial

Figure 3: The get it Manager

Blaise Pascal Magazine 93 2021 52


Install Aware Installer soon not only for Windows Page 2/7

¦ Three Major Platforms:


Code and compile natively on Linux, Mac,
and Windows. Build for any platform from
any environment – ex: you will be able to
build Mac installers on a PC, and vice
versa!
¦ Advanced Dialogue Editing: Enjoy a
dialogue editor virtually identical to its
Windows Installer brethren, with the same
ease of use, drag&drop design
experience, and visual configuration.
¦ Conditionally Flowing Setup Script: Code,
commands, and syntax to remain as
similar as possible to InstallAware‘s
existing scripting language, and a
zero learning curve.
¦ NO JAVA: InstallAware Multi Platform
offers 100% native code setup engines for
Linux, Mac, and Windows –
ZERO DEPENDENCIES and runtime free
delivery!
Figure 4: The Quick Start Option which we test here.
Since I downloaded the program a few weeks
ago I had to restart my memory and started
the program again. Now I need to (see figure)
state that I would like to try it again.
As I hoped the program started. To begin with:
let’s do a quick start.

QUICK START
Running through the Install setup is easy.
Because I wanted to do something useful, I
tried a program example I made earlier and
which could use an update. The ClockAgenda.
The clock for the desktop you can put as a
small app somewhere on your desktop which I
want to give an update in the next issue:
create a colouring menu, add a startup for the
app when windows starts and make it also in
Lazarus, so you can choose what you want: Figure 5: The subtext on the wizard shows the
Windows/Linux or Mac. importantant messages
The code is of course as always free…
Hopefully by that time the new InstallAware Anything you do in this wizzard can also be
abilities will be available… done (or changed) using the IDE visual desginer
(see figure 7, page 4/7) or MSIcodesript editor
The Install-Setup is decorated with all the (see figure 8, page 5/7).
windows that pop up during the process.
You’ll find the extra info under each picture.

Blaise Pascal Magazine 93 2021 53


Install Aware Installer soon not only for Windows Page 3/7

Figure 5: The compile button

In the various options of the InstallAware


Program Manager are endless, so it will be
possible to create a very well optimized
installation for your program. At the top there
are three tabs available that have even more
detailed options, as you can see in the figure 5
at the top. I am impressed:
It’s simple and quite easy to understand. In
this way it’s even fun to make a specialized
install meant for ones program. I haven't
tested it yet fully but the first impression is

Figure 6: The Project Manager

Blaise Pascal Magazine 93 2021 54


Install Aware Installer soon not only for Windows Page 4/7

Figure 7: The Visual Designer

The Visual Designer shows at the left a list of Here you see what you could do with the
subjects which show a more detailed plan at Windows registry, if you need a controlled
the The main window in the middle/right installation.
section. Its worth to browse through them. It
will maybe even give you new ideas. I think if
they are capable of doing this for various OS’s
this Installer is a must have.

Blaise Pascal Magazine 93 2021 55


Install Aware Installer soon not only for Windows Page 5/7

Figure 8: The MSIcode manager

Using the MSIcode tab you


can drag and drop scripting
elements, as you can see in
the right column. In some
case you will be offered
detailed windows to fill out
specifications.

Blaise Pascal Magazine 93 2021 56


Install Aware Installer soon not only for Windows Page 6/7

Figure 9: The Quick Start menu

Figure 11: Filling in the Application folder


Figure 10: Filling in the product name

Blaise Pascal Magazine 93 2021 57


Install Aware Installer soon not only for Windows Page 8/7

Figure 12: adding the executable

Figure 13: If you need you can add a


file type extension

Figure 14: Build the stup

Blaise Pascal Magazine 93 2021 58


For your components and workouts

Deleaker
RemObjects
Enterprise Connectors
DevExpress VCL Controls
TMS Software
Gnostice Document Processing
Steema
FastReport
QuickReport
Woll2Woll
Devart Delphi Access Components
uniGUI
Elevate Software
ImageEN Software
Multilizer
CrossVcl

https://www.barnsten.com/product-category/components/
Infotorial

What's coming in TMS WEB Core v1.7


Ancona

The new version v1.7 of TMS WEB Core has been in development for about 6 months by
now. Many of its features were already in development in parallel to v1.6. And yes, our team
already
- is working on v1.8! It will not come as a surprise to you that in v1.7 there are new
game changing features in TMS WEB Core also.
Those who have been following the TMS WEB Core development since the first version
TMS WEB Core v1.0 Brescia will know that we name the releases after cities along the
famous historic race “MilleMiglia”. To be more precise, the legendary race of 1955. And as
such, after we visited the city Pesaro with v1.6, for v1.7 we land in Ancona. The historical
meaning of the word “Ancona” is elbow which is commonly associated with the shape of the
coastline. After the 'elbow' Ancona, there are new sights towards the more southern coasts of Italy.
Enough history! Let's bring an overview of what our team has been working on for TMS
WEB Core v1.7 Ancona.
u Components wrapping browser API for local file access
The W3C consortium proposed an API forlocal file access from Web browser applications
and Google Chrome implements it already. Given that Microsoft uses the Google Chromium
engine, it is also available in Microsoft Edge Chromium. With TMS WEB Core, you can take
a head start, explore, and start using this with its three components today:
• TWebLocalTextFile
• TWebLocalBinaryFile

Blaise Pascal Magazine 93 2021 tmssof two r . com 60


Infotorial
These components allow you to directly open text and binary files from the local file system
as well as traverse the local file system’s folder structure from a Web application. Of course,
for security reasons, the users have to give their consent first.

v Popup menu component and popup menu


support in components
In TMS WEB Core, we offered the regular TWebMainMenu since its inception and now we
completed this trend with the new TWebPopupMenu. It works very similar to a Windows
VCL TPopupMenu. Simply drop a TWebPopupMenu on your Web forms and assign it to
control.PopupMenu to obtain an automatic context menu for controls.

w USB device access

The times that software developers thought you could never use a Web application for
controlling your machine's hardware are officially over. We already introduced support for
Bluetooth with our TWebBluetooth component, and with this release we add two new
components TWebUSBSerial and TWebUSBHID that allow you to write applications
communicating with locally connected USB devices using a serial protocol or the HID
protocol. This opens up a whole new field of applications that can be implemented using Web
technologies.

x TWebStringGrid & TWebDBGrid extensions


We added a whole range of new grid features in TWebSt ringGrid and TWebDBGrid. There are now:
• Methods to insert & remove rows
• A range of different inplace editor types
• Cell merging and cell splitting
• Loading and saving to streams
• Loading from a stringlist with CSV data
• Direct access to grid data as TJSArray
• Add checkboxes to the grid

Blaise Pascal Magazine 93 2021 tmssof two r . com 61


Infotorial
y Async methods
There is no way around it in the Web browser, there are different APIs that can only be used
in an asynchronous way. The reason for this is very clear: Always guarantee a responsive UI
even when lengthy operations are taking place in the application.
Many developers struggle with implementing sequential logic for processes that occur asynchronously.
We already offered anonymous methods that can be used to handle results of methods asynchronously,
but, in v1.7, we added a whole range of async methods to classes. With a simple await() construct
around an async method, you can write your code as if it were synchronous and sequential,
- but, behind
the scenes, the browser still handles it asynchronously and keeps your UI responsive. The components
to perform HTTP(S) requests for example, load data from a URL, load images from URL, etc... now all
have async equivalents making you write code that is cleaner and consequently easier to maintain.
plain
view text

1. var
2. ms: TMemoryStream;
3. begin
4. ms := TMemoryStream.Create;
5. try
6. await(boolean,ABinaryFile.LoadStream(ms));
7. ms.Position := 0;
8. webmemo2.lines.LoadFromStream(ms);
9. finally
10. ms.Free;
11. end;
12. end;

z Miletus framework
This is probably the biggest feature of TMS WEB Core v1.7! Miletus is a framework for
creating native desktop applications with Web technologies. It permits to create wonderful
and modern user-interfaces using (and in many cases reusing) HTML/CSS templates.

62
Infotorial
Still, it allows to run as a desktop application and to access desktop features normally
reserved for a native desktop app. This includes:
• local file access
• operating system menu
• drag & drop interaction with the operating system
• access to the taskbar
• access to local databases (SQLite, MSSQL, PostgreSQL, mySQL, MS Access)
• so much more...
This first introduction of Miletus in TMS WEB Core offers the capability to create Win32
and Win64 native single EXE file applications with a size below 10MB. And in the near
future, we will add macOS and Linux to that.
Stay tuned for another blog with a more detailed overview of the Miletus features. An
additional benefit of Miletus is that we developed this framework from the ground up as
opposed to a similar framework called Electron that is from a 3rd party. This means that for
the future, we have full control to design any feature set we want for Miletus.

{ TWebSocketClient method added to send &


receive binary data
When communicating with a web socket server, TWebSocketClient can now directly send &
receive binary data whereas in previous versions this had to be sent as Base64 encoded string
data.

| TWebForm extended
We added more flexibility to the TWebForm. This includes:
• Option to have a close button in the caption
• Property to choose whether a shadow border is used or not
• ElementCaptionClassName property added to allow the use of CSS for the caption
• OnDOMContentLoaded event added, that signals when the browser loaded the entire
DOM content
• OnHashChange event added to handle browser back & forward buttons

} New server-side filtering + multi-tenant support


in TWebFireStoreClientDataSet
We have also significantly improved TWebFireStoreClientDataSet. Now,TWebFireStoreClientDataSet
supports to create more flexible and more performant Web client applications using Google's Firestore
as the backend for data storage. In the new version, it is possible to specify server-side filters.
This facilitates not only multi-tenant scenarios but also increases performance by minimizing data
returned from the server.

~ Numerous smaller extensions & improvements


to various components & IDE integration
Not only was the TMS WEB Core framework improved in almost any corner, the IDE integration got
further fine-tuning as well. The capability to use environment variables in the compiler path with the
$() syntax was added. The same is possible with custom compiler directives.
And finally, also the pas2js compiler & RTL were updated to the latest version v2.0.4.
Blaise Pascal Magazine 93 2021 tmssof two r . com 63
Infotorial
Planning
The first step is that we will release the beta version of TMS WEB Core v1.7 in the next few
days to all TMS ALL-ACCESS users and registered users of TMS WEB Core. We expect the
upgrade process should be smooth and painless as we paid a huge amount of attention to
backwards compatibility. This is proven by the fact that we did not have to make any
modifications to the meanwhile over 100 demos included. However, we want to put the v1.7
beta into your hands first and listen closely to your feedback. That allows us to apply further
polish where needed.
After this beta period, TMS WEB Core v1.7 Ancona will be officially released, and our team
will continue to work hard on the next milestones.

TMS WEB Core for Visual Studio Code v1.3


The new version v1.3 of TMS WEB Core for Visual Studio Code is also around the corner.
The major new feature of v1.3 will be extensibility via 3rd party components with a package
system and with this, the whole portfolio of TMS FNC components will also become usable
at design-time in Visual Studio Code. The TMS WEB Core framework will be at the same
level as TMS WEB Core v1.7 for Delphi & Lazarus. The only feature that will not yet be
included in TMS WEB Core for Visual Studio Code v1.3 is Miletus support. That is reserved
for v1.4 and with this, it is expected to already bring Miletus for Windows, macOS, and Linux.

TMS WEB Core v1.8


There are several ongoing new developments for TMS WEB Core that we cannot reveal yet,
but it is clear that v1.8 will come with Miletus support for macOS and Linux. We already
have proof of concept versions working in the lab, but further work is needed before this is
considered “feature complete”. This will very likely be the case in v1.8.

Get started today!


The only constant in software development is change. Web technologies open up exciting
new capabilities for us Delphi, Lazarus, or Object Pascal developers in general. It allows us
to create with RAD component-based techniques and a strongly-typed object-oriented
language no-deploy web applications. Further, we may create PW As for iOS and Android
that can be installed and run offline when needed. Best of all, we do not need to conform to
Apple or Google store censorship. Alternatively, you can create cross-platform desktop
applications with Electron or Miletus at the same time.
We are of course curious to hear what you like the most about TMS WEB Core v1.7 Ancona
or what you wish to see in future versions of TMS WEB Core! We look forward to
discussing all these great milestones with you!
Webinar
If you want to see the new capabilities in TMS WEB Core 1.7 Ancona demonstrated live and
ask questions, we have organized this opportunity for you! Attend our free webinar on April 8, 2021,
from 15h00 to 16h00 UTC (17h00 18h00 CEST).
Register for the webinar here https://www.tmssoftware.com/site/tmswebacademy.asp?id=75
Blaise Pascal Magazine 93 2021 tmssof two r . com 64
Lazarus: Webform inside Lazarus
A small revolution for Pascal on the desktop
Page 1/11
By Michaël Van Canneyt

ABSTRACT Delphi’s VCL or Lazarus’ LCL and derived


The Chrome browser is by far the most popular components are hopelessly outdated where
browser of the moment. The technology it concerns visual effects and gadgets, simply
underlying this browser is freely available: the because the Javascript world is meanwhile
Chromium project distributes the rendering much bigger and more people contribute to its
and Javascript engine underlying this browser. development. You may ask: Do these visual
In this article we show how to embed the effects really matter, and is it worth the effort?
Chromium browser in your Lazarus Each must decide this for himself, but the
Application. technology exists, and the FREE PASCAL &
LAZARUS FOUNDATION wants to make it
available for Object Pascal programmers.
starter expert

With the development of PAS2JS and TMS Web


core, it is possible to program the browser
INTRODUCTION
itself.
Survey after survey shows that the Chrome
This means that we can now create a program
browser is by far the most popular browser of
that has a native part, programmed in Pascal,
this moment. Google has made the technology
underlying this browser freely available: and a GUI part running in the browser - also
The CHROMIUM EMBEDDED FRAMEWORK, programmed in pascal. This opens new
managed by the Chromium project, makes the perspectives.
RENDERING & JAVASCRIPT ENGINE available
to any programmer.
This can be used to do simple matters such as
show webpages in your application:
this can be used to embed „help“ or even a
complete „helpdesk“ in your application.
If you’re adventurous, you can try to build a Figure 1: Install from external repository
complete browser.
But one can go even We can now create a program that has a
native part, programmed in Pascal, So, you want to embed the
further: projects such as
and a GUI part running GETTING
in the STARTED
browser - browser in your
NODE.JS, ELECTRON,
ATOM, SPOTIFY and also programmed in Pascal. application. How to start ?
many others use this The first thing to do is to
technology since a long time to allow you to download the Chromium Embedded
run Web Applications on the desktop or on a Framework. You can find binaries for your
tablet: platform on
The CHROMIUM EMBEDDED FRAMEWORK https://cef-builds.spotifycdn.com/index.html
runs on all major platforms, so when using it,
Second is to install CEF4Delphi in the Lazarus
your program will run on all major programs,
IDE. CEF4Delphi was initially developed
with just a single codebase.
as DCEF3 by Henri Gourvest, and is continued
Now why would one want to do this ?
by Salvador Diaz Fau.
Isn’t it better to run native applications ?
It all depends on what your application is The name suggests that the project was
meant for. For applications with an extensive initially developed for Delphi and as such the
and rich UI, the choice to run the UI in a support was best on Windows. There was
browser has considerable advantages: preliminary support for Lazarus, and the
There is a multitude of UI frameworks for the Free Pascal and Lazarus foundation has
browser, and if you want to roll your own, the sponsored some development by Martin Friebe
standards of HTML and CSS allow you to fine- to make it universally usable on all major
tune your UI and add visually appealing effects Lazarus-supported platforms:
with little or no effort. Windows, Linux and MacOS.

Blaise Pascal Magazine 93 2021 65


Lazarus: Webform inside Lazarus
A small revolution for pascal on the desktop
Page 2/11

° TChromium
The CEF4Delphi project has a package file for
installation in Lazarus (CEF4Delphi_Lazarus). The general interface to the Chromium
The Lazarus OnLine Package manager can be Embedded Framework: It basically
used to install this package. gives you access to the CEF API, and can
You will need to install the DCPCrypt package as be seen as the API for the browser.
° TBufferPanel
well, as the CEF4Delphi_Lazarus package
A panel which can be used by the CEF
depends on this package.
browser to draw on, it provides
double buffering (See the simple OSR
Note that when installing through the Online
(Off Screen Rendering) Browser demo)
Package Manager, you must install from the ° TCefServerComponent
external repository, as shown in figure 1 on A small non-visual component that
page 2. implements a small webserver and
The reason is that the changes needed websocket server.
to run in Lazarus are not yet packaged in the ° TChromiumWindow
zip distributed by the people managing the A TWinControl descendent which can be
Online Package manager. used by the CEF browser to host its
Alternatively, you can also install directly from windows. Normally you will not use this,
the CEF4Delphi sources. you should use TBrowserWindow
Simply clone the official repository using your ° TCEFWindowParent
favourite git client: A TWinControl descendent which can be
https://github.com/salvadordf/CEF4Delphi used by the CEF browser to host its
windows. Normally you will not use this,
The Lazarus package is located in the packages you should use TBrowserWindow
directory. The package is a Lazarus package as ° TCEFLinkedWindowParent
any other and can be installed in the IDE with A TWinControl descendent which can be
the usual ’Use Ú Install’ menu from the used by the CEF browser to host its
package dialog. windows. Normally you will not use this,
The Lazarus IDE will offer to rebuild itself, and if you should use TBrowserWindow
all goes well, 2 extra tabs will appear on the ° TCEFURLRequestClientComponent
component palette, shown in Figure 2 on page a TComponent wrapper around a
2/11 and Figure 3 on page2/11. (See below) TCustomCefUrlrequestClient,
The following components are registered on used to handle request progress.
° TCEFWorkScheduler
the ’Chromium’ tab:
a component that can be used to control
when the browser does work and when it
is idle.
° TBrowserWindow
A control that is essentially a combination
Figure 2: Chromium components - Tab 1
of a TCEFLinkedWindowParent
control and TChromium component.
Usually this will be sufficient for most
applications.
° TOSRBrowserWindow
a control similar to TBrowserWindow that
Figure 3: Chromium components - Tab 2
shows the browser window using OSR
(Off Screen Rendering).
° TCEFSentinel
a control that can be used to check the
status of the CEF browser:
You must be careful when to close the
window, when the window is ready for
you to send commands etc.

Blaise Pascal Magazine 93 2021 66


Lazarus: Webform inside Lazarus
A small revolution for pascal on the desktop
Page 3/11

The components on the ’Chromium Views The first line tells the browser to close itself.
Framework ’ tab are normally not necessary for The second line checks if the browser window
embedding the browser. They are wrappers was actually closed, and if so, allows the form
around CEF classes which - under normal to be closed.
circumstances - you will not need, but they are But what if the browser form was not yet
provided for completeness. closed ? How to close the form ? Well, the
This might look like a lot of components just to TBrowserWindow window as an
implement a browser, but for simple cases, OnBrowserClosed event that is triggered
only a single component is needed: when the browser form is actually closed.
TBrowserWindow. This visual control has We can use this event to close the main form
a TChromium component built-in and it uses again:
this component to control the browser. procedure TForm1.bwBrowserBrowserClosed(Sender: TObject);
begin
CREATING A SIMPLE BROWSER Close;
end;
To create a simple browser, not much code is
needed. To show this, we create a small demo The effect of these 2 event handlers is the
program. We drop an edit-control along the following sequence of events:
top border of the window (edtAddress), u The user closes the main form.
and a TBrowserWindow control that occupies v The OnCloseQuery event is triggered.
the rest of the window: bwBrowser . It tells the browser window to close.
Next to the address bar, we put a small button If the window is not yet closed, the main
btnGo. In the OnClick handler of the button, form is prohibited from closing.
we place the following code: w When the browser window is closed,
the OnBrowserClosed event is triggered.
bwBrowser.LoadURL(UTF8Decode(edtAddress.Text));
It closes the main form.
x Again the OnCloseQuery event is
The UTF8Decode is needed because the LCL triggered. But this time, the IsClosed will
uses UTF8 for all texts in controls, but the evaluate to True, and the main form is
CEF API expects a WideString (or Unicode
allowed to close.
String) in its APIs.
If this were all there was to it, it would of
course be very simple.
Alas, some more work is needed.
The Chromium browser is a complex piece of
software. To let it work correctly, some
initialization is needed, and when closing
down, also some extra code is needed to make
sure the CEF browser close down properly.
Specifically, you can’t just close the form on
which the browser window is located. In the Additionally, on Windows, some extra code is
OnCloseQuery of the form, you must check needed to handle the use of the menu. The
whether the browser window was actually menu uses a separate modal loop, and this
closed before allowing the form to be closed. must be communicated to the CEF browser.
The following code can be inserted in the form
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); declaration:
begin
With bwBrowser do {$IFDEF WINDOWS}
begin procedure WMEnterMenuLoop(var aMessage: TMessage); message WM_ENTERMENULOOP;
CloseBrowser(True); procedure WMExitMenuLoop(var aMessage: TMessage); message WM_EXITMENULOOP;
CanClose:=IsClosed; {$ENDIF}
end;
end;

Blaise Pascal Magazine 93 2021 67


Lazarus: Webform inside Lazarus
A small revolution for pascal on the desktop
Page 4/11

And the methods must be implemented as follows: unit CEFControl;


{$mode objfpc}
uses
uCEFApplication; {$h+}
{$IFDEF WINDOWS}
procedure TForm1.WMEnterMenuLoop(var aMessage: TMessage); interface
begin
inherited; uses
if (aMessage.wParam = 0) and (GlobalCEFApp <> nil) then uCEFApplication, uCEFWorkScheduler;
GlobalCEFApp.OsmodalLoop := True; Procedure InitCEF;
end; Procedure StopCEF;
procedure TForm1.WMExitMenuLoop(var aMessage: TMessage);
begin implementation
inherited;
if (aMessage.wParam = 0) and (GlobalCEFApp <> nil) then Procedure InitCEF;
GlobalCEFApp.OsmodalLoop := False; var
end; Dir : String;
{$ENDIF} begin
if Assigned(GlobalCEFApp) then exit;
{$IFDEF DARWIN}
The uCEFApplication unit contains the AddCrDelegate;
GlobalCEFApp object instance which takes {$ENDIF}
CreateGlobalCEFApp;
care of communication with the CEF library. // Set the location of the CEF libs.
Setting its OsmodalLoop property notifies {$IFDEF WINDOWS}
the CEF library that a menu global event loop is Dir:='c:\CEF\Current\Dist':
{$ELSE}
active (or not). Dir:='/opt/CEF/current/dist';
The above code is not so difficult, and is the {$ENDIF}
same for every application that uses CEF. GlobalCEFApp.FrameworkDirPath:=Dir;
GlobalCEFApp.ResourcesDirPath:=Dir;
Alas, this is not yet everything you must do. GlobalCEFApp.LocalesDirPath:=Dir+PathDelim+'locales';
if not GlobalCEFApp.StartMainProcess
INITIALIZING THE CEF LIBRARY then
begin
The CEF library itself must also be initialized StopCEF;
and stopped. Because the CEF browser halt(0); // exit the subprocess
end;
runs in a separate process (this is a security end;
measure), this takes time to set up and a lot
Procedure StopCEF;
of initialization needs to be done. Luckily, the begin
CEF components take care of a lot of the if GlobalCEFWorkScheduler <> nil then
details involved in setting up the library. In a GlobalCEFWorkScheduler.StopScheduler;
DestroyGlobalCEFApp;
Lazarus program, you don’t need to code a DestroyGlobalCEFWorkScheduler;
lot to start the initialization process. end;
Unfortunately, this must be done at different
{$IFDEF LINUX}
points in time, depending on the OS you are initialization
using: on Linux, the initialization must happen InitCEF;
before the LCL itself is initialized. On {$ENDIF}
end.
Windows and Mac, the LCL must be initialized
before starting CEF.
The best way to do this is to put all code in a On Linux, the InitCEF routine is called in the
separate unit. We’ll name it CEFControl: initialization section of the unit. If the
CEFControl unit is inserted before the
Interfaces unit in the program’s uses clause,
the result is that CEF will be initialized before
the LCL is initialized.
To initialize CEF on MacOS andWindows, the
InitCEF is called in the Initialization
of the main form unit:

Blaise Pascal Magazine 93 2021 68


Lazarus: Webform inside Lazarus
A small revolution for pascal on the desktop
Page 5/11

initialization
InitCEF;
This means that you must copy the complete
finalization contents of the Resource and Release (about
StopCEF; 1.2 Gb ) to your application directory, and this
end.
for every time you create an application that
Since the initialization section of the main uses CEF.
form is only executed after the LCL was That’s of course not very convenient when
initialized, you’re making various applications.
the CEF library will be initialized only after the A better approach may be to copy the contents
LCL is initialized, and CEF will be stopped
of these 2 directories to a single directory
before the LCL is finalized. Let’s see what (in the above example code this is
happens in more detail during initialization: CEF/current/dist ) and tell CEF4Delphi to use
The first line of the InitCEF routine checks if the libraries and support files in that directory.
the global CEF application exists. That is what these lines in InitCEF do:
If it does, it exits: this ensures that even on
$IFDEF WINDOWS}
Linux, the CEF library is initialized only once.
Dir:='c:\CEF\Current\Dist':
On MacOS, after this, an application delegate {$ELSE}
is created, this is a MacOS-specific routine, Dir:='/opt/CEF/current/dist';
needed to handle communications with CEF. {$ENDIF}
GlobalCEFApp.FrameworkDirPath:=Dir;
The call to CreateGlobalCEFApp creates the GlobalCEFApp.ResourcesDirPath:=Dir;
actual GlobalCEFApp instance, and GlobalCEFApp.LocalesDirPath:=Dir+PathDelim+'locales';
does some configuration.
procedure PumpWork(const aDelayMS : int64); Depending on the configuration this will
begin start a second (sub) process. In the
if (GlobalCEFWorkScheduler <> nil) then
GlobalCEFWorkScheduler.ScheduleMessagePumpWork(aDelayMS); subprocess the return value of this
end; function is False, in the main process the
procedure CreateGlobalCEFApp; function returns True. The subprocess
begin should stop at once, as actually a new
if GlobalCEFApp <> nil then exit; program is started in the sub process.
GlobalCEFWorkScheduler := TCEFWorkScheduler.Create(nil);
GlobalCEFApp:= TCefApplication.Create; That’s it.
GlobalCEFApp.ExternalMessagePump:= True; Now the program is ready to go. Running
GlobalCEFApp.MultiThreadedMessageLoop:= False; the program will result in something like
GlobalCEFApp.OnScheduleMessagePumpWork:= @PumpWork;
{$IFDEF LINUX}
figure 4 on article page 6/11.
GlobalCEFApp.DisableZygote := True;
{$ENDIF}
end;

The configuration is to handle messages; in the


above case the message pump is handled in
PumpWork. There are other ways to handle
this, but it is outside the scope of this article to
treat all possibilities: The above code can
simply be used in most case.
After calling CreateGlobalCEFApp,
a couple of lines set some path properties of
the global GlobalCEFApp instance.
This needs some explanation.
By default, CEF4Delphi looks for the CEF
libraries and auxiliary files in the same
directory as your application.

Blaise Pascal Magazine 93 2021 69


Lazarus: Webform inside Lazarus
A small revolution for pascal on the desktop
Page 6/11

Figure 4: Simple browser

Using these functions, it is easy to add 2 As developers, it is useful to be able to show


buttons to go back and forth in the browser the browser developer tools: this way we
history. can inspect the HTML, CSS or debug the
To demonstrate this, we add 2 buttons to the Javascript in the webpage. The chromium
top panel, btnForward and btnBack. component also has a method to help with
Their OnClick handlers are quite simple: this: ShowDevtools and its counterpart
HideDevTools. So, we create a menu button
procedure TMainForm.btnBackClick(Sender: TObject);
begin that shows a popup menu, and in the
if bwbrowser.Chromium.CanGoBack then popup menu, we add menu items to show and
bwbrowser.Chromium.GoBack; hide the developer console.
end;

procedure TMainForm.btnBackClick(Sender: TObject); The ShowDevtools call has 2 arguments: a


begin
if bwbrowser.Chromium.CanGoBack then
point and a TWinControl instance.
bwbrowser.Chromium.GoBack; The point is a coordinate in the browser
end; window that will be inspected in the developer
tools HTML inspector. The TWinControl
The CanGoBack and CanGoForward functions instance is a TWinControl instance that will
can be used to create actions in an actionlist be replaced with the developer tools.
and let the buttons be enabled or disabled, The latter can be Nil, in which case the
depending on whether there is history to developer tools are shown in a floating
go forward or backward to. This is left as an window.
exercise for the reader.

Blaise Pascal Magazine 93 2021 70


Lazarus: Webform inside Lazarus
A small revolution for pascal on the desktop
Page 7/11

We’ll create a bottom-aligned panel, controller loop as finished processing pending


by a splitter, which will contain a second messages. This callback is therefor called in
panel: the second panel will be replaced with the main application thread, and so it can be
the developer tools. Initially, the panel is used to update the UI.
invisible, and when the user asks to see the To demonstrate this, we’ll use a simple event.
developer tools, we’ll make the panel visible. The OnTitleChange event of the TChromium
When the user asks to close the developer component notifies you when a HTML page
tools, we ask the browser to close them and has a Title tag in it, and it sends you the
hide the panel. title. We can use this event to update the title
bar of the form:
procedure TMainForm.miHideDevToolsClick(Sender: TObject);
begin
bwBrowser.Chromium.CloseDevTools(pnlDevToolsInner);
splDevtools.Visible:=False;
pnlDevtools.Visible:=False;
end;
procedure TMainForm.miSHowDevToolsClick(Sender: TObject);
begin
splDevtools.Visible:=True;
pnlDevtools.Visible:=True;
pnlDevtools.Height:=ClientHeight div 3;
bwBrowser.Chromium.ShowDevTools(Point(0,0),pnlDevToolsInner);
bwBrowser.Chromium.OnDevToolsAgentDetached:=@DoDevtoolsDetached;
end;

procedure TMainForm.ChromiumTitleChange(Sender: TObject;


The visibility of the panel can be used to const browser: ICefBrowser; const title: ustring);
enable/disable the appropriate menu items in begin
if (length(title) > 0)
our popup menu:
then FNewTitle := UTF8enCode(title)
procedure TMainForm.pmMenuPopup(Sender: TObject); else
begin FNewTitle:=UTF8enCode(bwBrowser.Chromium.DocumentURL);
miSHowDevTools.Enabled:=not pnlDevtools.Visible; Application.QueueAsyncCall(@DoSetHTMLTitle,0);
miHideDevTools.Enabled:=pnlDevtools.Visible; end;
end;
The new title is saved to a temporary variable,
EVENTS FROM THE BROWSER and an async call is scheduled: DoSetHTMLTitle:
The TChromium component has a lot of event procedure TMainForm.DoSetHTMLTitle(Data: PtrInt);
handlers. These are used by the CEF begin
framework to notify your program of many Caption:=FNewTitle;
end;
things.
However, care must be taken when using these Since this call is executed in the main thread, it is
event handlers: The browser is running in safe to update the form caption. The result of
a separate process, so all communication this can be seen in figure 5 on page 11/11.
happens through the sending of messages,
which are translated to events by CEF4Delphi.
These events arrive in a thread which does not
necessarily have to be the main UI thread.
Since the widgetsets used by the LCL are not
thread-safe this means that you cannot just
update the GUI in the event handler. Luckily,
Lazarus has a mechanism that can be used for
this: Appliction.QueueAsyncCall .
QueueAsyncCall schedules a callback, which
will be called when the main application

Blaise Pascal Magazine 93 2021 71


Lazarus: Webform inside Lazarus
A small revolution for pascal on the desktop
Page 8/11

USING YOUR OWN SCHEME TO SERVE LOCAL FILES


The browser normally uses the ’http(s)://’ URL scheme to access files on a webserver,
if you double-click on a HTML file in the file explorer, the ’file://’ URL scheme.

If you want to create a GUI using a browser, and you want to distribute an application that can be only
be used to load the files you want, you can register a custom URL scheme.

You can use this to serve a restricted list of files, only files from a ZIP file, or even not to distribute files,
but have all files in resources embedded in the executable.

Blaise Pascal Magazine 93 2021 72


Lazarus: Webform inside Lazarus
A small revolution for pascal on the desktop
Page 9/11

We’ll demonstrate this by creating an To be able to add this definition, you need to
application that plays the Pacman demo from add the uCEFInterfaces, and
the pas2js demos. uCEFResourceHandler
To do this is not very difficult. We’ll use the first units to the uses clause.
demo and extend it a little. When the This class must be registered with the browser,
GlobalCEFApp application is created in the the CefRegisterSchemeHandlerFactory
CEFControl unit, we add a callback in function from the uCEFMiscFunctions unit
which custom URL schemes can be registered: can be used for this:
GlobalCEFApp.OnRegCustomSchemes:=@CEFRegisterCustomSchemes;
CefRegisterSchemeHandlerFactory('local','',TLocalResourceHandler);

This routine will be called when the browser is Now, when the browser needs to handle a URL
started, and is quite simple. When called, it scheme of ’local’, it will create an instance
gets a reference to a scheme registrar object , of TLocalResourceHandler, and call
which can be used to register a scheme: ProcessRequest, GetResponseHeaders
procedure CEFRegisterCustomSchemes(const registrar: TCefSchemeRegistrarRef); and ReadResponse,
Var aOptions : TCefSchemeOptions; in that order.
begin
aOptions:=CEF_SCHEME_OPTION_STANDARD or CEF_SCHEME_OPTION_LOCAL;
registrar.AddCustomScheme('local', aOptions);
end;

We register here the URL Scheme name ’local’.


The options mean that the scheme is a
local one, which ensures that the browser will
use the same safety mechanisms as when
using the file:// scheme.
The TCefSchemeRegistrarRef class is
defined in unit uCEFSchemeRegistrar,
so we must add that to the uses class of our
CEFControl unit. Likewise we need the
uCEFTypes unit for the TCefSchemeOptions
and the uCEFConstants unit for
the various constants. The above just tells the
browser it can expect to see URLS starting with
the local:// scheme. It does not yet handle
this scheme. To actually handle the ’local’
scheme, we need to implement a descendent
of the TCefResourceHandlerOwn
class and register it. At least 3 methods of this
class must be overridden:
TLocalResourceHandler = Class(TCefResourceHandlerOwn)
private
FFileName : String;
FStream : TStream;
Public
function ProcessRequest(CEFRequest: ICefRequest; callback: ICefCallback): Boolean; override;
procedure GetResponseHeaders(CEFResponse: ICefResponse;
out responseLength: Int64;
out redirectUrl: ustring); override;
function ReadResponse(const dataOut: Pointer; bytesToRead: Integer;
var bytesRead: Integer;
callback: ICefCallback): Boolean; override;
Destructor destroy; override;
end;

Blaise Pascal Magazine 93 2021 73


Lazarus: Webform inside Lazarus
A small revolution for pascal on the desktop
Page 10/11

The first method to be called is ProcessRequest:


function TLocalResourceHandler.ProcessRequest(const CEFRequest: ICefRequest;
const callback: ICefCallback): Boolean;
Var
S : String;
P : Integer;
begin
S:=CEFRequest.GetUrl;
P:=Pos('://',S);
if P>0 then
Delete(S,1,P+2);
FFileName:=SysUtils.SetDirSeparators(ExtractFilePath(ParamStr(0))+S);
Result:=FileExists(FFileName);
if Result then
FStream:=TFileStream.Create(FFileName,fmOpenRead or fmShareDenyWrite);
if assigned(CallBack) then
Callback.Cont;
end;

For this example we just check if the file exists,


and if it does, we return True, otherwise
we return false. For a real application, you
would probably check that the URL does not
contain any strange or forbidden locations, or
is restricted to a list of files. When the file
exists and can be served, we create a file Normally, you would also set other HTTP headers
stream (it is destroyed in the destructor). of the request, but for simplicity we’ve
The browser passes a callback, which you must omitted that part in our implementation.
call in order to indicate that the process can After these 2 calls, if there is data to be read, the
continue. browser will call ReadResponse to
After this call, the GetResponseHeaders is actually read the data. This is quite simple, we
called. This method should simulate the just read the data from the stream we
headers of a HTTP Response, and return the created in ProcessRequest, taking care we do
size of the data: not read too much data:
procedure TLocalResourceHandler.GetResponseHeaders(const CEFResponse: ICefResponse;
out responseLength: Int64; out redirectUrl: ustring);
Var
Ext : String; function TLocalResourceHandler.ReadResponse(
begin const dataOut: Pointer; bytesToRead: Integer;
Ext:=ExtractFileExt(FFileName); var bytesRead: Integer; const callback: ICefCallback
Ext:=Copy(Ext,2,Length(Ext)-1); ): Boolean;
if Assigned(FStream) Var
then aAvail : Integer;
begin begin
CefResponse.Status:=200; Result:=Assigned(FStream) and Assigned(DataOut);
CefResponse.StatusText:='OK'; if Result then
responseLength:=FStream.Size; begin
end aAvail:=FStream.Size-FStream.Position;
else If aAvail>BytesToRead then
begin aAvail:=BytesToRead;
CefResponse.Status:=400; BytesRead:=FStream.Read(DataOut^,aAvail);
CefResponse.StatusText:='NOT FOUND'; Result:=aAvail>0;
responseLength:=0; end;
end; end;
CefResponse.MimeType:=CefGetMimeType(Ext);
// No other headers.
end;

Blaise Pascal Magazine 93 2021 74


Lazarus: Webform inside Lazarus
A small revolution for pascal on the desktop
Page 11/11

Note that the function must return True if data CONCLUSION


was read, and False if there is no more In this article, we showed how to embed a
data, or the browser will keep trying to read browser in your Lazarus application: due to
data. (If the size of the data is not known in recent improvements in the CEF4Delphi
advance, this can happen ). framework, this has been made really easy.
That’s it. Our application is now ready to use But the article has scratched only the surface
the ’local://’ scheme. of what is possible. In a next article, we’ll show
We remove the address bar, the go button, and how to interact with the host application from
simply load the HTML file we wish to show within the browser application.
in the browser with the local scheme:
procedure TMainForm.FormCreate(Sender: TObject);
begin
CefRegisterSchemeHandlerFactory('local','',TLocalResourceHandler);
bwBrowser.LoadURL('local://files/index.html');
end;

When using the pacman example from pas2js,


this will look as in figure 6 on page 75 Figure 6: PacMan example

Blaise Pascal Magazine 93 2021 75


ADVERTISEMENT

S
ARU

LAZARUS HANDBOOK
S
RU LAZ
AZA ND
LAZARUS HANDBOOK 2

DL L A
AN CA
AL PAS
ASC REE
EP ITHF
FRE
LAZARUS HANDBOOK 1

W
ITH ING
GW MM
MIN ROGRA
AM P
GR FOR
PRO
FOR

+ 9 34
PA
GE
S

Sewn POCKET (2)


50 euro
ex Vat including shipment inc. PDF
LAZARUS HANDBOOK POCKET edition is
also sewn, to make sure you will not lose pages
after a while. It is printed on 100 percent
guaranteed FSC certified Paper

INCLUDED:
bookmark - creditcard - usb stick
which contains the personalized pdf
file of the book and the extra program files. So 934 pages
in two books
you have your electronic as wel the printed book
in one product.

For ordering go to:


https://www.blaisepascalmagazine.eu/product-category/books/

Blaise Pascal Magazine 93 2021 76


ADVERTISEMENT

R USOK S R USOK S
ZADBOARUOOK ZADBOARUOOK
S
AL AL RU
SC SC ZA
PA PA LA

A
L N AZ B W
IT
H
FR
EE

PA
SC
AL
A
L N AZ B W
IT
H
FR
EE

PA
SC
AL
PAS
CA
LA
ND

HA L AND HA L AND
G EE G EE EE

LAZARUS HANDBOOK
IN FR IN FR
MM H MM H FR
RA IT RA IT TH
OG G
W OG G
W WI
PR IN PR IN G
IN
R MM R MM
FO
H FO
R
PR
OG
RA FO
H FO
R
PR
OG
RA

FO
R
PR
OG
RA
MM

+
u th s G ig, D
A ttia in
Ma n H
Sv
e
e
an
l v ssa ee
ae ou erb
ich r In Ov
: M ne tlef
ors ärt e
k
t,
ey ng
nn dra
Ca Oue
o,
2 Bla
ise
Pa
sca
l

th
Au ttias inig
Ma n H
Sv
e
e
,
an
l v ssa ee
ae ou erb
ich r In Ov
: M ne tlef
ors Gärt De
k
t,
ey ng
nn dra
Ca Oue
o,
2 Bla
ise
Pa
sca
l

4
PA
GE
S

93

The books The extra protection cover Including the PDF

HardCover (3)
934 Pages
75 euro ex Vat
including shipment in two books
including. PDF
https://www.blaisepascalmagazine.eu/product-category/books/

Blaise Pascal Magazine 93 2021 77


CODE SNIPPETS Part 10 Printing With Lazarus Page 1/5
By Detlef Overbeek , project by Michael van Canneyt
starter expert

INTRODUCTION
Printing is closely related to graphics and
drawing: when you want to print something,
you must draw it on a canvas – in this case a
printer page. Printing is implemented in the
Printer4Lazarus package. (There is a similar-
sounding package called Printers4lazide,
which enables a Print Menu in the IDE itself,
which is not necessary for regular printing
support in a LCL application).

THE TPRINTER OBJECT


The canvas on which to draw the pages you
want to print, can be obtained from the Printer
instance which has a Canvas property. There is
always a global Printer object of type TPrinter
available, if Printers is included in your form’s
uses clause. The TPrinter class encapsulates
printer functionality for the LCL. TPrinter has
the following public methods:

Method Purpose
Abort Stop the current printing job, discarding all pages.
BeginDoc Start a new printing job.
NewPage Starts a new page in the current print job, saving the current page
and increasing PageNumber.
EndDoc Ends the printing job, and sends the job to the printer.
Refresh Refreshes the list of printers and fonts.
SetPrinter Set the current printer.
RestoreDefaultBin Restore the default bin on the printer.
Write Write something directly to the printer
(to be used only in raw printing mode).

To print something means using the following


methods in a simple loop:
Printer .BeginDoc ;
While not DonePrinting do
begin
// Draw the current page, setting DonePrinting if the last page is now drawn
If not DonePrinting do
NewPage;
end;
Printer.EndDoc;

If something goes wrong (e.g. the user presses a


Cancel button during the printing process)
then
Printer .Abort ;
stops the printing process.

Blaise Pascal Magazine 93 2021 78


CODE SNIPPETS Part 10 Printing With Lazarus Page 2/5
Property Type Purpose
Aborted Boolean Indicates whether the current print job was
aborted or not.
BinName string Name of the selected paper bin on the printer.
CanPrint Boolean Indicates whether the printer is ready to print.
CanRenderCopies Boolean Indicates whether the printer can make multiple
copies of a document by itself.
Canvas TCanvas The page canvas.
CanvasClass TPrinterCanvasRef The TCanvas class to use for Canvas
Copies Integer Number of copies to print
(only observed if CanRenderCopies is True)
DefaultBinName string Name of the default paper bin.
FileName string The file name to which the file will be printed.
Fonts TStrings A list of font names available for printing.
Orientation TPrinterOrientation Page orientation.
PageHeight Integer Printable page height in dots.
PageNumber Integer Current page number.
PageWidth Integer Printable page width in dots.
PaperSize TPaperSize Current paper size.
PrinterIndex Integer Index of currently selected printer in the list of
printers.
PrinterName string Currently selected printer.
Printers TStrings A list of the names of available printers on the
system.
PrinterState TPrinterState Current printer state.
PrinterType TPrinterType Current printer type.
Printing Boolean Is the printer printing?
RawMode Boolean Is the printer in RAW mode (usable for matrix
printers etc.)?
SupportedBins TStrings Paper bins supported by this printer.
Title string Title of the current print job.
XDPI Integer Horizontal resolution of the selected printer.
YDPI Integer Vertical resolution of the selected printer.

The page Orientation (of type PrinterOrientation) can take one of four self-descriptive values:
poPortrait, poLandscape, poReverseLandscape, poReversePortrait.
The PrinterType property (of type TPrinterType) can take one of two self-descriptive values: ptLocal
or ptNetWork.
The PrinterState property can have one of the TPrinterState enumeration values:
psNoDefine, psReady, psPrinting, psStopped. These enumerations are
self-explanatory, except psNoDefine which here means that printer state information is not available.
The TPaperSize class contains information about the currently selected printer paper size.
TPaperSize has the following properties:
Property Type Purpose
DefaultPaperName String The name of default paper size.
DefaultPapers Boolean Is this class using a default list of predefined papers?
Height Integer The paper height in dots.
PaperName String The name of the currently selected paper.
PaperRect TPaperRect A structure describing the (printable and actual)
paper rectangles.
PaperRectOf Array An array of paper rectangles,
indexed by paper name.
SupportedPapers TStrings A list of supported (or predefined) paper sizes.
Width Integer The paper width in dots.

Blaise Pascal Magazine 93 2021 79


CODE SNIPPETS Part 10 Printing With Lazarus Page 3/5

The LCL provides several dialogs to manipulate these properties:


Class Purpose
TPrintDialog A printer selection dialog. This modifies the Printer instance,
applying the properties of the selected printer.
TPrinterSetupDialog A printer properties dialog, which modifies the Printer instance
with the selected properties.
TPageSetupDialog A page set-up dialog, which shows settings for printing a page,
such as margins etc. This dialog’s properties are not applied to the
Printer object, but must be read and used via code.

The Lazarus SelectPrinter example demonstrates the use of these dialogs and how they affect the Printer
object. A screenshot of this demo is shown below.
It is important to note that the
coordinate system of the printer
canvas is in dots,
and that the actual size of all things
printed or drawn will depend on the
resolution of the printer. Also note that
the actual printable area is often
smaller than the whole page. Many
laser, inkjet and dot-matrix printers
cannot print across the entire paper
surface. The actually available page
width and height are therefore
important, and the coordinate system
of the page starts at the origin of the
printable area.

The following short program


demonstrates both the Printer Set-Up
Dialogs, and how the printable area
applies through printing the content of
a memo on one or more pages. The
program draws a border around the
text, based on the margins set in the
Page Set-Up Dialogs.
The coordinates of the border
rectangle for the printer canvas
coordinate system (taking into account
the origin and usable print area of the
page), are calculated as follows, where
the WorkRect property holds critical
information obtained from the
selected printer:

Figure 1: Win32 Check

Blaise Pascal Magazine 93 2021 80


CODE SNIPPETS Part 10 Printing With Lazarus Page 1/5
procedure TMainForm.GetPageRect(Out PageRect : TRect);
The units for the printer set-up dialog margins
function ToPixels(aUnit : Double; ares : Integer) : Integer; are in 1/100 of a unit. They are converted to
begin pixels (dots) by the following transformation
if PSDemo.Units in [pmDefault,pmMillimeters] then
Result:=MMtoPixel(aUnit/100,Ares) functions:
else Function MMToPixel(aMM : Double; aRes : integer) : Integer;
Result:=InchToPixel(aUnit/100,Ares) begin
end; Result:=Round((aMM/25.4) * aRes)
end;
var
LM,RM,TM,BM,H,W : Integer; Function InchToPixel(aInch : Double; aRes : integer) : Integer;
WR : TRect; begin
begin Result:=Round(aInch * aRes);
LM:=ToPixels(PSDemo.MarginLeft,Printer.XDPI); end;
RM:=ToPixels(PSDemo.MarginRight,Printer.XDPI);
TM:=ToPixels(PSDemo.MarginTop,Printer.YDPI); The results of these calculations obviously
BM:=ToPixels(PSDemo.MarginBottom,Printer.YDPI);
// Work rect depend on the X and Y resolution of the printer.
WR:=Printer.PaperSize.PaperRect.WorkRect;
W:=Printer.PaperSize.Width-WR.Left;
H:=Printer.PaperSize.Height-WR.Top;
PageRect:=Rect(LM-WR.Left,TM-WR.Top, W-RM,H-BM);
end;

With this, the contents of a memo can be printed as follows:


procedure TMainForm.PrintMemo(DrawBorder : Boolean);
Var PageRect : Trect; I,D,T,L,Y : Integer;
begin // Global options
Printer.BeginDoc;
Printer.Title:='Print demo page';
Printer.PaperSize.PaperName:='A4';
with Printer.Canvas do begin // How to draw and what font to use
Pen.Color:=clBlack;
Pen.Style:=psSolid;
Brush.Style:=bsSolid;
Brush.Color:=clNone;
Font.Name:= 'Dejavu Sans';
Font.Size:=10;
// Get work area
GetPageRect(PageRect);
if DrawBorder then
Rectangle(PageRect);
// Prepare for the text printing loop
L:=PageRect.Left+MMToPixel(5,Printer.XDPI);
T:=PageRect.Left+MMToPixel(5,Printer.YDPI);
D:=Round(TextHeight('M')*1.2);
I:=0;
Y:=T;
While (I<MText.Lines.Count) do begin
TextOut(L,Y,MText.Lines[i]);
Y:=Y+D;
Inc(I);
// Check whether the text will overflow the workable area, and start new page
If (Y>=PageRect.Bottom-(D div 2)) and (I<MText.Lines.Count) then
begin
Printer.NewPage;
Y:=T;
if DrawBorder then Rectangle(PageRect);
end;
end;
end;
Printer.EndDoc; // Send everything to the printer
end;

Blaise Pascal Magazine 93 2021 81


CODE SNIPPETS Part 10 Printing With Lazarus Page 5/5

The running program and look like this:

Blaise Pascal Magazine 93 2021 82


WEB SERVICE PART 2 - STORAGE THE DELPHI COMPANY
-est 1998-
Page 1/12
By Danny Wind starter expert

This series of articles is about writing your own consumes your web service could be caching
web services server and client in Delphi. The requests. It’s easy to notice when you run into
approach of all articles is pragmatic. The first this.
article introduced some of the concepts you
need to know and shows you how to create and If you get the same result from a GET request,
consume your own web service in Delphi with even if the data in the server has changed, then
just the GET request. This second article shows your web client is caching. Taking a look at
you how to update the data in the web service network traffic helps as well. If the web client
and how to create in-memory storage for the only generates network traffic on the first net
web service. request, you know what’s happening. It’s easy
to prevent this type of caching behaviour, by
In the previous article we only used the HTTP setting the Cache-Control and Expires elements
GET request to return data from our web in the HTTP header. Remember this if you’re not
service. This time we will add the other three getting the new data that you want to get from
HTTP commands to our web service. your GET.

HTTP GET Retrieves data from the resource


idempotent, cacheable
usage in our web service SELECT
(get existing record, disallow caching so we get new
data each time)
HTTP POST Appends data to the existing resource
not idempotent, not cacheable/stale
usage in our webservice UPDATE existing
(partial update of fields in a record,
not updating the primary key)
HTTP PUT Replace the existing resource or inserts data as
idempotent, not cacheable/stale a new resource
usage in our web service INSERT new (or REPLACE)
(insert new record with new primary key,
or replace entire record)
HTTP DELETE Deletes the resource
idempotent, not cacheable/stale
usage in our web service DELETE
(delete existing record or return error if it doesn’t exist)

Before we do that however we need to know IDEMPOTENT METHODS (RFC definition)


what the idempotent and cacheable Methods can also have the property of "idempotence" in that
properties of the HTTP commands mean for (aside from error or expiration issues) the side-effects of N > 0
our web service. identical requests is the same as for a single request. The
methods GET, HEAD, PUT and DELETE share this property.
Idempotency means that after the first Also, the methods OPTIONS and TRACE SHOULD NOT have
request a second (or third and so on) request side effects, and so are inherently idempotent.
of an idempotent method should yield the
same effect, unless there is an error or it has However, it is possible that a sequence of several requests is
non- idempotent, even if all of the methods executed in that
expired.
sequence are idempotent. (A sequence is idempotent if a
single execution of the entire sequence always yields a result
The cacheable property means that a that is not changed by a reexecution of all, or part, of that
requester is allowed to cache a request. So sequence.) For example, a sequence is non-idempotent if its
instead of sending a repeated request to the result depends on a value that is later modified in the same
sequence.
server again, it can just return a cached result. A sequence that never has side effects is idempotent, by
Both idempotency and cacheable combined in definition (provided that no concurrent operations are being
the GET request means that a web client that executed on the same set of resources).

Blaise Pascal Magazine 93 2021 84


WEB SERVICE PART 2 - STORAGE THE DELPHI COMPANY Page 2/12
-est 1998-

Looking at PUT, you see that PUT is considered


idempotent and not-cacheable. So the same
PUT request, when repeated, should yield the
same result. However PUT is not considered
cacheable, so if you PUT a resource, then
DELETE that resource from another location and
PUT it again it will result in the new resource.
The second PUT is not cached on the client-
side, it’s always considered stale and thus sent
to the server. In short, if you PUT something
twice it should always successfully replace the
existing resource. Your PUTs won’t disappear.

For POST the defined behaviour is a bit


different, as POST is not idempotent. So if you
want to update a resource it could work the first
time, but if someone else uses DELETE on that
resource a subsequent POST (append) to the
same resource could yield an error or just fail.
HTTP Commands
A good thing to know is that the definition of the
HTTP commands in RFC allows for multiple usage
scenarios of each command.
Because there is some leeway between definition
Figure 1: Tools Ú REST Debugger
and interpretation of its usage for PUT and POST in
web services it's perfectly valid for us to create a
Let’s run the REST Debugger and use it to test
web service that uses PUT as an equivalent for
INSERT or REPLACE and POST as an equivalent for the web service we created in the previous
an UPDATE. article. We can use the GET request for Number.
http://localhost:8080/Number
There is an interpretation that wants you to use
POST to get data, when the GET request
manipulates the data on the server. In our web
service we return a random number with a GET
request, and this interpretation would suggest
using POST instead, as a POST is not idempotent
and is allowed to change the server state.

Nevertheless in this article we will continue using


GET with Cache-Control and Expires elements in
the returned HTTP header to prevent caching.

Before we start coding and add PUT, POST


and DELETE methods to our web service, let’s
first expand our toolkit and introduce the REST
Debugger. This is a handy tool that comes
bundled with the Delphi IDE. You can use it to
test and debug your web service. You can find
the REST debugger in the Delphi IDE under
Tools Ú REST Debugger.

Blaise Pascal Magazine 93 2021 85


WEB SERVICE PART 2 - STORAGE THE DELPHI COMPANY Page 3/12
-est 1998-

Figure 2:
In the REST Debugger we can see that the returned Content-Type = application/json
and if we open the tab Body we see that the returned JSON is valid.

Figure3: Result

Blaise Pascal Magazine 93 2021 86


WEB SERVICE PART 2 - STORAGE THE DELPHI COMPANY Page 4/12
-est 1998-

We are now ready to add some new methods to The next step is creating an actual Key Value
our web service. store in-memory to hold the data for this web
service. We will be using a generic TDictionary
OPEN THE WEB SERVER SERVICE to store the Key Value pairs.
(WebServiceServerWithGUI ) we created in the To safely and successfully use this in-memory
previous article in Delphi. It’s compatible with Key Value store we need to know how the
either Delphi 10 Community, Delphi 10 WebModule handles incoming requests. A Web
Professional, Enterprise or up. Broker application has only one WebModule
class variable as you can see in the interface
u In the WebModuleUnit edit the Actions section of the WebModuleUnit
property and add a new handler with name
var
WebActionItemKeyValueGET, MethodType WebModuleClass: TComponentClass = TWebModule1;
mtGet and pathinfo /KeyValue. Figure 4:

However for each


request a new
WebModule instance
may be instantiated
and each request is
handled in its own
thread. For us this
means we will need to
serialize access to our
in-memory Key Value
v2. In the OnAction event-handler for this new store to make it thread safe. Also the Key Value
item code a test response in the format of store will be created as a global variable to make
a JSON string. it accessible to all WebModule instances.
procedure TWebModule1.WebModule1WebActionItemKeyValueGETAction(
Sender: TObject; Request: TWebRequest; Response: TWebResponse;
x 4. Declare the gLock and
gKeyValueStore variables and add
var Handled: Boolean);
begin System.Generics.Collections and
Response.ContentType := 'application/json; charset=UTF-8'; System.SyncObjs to the uses
Response.Content := '{"message":"it works"}'; clause of your WebModule Unit.
end;

w
3. Run the web service again, click the Start
button and start the REST Debugger and
test if your web service still works and a GET
request of this URL yields the expected
valid JSON result.
http://localhost:8080/KeyValue

Figure 5: Response

Blaise Pascal Magazine 93 2021 87


WEB SERVICE PART 2 - STORAGE THE DELPHI COMPANY Page 5/12
-est 1998-

var WebModuleClass: TComponentClass = TWebModule1; This * makes sure that any URL that
starts with /KeyValue, but continues with
implementation
additional URL segments actually ends
{%CLASSGROUP 'System.Classes.TPersistent'} up in this WebActionItem handler. So
{$R *.dfm} http://localhost:8080/KeyValue/0
uses is now also handled by this action
System.StrUtils, System.Generics.Collections, System.SyncObjs; handler.
var
gLock: TObject;
{ Next we create a function to parse
both the URL query parameters as
gKeyValueStore: TDictionary<string, string>; well as the URL segment
parameters. Add a protected
y
. At the end of the WebModule unit add an function declaration to the
initialization section where you create both WebModule.
the locking object and the Tdictionary. private
initialization { Private declarations }
protected
gLock := TObject.Create; function GetParameters(const aActionPath,
gKeyValueStore := TDictionary<string, string>.Create; aRequestPath: string): TStringDynArray;
gKeyValueStore.AddOrSetValue('0', 'Zero'); public
{ Public declarations }
end. end;

We now have an in-memory Key Value store. To | And write the following code to parse both
retrieve a value in response from a HTTP GET types of parameters from the URI
request we need to do some additional legwork. function TWebModule1.GetParameters(const aActionPath,
aRequestPath: string): TStringDynArray;
var
First we need to parse the parameters in a HTTP lActionPathLength, lRequestPathLength: Integer;
lParameter: string;
request for our resource identifiers. In a HTTP lParameters: TStringDynArray;
request to a REST webservice a parameter is begin
SetLength(Result, 0);
usually sent by using additional URL segments. So lActionPathLength := aActionPath.Length;
to get the Value for Key 0 in the KeyValue resource lRequestPathLength := aRequestPath.Length;
if (lRequestPathLength > lActionPathLength) then
you’d use a URI like this begin
http://localhost:8080/KeyValue/0 lParameter := RightStr(aRequestPath,
lRequestPathLength - lActionPathLength);
For REST web services using URL segments is lParameters := SplitString(lParameter,'/');
the preferred and also the most simple method. if (Length(lParameters) > 0) then
But if you want to you can also support begin
Result := lParameters;
specifying them as URL query parameters, end
starting with the question mark and separated end;
by ampersands. end;
http://localhost:8080/KeyValue?key=0
This second method is already supported in the
TWebRequest with the QueryFields method, but
to support using the preferred URL segment Figure 6: Response
parameters we need to add a bit of
code as well as change the PathInfo
of the Item for the KeyValue GET.

z Modify the PathInfo for the


WebActionItem for the
KeyValue GET, and add a * at
the end like this (see figure 6)

Blaise Pascal Magazine 93 2021 88


WEB SERVICE PART 2 - STORAGE THE DELPHI COMPANY Page 6/12
-est 1998-

} Then modify the OnAction event-handler for


the WebActionItemKeyValue GET Action
procedure TWebModule1.WebModule1WebActionItemKeyValueGETAction(
Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
{GET - "Select" / Idempotent}
var
lParameters: TStringDynArray; lKey, lValue: string;
begin
lKey := '';
{parse URL query parameters - http://localhost:8080/KeyValue?key=0}
lKey := Request.QueryFields.Values['key'];
if (lKey.IsEmpty) then
begin {parse URL segment parameters - http://localhost:8080/KeyValue/0}
lParameters := GetParameters((Sender as TWebActionItem).PathInfo, Request.PathInfo);
if (Length(lParameters) > 0) then
begin
lKey := lParameters[0];
end;
end;
if not(lKey.IsEmpty) then
begin
Response.ContentType := 'application/json; charset=UTF-8';
gKeyValueStore.TryGetValue(lKey, lValue);
if not(lValue.IsEmpty) then
begin // {"result":["string"]}
Response.Content := '{"result":["' + lValue + '"]}';
end
else
begin // {"error":"Item not found"}
Response.Content := '{"error":"Item not found"}';
end;
Handled := True;
end
else {No parameters on URL for GET request}
Handled := False;
end;

Test if this works, either with the REST debugger


or using the web browser. The results should
look like this.

Figure 7: Zero

prefered

Blaise Pascal Magazine 93 2021 89


WEB SERVICE PART 2 - STORAGE THE DELPHI COMPANY Page 7/12
-est 1998-

Our next major step is to add both a PUT and a POST handler.
When data is sent to a web service, the data can be sent as part of a URL segment like this
http://localhost:8080/KeyValue/1/One but his method has some limitations, one obvious one
being that not all characters are allowed in URL segments as they have a special meaning. If you want
to send larger or more complex items you would use the HTTP requests body. We want to support
both methods of sending data to our web service.

~ Add a PUT handler to the WebModule unit, with method type mtPut.

Figure 8: Actions

Then code the handler


procedure TWebModule1.WebModule1WebActionItemKeyValuePUTAction(
Sender: TObject; Request: TWebRequest; Response: TWebResponse;
var Handled: Boolean);
{PUT - "Insert or Update" / Idempotent}
var
lParameters: TStringDynArray;
lKey: string;
lValue: string;
begin
lParameters := GetParameters((Sender as TWebActionItem).PathInfo, Request.PathInfo);
if (Length(lParameters) > 0) then
begin
lKey := lParameters[0];
lValue := '';
if (Length(lParameters) > 1) then
begin {Value is part or URL and a simple string}
lValue := lParameters[1]
end
else
begin {Value is send as content in the request and possibly a JSON or other complex string}
lValue := Request.Content;
end;
if not(lValue.IsEmpty) then
begin
Response.ContentType := 'application/json; charset=UTF-8';
gKeyValueStore.AddOrSetValue(lKey, lValue);
Response.Content := ' {"result":[]}';
Handled := True;
end
else
begin
Handled := False;
end;
end
else
begin
{Do not reply}
Handled := False;
end;
end;

Blaise Pascal Magazine 93 2021 90


WEB SERVICE PART 2 - STORAGE THE DELPHI COMPANY Page 8/12
-est 1998-

Now test this new PUT method and insert


some data into your webservice using the
REST Debugger. Figure 9: Result

And request the new item to see if it was


saved correctly.

Figure 10: Result One

Blaise Pascal Magazine 93 2021 91


WEB SERVICE PART 2 - STORAGE THE DELPHI COMPANY Page 9/12
-est 1998-

At first glance the result might seem odd, but


that is because the result in this case is
returned as a JSON array, and the first item of
an array has index 0. If you look at it in the
REST debugger you’ll see that this is valid
JSON.

Figure 11: Result One

We will do the same for POST. We add a


handler and use method type mtPOST.

Figure 12: Post

Blaise Pascal Magazine 93 2021 92


WEB SERVICE PART 2 - STORAGE THE DELPHI COMPANY Page 10/12
-est 1998-

And the code


procedure TWebModule1.WebModule1WebActionItemKeyValuePOSTAction(
Sender: TObject; Request: TWebRequest; Response: TWebResponse;
var Handled: Boolean);
{POST - "Update"}
var
lParameters: TStringDynArray;
lKey: string;
lValue: string;
begin
lParameters := GetParameters((Sender as TWebActionItem).PathInfo, Request.PathInfo);
if (Length(lParameters) > 0) then
begin
lKey := lParameters[0];
lValue := '';
if (Length(lParameters) > 1) then
begin {Value is part or URL and a simple string}
lValue := lParameters[1]
end
else
begin {Value is send as content in the request and possibly a JSON or other complex string}
lValue := Request.Content;
end;

if not(lValue.IsEmpty)
then
begin
Response.ContentType := 'application/json; charset=UTF-8';
gKeyValueStore[lKey] := lValue;
Response.Content := ' {"result":[]}';
Handled := True;
end
else
begin
Handled := False;
end;
end
else
begin
{Do not reply}
Handled := False;
end;
end;

Test it with the REST Debugger. First add an


item with Key 1 and Value One and then
update this existing item using POST, changing
the Value to something other than One. In my
example I used Een, which is the dutch word
for One. You probably never guessed you’d
learn a dutch word from reading this article.

Blaise Pascal Magazine 93 2021 93


WEB SERVICE PART 2 - STORAGE THE DELPHI COMPANY Page 11/12
-est 1998-

Figure 13: Post


And a request in the web browser to verify it
worked.

Figure 14: Result: Een

At this point you may have already run into a Our last HTTP Command will be the
potential issue we just introduced when DELETE. Just add it to the handlers as
adding the POST method. What happens if you before, this time with mtDELETE.
try to POST a Value for a non-existing key?

Just try it out with the REST Debugger.


We need to improve on this, but we will do so
in our next article.

Blaise Pascal Magazine 93 2021 94


WEB SERVICE PART 2 - STORAGE THE DELPHI COMPANY Page 12/12
-est 1998-

Figure 15: mtDelete

The code is straightforward:


procedure TWebModule1.WebModule1WebActionItemKeyValueDELETEAction(Sender: TObject; Request: TWebRequest;
Response: TWebResponse; var Handled: Boolean);
DELETE - "Delete"}
var
lParameters: TStringDynArray;
lKey: string;
begin
lParameters := GetParameters((Sender as TWebActionItem).PathInfo, Request.PathInfo);
if (Length(lParameters) > 0) then
begin
lKey := lParameters[0];
gKeyValueStore.Remove(lKey);
Response.ContentType := 'application/json; charset=UTF-8';
Response.Content := '{"result":[]}';
Handled := True;
end
else {No parameters on URL for GET request}
Handled := False;
end;

You may have noticed that we left out URL query As a teaser we also added a gLock object, but
parameter parsing in the PUT, POST and we did not actually write any code for it. We
DELETE. This was intentional, as using URL will do that in our next article, where we’ll add
segment parameters is the preferred method for some code to make sure any access to our in-
a REST web service. However due to the memory Key Value store is handled in a thread
limitations of URL segment parameters, you safe manner. In that next article we will also
may wish to add URL query parameters for the add error handling and of course expand our
PUT/POST and DELETE as well. This could be Web Service client to consume our web
done quite easily with a duplicate of the sample service. There might even be some JavaScript
code from the GET request handler. code to consume our web service and further
on some additional JSON serialization. Stay
A short recap of the things we have done in this tuned!
article. We created a GET request that correctly
parses both URL query parameters and URL
segment parameters and returns a value from
the in-memory Key Value store. We also created
PUT and POST requests that handle passing
content as part of the URL segment, for short
values, as well as from the HTTP content
stream, for larger more complex values.

Blaise Pascal Magazine 93 2021 95


ADVERTISEMENT
Advertisement

L I B R A R Y 2 0 2 0

89
90
87
88
86
85 51 52 53
84 50 54
49 55 26 27 28
83 29 25
48 56
81 30
24
82 47 9 10 11 57
12 31
80 46 23 8 1
2 13 32 58
78 22 7 3
79 45 14 33
21 4 59
77 44 6
20 5 15 34
75 60
76 43 19 16 35
18 17 61
73 42 36
74
41 37 62
72 40 39 38
71 69 63
70 67 64
68 66 65

ALL CODE ABOUT THE USE

BLAISE PASCAL MAGAZINE


ALL ISSUES IN ONE FILE

Editor in Chief: Detlef Overbeek


BLAISE PASCAL MAGAZINE Edelstenenbaan 21 3402 XA
IJsselstein Netherlands
BLAISE PASCAL MAGAZINE

procedure procedure
var var
begin begin
for I := 1 to 9 do for I := 1 to 9 do
begin Prof Dr.Wirth, Creator of Pascal Programming language begin
... ...
end end
end; end;
Prof Dr.Wirth, Creator of Pascal Programming language Blaise Pascal, Mathematician
[email protected] Prof Dr.Wirth, Creator of Pascal Programming language Blaise Pascal, Mathematician
https://www.blaisepascalmagazine.eu

1 year Subscription+
the new LibStick
(on USB Card - 90 Issues)
€ 70
ex vat / inc. shipment
ORM in kbmMW #3 – Copying a table from one database to another Page 1/4
By Kim Bo Madsen

Surfacing a table means that the ORM gathers


PREFACE very detailed information about the table
In 5.15.xx kbmMW’s ORM got even better since structure, indexes, generators, constraints etc.
it allow us to easily copy table structure and and provide us with a TkbmMWORMTable
data from one table in one database to another instance that we can use for accessing that
database. table via the ORM.
In fact enough detail is collected to be able to
THE TABLE STRUCTURE reproduce the table (within the scope of the
ORM tables can be defined in a couple of ways, ORM) elsewhere, which we utilize by asking
where a usual way is to define a Delphi class the ORM to generate the Delphi code for us for
and provide attributes for it that makes the class that particular surfaced table using the
a template for a table in the ORM, which in turn GenerateDelphiClass method.
then can be used to automatically create a table The output of the calling the method with the
in the datastore which the current ORM is table name TBLNEWS looks like this
connected to. interface

uses
But what if the table in the database do not exist DB, Math, Classes, System.Generics.Collections,
as a Delphi class? Well the ORM is fortunately kbmMWGlobal, kbmMWObjectMarshal, kbmMWNullable,
kbmMWORM, kbmMWRTTI;
able to create one for us, based on just about
any existing table in any of the supported type
databases. [kbmMW_Table('name:TBLNEWS')]
TTBLNEWS = class
procedure TForm1.CreateDelphiClass(const ATableName:string; const AStrings:TStrings);
var
t:TkbmMWORMTable;
begin
t:=FORMSrc.SurfaceDynamicTable(ATableName,[mwsdtoPromoteFieldDefaultsAsGenerators]);
if t<>nil then
AStrings.Text:=FORMSrc.GenerateDelphiClass(t,[mwocgoNoSchemaNameInClassName]);
end;

private
The above code shows how to easily have the FAUTOINC:integer;
ORM, at runtime, generate the needed Delphi FGROUPNO:kbmMWNullable<integer>;
code that describes a table, and thus can be FARTICLENO:kbmMWNullable<integer>;
FPARENTNO:kbmMWNullable<string>;
used for creating tables in all sorts of ORM FTHREADNO:kbmMWNullable<string>;
connected databases. FCLIENTDATE:TkbmMWDateTime;
FSERVERDATE:TkbmMWDateTime;
FDATESTR:kbmMWNullable<string>;
In the above example, FORMSrc is a FNUMLINES:kbmMWNullable<integer>;
variable/field of type TkbmMWORM, which has FNUMBYTES:kbmMWNullable<integer>;
FCONTENTTYPE:kbmMWNullable<string>;
been connected to a connection pool, that FCANCELLED:word;
represents the database. FMAILFROM:kbmMWNullable<string>;
FFROMADDRESS:kbmMWNullable<string>;
FORMSrc:=TkbmMWORM.Create(cpSrc); FREPLYTONAME:kbmMWNullable<string>;
FREPLYTOADDRESS:kbmMWNullable<string>;
chSrc is the connection pool, defined at FSUBJECT:kbmMWNullable<string>;
designtime, and in this case hooked up to a FMESSAGEID:kbmMWNullable<string>;
FNREFERENCES:kbmMWNullable<string>;
FireDAC database instance connected to an FHEADER:kbmMWNullable<string>;
old Firebird 1.5 database (which happens to FBODY:kbmMWNullable<string>;
be our old newsgroup database). FLASTTHREADPOST:TkbmMWDateTime;
FLASTTHREADPOSTNO:kbmMWNullable<integer>;
FLASTTHREADPOSTFROMNAME:kbmMWNullable<string>;
All we need to do is to ask the ORM to surface FTOTALTHREADPOSTS:kbmMWNullable<integer>;
the table based on the table name, and then FTOTALREPLIES:kbmMWNullable<integer>;
FAPPROVED:word;
produce the class for that table. FIPADDR:kbmMWNullable<string>;

Blaise Pascal Magazine 93 2021 COMPONENTS


DEVELOPERS 4 97
ORM in kbmMW #3 – Copying a table from one database to another Page 2/4
By Kim Bo Madsen
public
[kbmMW_Field('name:AUTOINC, primary:true', ftInteger)]
[kbmMW_NotNull]
property AUTOINC:integer read FAUTOINC write FAUTOINC;

[kbmMW_Field('name:GROUPNO', ftInteger)]
property GROUPNO:kbmMWNullable<integer> read FGROUPNO write FGROUPNO;

[kbmMW_Field('name:ARTICLENO', ftInteger)]
property ARTICLENO:kbmMWNullable<integer> read FARTICLENO write FARTICLENO;

[kbmMW_Field('name:PARENTNO', ftMemo)]
property PARENTNO:kbmMWNullable<string> read FPARENTNO write FPARENTNO;

[kbmMW_Field('name:THREADNO', ftMemo)]
property THREADNO:kbmMWNullable<string> read FTHREADNO write FTHREADNO;

[kbmMW_Field('name:CLIENTDATE', ftDate)]
property CLIENTDATE:TkbmMWDateTime read FCLIENTDATE write FCLIENTDATE;

[kbmMW_Field('name:SERVERDATE', ftDate)]
property SERVERDATE:TkbmMWDateTime read FSERVERDATE write FSERVERDATE;

[kbmMW_Field('name:DATESTR', ftString, 50)]


property DATESTR:kbmMWNullable<string> read FDATESTR write FDATESTR;

[kbmMW_Field('name:NUMLINES', ftInteger)]
property NUMLINES:kbmMWNullable<integer> read FNUMLINES write FNUMLINES;

[kbmMW_Field('name:NUMBYTES', ftInteger)]
property NUMBYTES:kbmMWNullable<integer> read FNUMBYTES write FNUMBYTES;

[kbmMW_Field('name:CONTENTTYPE', ftString, 50)]


property CONTENTTYPE:kbmMWNullable<string> read FCONTENTTYPE write FCONTENTTYPE;

[kbmMW_Field('name:CANCELLED', ftSmallInt)]
[kbmMW_NotNull]
property CANCELLED:word read FCANCELLED write FCANCELLED;

[kbmMW_Field('name:MAILFROM', ftString, 100)]


property MAILFROM:kbmMWNullable<string> read FMAILFROM write FMAILFROM;

[kbmMW_Field('name:FROMADDRESS', ftString, 100)]


property FROMADDRESS:kbmMWNullable<string> read FFROMADDRESS write FFROMADDRESS;

[kbmMW_Field('name:REPLYTONAME', ftString, 100)]


property REPLYTONAME:kbmMWNullable<string> read FREPLYTONAME write FREPLYTONAME;

[kbmMW_Field('name:REPLYTOADDRESS', ftString, 100)]


property REPLYTOADDRESS:kbmMWNullable<string> read FREPLYTOADDRESS write FREPLYTOADDRESS;

[kbmMW_Field('name:SUBJECT', ftString, 180)]


property SUBJECT:kbmMWNullable<string> read FSUBJECT write FSUBJECT;

[kbmMW_Field('name:MESSAGEID', ftString, 180)]


property MESSAGEID:kbmMWNullable<string> read FMESSAGEID write FMESSAGEID;

[kbmMW_Field('name:NREFERENCES', ftMemo)]
property NREFERENCES:kbmMWNullable<string> read FNREFERENCES write FNREFERENCES;

[kbmMW_Field('name:HEADER', ftMemo)]
property HEADER:kbmMWNullable<string> read FHEADER write FHEADER;

[kbmMW_Field('name:BODY', ftMemo)]
property BODY:kbmMWNullable<string> read FBODY write FBODY;

[kbmMW_Field('name:LASTTHREADPOST', ftDate)]
property LASTTHREADPOST:TkbmMWDateTime read FLASTTHREADPOST write FLASTTHREADPOST;

[kbmMW_Field('name:LASTTHREADPOSTNO', ftInteger)]
property LASTTHREADPOSTNO:kbmMWNullable<integer> read FLASTTHREADPOSTNO write FLASTTHREADPOSTNO;

[kbmMW_Field('name:LASTTHREADPOSTFROMNAME', ftString, 180)]


property LASTTHREADPOSTFROMNAME:kbmMWNullable<string> read FLASTTHREADPOSTFROMNAME write FLASTTHREADPOSTFROMNAME;

[kbmMW_Field('name:TOTALTHREADPOSTS', ftInteger)]
property TOTALTHREADPOSTS:kbmMWNullable<integer> read FTOTALTHREADPOSTS write FTOTALTHREADPOSTS;

[kbmMW_Field('name:TOTALREPLIES', ftInteger)]
property TOTALREPLIES:kbmMWNullable<integer> read FTOTALREPLIES write FTOTALREPLIES;

[kbmMW_Field('name:APPROVED', ftSmallInt)]
[kbmMW_NotNull]
property APPROVED:word read FAPPROVED write FAPPROVED;

[kbmMW_Field('name:IPADDR', ftString, 64)]


property IPADDR:kbmMWNullable<string> read FIPADDR write FIPADDR;

end;
implementation

initialization

TkbmMWRTTI.EnableRTTI([TTBLNEWS, TObjectList<TTBLNEWS>]);
kbmMWRegisterKnownClasses([TTBLNEWS, TObjectList<TTBLNEWS>]);

Blaise Pascal Magazine 93 2021 COMPONENTS


DEVELOPERS 4 98
ORM in kbmMW #3 – Copying a table from one database to another Page 3/4

Obviously we can simply use


FORMDst.CreateOrUpgradeTable(TTBLNEWS);

to create the table structure in a different


database, pointed to by the FORMDst
TkbmMWORM instance.
After that we can copy the data over.
However we can do it even simpler, without
the need to compile an application containing
our specific TTBLNEWS class.
tSrc:=FORMSrc.SurfaceDynamicTable(ATableName,[mwsdtoPromoteFieldDefaultsAsGenerators]);
if tSrc<>nil then
begin
// If source table surfaced, clone it to the destination ORM.
tDst:=tSrc.Clone(FORMDst);
FORMDst.CreateOrUpgradeTable(tDst);
end;

Again we surface the original table, but this


time we do not create a Delphi class. Instead procedure TForm1.MoveTable(const ATableName:string);
var
we ask the ORM to clone the TkbmMWORMTable tSrc,tDst:TkbmMWORMTable;
instance onto another ORM (FORMDst) ds:TkbmMWCustomPooledCursor;
connected to another database. ls:IkbmMWORMQueryStage<TkbmMWORMQueryStageTable>;
begin
As the FORMDst ORM now knows about our // Check if destination table exists, then drop it.
table, we can directly use it to tDst:=FORMDst.SurfaceDynamicTable(ATableName,
CreateOrUpgradeTable , and thus very easily [mwsdtoPromoteFieldDefaultsAsGenerators]);
if tDst<>nil then
have copied the table structure completely FORMDst.DeleteTable(tDst);
dynamically without linking in any Delphi
classes describing the tables. // Now create table from source.
tSrc:=FORMSrc.SurfaceDynamicTable(ATableName,
THE DATA [mwsdtoPromoteFieldDefaultsAsGenerators]);
if tSrc<>nil then
Now all that is missing is copying the data. begin
This can fortunately also be done easily. // If source table surfaced, clone it to the destination ORM.
Simply query the source ORM , make sure that tDst:=tSrc.Clone(FORMDst);
FORMDst.CreateOrUpgradeTable(tDst);
the data is marked as to be inserted and
persist the data in the destination ORM. // Copy data.
ls:=FORMSrc.Using(tSrc).
AsInserted.Batched.Query([],mwoqoEQ);
And in our case, try to move the data in repeat
batches, to avoid loading loads of records into ds:=TkbmMWCustomPooledCursor(ls.AsDataset);
memory. This is not important for smaller if ds<>nil then
FORMDst.PersistDataset(tDst,ds);
tables (few tens of thousands of records), until ds=nil;
but for a very large amount of records, end;
using the new batch features in kbmMW v. end;
5.15.xx may be of good assistance.

NOTICE though that I have had limited success


getting FireDAC to actually not fetching all data
from the Firebird 1.5 database, so even if
kbmMW may batch, any DB API may not always
do it.
A final MoveTabl e method could look like this

Blaise Pascal Magazine 93 2021 COMPONENTS


DEVELOPERS 4 99
ORM in kbmMW #3 – Copying a table from one database to another Page 4/4

In this case we first check to see if the PROLOGUE


destination database already contains a table The above demonstrates one new ORM feature
with same name. If so, we delete it. You may in 5.15.xx .
not like to do that and could thus simply avoid
the call to DeleteTable. Another new feature in v. 5.15.xx is that it is
able to understand partial Firebird/Interbased
Next we establish information about the intermediate language (BLR) and thus able to
source table and clone it to the destination determine if default column values has been
ORM after which we ask the ORM to ensure that defined and which they are, as long as they
a compatible table with that name and have been defined to a constant.
structure exists or will be made to exist on the
database represented by the destination ORM.

Finally we use a new 5.15.xx feature allowing


us to query records and have them returned
ready for insert elsewhere, and in a batched
mode in the following statement
ls:=FORMSrc.Using(tSrc).AsInserted.Batched.Query([],mwoqoEQ);

We use the fluid variant of the query syntax to


ask for data from the source table, matching
any key value, returned ready for insertion,
and we only want a batch at a time. A batch is
currently 100 records and as is not
configurable.

When we execute the line


ds:=TkbmMWCustomPooledCursor(ls.AsDataset);

we will be given a batch, or if there are no


more batches the value nil will be returned to
us.

While ds has a value we persist the dataset


using the destination ORM, and loop until we
get the value nil at which point no more
records can be copied.

Do not free the returned ds instance. That is


entirely handled internally by the ORM query
stage logic when it goes out of scope.

Blaise Pascal Magazine 93 2021 COMPONENTS


DEVELOPERS 4 100
The Bumble Bee...
COMPONENTS
DEVELOPERS 4
Bumblebees are in danger in many developed
countries due to habitat destruction and collateral
pesticide damage. The European Food Safety
Authority ruled that three neonicotinoid pesticides
(clothianidin, imidacloprid, and thiamethoxam)
presented a high risk for bees. While most work on
neonicotinoid toxicity has looked at honeybees,
a study on B. terrestris showed that "field-realistic"
levels of imidacloprid significantly reduced growth
rate and cut production of new queens by 85%,
implying a "considerable negative effect" on wild
bumblebee populations throughout the developed
world. However, in another study, following chronic
exposure to field-realistic levels of the
neonicotinoid pesticide thiamethoxam, colony
weight gain was not affected, nor were the number
or mass of sexuals produced.
By Panoramedia - Own work, CC BY-SA 3.0,
https://commons.wikimedia.org/w/index.php?curid=20441726
Low levels of neonicotinoids can reduce the number
POPULATION DECLINE of bumblebees in a colony by as much as 55%,
Bumblebee species are declining in Europe, North and cause dysfunction in the bumblebees' brains. The
America, and Asia due to a number of factors, Bumblebee Conservation Trust considers this
including land-use change that reduces their food evidence of reduced brain function "particularly
plants. In North America, pathogens are possibly alarming given that bumblebees rely upon their
having a stronger negative effect especially for the intelligence to go about their daily tasks.“
subgenus Bombus. A study on B. terrestris had results
A major impact on bumblebees was BOMBUS BALTEATUS, that suggests that use of
caused by the mechanisation of neonicotinoid pesticides can affect
agriculture, accelerated by the urgent BOMBUS TERRICOLA, how well bumblebees are able to
need to increase food production during BOMBUS AFFINIS, forage and pollinate.
the Second World War. Bee colonies that had been
Small farms depended on horses to BOMBUS OCCIDENTALIS, affected by the pesticide
pull implements and carts. ARE IN SERIOUS DECLINE released more foragers and
The horses were fed on clover collected more pollen than bees
and hay, both of which were permanently grown on a who had not been dosed with neonicotinoid. Although
typical farm. Little artificial fertiliser was used. the bees affected by the pesticide were able to collect
Farms thus provided flowering clover and flower-rich more pollen, they took a longer amount of time doing
meadows, favouring bumblebees. so.
Mechanisation removed the need for horses and most
of the clover; artificial fertilisers encouraged the Of 19 species of native nestmaking bumblebees and
growth of taller grasses, outcompeting the meadow six species of cuckoo bumblebees formerly
flowers. Most of the flowers, and the bumblebees that widespread in Britain, three have been extirpated,
fed on them, disappeared from Britain by the early eight are in serious decline, and only six remain
1980s. widespread. Similar declines have been reported in
The last native British short-haired bumblebee was Ireland, with four species designated endangered,
captured near Dungeness in 1988. The significant and another two considered vulnerable to extinction.
increase in pesticide and fertilizer use associated with A decline in bumblebee numbers could cause large-
the industrialization of agriculture has had adverse scale changes to the countryside, resulting from
effects on the genus Bombus. inadequate pollination of certain plants.
The bees are directly exposed to the chemicals in two
ways: by consuming nectar that has been directly Some bumblebees native to North America are also
treated with pesticide, or through physical contact vanishing, such as Bombus balteatus, Bombus
with treated plants and flowers. terricola, Bombus affinis, and Bombus occidentalis,
The species Bombus hortorum in particular has been and one, Bombus franklini, may be extinct.
found to be impacted by the pesticides; In South America, Bombus bellicosus was extirpated
their brood development has been reduced and their in the northern limit of its distribution range, probably
memory has been negatively affected. Additionally, due to intense land use and climate change effects.
pesticide use negatively impacts colony development
and size.
Blaise Pascal Magazine 93 2021 COMPONENTS
DEVELOPERS 4 101
KBMMW PROFESSIONAL AND ENTERPRISE EDITION
V. 5.14 RELEASED!
· New HTTP and kbmMW server status message handling
● RAD Studio XE5 to 10.4.1 Sydney supported support in Smart services
● Win32, Win64, Linux64, Android, IOS 32, IOS 64 and · New support for TkbmMWGenericMagneticStripeReaderHID
OSX client and server support and TkbmMWGenericBarcodeReaderHID
● Native high performance 100% developer defined
application server · New support for pivot based counters in the ORM
● Full support for centralized and distributed load · New support for transport native file sending for HTTP.Sys
balancing and failover transport
● Advanced ORM/OPF support including support of
existing databases
· New support for automatic GZIP compression of responses
from HTTP Smart services
● Advanced logging support
● Advanced configuration framework · Several feature improvements and fixes.
● Advanced scheduling support for easy access to
multithread programming · More features improvements and fixes.
● Advanced smart service and clients for very easy
publication of functionality Please visit
● High quality random functions. http://www.components4developers.com
● High quality pronouncable password generators. for more information about kbmMW
● High performance LZ4 and Jpeg compression
● Complete object notation framework including full
● High speed, unified database access (35+ supported
support for YAML, BSON, Messagepack, JSON and XML
database APIs) with connection pooling, metadata and
● Advanced object and value marshalling to and from
data caching on all tiers
YAML, BSON, Messagepack, JSON and XML
● Multi head access to the application server, via REST/AJAX,
● High performance native TCP transport support
native binary, Publish/Subscribe, SOAP,
● High performance HTTPSys transport for Windows.
XML, RTMP from web browsers, embedded devices, linked
● CORS support in REST/HTML services.
application servers, PCs, mobile devices, Java systems
● Native PHP, Java, OCX, ANSI C, C#, Apache Flex client
and many more clients
support!
● Complete support for hosting FastCGI based applications
kbmMemTable is the fastest and most feature rich in (PHP/Ruby/Perl/Python typically)
memory table for Embarcadero products. ● Native complete AMQP 0.91 support (Advanced Message
● Easily supports large datasets with millions of records Queuing Protocol)
● Easy data streaming support ● Complete end 2 end secure brandable Remote Desktop with
● Optional to use native SQL engine near realtime HD video, 8 monitor support,
● Supports nested transactions and undo texture detection, compression and clipboard sharing.
● Native and fast build in M/D, aggregation/grouping, ● Bundling kbmMemTable Professional which is the fastest
range selection features and most feature rich in memory table for Embarcadero
● Advanced indexing features for extreme performance products.

COMPONENTS
DEVELOPERS 4 DX
EESB, SOA,MoM, EAI TOOLS FOR INTELLIGENT SOLUTIONS. kbmMW IS THE PREMIERE N-TIER PRODUCT FOR DELPHI / C++BUILDER

You might also like