If your lines seem too thick in a TeeChart

 Delphi  Comments Off on If your lines seem too thick in a TeeChart
Aug 312018

… you might not be used to anti-aliasing. Recent (#1) versions of TeeChart switched to GDI+ as their default drawing engine which also switched on anti-aliasing by default. The difference looks like this:

(Apparently this wasn’t obvious: These screen shots have been magnified to show the cause of the “thick line” effect.)

It’s a matter of personal taste (and the use case) which one looks “better”. Some of my users started to complain about thick and blurry lines. So, how do you turn off this feature, once you know that it exists? There is nothing about anti-aliasing in the chart’s properties. Of course it’s somewhere in the complex setup dialog, but where? It’s here:

But it’s more complex than that: There is no property for this in the TChart control. Instead this property editor adds a new component of the type TTeeGDIPlus to the form. And there we can find that setting:

I guess it’s yet another case of RTFM, but you know how they say “If everything else fails, read the docs!”

As Daniela Osterhagen commented on my Google+ post, it can also be done in code only:

procedure TForm1.FormCreate(Sender: TObject);
  Renderer: TTeeGDIPlus;
  Renderer := TTeeGDIPlus.Create(Self);
  Renderer.TeePanel := TheChart;
  Renderer.Antialias := False;

(No need to keep that instance around, it will automatically be freed with the form.)

(#1: Where recent means something like 5 years ago. We just recently moved some of our projects to use the latest version)

 Posted by on 2018-08-31 at 09:46

Using escape characters in GExperts Grep replace

 Delphi, GExperts  Comments Off on Using escape characters in GExperts Grep replace
Aug 262018

If you enable regular expressions in the GExperts Grep search form, you can search for escape sequences like \t which is expanded to a tab character or \x20 which is expanded to char($20), the space character.

Up to now it was not possible to use \t (and similar escape sequences) in the Grep replace dialog. They were not expanded properly but the \ was treated as escaping the character following it, meaning \t was replaced by a simple t character.

I changed that, so now the same escape characters that are allowed in the search expression are also allowed in the replace expression. Note though, that \x{nnnn} for Unicode characters is not supported, maybe I’ll add that later.)

This solves Bug #82.

I also removed the restriction, that you could not search for space character(s). (Bug #81)

A word of warning:
Please keep in mind, that the Grep Replace functionality is still pretty much experimental. It replaces literal characters, so it is probably not a good idea to replace ‘\r\n’ with “\n” only, it will break the editor. Also, be very careful with replacing matches in all files. It might completely destroy your source code as it also replaces matches in the dpr file and dfm files (I had to revert the full project using SubVersion the first time I tried it. I lost all my not committed changes because of that. You learn from your mistakes, especially when they hurt you like this.)

There is no release with this functionality yet, but you can always compile your own dll.

 Posted by on 2018-08-26 at 12:40

svnrdump for dumping and loading remote svn repositories

 Delphi, TortoiseSVN  Comments Off on svnrdump for dumping and loading remote svn repositories
Aug 252018

Since I keep forgetting what the tool is called and how to use it:

svnrdump is a tool that can dump a remote svn repostory to a text file and also load that text file into a different remote svn repository. It comes with the TortoiseSVN installation (but is really part of the standard Subversion tool set).

My use case is migrating projects from SourceForge to OSDN. On the OSDN side the option “Allow to modify revision properties for project members” must be enabled which is available on the Subversion -> Admin page. It really takes a few minutes for that option to become active.

To dump a repository:

svnrdump dump https://source.site/some/repository/ > somerepository.dump

To load a repository:

svnrdump load https://dest.site/some/repository < somerepository.dump

Of course, since svnrdump writes to stdout and reads from stdin, it should be possible to do both in one go:

svnrdump dump https://source.site/some/repository/ | svnrdump load https://dest.site/some/repository

But I have never tried it. I prefer getting a dump file first, just in case anything goes wrong.

Today I moved bdsproj2cfg and dof2cfg.

 Posted by on 2018-08-25 at 18:02

GNUGetText support for the GExperts Message Dialog expert

 Delphi, GExperts  Comments Off on GNUGetText support for the GExperts Message Dialog expert
Aug 182018

Based on an idea and partial implementation submitted by Sven Harazim from Landrix Software I have just added support for GNUGetText to the GExperts Message Dialog expert. It now looks like this:

And generates Code like this:

MessageDlg(_('first line'+#13#10+'second line'), mtWarning, [mbOK], 0);

Or, if you’d rather use the Windows API:

which generates code like this:

MessageBox(0, PChar(_('first line'+#13#10+'second line')), PChar(_('The Caption')), MB_ICONWARNING or MB_OK);

There are even two new configuration options:

Depending on the settings the code could look like any of this:

MessageDlg(_('first line'+#13#10+'second line'), mtWarning, [mbOK], 0);
MessageDlg(GetText('first line'+#13#10+'second line'), mtWarning, [mbOK], 0);
MessageDlg(_('first line')+#13#10+_('second line'), mtWarning, [mbOK], 0);
MessageDlg(GetText('first line')+#13#10+GetText('second line'), mtWarning, [mbOK], 0);

or this:

MessageBox(0, PChar(GetText('first line')+#13#10+GetText('second line')), PChar(GetText('The Caption')), MB_ICONWARNING or MB_OK);
MessageBox(0, PChar(_('first line')+#13#10+_('second line')), PChar(_('The Caption')), MB_ICONWARNING or MB_OK);
MessageBox(0, PChar(_('first line'+#13#10+'second line')), PChar(_('The Caption')), MB_ICONWARNING or MB_OK);
MessageBox(0, PChar(GetText('first line'+#13#10+'second line')), PChar(GetText('The Caption')), MB_ICONWARNING or MB_OK);

It also generates code for C++, but I have no idea whether it works:

MessageDlg(GetText("first line\nsecond line"), mtWarning, TMsgDlgButtons() << mbOK, 0);
MessageBox(0, GetText("first line\nsecond line"), GetText("The Caption"), MB_ICONWARNING|MB_OK);

I hope it will be useful for some. I myself don't use that expert at all.

There is no release with this feature yet. If you want to use it, you will have to compile your own DLL.

 Posted by on 2018-08-18 at 16:52

Building less annoying user interfaces (part 1)

 Delphi  Comments Off on Building less annoying user interfaces (part 1)
Aug 182018

I am not claiming to be an expert in building good user interfaces, in fact I have been known to use terrible color combinations, overload forms with too many controls and confusing the user. But on the other hand I have been using computers for all of my adult life and I have seen quite a lot of really bad user interfaces, so I think I know a bit about what not to do.

Being a Delphi programmer by profession, even by passion, most of this applies to Delphi, but probably a lot of it applies to other tools. So, here we go:

Do not trap your users

One of the worst feelings for a computer user is that he has done something and cannot get back. Some programmers think it is a good idea to check the user input and force him to enter valid data. E.g. there is an entry field that only allows numerical input and if the user dares to enter something the program does not like, that field will turn red and will not let go of the input focus until the user has done what is required of him. Often this even means that he cannot press the Cancel button or close the window. Instead an error dialog is shown with a more or less generic message. Combine that with some annoying Pling sound and you will certainly entertain the whole office.

So, what do I suggest?

  • Input validation, even coloring the background is a good thing, but use a color that won’t reduce readability, like a very light red. I for one prefer yellow.
  • Do not force the input focus anywhere. If the user decides he wants to fill in other fields first, before going back to a field that was marked as invalid, that’s fine. He might have a reason for it. E.g. he might have just copied some text from another application to the clipboard in order to paste it into that input field.
  • Of course, any button for submitting the input should be disabled until the input passes validation.
  • Do not play error sounds. In today’s open plan offices but even in a smaller, shared office, this will absolutely annoy not just the user but also his colleagues.
  • Do not pop up error dialogs. They unnecessarily disrupt the user’s focus on your dialog. Most people nowadays are keyboard averse and will in that case use the mouse to close that dialog which disrupts their work even further. Also, as we all know, users don’t read error messages, they just want that annoying dialog go away.
  • If input validation fails, the user needs to know, where and why. Do not just disable the OK button, but give visual feedback what is wrong. Personally I prefer invalid input to get yellow background (As I said above: My color perception may be warped.). Also, there should be a text telling the user what kind of input is expected. That can be a text in the status bar or maybe even better near the input field that contains the offending input.
  • Do not automatically clear input fields with wrong content (Yes, I have seen programs do that, but that bad habit is most common with online forms.). It’s always easier to correct the input than to type it again. Imagine some user pasting a 10 digit number from his spreadsheet into your program and getting the decimal separator wrong (Yes, my American readers: There is such a thing as decimal separator other than the point. Many European countries use the comma. And don’t even get me started about date formats!). He might then simply replace that one character with the correct one rather than typing the whole 11 characters again.
  • Do not prevent pasting from the clipboard. Some people think it is a security risk to allow users to paste data from the clipboard into their program. In particular some programs do not allow pasting passwords. I might be wrong here, but I don’t see how not allowing paste from the clipboard improves security. If the system is compromised, the user is f***ed anyway. Of course copying from password input fields to the clipboard is a different matter.
  • Another thing about password input fields is the display. In some environments, showing the password in clear text is definitely not a good idea as somebody might be “shoulder surfing”. On the other hand, the user needs some way to determine whether he might have mistyped his password and correct it. Passwords are commonly displayed as *** or similar characters. Personally I like an option to temporarily display the password in the clear, e.g. a button which shows it as long as it is being pressed. There is a slight security risk (apart from “shoulder surfing”) here: If the user leaves the computer with this input mask open, somebody else can also press that button and read the password.
  • Be consistent! If you in one part of your program use yellow as the error color and display the input hint in the status bar, you should do that everywhere. If you develop internally used software for a company, somebody should decide how to do error handling and this should be enforced.

The above would not be complete without a link to my own input validation unit in dzlib.

That’s the end of part 1. I am sure I will continue that series at some time. Be prepared to hear me rant about tab order and resizable forms next.

 Posted by on 2018-08-18 at 10:57

Delphi disabled packages in the registry

 Delphi  Comments Off on Delphi disabled packages in the registry
Aug 142018

Note to self:

The Delphi IDE stores a list of disabled packages (that is packages where the user removed the check mark in front of the package under Components -> Packages) in the registry under HKCU\<basekey>disabled packages.

<basekey> is the base key of the Delphi configuration, e.g.


So the disabled packages for Delphi XE2 are stored in

HKCU\Software\Embarcadero\BDS\9.0\disabled packages

If you remove the package from the list of known packages (stored in the registry under Known Packages) and later on add them again, these packages might still be disabled and sometimes setting the check mark in the dialog does not enable them. To fix that, just delete these packages from the disabled packages list using the Registry Editor.

 Posted by on 2018-08-14 at 12:27

dzMdbViewer moved to OSDN

 Delphi  Comments Off on dzMdbViewer moved to OSDN
Aug 122018

Even though it has become better again, the stability of svn hosting on SourceForge has not been up to par for several months. I got tired of this, so, I moved one more of my projects from SourceForge to OSDN.

dzMdbViewer is a viewer for Microsoft Access database files which I wrote when I was stuck without an MS Access installation but had to look into an MDB.

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

 Posted by on 2018-08-12 at 14:19

GExperts 1.3.11 experimental twm 2018-08-05 released

 Delphi, GExperts  Comments Off on GExperts 1.3.11 experimental twm 2018-08-05 released
Aug 052018

After the massive improvement to the Uses Clause Manager it’s time for another GExperts release.

New features include:

New features include:

There were also several bug fixes.

Please be aware that I mostly work with Delphi 2007, so this version can be regarded as tested quite well, followed by Delphi XE2. The others are only known to compile and new features are usually tested superficially with all versions. This is particularly true for Delphi 6/7 and 2005/2006.

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

 Posted by on 2018-08-05 at 12:15

Broken download links for GExperts 1.3.10

 Delphi, GExperts  Comments Off on Broken download links for GExperts 1.3.10
Aug 052018

No idea why nobody told me about this, but today I discovered that the download links for the GExperts 1.3.10 installers were broken due to a superfluous dash in the date part. It’s fixed now. I could have sworn that I tested those links when I released that version.

But before you now go to that download page: I have just released GExperts 1.3.11. Maybe you would prefer that one instead?

 Posted by on 2018-08-05 at 12:01

Improved Uses Clause Manager in GExperts

 Delphi, GExperts  Comments Off on Improved Uses Clause Manager in GExperts
Aug 042018

The Uses Clause Manager Expert in GExperts used to look like this:

While it was a very useful tool as it was, I have added to it quite a lot in the recent weeks:

Let’s start with the simple changes:

Interface and Implementation uses clauses are now visible at the same time. This allowed me to add buttons to delete from each and to move from one to the other. These Buttons also have corresponding popup menu entries and keyboard shortcuts that depend on the context:

  • Del always deletes from the currently focused list. This is also the default action executed with a double click (Actually it has always been the default action.).
  • Ctrl+M moves from the current list to the other
  • Ins adds the currently selected unit(s) to the favorite units list (also works in the Sarch Path, Project and VCL/RTL lists).
  • Ctrl+O opens the currently selected unit in the editor and closes the dialog
  • In addition to drag and drop from the available units lists to the uses lists it’s now also possible to drag and drop entries between the two uses lists.

There are also buttons to add or remove the dotted unit prefixes, e.g. they convert “Registry” to “System.Win.Registry” and vice versa.

Then there is an Open Unit button which can be used to open the currently selected unit in all lists.

Also, there is a new button to add all units from a list to the Favorite list. This list has become more important than it used to be, see below.

And last but not least there is a context menu entry to unalias all units. This means that it will replace units like WinTypes and WinProcs which have been declared as aliases to Windows for ages with their actual unit. The same goes for dbiTypes, dbiProcs and dbiErrs which will be replaced with BDE.

I have also replaced the ListViews with StringLists which makes the display much faster for large lists (see below) and allows me to distinguish between the currently selected item(s) in each list (dark gray) and the currently focused control (blue).

And now to the huge change:

It’s a new tab with a list of all identifiers that are declared in the interface sections of all units in your favorite list. Similar to the already existing filter for unit names it allows to filter for identifiers. In the screen shot, I typed “TWinControl” and the list was filtered down to just 7 of the several thousand entries. This is a replacement for the IDE feature Refactor -> Find Unit, but in contrast to that feature, it works (Find Unit fails for me in about 30% of all calls.). And of course it also works for the old IDEs which did not have that feature.

Btw.: Did you known that you can scroll within the lists while the focus in on the filter edit?

I plan to make a new release including these features later this weekend. So stay tuned!

 Posted by on 2018-08-04 at 15:25