Drawing a Bitmap on a Paintbox in Delphi

 none  Comments Off on Drawing a Bitmap on a Paintbox in Delphi
Oct 252016

Yes, I know, this is far from news, but since I just spent several hours trying to find out why my code didn’t work, I’ll document it here so I can look it up later.

There are various ways to draw a bitmap on a paintbox in Delphi. I’ll focus on the Windows API function StretchBlt.

  // first, get the bitmap from somewhere
  if not GetBitmap(FPreviewBmp) then

  // calculate the available size to display the bitmap
  // keeping the aspect ratio
  cnv := pb_Preview.Canvas;
  BoxWidth := pb_Preview.Width;
  BoxHeight := pb_Preview.Height;
  BmpWidth := FPreviewBmp.Width;
  BmpHeight := FPreviewBmp.Height;
  HeightFactor := BoxHeight / BmpHeight;
  WidthFactor := BoxWidth / BmpWidth;
  if HeightFactor > WidthFactor then
    Factor := WidthFactor
    Factor := HeightFactor;
  // we do not want to enlarge the picture
  if Factor > 1 then
    Factor := 1;
  // calculate size and offsets so it is shown centered
  BmpWidth := Trunc(BmpWidth * Factor);
  BmpHeight := Trunc(BmpHeight * Factor);
  BmpTop := (BoxHeight - BmpHeight) div 2;
  BmpLeft := (BoxWidth - BmpWidth) div 2;
  // set the StretchBlt mode (you basically always want COLORONCOLOR)
  SetStretchBltMode(cnv.Handle, COLORONCOLOR);
  // draw the bitmap to the paintbox
  // note that you need to use the Canvas handle of the bitmap,
  // not the handle of the bitmap itself
  Res := StretchBlt(
    cnv.Handle, BmpLeft, BmpTop, BmpWidth, BmpHeight,
    FPreviewBmp.Canvas.Handle, 0, 0, FPreviewBmp.Width, FPreviewBmp.Height,
    if not Res then begin
      err := GetLastError;
      cnv.TextOut(0, 0, Format('LastError: %d %s', [err, SysErrorMessage(err)]));

It took me hours to find out why in my original code StretchBlt failed with error code 6 (The handle is invalid). It was very simple:
StretchBlt must be passed FPreviewBmp.Canvas.Handle rather than FPreviewBmp.Handle.

After changing that, it simply worked.

Writing large INI files

 Delphi, GExperts  Comments Off on Writing large INI files
Oct 232016

INI files, once the most used way for storing program configurations, are still popular due to their simplicity. Delphi offers two ways for accessing them:

If you only want to read or write a few values, it’s fine to use TIniFile. The underlying Windows API functions have a size limit of 64 KB though, which you might or might not reach. Once you reach it, you will experience very odd behaviour. I could not find any official documentation on whether this limit has been lifted in recent versions of Windows.

TMemIniFile does not suffer from that restriction, but it has its own: First, it might have worse performance if you only read or write a few values, because it reads the full file into memory. It also ignores any comments marked by ‘;’, so writing the file back will remove these comments. (You can still use a different comment marker e.g. // or # though.) And don’t forget to call UpdateFile if you changed it! Otherwise your changes are lost.

For writing large INI files, don’t even consider using TIniFile. It takes forever! But what about TMemIniFile? It’s much faster, but is it as fast as possible? No, it’s not. Here are two methods for writing an INI file that are even faster:

  • TStringList – but only if you recreate the full file anyway and the entries are simple
  • TFastIniFile – if you want to use a 3rd party library

The GExperts Class Browser expert writes .gex files which are INI files with a different extension to store the class list it retrieved from source files. These .gex files can be large e.g. if you add the VCL directory of Delphi 2007 the resulting file is 68 KB and contains 617 entries. The class browser used to use TIniFile to read and write these files. Here are my timing results:

Writing with TIniFile took 2,368 s
Writing with TMemIniFile took 0,236 s
Writing with TMemIniFile.SetStrings took 0,005 s
Writing with TStringList.SaveToFile took 0,004 s

So, there is a factor of 10 between TMemIniFile and TIniFile and a factor of *drumroll* 50 between TStringList and and TMemIniFile. Changing the code from TIniFile to TStringList sped up that code by a factor of whooping 500! And since these files tend to get large that’s significant.

But what if you don’t rewrite the whole file? If you just want to, say, add a new section with 100 entries to it? Yes, you could still use TStringList but that would be rather inconvenient. INI files are mostly about convenience. So I looked for a faster implementation and found TFastIniFile by Pieter Zijlstra. According to Pieter it has been updated to Delphi XE4. I tested it with Delphi 2007 and the results are impressive. It’s nearly as fast as using a TStringList and has a few features that TMemIniFile has not: It preserves comments and blank lines. It supports inline comments. Here is the result of the speed benchmark from the demo program he supplies:

(Re)write 400 sections each with 10 ident=value’s
TIniFile 25,333 s 87224 Kb
TMemIniFile 0,037 s 88504 Kb
TFastIniFile ANSI 0,008 s 88504 Kb
TFastIniFile 0,010 s 88504 Kb

I didn’t use it in GExperts because it was not necessary but it might be well worth checking out if your program routinely works with large INI files.

My thanks to Daniela Osterhagen for reminding me that writing an INI file can easily be done with a TStringList.

Getting the system boot time in Windows

 Windows  Comments Off on Getting the system boot time in Windows
Oct 132016

Today I needed to get the system boot time of my computer.

You can either open the system log and look for the entries a Windows start up writes there, or you can let a tool do the work:

@echo off
systeminfo | find "System Boot Time"

In my case the result looks like this:

System Boot Time:          13.10.2016, 09:14:50
Press any key to continue . . .

There are a lot more options, detailed in this answer on StackOverflow.

New GExperts IDE form enhancement for the Goto dialog

 Delphi, GExperts  Comments Off on New GExperts IDE form enhancement for the Goto dialog
Oct 092016

GExperts has got several options to enhance various IDE forms. They can be enabled and disabled on the configuration dialog’s IDE tab.


There is now a new one: Enhance Goto dialog. It’s the dialog you get when selecting Search -> Go to Line Number which looks like this in it’s original full glory:


It hasn’t changed since Delphi 1 (OK, I’m not sure about Delphi 1, but definitely not since Delphi 6), including such meaningful component names as Label1 and Bevel1.

This is how it looks when you enable the new enhancement:


As you can see I have added a listbox which is filled with the interesting positions in a unit:

  • Unit
  • Interface
  • Interface Uses
  • Implementation
  • Implementation Uses
  • Initialization (or Begin)
  • Finalization
  • End.

You can simply press the up or down arrow to select them and the corresponding line number will automatically entered for you. But manually entering a line number or selecting one from the combobox’s dropdown list still works as before.

In addition, I have fixed several form positioning bugs in the Delphi IDE in a multi monitor setup, where dialogs were always placed on the primary monitor regardless of where the IDE window was located.

  • In Delphi 2005 to 2007 it was the Search -> Replace dialog
  • In Delphi 2009 to 10 Seattle it were the File -> New -> Other and the Project -> Resources And Images dialogs

If you enable “Enhance IDE dialogs (and fix form positioning bugs)”, these dialogs will now be moved to the monitor of the IDEs main window.

There is no release yet, so if you want these goodies, you’ll have to compile GExperts yourself.

Delphi Live Templates: raise exception.CreateFmt

 Delphi  Comments Off on Delphi Live Templates: raise exception.CreateFmt
Oct 052016

Delphi (XE2) comes with various predefined so called live templates which you can display with View->Templates. One of them is called “raise” and expands to

raise exception.Create('Error Message');

I don’t know about you but I use Exception.CreateFmt much more often than simply Exception.Create, so it annoys the hell out of me when every time I type raise I get the simple Create call and have to edit it. Also, I usually use DxGetText to translate my error messages using the _() function. So I have to add that as well.

Today I got tired of this and simply changed the template:

  1. Since you cannot edit the predefined templates, the first thing you do, is open it and copy the whole text into the clipboard.
  2. Add a new template and paste the text into it.
  3. Change it to your liking.
  4. Save it with the same file name but to the directory for user defined code templates, which is [your documents folder]\RAD Studio\code_templates.

That’s it, now the new user defined template will be called rather than the predefined one.

Now to the template itself. This is the original template:

<?xml version="1.0" encoding="utf-8" ?>
<codetemplate	xmlns="http://schemas.borland.com/Delphi/2005/codetemplates"
<template name="raise" invoke="auto">
	Create and raise an instance of an Exception class
	Embarcadero (with thanks to Erik Berry)
  <point name="exception">
	<script language="Delphi">InvokeCodeCompletion;</script>
	<hint>Exception class</hint>
  <point name="errormessage">
	<text>Error Message</text>
	<hint>Exception Message</hint>
  <code language="Delphi" context="methodbody" delimiter="|">
   <![CDATA[raise |exception|.Create('|errormessage|');|end|]]>

And this is my changed template:

<?xml version="1.0" encoding="utf-8" ?>
<codetemplate	xmlns="http://schemas.borland.com/Delphi/2005/codetemplates"
<template name="raise" invoke="auto">
	Create and raise an instance of an Exception class
	Embarcadero (with thanks to Erik Berry)
  <point name="exception">
	<script language="Delphi">InvokeCodeCompletion;</script>
	<hint>Exception class</hint>
  <point name="errormessage">
	<text>Error Message</text>
	<hint>Exception Message</hint>
  <point name="parameters">
	<hint>Parameters go here</hint>
  <code language="Delphi" context="methodbody" delimiter="|">
   <![CDATA[raise |exception|.CreateFmt(_('|errormessage|'), [|parameters|]);|end|]]>

As you can see, I changed Create to CreateFmt, added the call to _() and also added a point element “parameters” for entering the parameters for the format specifiers, which is then referenced in the code element.

You can find more about live templates here:

GExperts 1.38 experimental twm 2016-10-03 released

 Delphi, GExperts  Comments Off on GExperts 1.38 experimental twm 2016-10-03 released
Oct 032016

I must admit I’m getting tired of waiting for Erik to make a new official GExperts release. So, here is another experimental one.

The motive for making this release is twofold:

  1. The Delphi 10.1 Berlin update 1 for which I released a hotfix
  2. A bug I discovered and fixed yesterday that caused GExperts to crash with an access violation when the IDE was exiting (I’ve only seen this in Delphi 10.1 Berlin update 1 so far, but it could happen in any version.)

There are also some other changes / bugfixes:

  • The Make Relative and Make Absolute buttons on the search path dialog (only visible if you switch to Memo) did not convert the content of the edit control. This might also solve the problem that sometimes the content of the edit control was added to the search path when the dialog was closed, resulting in duplicate entries.
  • Make Absolute also converted entries starting with $(BDS) which was definitely not what you want.
  • I replaced the dialog that was shown by the Change Case expert with a popup menu. Basically the usage remains unchanged because the popup menu uses the same accelerator chars and it also remembers the last option you picked and makes it the default entry which you can select by pressing Enter. (Yes, I known the vote on this feature was undecided, but I did i anyway, just for the hell of it.)
  • There is a new Convert Strings editor expert. It is my first try to replace the existing Paste Strings As, Copy Raw Strings and Convert Raw Strings experts with something that’s easy to use without actually having to memorise how they work. It can probably still be improved.
  • Bugfix: The Uses Clause Manager no longer removes units and adds them to the end of the list when adding or removing unit prefixes.
  • Bugfix by
    Jeroen Wiert Pluimers
    for Add/Remove Unit Prefixes not catching generics.collections
  • Another improvement by Jeroen Wiert Pluimers to fix the case of the unit names to match the actual file names in the Add/Remove Unit Prefixes functioality.
  • Some internal refactoring e.g. I got rid of the FParser field in TUsesManager because that field was only ever used in a single method

One last thing I always wondered about: Several Embarcadero employees are blogging regularly about what happened in other blogs and which tools were updated. My posts about GExperts releases were only mentioned once but usually ignored. So I wonder whether this is somehow on purpose. Is it me? (I sometimes post quite critical things about Deplhi and Embarcadero on G+.) Is it GExperts? (It still supports old Delphi versions back to Delphi 6. I can understand that Embarcadero would like people to have yet another reason to upgrade to the latest and (in my opinion not always so) greatest Delphi version.)

Head over to the Experimental GExperts page to download the latest release it.

dzMdbViewer 1.0.2 released

 Delphi  Comments Off on dzMdbViewer 1.0.2 released
Sep 302016

dzMdbViewer is a small tool I wrote, when I was stuck without a MS Access installation but needed to have a look into a .MDB file (and later .ACCDB file, if the Access Database Engine 2012 is installed).

It can open these files and display a list of queries and tables stored in them as well as the data they contain.

Table Data

Also, for tables, it can show the field definitions.

Table Definition

Today I added support for command line parameters, so it can be used as the default program for opening these kind of files. Download it from SourceForge. The source code is available too. (I got tired of the inconveniences of Mercurial, so I moved this project to Subversion.)

First steps with REST and JSON

 Delphi  Comments Off on First steps with REST and JSON
Sep 252016

I must admit that I haven’t done much programming regarding the web. There was an attempt to write an RSS reader some time back and there is my virtual radio alarm clock (with which I’m currently listening to SWR3). But this is my first try to do something with REST and JSON. The server side is provided by the Delphi Dabbler SWAG archive the client is written with Delphi 10.1 Berlin.

At first I tried to make sense from the tutorial provided by Embarcadero but I found it rather confusing and it stops exactly when actually trying to access the data returned in a meaningful way.

So, I threw away the TRESTxxx components I had put on the form and went back to some actual programming rather than dropping components and setting properties without understanding what I am doing. Here is what I ended up with:


The program itself consists of two parts: Requesting data from the server and interpreting its answers. Requests are sent via http using a TidHttp object which is dynamically created and destroyed for each request.

procedure Tf_DelphiDabblerSwag.doRequest(const _Command: string; out _Response: TJSONObject);
  JSON: string;
  HTTP := TIdHTTP.Create(nil);
    JSON := HTTP.Get('http://swag.delphidabbler.com/api/v1/' + _Command);
//    m_Result.Lines.text := JSON;
  _Response := TJSONObject.ParseJSONValue(JSON) as TJSONObject;

It expects a Command which is simply sent to the server by appending it to the API url as described in the documentation.

It returns a TJSONObject which is then interpreted by the caller. (I don’t do much error handling here, it’s merely a learning experiment.)

The API is simple, it knows only 4 different commands:

  • categories
  • snippet
  • snippet-count
  • snippets

I implemented each of them as a method:


procedure Tf_DelphiDabblerSwag.RequestCategories(_Categories: TObjectList<TIdTitleObj>);
  JObj: TJSONObject;
  JCategories: TJSONArray;
  i: Integer;
  JCategory: TJSONObject;
  Category: TIdTitleObj;
  doRequest('categories', JObj);
    m_Result.Lines.Add('status: ' + JObj.GetValue('status').Value);
    m_Result.Lines.Add('command: ' + JObj.GetValue('command').Value);
    JCategories := JObj.Get('categories').JsonValue as TJSONArray;
    for i := 0 to JCategories.Count - 1 do begin
      JCategory := JCategories.Items[i] as TJSONObject;
//        m_Result.Lines.Add(Format('Category: (ID: %s, Title: %s', [JCategory.GetValue('id').Value, JCategory.GetValue('title').Value]));
      Category := TIdTitleObj.Create(JCategory.GetValue('id').Value, JCategory.GetValue('title').Value);

The first thing the program does is getting a list of all categories. For that it sends the “category” command to the server and interprets its response.

      "title":"ANSI Control & Ouput"
      "title":"Archive Handling"

    ... more category elements ...


All categories are stored in a TObjectList and returned to the caller. It took me a while to figure out how to access the array of categories: You access a name value entry and type cast it to TJSONArray. After I understood that, everything else was easy.


Next is getting a list of all snippets of a category.

procedure Tf_DelphiDabblerSwag.RequestSnippets(const _CategoryId: string; _Snippets: TObjectList<TIdTitleObj>);
  JObj: TJSONObject;
  i: Integer;
  JSnippets: TJSONArray;
  JSnippet: TJSONObject;
  Snippet: TIdTitleObj;
  doRequest('snippets/' + _CategoryId + '?fields=id,title', JObj);
  m_Result.Lines.Add('status: ' + JObj.GetValue('status').Value);
  m_Result.Lines.Add('command: ' + JObj.GetValue('command').Value);
  JSnippets := JObj.Get('snippets').JsonValue as TJSONArray;
  for i := 0 to JSnippets.Count - 1 do begin
    JSnippet := JSnippets.Items[i] as TJSONObject;
    Snippet := TIdTitleObj.Create(JSnippet.GetValue('id').Value, JSnippet.GetValue('title').Value);
//    m_Result.Lines.Add(Format('Snippet: (ID: %s, Title: %s', [JSnippet.GetValue('id').Value, JSnippet.GetValue('title').Value]));

The “snippets” command needs a some parameters:

  • The id of the category
  • The fields we are interested in

They are appended to the command.

Then again, we simply parse the result and return it in a TObjectList.

      "title":"Getting the Line number in a memo Field",
      "title":"Capturing the Desktop to a form",
      "title":"File Copying in DELPHI",
      "title":"File Manager Drag\/Drop",


The last part is getting a snippet’s text.

procedure Tf_DelphiDabblerSwag.RequestSnippetText(const _SnippetId: string; out _Text: string);
  JObj: TJSONObject;
  JSnippet: TJSONObject;
  doRequest('snippet/' + _SnippetId + '?fields=source_code', JObj);
    m_Result.Lines.Add('status: ' + JObj.GetValue('status').Value);
    m_Result.Lines.Add('command: ' + JObj.GetValue('command').Value);
    JSnippet := JObj.GetValue('snippet') as TJSONObject;
    m_Snippet.Lines.Text := JSnippet.GetValue('source_code').Value;

The “snippet” command requires a snipped id and we also must specify the fields we want to get. In this case we only want the source_code.

    "source_code":"\r\n{This way uses a File stream.}\r\nProcedure ..."

The response is then parsed and returned as a string. Note that “snippet” is an object, so in order to get the source code we need to type cast the snippet value to a TJSONObject before we can access its source_code value.

That’s about it. The rest of the program is a few event handlers that call the methods described above and fill the result into the GUI. I won’t get into that, it’s boring.

The source code is available for download here and in case you simply want to browse the SWAG archive using that program, there is also a precompiled executable

As I already said in the title: These are my first steps. I’m pretty satisfied with the result, but I’m sure I made some mistakes and there are probably easier ways to implement this.

GExperts 1.38 experimental twm 2016-09-18 released

 Delphi, GExperts  Comments Off on GExperts 1.38 experimental twm 2016-09-18 released
Sep 182016

Since apparently Erik needs more time for the official GExperts 1.39 release, here is another experimental test release. Please report any bugs you may find (preferentially in the GExperts community on Google+ or the bug tracker on SourceForge)

Again, I have built installers for each Delphi version. These installers should install everything that is necessary, including the files for the Code Formatter.

Apart from several bugfixes I have added three new experts:

  • There is the Warn Directives Expert which allows you to select a warn directive like SYMBOL_PLATFORM and insert it as {$WARN SYMBOL_PLATFORM OFF}, {$WARN SYMBOL_PLATFORM ON}, {$WARN SYMBOL_PLATFORM DEFAULT} or {$WARN SYMBOL_PLATFORM ERROR}.
  • Then there is the IfDEF Expert which alows you to insert various IFDEF, IF or IFOPT directives. It automatically scans for include files in the current unit and offers the conditional defines from there as well. You can also add another include file from the search path and if you add directives for conditional defines from it, the expert will automatically add an {$I <filename>} directive to the unit.
  • And last but not least there is the Add to Formatter Capitalization Expert which allows you to add the current identifier to the code formatter’s captitalization file without clicking your way through the various configuration dialog levels.

GExperts IFDEF Expert

Head over to the Experimental GExperts page to download it.