OTAPI

Beneath the hood of RAD Studio

Delphi Cookbook Cover

31st October 2014
by Simon J Stuart
0 comments

Book Review – Delphi Cookbook by Daniele Teti

Delphi Cookbook Cover

Delphi Cookbook Cover

Full Disclosure

In the interests of transparency, I want to make it clear from the outset that I expressed an interest in reading and reviewing Delphi Cookbook, and was sent a copy free of charge from the publisher (Packt Publishing).

The only condition of this agreement was that I publish a review for Delphi Cookbook here on my blog (which is what I would have done even if I had paid for it).

With that said, the views and opinions expressed in this review are 100% genuine. While I am more than happy to review any Delphi publications (solicited or otherwise), my views and opinions are not for sale, and my reviews are always completely honest. To publish anything other than a completely honest review would be as unethical as it would be to the detriment of my reputation for sharing my honest (and blunt) opinion of any topic.

You can find Delphi Cookbook on the publisher’s website (by clicking this link)

Pre-reading: A little background on the book

At the point of writing this section of this review, I have not yet begun reading the book itself (beyond its cover page and marketing information). I feel it is important when writing a review to share any preconceptions I have based on nothing but the cover, and whatever information I have read about the book itself before I begin reading.

So, it is my understanding that Delphi Cookbook was originally going to be titled “The Delphi XE6 Cookbook”, and that the “XE6″ part was subsequently omitted (wisely) so-as not to date the book (i.e. to suggest that the book applies only to the XE6 version of Delphi).

Based on the front cover (specifically the tagline “Quick answers to common problems”), Delphi Cookbook appears to focus on teaching people how to accomplish particular goals in Delphi, rather than serving as a broader language or library reference.
This would indicate that Delphi Cookbook could serve as a good introduction to Delphi for newcomers, as well as a good way for developers migrating from much older versions of Delphi to the newer (cross-platform, FireMonkey) versions to quickly get up to speed on newer features and changes.

Cover to cover, Delphi Cookbook constitutes 328 pages… so it’s a little more than just some “light reading”, so at this point I’m hoping for a well-structured contents.

Now to begin reading…

Contents

As I had hoped, the contents illustrates a reasonable structure to the progression of the book.

There are 7 distinct chapters (each chapter broken down further into discrete topics):

  1. Delphi Basics - Covers various aspects of working with the IDE, Project Wizards, and Designers/Editors. There appear to be some code-inclusive topics within this chapter, which we’ll get to in the process of this review.
  2. Becoming a Delphi Language Ninja – As the title of this chapter suggests, the topics within cover various aspects of the Delphi Language, including “anonymous methods”, “enumerable types”, the enhanced RTTI (introduced in Delphi 2010), “Class Helpers” and String (with Regular Expressions).
  3. Going Cross Platform with FireMonkey – Covers FireMonkey topics such as styles, composited controls, animations, LiveBindings, vectors and paths and intermixing FireMonkey with VCL Applications (I sure hope he mentions my MonkeyMixer plugin within this topic)
  4. The Thousand Faces of Multithreading – Covers various aspects of working with Threads in Delphi (Synchronizing, thread-safety etc)
  5. Putting Delphi on the Server – Covers producing network/web services and client-side consumers using WebBroker, JSON, HTTP POST, RESTful interfaces, UDP, DataSnap and App Tethering.
  6. Riding the Mobile Revolution with FireMonkey – Builds on chapter 3 by showing how to make FireMonkey applications for mobile devices (iOS and Android)
  7. Useing Specific Platform Features - Explains how to exploit platform-specific features such as Android SDK Java classes, Objective-C SDK classes, and even using Android’s Text-To-Speech engine.

As one would expect, there’s also an Index at the end of the book.

 Post-read summary

Having now read the book (which took me a week, reading casually… one chapter per day) I’m now ready to render verdicts on various aspects of the book.

The overall format of the book makes for easy reading.

The book is prefaced by defining the structure and formatting, so you know right from the start when you’re looking at a code block, which segments of a code block are of particular note (these are printed in bold text), when you’re looking at a command-line input or output, where to find warnings, note and tips, and how instructions (and similar important steps in a process) are defined.

Better still, all of the sample projects used to illustrate the various techniques and topics covered in Delphi Cookbook are available to download, so you can easily load the related demo in the IDE and follow along using the code editor and form designer (which saves having to copy all of the code snips from the book to produce the working demo).

Contact information is provided for asking questions, leaving feedback, or pointing out any errors you may find in the book (no such errors jumped out at me in reading the book, however)

The arrangement of the book is useful for those either new to Delphi, or making a leap from a significantly older version to one of the newer (cross-platform) versions, as the first chapter covers the basics of the form editors. Obviously, those already possessing this knowledge can simply skip over the chapter if they choose to the bits of interest to them.
I will say, however, that there were a couple of useful IDE tips in the first chapter that even I wasn’t aware of, so in the very least a cursory scan through Chapter 1 may well be useful to everyone, even those of us with significant experience.

Screenshots are provided to show the results of anything visual.

The coverage on VCL Styles (also in Chapter 1) made for interesting reading for me, having never made use of the VCL styles features before. This was a very good test of the book in terms of how well the information was presented. I found the instructions, tips and insight into the concept of VCL styles very easy to understand, and within minutes had a little demo running with a VCL style defined, which allowed the user to switch between styles at runtime.

What I enjoy particularly about the way Delphi Cookbook is structured is that it doesn’t just dictate to the read how to do something, it goes on to explain how that something works. This information is presented at the end of each topic’s example as a bullet-point breakdown of the key steps, so if you find yourself requiring a quick reminder down the line, you can simply skim through the “How it works…” subsection and the knowledge you’ve absorbed by reading the chapter previously completes the memory for you.

Better still, the section on VCL Styles goes beyond merely consuming pre-packaged styles to explain how to produce custom styles, both pre-generated, and “owner-drawn” (drawn at runtime).  While I have previous experience working with VCL canvasses in Delphi, I had no understanding of the makeup of a VCL Style package prior to reading Delphi Cookbook…. now I do!

In terms of the structuring for each demonstration within the book, they are laid out in the following order:

  • Getting ready
  • How to do it
  • How it works
  • “There’s more” (further information building on what you’ve just learned, acting as something of a segway to something else)

In a sense, you’re starting out with a simple explanation of the problem, given a concise solution to that problem, the solution is summarized in a bullet-point form, then you build on that solution to solve a more complex problem.

This technique is very clever, as you find yourself absorbing the information in a more digestible manner.

Useful links related to each subject (where applicable) are provided in each chapter. I was pleased to see MonkeyMixer got a mention in there as well (though the associated link was to Jim McKeeth’s blog, rather than the MonkeyMixer GitHub repository, which would’ve been the more logical address)

Conclusions

While Delphi Cookbook is certainly tailored more towards developers new to Delphi (or leaping to a newer version from a significantly older one) there’s something in there for all of us. As developers, it’s important for us to always expand our knowledge beyond just what we’re making use of on a daily basis.
This was why I spent quite a bit of time reading the section on VCL styles and following along in the exact same way I would imagine a complete newcomer to Delphi would. Doing this served as an ample test of the book in accomplishing its primary objective (teaching newcomers the ropes).

Indeed, I discovered useful information in virtually every topic of every chapter, whether it be simply an alternative way of achieving something, or a feature I didn’t know existed that may well be useful to me in the future.

As I knew going in, Delphi Cookbook is not a comprehensive language reference. This is actually a good thing, as language references tend to be forbidding tomes, unfocused and generally serving the same purpose as the Wiki (search the index to find the declaration and definition of a type or method within a large code framework).

Daniele Teti has done a brilliant job of covering each topic thoroughly, while keeping the descriptions and explanations concise and on-point (something I often struggle to do, as you’ve probably noticed if you’ve read my other articles).

The structuring of topics (which I’ve already praised in this review) is clean, logical and flawless.

In terms of the primary objective of Delphi Cookbook, having approached the topic of VCL Styles as a complete newcomer, and learned much in so doing, I have to conclude that this objective is achieved superbly.

The copy I have read has been the PDF eBook, which has the advantage that you can click on a chapter or section title within the contents to navigate directly to that page. This is very useful when you want to refer back to something you’ve read in the book (perhaps to refresh your memory) quickly and easily.

Would I recommend Delphi Cookbook?

In short: yes! Whether you’re entirely new to Delphi XE5 through XE7, or a seasoned veteran, you’re almost sure to learn something new from Delphi Cookbook.

Certainly, those with less Delphi experience will benefit more from this book than those with more experience, however we should all know that no one of us is a master of all things, and it is my belief that – as developers – we should always strive to learn more. Every day should be a learning experience, and Delphi Cookbook‘s clean (logical) structuring makes absorbing the knowledge contained in its pages intuitive.

Definitely one to have in the library!

TLKPrecisionThread Properties

23rd October 2014
by Simon J Stuart
0 comments

Threading Evolved… again – High Precision Thread as a Component

LKSL

This article uses the LaKraven Studios Standard Library[LKSL]. If you wish to follow along with the code snips provided herein, you should download the latest version from the GitHub repository, and run the LKSLInstaller.exe program to configure the RAD Studio IDE so that you can easily use the LKSL units in your programs.

You will also need to install the Component Package provided within that same repository.

Introduction

In a previous article, I delved into the world of High Precision Threads as defined by the LaKraven Studios Standard Library.

I won’t repeat the entire article here (because you can read the original article for that) but as a brief summary, the article explained and demonstrated a special kind of Thread, designed to provide incredibly high-precision interpolation and extrapolation for a looped Threaded process.

Well, I have now added something new to the LKSL, which makes exploiting this special form of Threading much easier…

TLKPrecisionThread Component

When you install the Component Package provided within the LKSL repository, you’ll see a new entry on the component pallet called [LKSL] Threads.

TLKPrecisionThread Pallet

TLKPrecisionThread Pallet

TLKPrecisionThread works on both VCL and FireMonkey projects, on all platforms presently supported by Delphi: Win32, Win64, Mac, iOS and Android.

When you drop a TLKPrecisionThread component on a Form (or Data Module) you can simply double-click on that instance to implement an OnTick event.

Because TLKPrecisionThread is a Component intended to serve as an alternative to TTimer with numerous advantages over TTimer, and operating on a principal of Ticks Per Second rather than an Interval, the OnTick event callback is synchronized on the UI thread by design. If you don’t want the OnTick call to be synchronized, then you should implement a custom descendant of TLKThread entirely in code (as demonstrated in the previous article).

Properties

TLKPrecisionThread Properties

TLKPrecisionThread Properties

As you can see from this image (above), most of the Properties are read-only. This is because they provide calculated metrics for the performance of the Thread.

TickRateAverageOver, TickRateDesired and TickRateLimit are read-write properties, which influence the way the Thread operates, thus the way the metrics are calculated.

The properties represent (verbatim) their counterpart properties from TLKThread (and are discussed in more detail in the previous article).

The Active property toggles the Thread on and off (just like TTimer). The implementation is designed to prevent the Active property from initiating the Thread at design-time (otherwise the IDE will eat up an entire CPU core, which would be a bad thing).

Something to be careful of

If your TLKPrecisionThread instance communicates directly with a Form, Module, or other components thereon… you may wish to add an OnClose implementation to deactivate the TLKPrecisionThread instance to prevent OnTick from executing at the same time as the destructor.

Summary

In short, TLKPrecisionThread functions as a Threaded Timer, allowing you to specify the number of Ticks (or “iterations”) per second at which you would like it to operate. A Tick Rate Limit of 0 (zero) instructs the Thread to operate as quickly as it physically can, unlike TTimer‘s Interval property (where a setting of zero effectively disables the timer entirely).

If you require a simple alternative to TTimer which provides vastly superior precision, and provides useful performance metrics, TLKPrecisionThread is going to be useful to you.

Questions and feedback are always appreciated, and thanks for reading!

Multi-Touch Playground - Moving Controls

13th October 2014
by Simon J Stuart
1 Comment

Working with Multi-Touch Input in Delphi XE7 (Part 2)

Previously…

In the first part of this series of articles, we took a look at how the OnTouch event introduced in XE7 works, and discovered some potential stumbling blocks when it comes to taking advantage of this new feature.

In this part of the series, we’re going to look at potential “workarounds” for these problems; alternative (albeit slightly more complicated) methods of harnessing multi-touch input information for practical purposes in Delphi applications.

Another “quirk” in the way XE7’s Multi-Touch Input Handler Works

Since posting the first article in this series, I have conducted many more tests, and discovered that it continues to track Touch Move and Touch Up events even after one or more Touch Points leave the constraints of your Form.

Now, this shouldn’t necessarily be considered a “bug” or even a problem, as it means we can (in theory anyway) use multi-touch input to perform “drag and drop” operations on Windows (possibly also Mac) beyond the constraints of your Form(s).

It is, of course, fairly trivial to determine whether or not a Touch Point is inside the constraints of your Form.

I just wanted to share this observation for the benefit of others, as it may just effect the way you work with multi-touch input in your applications.

Detecting when a Multi-Touch Input Event Begins and Ends

We previously discovered that the Touch Down action seems to occur once for each additional Touch Point (finger) introduced to the touch screen (effectively making that action “re-entrant”), yet the Touch Up action doesn’t necessarily occur separately for each Touch Point removed from the touch screen.

So, since the OnTouch event behaves in a somewhat-inconsistent way, we need an inventive solution to decide when a multi-touch input event begins and ends.

Since we know that a multi-touch input event will begin with a Touch Down action, we can define a Boolean member to act as a “flag”. Also, we can say with relative certainty that a multi-touch input event will end either with a Touch Up action, or a Touch Cancel action, and I’ve determined that, where it ends with a Touch Up action, that action will contain either one or zero items in the Touch Point array (Touches parameter).

This means we have a logical principle on which to base our multi-touch input event detection.

unit Unit2;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls;

type
  TForm2 = class(TForm)
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormTouch(Sender: TObject; const Touches: TTouches; const Action: TTouchAction);
  private
    FTouching: Boolean;
    FTouchHistory: Array of TTouches;
    procedure TouchNone(Sender: TObject; const Touches: TTouches);
    procedure TouchUp(Sender: TObject; const Touches: TTouches);
    procedure TouchDown(Sender: TObject; const Touches: TTouches);
    procedure TouchMove(Sender: TObject; const Touches: TTouches);
    procedure TouchCancel(Sender: TObject; const Touches: TTouches);
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.fmx}

procedure TForm2.FormCreate(Sender: TObject);
begin
  FTouching := False;
end;

procedure TForm2.FormTouch(Sender: TObject; const Touches: TTouches; const Action: TTouchAction);
begin
  case Action of
    TTouchAction.None: TouchNone(Sender, Touches);
    TTouchAction.Up: TouchUp(Sender, Touches);
    TTouchAction.Down: TouchDown(Sender, Touches);
    TTouchAction.Move: TouchMove(Sender, Touches);
    TTouchAction.Cancel: TouchCancel(Sender, Touches);
  end;
end;

procedure TForm2.TouchCancel(Sender: TObject; const Touches: TTouches);
begin
  FTouching := False;
  Label1.Text := 'Touch Cancelled!';
end;

procedure TForm2.TouchDown(Sender: TObject; const Touches: TTouches);
begin
  if (not FTouching) then
  begin
    FTouching := True;
    Label1.Text := Format('Touch Points: %d', [Length(Touches)]);
  end;
end;

procedure TForm2.TouchMove(Sender: TObject; const Touches: TTouches);
begin
  Label1.Text := Format('Touch Points: %d', [Length(Touches)]);
end;

procedure TForm2.TouchNone(Sender: TObject; const Touches: TTouches);
begin
  // I genuinely don't know what this is for!
end;

procedure TForm2.TouchUp(Sender: TObject; const Touches: TTouches);
begin
  if (FTouching) then
  begin
    if Length(Touches) <= 1 then
    begin
      FTouching := False;
      Label1.Text := 'Not Touching';
    end else
      Label1.Text := Format('Touch Points: %d', [Length(Touches)]);
  end;
end;

end.

This code snip (above) works on Win32, Win64, Mac, Android and iOS. It illustrates a way of determining when an individual multi-touch input event begins and ends (in this case, by displaying the current “Touch State” on a TLabel control on the Form).

Pay special attention to the TouchUp procedure, which uses a simple if statement to determine whether or not we should consider the multi-touch input event as completed.

Put simply, while we won’t necessarily always get a Touch Up action when each separate Touch Point is lifted from the screen, we always get at least one (assuming that we don’t get a Touch Cancel event instead, I mean), and this final Touch Up action will only ever contain either one or zero Touch Points in the Touches array.

This gives us a very simple workaround for that inconsistent behaviour, one which (according to my extensive testing, at least) appears to work 100% of the time.

The FTouching boolean member plays a fairly important role, in that it prevents TouchDown from acting in a re-entrant manner. It would be problematic (to say the least) if we allowed the TouchDown procedure to perform its function multiple times during an existing Touch Event… particularly when you consider a “drag and drop” operation as an example.

I also just want to point out that I have been completely unable to get TouchNone to occur, on any platform, under any set of circumstances. At this point, I have genuinely no idea what that particular Touch Action Type is for, or under what set of bizarre circumstances it will occur.

You can download the working demo (tidied up a lot) of this code snip here.

Something Fun: Moving Controls At Runtime (using multi-touch input)

Okay, now that we’ve solved the problem of adequately detecting when a multi-touch event starts and ends, let’s put this solution to use and make something entertaining.

What we’re going to do now is make a little “multi-touch playground” project, allowing us to drag multiple controls around the screen at the same time with individual fingers on a touch screen. At face value, this little “toy project” might not seem all that useful, however this same principal can be applied to a simultaneous drag-and-drop solution that could be useful.

 

Multi-Touch Playground - Moving Controls

Multi-Touch Playground – Moving Controls

Basically, with this demo we can simply drop a bunch of controls onto the Form, and use multi-touch input to move one or more of those controls around.

Here’s the code for this demo:

unit uMainForm;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Objects, FMX.StdCtrls;

type
  TControlTouch = record
    Control: TControl;
    Origin: TPointF;
  end;

  TfrmMain = class(TForm)
    Rectangle1: TRectangle;
    RoundRect1: TRoundRect;
    Ellipse1: TEllipse;
    Pie1: TPie;
    Label1: TLabel;
    Label2: TLabel;
    procedure FormTouch(Sender: TObject; const Touches: TTouches; const Action: TTouchAction);
  private
    FTouching: Boolean;
    FControls: Array of TControlTouch;
    function GetControlAtPoint(const APoint: TPointF): TControl;
    procedure GetControlsAtEachTouchPoint(const Touches: TTouches);
    procedure TouchEnd;
    procedure TouchNone(Sender: TObject; const Touches: TTouches);
    procedure TouchUp(Sender: TObject; const Touches: TTouches);
    procedure TouchDown(Sender: TObject; const Touches: TTouches);
    procedure TouchMove(Sender: TObject; const Touches: TTouches);
    procedure TouchCancel(Sender: TObject; const Touches: TTouches);
  public
    { Public declarations }
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.fmx}

procedure TfrmMain.FormTouch(Sender: TObject; const Touches: TTouches; const Action: TTouchAction);
begin
  case Action of
    TTouchAction.None: TouchNone(Sender, Touches);
    TTouchAction.Up: TouchUp(Sender, Touches);
    TTouchAction.Down: TouchDown(Sender, Touches);
    TTouchAction.Move: TouchMove(Sender, Touches);
    TTouchAction.Cancel: TouchCancel(Sender, Touches);
  end;
end;

function TfrmMain.GetControlAtPoint(const APoint: TPointF): TControl;
var
  I: Integer;
  LObject: TControl;
  LRect: TRectF;
begin
  Result := nil;
  for I := ChildrenCount - 1 downto 0 do
  begin
    if (Children[I] is TControl) then
      if TControl(Children[I]).HitTest then
      begin
        LObject := TControl(Children[I]);
        LRect := RectF(LObject.Position.X,
                       LObject.Position.Y,
                       LObject.Position.X + LObject.Width,
                       LObject.Position.Y + LObject.Height);
        if LRect.Contains(APoint) then
        begin
          Result := LObject;
          Break;
        end;
      end;
  end;
end;

procedure TfrmMain.GetControlsAtEachTouchPoint(const Touches: TTouches);
var
  I: Integer;
begin
  // Hold a reference to whatever controls are under each respective touch point
  SetLength(FControls, Length(Touches));
  for I := Low(Touches) to High(Touches) do
  begin
    FControls[I].Control := GetControlAtPoint(Touches[I].Location);
    FControls[I].Origin := Touches[I].Location;
  end;
end;

procedure TfrmMain.TouchCancel(Sender: TObject; const Touches: TTouches);
begin
  TouchEnd;
end;

procedure TfrmMain.TouchDown(Sender: TObject; const Touches: TTouches);
begin
  if (not FTouching) then
  begin
    FTouching := True;
    // Release any existing history
    SetLength(FControls, 0);
  end;
  GetControlsAtEachTouchPoint(Touches);
end;

procedure TfrmMain.TouchEnd;
begin
  FTouching := False;
end;

procedure TfrmMain.TouchMove(Sender: TObject; const Touches: TTouches);
var
  I: Integer;
  LDifference: TPointF;
begin
  if Length(Touches) = Length(FControls) then
  begin
    // Move the controls
    for I := Low(Touches) to High(Touches) do
      if FControls[I].Control <> nil then
      begin
        LDifference := PointF(Touches[I].Location.X - FControls[I].Origin.X,
                              Touches[I].Location.Y - FControls[I].Origin.Y);
        FControls[I].Control.Position.X := FControls[I].Control.Position.X + LDifference.X;
        FControls[I].Control.Position.Y := FControls[I].Control.Position.Y + LDifference.Y;
        FControls[I].Origin := Touches[I].Location;
      end;
  end else
    GetControlsAtEachTouchPoint(Touches);
end;

procedure TfrmMain.TouchNone(Sender: TObject; const Touches: TTouches);
begin

end;

procedure TfrmMain.TouchUp(Sender: TObject; const Touches: TTouches);
begin
  if (FTouching) and (Length(Touches) <= 1) then
    TouchEnd
  else
    GetControlsAtEachTouchPoint(Touches);
end;

end.

This code snip (above) obtains a handle on whatever control is underneath each Touch Point, and basically moves them by their respective offsets on each Touch Move event.

Please note that this demo source observes the value of each control’s HitTest property, so if you set HitTest to False, you won’t be able to drag it around (such as the two TLabel controls included in the downloadable sample)

When the number of touch points changes, it re-establishes the Array of relevant controls for each Touch Point.

As with all the other demos in this series of articles, this will work on Windows, Mac, iOS and Android.

You can download the working demo of this code snip here.

Coming up next…

In the next part of this article, we’ll take a look at solving the “Order of Contact” problem (discussed in the first part of this series) and take a look at some other fun (and useful) uses for multi-touch input.

Visit Us On Google PlusVisit Us On Youtube