TMenuItem-Shortcuts覆盖控件的快捷方式(TMemo)

时间:2009-07-09 14:48:53

标签: delphi delphi-2009

如果菜单项的快捷方式不会覆盖本地控件的快捷方式,我该怎么办? 想象一下截图中的这个简单的应用程序。它有一个“撤消”菜单项,分配给它的快捷键CTRL + Z(德语为Strg + Z)。当我在备忘录中编辑一些文本并按CTRL + Z时,我假设备忘录中的最后一个输入被还原,而是执行菜单项。

这在这个虚构的应用程序中尤其糟糕,因为撤消功能现在将删除我上次添加的“项目3”,我正在编辑哪些属性。

CTRL + Z只是一个例子。其他流行的快捷方式会导致类似的问题(复制和粘贴:CTRL + X / C / V,全选:CTRL + A)。

Mini Demo with menu item with CTRL+Z short-cut http://img31.imageshack.us/img31/9074/ctrlzproblem.png

2 个答案:

答案 0 :(得分:3)

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 :(得分:1)

您可能需要一个类似的解决方案,如下所示。是的,感觉很麻烦,但这是我当时想到的最简单的方法。如果只有Delphi允许鸭子打字!

  { 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;

....