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?
