2009-07-09 76 views
1

我能做些什麼菜單項的快捷方式不會覆蓋來自本地控件的快捷方式? 想象一下這個簡單的應用程序的截圖。它有一個「撤消」菜單項,並且CTRL + Z(德語的Strg + Z)分配給它。當我在備忘錄中編輯一些文本並按CTRL + Z時,我假定備忘錄中的最後一個輸入被恢復,但是相反,菜單項被執行。TMenuItem-Shortcuts覆蓋控件的快捷方式(TMemo)

這在這個虛構的應用程序中尤其糟糕,因爲撤消功能現在會刪除我最後添加的「Item 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

+0

爲什麼添加一個撤消功能,當你正在使用的控件已經有一個內置? – 2009-07-09 14:59:25

+2

如果編輯框有焦點,他想撤消對文本的更改。如果別的東西有焦點,他希望將整體變化撤回到最後一次保存的時間。 – 2009-07-09 15:38:58

回答

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

您可能需要一個類似的解決方案如下。是的,感覺很麻煩,但這是我當時想到的最簡單的方法。如果只有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; 

....