Как добавить связывание клавиш Shift+Ctrl+H X в Delphi IDE с помощью ToolsApi?

Добавление нового ShortCut в Delphi IDE не так уж сложно, поскольку API Open Tools предоставляет для этого сервис. Я пытаюсь сделать что-то более сложное: добавить Wordstar, как дополнительный ShortCut:

Я хочу, чтобы что-то произошло, когда пользователь нажимает

Shift+Ctrl+H, сопровождаемый единственной клавишей X

где X должен работать независимо от состояния клавиши Shift.

Это мой код:

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

Итак, если я установлю ShiftState:= [ssCtrl] нажав

Ctrl+H X

вызывает мой метод TwoKeyBindingHandler.

Но с ShiftState:= [ssShift, ssCtrl] нажатие

Shift+Ctrl+H X

ничего не делает.

Как ни странно, при указании ShiftState:= [ssShift, ssCtrl] (который должен влиять только на первую клавишу) нажатие

Shift+Ctrl+H Shift+X

вызывает мой метод TwoKeyBindingHandler, хотя второй ShortCut добавляется без клавиши-модификатора.

Любая идея? Может быть, это известное ограничение / ошибка API Delphi IDE/Open Tools? Есть ли известный обходной путь?

Я пробовал это в Delphi 2007 и Delphi 10 Seattle, без разницы.

2 ответа

Вы должны быть в состоянии сделать это, используя функцию GetKeyState.

У программы есть две операции - Думайте об этом как об открытии пункта выпадающего меню. При нажатии ctr-shift-h вашей программе нужно будет отметить, что "Меню" теперь открыто и что последующие нажатия клавиш либо активируют опцию, либо закрывают "Меню", если нажата недопустимая клавиша.

function IsKeyDown(const VK: integer): boolean;
begin
  IsKeyDown := GetKeyState(VK) and $8000 <> 0;
end;

procedure Form1.OnkeyDown(...)   
begin
 if Not H_MenuOpen then 
 if IsKeyDown(vk_Control) and IskeyDown(vk_Shift) and IsKeyDown(vk_H) then
 begin
      //Some Boolean in the form
      H_MenuOpen:=True;
      //Will probably need to invalidate some parameters here so that 
      //no control tries to process the key
      exit;
 end;

 if H_MenuOpen then
 begin
      if key=vk_X then 
      begin
          //x has been pressed
          *Your code here* 
          //possibly invalidate some of the params again
          exit;
      end;
     //Nothing valid
    H_MenuOpen:=False;
 end;

конец;

Хорошо, так как, очевидно, никто не нашел ответа, вот что я в итоге сделал:

Я уже планировал показать окно подсказки со списком всех возможных символов для второго ключа (фактически этот код уже работал нормально, используя подход, предложенный Хелен Фэргрив в ее ответе на этот вопрос). Вместо этого я теперь регистрирую только комбинацию клавиш:

BindingServices.AddKeyBinding([FirstShortCut],
  TwoKeyBindingHandler, nil,
  DefaultKeyBindingsFlag, '', '');

А в методе TwoKeyBindingHandler я показываю всплывающее меню, которое содержит эти символы в качестве ярлыков. Затем IDE/VCL/Windows обрабатывает все остальное для меня.

Вот как это выглядит: анимированный GIF с результатом

Это не ответ на актуальный вопрос, но он решает мою проблему. Извините, если вы попали сюда, ожидая чего-то большего.

Другие вопросы по тегам