Fake TSpeedButton based on TBitBtn updated again

 Delphi  Comments Off on Fake TSpeedButton based on TBitBtn updated again
Nov 102018

My fake TSpeedButton based on TBitBtn has been updated again. It now supports any combination of Glyph and single/multi line Text. It also supports setting Margin and Spacing.

Note that it still requires the Glyph to be on the left.

(Yes, I know, I should have selected some examples where the text does actually fit the button. ;-). But this is just the same problem as in the original TBitBtn control, I even fixed some if its bugs.)

(Click on the image to view an animated demo.)

Also, the original BitBtn object is now exposed via a read only property and there is a new pointer type Data property to attach some additional information to the object.

In addition I added a new class TdzSpeedBitBtnGroup which easily emulates the behaviour of a TRadioGroup using TdzSpeedBitBtns.

The source code is part of my dzlib library which is available from OSDN.

Making “Stay-on-top-forms” do want you want in Delphi

 Delphi  Comments Off on Making “Stay-on-top-forms” do want you want in Delphi
Nov 052018

There is an article by Peter Laman on the topic Making “Stay-on-top-forms” do want you want on the Embarcadero blog. It’s from 2004 and of course the link to the component he talks about no longer works, because it points to cc.borland.com which no longer exists.

Here is a working link.

(I don’t know whether the component still works or is even reqired. I just encountered a problem with a stay on top form and found this article.)

Edit: It’s not a component but a class TStayOnTopForm derived from TForm. You are supposed to derive your form from this class and it does everything else for you. Unfortunately it doesn’t seem to work in my test program, but it does work in the demo that comes with it.

Creating Component Templates in Delphi

 Delphi  Comments Off on Creating Component Templates in Delphi
Nov 032018

One nice feature of the Delphi IDE that I keep forgetting are Component Templates. That means you drop and customize one or multiple components on a form and then give them a new name so you can easily create them again on a different form in a different program.

Let’s start with a simple template for an OK button:

  1. Drop a button on a form.
  2. Give it a meaningful name, e.g. “btnOK
  3. Set its “Caption” property to “OK”.
  4. Set its “Default” property to True.
  5. Make sure that the button is sill selected.
  6. Select Component -> Create Component Template from the menu.
  7. Give it a name, e.g. “OKButton”.

That’s it. A new entry has been added to the Tool Palette. Now, whenever you want to add an OK button, you simply press Ctrl+Alt+P to bring up the Tool Plaette, then enter “OK” and maybe some more keys to filter the list and select the new entry. A copy of the created template will be added to your form. No need to change its properties again.

Now, a form usually has not just an OK but also a Cancel button, why not create a template “OkCancelButtons” for that?

(Click on the picture for an animated tutorial for the below.)

  1. Drop a button on a form.
  2. Give it a meaningful name, e.g. “btnOK
  3. Set its “Caption” property to “OK”.
  4. Set its “Default” property to True.
  5. Drop another button on the form.
  6. Move it to your liking in relation to the OK button.
  7. Set its “Caption” property to “Cancel”.
  8. Give it a meaningful name, e.g. “btnCancel”
  9. Set its “Cancel” property to True.
  10. Select both buttons with Shift+Left Mouse Button.
  11. Select Component -> Create Component Template from the menu.
  12. Give it a name, e.g. “OKCancelButton”.

Again, a new entry has been added to the Tool Palette which you can use whenever you need these two buttons on any form in any program. They will have the correct captions, the Default and Cancel properties will be set and they will be in the right place in relation to each other.

To get rid of a component template you don’t need any more, use the “Delete <component name>” entry context menu on the entry in the Tool Palette.

Component templates are stored in the file
%AppData%\Roaming\Embarcadero\BDS\{version}\bds.dct for current versions, and in delphi.dct in the executable directory for Delphi 6 and 7. I don’t know whether even older versions supported them, but if yes I’d expect them to store them in the same way as Delphi 6 and 7.

(Thanks to Ondrej Kelle for that link.)

Two buttons to make a difference in the Set Tab Order expert

 Delphi, GExperts  Comments Off on Two buttons to make a difference in the Set Tab Order expert
Nov 012018

The Set Tab Order expert in GExperts allows you to change the tab order of controls by dragging them in a tree view. I have always wondered why the standard Tab Order dialog of the IDE has got buttons to move the current control up or down while the one in GExperts does not.

OK, now it has them too:

These buttons even have keyboard shortcuts: Ctrl+Up moves the current item up, Ctrl+Down moves it down.

I’m thinking about further improvements for that expert, but nothing concrete yet. I kind of like the approach that the CnPack IDE wizards take, but on the other hand too much automation can be bad too. What if I want to have a button on the lower left to be the last control in the tab order? Like an “About” button, which in my opinion should not be between the last input field and the OK button because I rarely click it?

download.dummzeuch.de now also supports https

 blog  Comments Off on download.dummzeuch.de now also supports https
Oct 272018

From now on, all *.dummzeuch.de subdomains are available via https. In particular that means download.dummzeuch.de (which contains all GExperts downloads) and my old home page www.dummzeuch.de.

I have changed the download links for the two latests GExperts releases. I will probably not bother with the older ones.

New GExperts Feature: Favorites menu

 Delphi, GExperts  Comments Off on New GExperts Feature: Favorites menu
Oct 272018

I have stolen yet another idea for a new GExperts feature, this time from Dave Nottage‘s Codex Delphi Expert. (But the code is all mine, including any bugs you might experience.)

It’s the Favorites sub menu in the File menu:

The content of this sub menu is generated on the fly, so it will always contain the current entries of the Favorite Files Expert. Since that expert’s dialog is non modal, you can change the configuration and immediately see that the Favorites sub menu content changes. All entries are prefixed with numbers 0-9 and then letters A-T, so there is a maximum of 10+20=30 entries on each level. In addition there is X for Configure which opens the Expert’s configuration dialog:

Unfortunately this new feature will only be available for Delphi 7 and later. I was unable to get it to work in Delphi 6. Sorry about that! But maybe somebody else wants to try it? The source code is here.

There is no release with this feature yet. To get it, for now you have to compile your own GExperts dll which isn’t exactly rocket science anyway.

The State of the GExperts Mailing list and G+ Community

 Delphi, GExperts  Comments Off on The State of the GExperts Mailing list and G+ Community
Oct 262018

You might have heard that Google is “sunsetting” Google+ so the GExperts community there will no longer exist after August 2019.

There is still the GExperts Mailing List on Yahoo, but unfortunately either Google Mail or Yahoo changed something so I am no longer able to post to it (I get a rather unhelpful error message.)

So I have asked Daniel, the administrator of Delphi Praxis whether I can get a GExperts sub forum in the new English Delphi Praxis.

I haven’t received an answer yet, but I hope it will be positive. If yes, I will announce it here and as soon as that sub forum goes live.

As for my general Google+ activity, I have not yet decided what to do. Currently it looks likely that I won’t migrate to any other “social media” site at all. I definitely won’t go to Facebook.

Exported GMail mbox contains GMail labels

 Google  Comments Off on Exported GMail mbox contains GMail labels
Oct 142018

Just in case it isn’t already common knowledge: The “Takeout” export of GMail will give you a single file in mbox format (which will be rather large).

That file contains the content of the “all mail” folder. And each of the messages in the file has a header like this:

X-Gmail-Labels: Archived,Important,Rechnung

So with the right tool it is possible to restore the labels you have set in GMail. Unfortunately I know of no such tool. And also I don’t know of any (Windows) email client that allows you to set user defined tags for emails.

EDIT: There is a tool called Google Takeout Data Converter that claims to do that. I haven’t tested it though.

EDIT2: Thunderbird apparently supports custom tags, not just the ones that are predefined.

EDIT3: Thunderbird also supports virtual folders e.g. based on tags.

Building less annoying user interfaces (Part 2)

 Delphi  Comments Off on Building less annoying user interfaces (Part 2)
Oct 142018

In Part 1 I was ranting about input validation, now it’s about form sizes.

In my previous post I already said that I am not a big fan of fixed size dialogs. They are fine as long as they are large enough to show all of their content, but as soon as there is a list that can grow to an arbitrary size, fixed size dialogs are a no go. Look at the Microsoft Printer installation dialog again:

It contains two lists, one of printer manufacturers and the other of printer models of the selected manufacturer. Of course, it could be even worse and have one list only (And even that wouldn’t have surprised me really. Microsoft has all sorts of bad UIs.). So the list of manufacturers is sorted and even has incremental search. It’s also not too long so it’s probably fine for most users. But the list of printer models is really stupid:

  1. All printer names are prefixed with the manufacturer name, so incremental search does not help.
  2. The list is not high enough to display all entries. Thus there is a vertical scroll bar. OK, for several hundred printers listed for HP alone no screen would have been large enough, so it can’t be avoided. But one page only shows 4 lines and the last one is even only half visible.
  3. And also, the list is not even wide enough to display the full text of the entries. So we get a horizontal scroll bar too which further reduces the number of lines visible.

In my opinion this is really bad UI design. That dialog could be improved a lot by simply changing it to be sizable, anchor both lists to the left, top and bottom and the right list to the right as well.

I faked that dialog with Delphi so I could show you what I mean:

I even reproduced the ridiculously large white areas around the lists. But this dialog can be sized and has even got a maximize button. Let’s see what it looks like if I make it just a little bit larger:

No horizontal scroll bar any more. And all visible lines are completely visible rather than only half of the last one. And if I increased the height even more, it would become much easier to scroll the printer list down to the right model.

OK, so we make all our dialogs sizeable and set the control’s anchors correctly. Easy as cake. Is that it?

No. With more freedom for the user we get more things he can screw up. Have a look at the next screen shot:

A sizeable dialog can also be made smaller and this is what it looks like. Eeek! So what can we do about it? We set size restrictions.

The easiest way to do that, is designing forms in the smallest size you want them to have and then set its minimum size to the designed size.

I have got two simple helper functions that do this for me:

  TControlConstraints = (ccMinWidth, ccMinHeight, ccMaxWidth, ccMaxHeight);
  TControlConstraintsSet = set of TControlConstraints;
  ccMin = [ccMinWidth, ccMinHeight];
  ccMax = [ccMaxWidth, ccMaxHeight];
  ccAll = [ccMinWidth, ccMinHeight, ccMaxWidth, ccMaxHeight];
  ccFixedHeightMinWidth = [ccMinWidth, ccMinHeight, ccMaxHeight];
  ccFixedWidthMinHeight = [ccMinWidth, ccMinHeight, ccMaxWidth];

procedure TControl_SetConstraints(_Control: TControl; _Which: TControlConstraintsSet);
  if ccMinWidth in _Which then
    _Control.Constraints.MinWidth := _Control.Width;
  if ccMinHeight in _Which then
    _Control.Constraints.MinHeight := _Control.Height;
  if ccMaxWidth in _Which then
    _Control.Constraints.MaxWidth := _Control.Width;
  if ccMaxHeight in _Which then
    _Control.Constraints.MaxHeight := _Control.Height;

procedure TControl_SetMinConstraints(_Control: TControl);
  TControl_SetConstraints(_Control, ccMin);

So, in the constructor I simply call:

constructor TMyForm.Create(_Owner: TComponent);

Since we started out with a fixed size form, this does not have any negative effects. The form still has a minimum size that corresponds to the fixed size it used to have, so even users whose monitors are too small aren’t any worse off, and those who have large monitors can use all the space they want to.

Two more screenshots to just give you an idea of the difference:

This is the original dialog on a 24″ monitor with 1920×1280 pixel resolution:

It feels like a postage stamp.

And this is my fake dialog resized to about 1/4 of the monitor resolution:

(Of course here you see that I didn’t bother to add more lines to the lists than necessary to get my point across.)

Here is another example where a fixed sized dialog is not a good idea.

There is one entry field that takes a file name. In a fixed sized dialog you would usually end up with clipping that name because nowadays file names are very long since nobody has to type them any more. If you are a user, you still want to be able to see the full path. So, you simply make the dialog wider and tadaaa:

This is a special case where you probably don’t want the dialog to become any higher than the designed size. So what do you do? Simple, you also restrict the height:

constructor TMyForm.Create(_Owner: TComponent);
  TControl_SetConstraints(Self, ccFixedHeightMinWidth);

Now that user can resize it to make it wider, but the height will not change.

I’ll leave it at that for now. Expect more rambling in a future post.

And while you are waiting for that one, you can read what
David Millington said in his blog posts on How to Design a Great UI (part 2, part 3).