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.

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 hes 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.

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.

Software\Embarcadero\BDS\9.0

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 enabled them. To fix that, just delete these packages from the disabled packages list using the Registry Editor.

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

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.

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?

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!

Improved keyboard navigation in the GExperts configuration dialog

 Delphi, GExperts  Comments Off on Improved keyboard navigation in the GExperts configuration dialog
Jul 222018
 

The GExperts configuration dialog, while I like the general look, has always been a keyboard navigation nightmare for me.

Assume you want to change the configuration of the Formatter Expert:

You first open the configuration dialog pressing Ctrl+H + X. Then you press Ctrl+Tab to switch to the Editor Experts tab. You type “form” which filters the list of experts to only display the “Code Formatter” and “Add To Formatter Capitalization” entries. So far, so good. Now, how to press the “Configure” button? You could of course now press Tab nine times until the focus has moved to the “Configure” button and press enter, but who wants to do that? I certainly don’t, so I usually resorted to using the mouse.

This has irked me for quite a while because I am more a keyboard person. So, today I added two functions that solve the issue for me:

First, you can now scroll the expert list using the up/down arrow and page up/down keys while the focus is on the filter control.

Second, when scrolling (or filtering) the list, the configuration button of first visible expert now automatically gets the Alt+C hotkey.

So, in order to open the Formatter Expert’s configuration dialog, you simple press Alt+C after you filtered the list. Much more to my liking!

Selecting alignment and anchors in the Rename Components expert

 Delphi, GExperts  Comments Off on Selecting alignment and anchors in the Rename Components expert
Jul 212018
 

A few weeks ago I added the option to set the alignment and anchors properties for controls that support them to the GExperts Rename Component expert. After having used it for a while I found that the navigation using arrow keys left something to desire. It just wasn’t intuitive, e.g.: Pressing the down arrow key while the “Top” button had the focus moved the focus to the “Left” button. Pressing down again moved it to the “Client” button and again to the “Right” button.

The intuitive way would be that the up arrow key moves the focus to the control above the current one, the down arrow key move the focus to the control below the current one etc., like this:

So, how do you get the dialog to behave like this?

My first try was to write OnKeyDown handlers for the buttons, but that didn’t work, the handlers were never called. The second try was an OnKeyDown handler for the form and setting its KeyPreview property to true. Again, this didn’t work, the handler was never called. WTF?

Some googling turned up this question on StackOverflow and an answer that worked for me: Adding a DialogKey message handler to the form. (Thanks Sertak Kyuz”! I always appreciate it when somebody supports my lazyiness.). So I added the following code to GX_CompRename:

procedure TfmCompRename.DialogKey(var Msg: TWMKey);
begin
  // make the selection of alignment and anchors via arrow keys more intuitive
  case Msg.CharCode of
    VK_DOWN: begin
        if ActiveControl = b_AlignTop then
          b_AlignClient.SetFocus
        else if (ActiveControl = b_AlignClient) or (ActiveControl = b_AlignLeft) or (ActiveControl = b_AlignRight) then
          b_AlignBottom.SetFocus
        else if (ActiveControl = b_AnchorTop) or (ActiveControl = b_AnchorLeft) or (ActiveControl = b_AnchorRight) then
          b_AnchorBottom.SetFocus
        else
          inherited;
      end;
    VK_UP: begin
        if ActiveControl = b_AlignBottom then
          b_AlignClient.SetFocus
        else if (ActiveControl = b_AlignClient) or (ActiveControl = b_AlignLeft) or (ActiveControl = b_AlignRight) then
          b_AlignTop.SetFocus
        else if (ActiveControl = b_AlignNone) or (ActiveControl = b_AlignCustom)then
          b_AlignBottom.SetFocus
        else if (ActiveControl = b_AnchorBottom) or (ActiveControl = b_AnchorLeft) or (ActiveControl = b_AnchorRight) then
          b_AnchorTop.SetFocus
        else
          inherited;
      end;
    VK_RIGHT: begin
        if ActiveControl = b_AlignLeft then
          b_AlignClient.SetFocus
        else if ActiveControl = b_AlignClient then
          b_AlignRight.SetFocus
        else if (ActiveControl = b_AnchorTop) or (ActiveControl = b_AnchorBottom) or (ActiveControl = b_AnchorLeft) then
          b_AnchorRight.SetFocus
        else
          inherited;
      end;
    VK_LEFT: begin
        if ActiveControl = b_AlignRight then
          b_AlignClient.SetFocus
        else if ActiveControl = b_AlignClient then
          b_AlignLeft.SetFocus
        else if (ActiveControl = b_AnchorTop) or (ActiveControl = b_AnchorBottom) or (ActiveControl = b_AnchorRight) then
          b_AnchorLeft.SetFocus
        else
          inherited;
      end;
  else
    inherited;
  end;
end;

Now it works as shown in the picture.

It’s a small improvement, but one that makes me a bit more efficient. It took me about 2 hours to implement and test properly. So, according to XKCD it’s time well spent: I definitely use it more that 5 times a day, so spending 2 hours to save one second is fine. It saves those two hours across five years. And since I am not the only one using GExperts I hope I have saved a lot more than those two hours.

Speaking about saving time: Did you know that you can configure the Rename Components expert to automatically pop up for new controls when you drop them on a form?

Some information about Embarcadero Licence Center

 Delphi  Comments Off on Some information about Embarcadero Licence Center
Jul 142018
 

I switched “my” (meaning the license my employer bought for me) Delphi “Named User License” with subscription to a “Network Named User License” in April 2018. The rationale behind that was, that it happened far too often that I needed yet another Delphi installation to debug a problem. Most of the time that was on a Friday and since my activation limit had been reached years ago, I needed somebody at Embarcadero to bump it up again. Of course that never happens on a weekend, so after I complained about this for the thousandth time, somebody suggested I switch to a different license scheme: Welcome to “Network Named User” (NNU) and the “Embarcadero License Center” (ELC).

Since that topic has come up in a recent discussion in the Delphi Developers community on Google+, I thought I’ll blog about my experience so I can simply link to this blog post when I need to tell that story again.

So, what is it about?

  • A NNU license allows an unlimited number of Delphi installations and activations for a given “named user”. A “named user” is defined as a unique user name for Windows logon. It does not matter whether that’s a domain logon or local logon. So, if JoeUser has got a NNU license for Delphi 2007 (which is the first version that supportes NNUs) he can install it on his workstation, his laptop, a customer’s computer (for debugging something that simply cannot be debugged any other way) and multiple virtual machines. There are only two restrictions:
    1. The Windows logon name must be JoeUser.
    2. The computer/VM must have a network connection to the ELC server.
  • He can even actively use up to three different installations at the same time.
  • If an installation loses contact to the ELC server (e.g. you take your laptop with you on a trip) it will keep working for up to 30 days.
  • The administrator of the ELC can change the user name assigned to a NNU license, so if JoeUser leaves the company, his successor JaneUser can simply use that license to install Delphi on her own computers. The old installations (under the Windows user JoeUser) will become defunct.
  • As far as I know the ELC does not require a permanent internet connection (e.g. to phone home to Embarcadero). It only needs it once to activate the license (and for each new license).
  • The ELC server is a Java application which is available for Windows and Linux (and possibly other OSes, I don’t remember). It runs fine in a virtual machine (I use Ubuntu Server on a XenServer VM.)
  • With a bit of ssh magic, it’s possible to connect to the ELC via a ssh tunnel from offsite. (I would not trust the ELC to be directly accessible from the internet.)

As far as I was told, it’s possible to switch a Named User License to a Network Named User License any time provided you have got an active subscription. According to Embarcadero Germany it is easier to make that switch before extending a subscription.

Note that a few weeks after you switched, all the non NNU installations using the old license keys will stop working (Embarcadero will turn them off). You will have to activate them again with the NNU license.

So far it has worked great for me. I have installations on my Work PC, Work Laptop, Home Office PC (which both use the ssh tunneling magic), private Laptop (with my employer’s consent of course), various VMs and on the computers on many of the measurement vehicles my employer operates to conduct road condition surveys.

Getting the ELC to work was a bit of a pita, but I got great support from Embarcadero for that. In particular from Matthias Eißing who also has published a video on YouTube (in German) on that topic.

As a side note: NNU licenses are not the only kind of licenses that are available through ELC. There are also concurrent licenses which work in a different way and are more expensive. See the ELC documentation or contact Embarcadero on how they work.

Some bit of trivia: Does anybody remember AppWave? Apparently ELC is the only remaining part of AppWave that still exists. There are several references to AppWave in the ELC documentation and web sites it generates.