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?

 Posted by on 2018-07-21 at 12:00