Feb 032016

The Delphi IDE comes preconfigured with quite a lot of keyboard shortcuts and the remaining keyboard combinations are getting less and less with every plugin that needs some more. Even worse, some functions have multiple shortcuts, e.g. the replace dialog can be called using each of Ctrl+Q H or Ctrl+R or Ctrl+H (what a waste!).

GExperts installs an entry in the main menu, which you can open with Alt+X, and then select one of the enabled experts with the keyboard, either with the menu item’s hotkey or using the up/down keys and Enter. So in theory it should be possible to call each expert with Alt+X + <some character>. And this in turn would alleviate the need for registering a shortcut for each of these experts, freeing this scarce resource for other uses.

So, problem solved? Unfortunately not. Depending on which experts are enabled, you get a few or many conflicting hotkeys for the menu entries. That wouldn’t be too bad, but unfortunately the IDE insists on remapping these hotkeys and in my opinion gets it totally wrong. Instead of first using the hotkeys assigned by GExperts and only then trying to resolve the conflicts, it totally screws it and we end up with many items that don’t get a hotkey, and even worse, which item gets which hotkey depends heavily on how many and which experts you have enabled. So, instead of memorizing Alt+X + G for “&Grep search”, (which is the hotkey assigned by GExperts) you might have to remember Alt+X H (“Grep searc&h”) or might even have to resort to using the arrow keys or the mouse.


(click for full size animation)

First I thought, I’d just disable this annoying behaviour by setting the GExperts menu’s AutoHotkeys property to maManual. This should have done the trick in theory, but in practice it does not work if the menu is bound to a toolbar rather than a form. I was unable to prevent the IDE from doing this stupid thing. So I went looking for other options.

The IDE itself still has some of the WordStar keyboard shortcuts that consist of not just one but two key presses, e.g. Ctrl+Q + F for accessing the search functionality or Ctrl+Q + G for replace. This got me thinking: Why not assign a similar leading shortcut, e.g. Ctrl+H to GExperts and let the user configure his own characters for the second key press? And display a hint window which keys are available, so it is easier to memorize them, e.g. like this.


The Open Tools API provides a mechanism to register these kinds of shortcuts. You simply specify more than one shortcut to a single callback method using the IOTAKeyBindingServices.AddKeyBinding method:

procedure TGxKeyboardBinding.BindKeyboard(const BindingServices: IOTAKeyBindingServices);
  DefaultKeyBindingsFlag = kfImplicitShift + kfImplicitModifier + kfImplicitKeypad;
  GExpertsShortcut: Byte;
  ShiftState: TShiftState;
  FirstShortCut: TShortCut;
  SecondShortCut: TShortCut;
  GExpertsShortcut := Ord('H');
  ShiftState := [ssShift, ssCtrl];
  FirstShortCut := ShortCut(GExpertsShortcut, ShiftState);
  SecondShortCut := ShortCut(Ord('X'), []);
  BindingServices.AddKeyBinding([FirstShortCut, SecondShortCut],
    TwoKeyBindingHandler, nil,
    DefaultKeyBindingsFlag, '', '');

The above registers Ctrl+Shift+H as the first shortcut and X as the second, so pressing Ctrl+Shift+H + X should call the TwoKeyBindingHandler. Simple, isn’t it? Not so. It worked for Ctrl+H + X but not for Ctrl+Shift+H + X. I couldn’t figure out what I might be doing wrong, so I turned to StackOverflow, which unfortunately for once didn’t provide a solution either.

And even worse: It turned out that pressing Ctrl+H in Delphi XE+ invoked the Replace dialog and there apparently was nothing I could do about this. So, back to square one (Do not pass Go. Do not collect $200…).

So, I gave up for the time being and went to bed (It was quite late anyway).

Maybe getting some sleep helped or maybe I am just a genius, but the solution I came up with today was quite simple:

Instead of going through the trouble of building and displaying a hint window, why not pop up a menu? This only requires one regular shortcut and by prepending the desired character to the menu items the IDE even does the work of calling the correct expert. No hooking Application.OnMessage for showing the hint window necessary. No two key shortcuts either. And even Ctrl+H no longer opened the the pesky Replace dialog in Delphi XE+. So here you go: An easy to memorize way to call the Experts.


(click for full size animation)

Now I just need to add the configuration UI for this.