Сочетания клавиш TMenuItem перезаписывают сочетания клавиш из элементов управления (TMemo) - PullRequest
1 голос
/ 09 июля 2009

Что я могу сделать, чтобы ярлыки для пунктов меню не перезаписывали ярлыки от локальных элементов управления? Представьте себе это простое приложение на скриншоте. У него есть один пункт меню «Отменить» с назначенным ему сочетанием клавиш CTRL + Z (Strg + Z на немецком языке). Когда я редактирую некоторый текст в заметке и нажимаю CTRL + Z, я предполагаю, что последний ввод в заметке отменяется, но вместо этого выполняется пункт меню.

Это особенно плохо в этом вымышленном приложении, потому что функция отмены теперь удалит мой последний добавленный «Элемент 3», свойства которого я редактировал.

CTRL + Z - только пример. Другие популярные ярлыки вызывают похожие проблемы (Копировать и вставить: CTRL + X / C / V, Выбрать все: CTRL + A).

Мини-демонстрация с пунктом меню с сочетанием клавиш CTRL + Z http://img31.imageshack.us/img31/9074/ctrlzproblem.png

Ответы [ 2 ]

3 голосов
/ 09 июля 2009

VCL разработан, чтобы дать приоритет ярлыкам пунктов меню. Однако вы можете написать свой обработчик щелчка элемента (или обработчик выполнения действия), чтобы выполнить некоторую специальную обработку, когда ActiveControl имеет значение TCustomEdit (вызов отменен и т. Д.)

Редактировать: Я понимаю, что вам не нравится обрабатывать все возможные особые случаи во многих местах вашего кода (все пункты меню или обработчики действий). Боюсь, я не могу дать вам полностью удовлетворительный ответ, но, возможно, это поможет вам найти более общее решение. Попробуйте следующий обработчик события OnShortCut в вашей форме:

procedure TMyForm.FormShortCut(var Msg: TWMKey; var Handled: Boolean);
var
  Message: TMessage absolute Msg;
  Shift: TShiftState;
begin
  Handled := False;
  if ActiveControl is TCustomEdit then
  begin
    Shift := KeyDataToShiftState(Msg.KeyData);
    // add more cases if needed
    Handled := (Shift = [ssCtrl]) and (Msg.CharCode in [Ord('C'), Ord('X'), Ord('V'), Ord('Z')]);
    if Handled then
      TCustomEdit(ActiveControl).DefaultHandler(Message);
  end
  else if ActiveControl is ... then ... // add more cases as needed
end;

Вы также можете переопределить метод IsShortCut аналогичным образом и извлечь формы вашего проекта из этого нового потомка TCustomForm.

1 голос
/ 09 июля 2009

Возможно, вам нужно похожее решение, как показано ниже. Да, кажется громоздким, но это самый простой способ, который я мог придумать в то время. Если бы только Дельфи разрешил печатать на утке!

  { you need to derive a class supporting this interface 
    for every distinct control type your UI contains }
  IEditOperations = interface(IInterface)
    ['{C5342AAA-6D62-4654-BF73-B767267CB583}']
    function CanCut: boolean;
    function CanCopy: boolean;
    function CanPaste: boolean;
    function CanDelete: boolean;
    function CanUndo: boolean;
    function CanRedo: boolean;
    function CanSelectAll: Boolean;

    procedure CutToClipBoard;
    procedure Paste;
    procedure CopyToClipboard;
    procedure Delete;
    procedure Undo;
    procedure Redo;
    procedure SelectAll;
  end;

// actions....

procedure TMainDataModule.actEditCutUpdate(Sender: TObject);
var intf: IEditOperations;
begin
  if Supports(Screen.ActiveControl, IEditOperations, intf) then
    (Sender as TAction).Enabled := intf.CanCut
  else
    (Sender as TAction).Enabled := False;
end;

procedure TMainDataModule.actEditCutExecute(Sender: TObject);
var intf: IEditOperations;
begin
  if Supports(Screen.ActiveControl, IEditOperations, intf) then
    intf.CutToClipBoard;
end;

....
...