开发者

How can I prevent the main form capturing keystrokes in a TMemo on another non-modal form?

I have an app that opens a non-modal form from the main form. The non-modal form has a TMemo on it. The main form menu uses "space" as one of its accelerator characters.

When the non-modal form is open and the memo has focus, every time I try to enter a space into the memo on the non-modal form, the main form event for the "space" shortcut fires!

I have tried turning MainForm.KeyPreview := false while the other form is open bu开发者_开发问答t no dice.

Any ideas?


Disable the menu item on the main form while the memo has focus, and re-enable it when the memo loses it. You can do this from the TMemo.OnEnter and TMemo.OnExit events.

procedure TOtherForm.Memo1Enter(Sender: TObject);
begin
  if Application.MainForm is TYourMainForm then
    TYourMainForm(Application.MainForm).MenuItemWithSpace. Enabled := False;
end;

procedure TOtherForm.Memo1Exit(Sender: TObject);
begin
  if Application.MainForm is TYourMainForm then
    TYourMainForm(Application.MainForm).MenuItemWithSpace. Enabled := True;
end;

The use of Application.MainForm and the typecast are to prevent hard-coding in a form variable name in the child form.


This may be an old topic, but i had the same issue a moment ago and searched for a suitable solution. Your topic came up but not with a solution i would want to use.

My problem was: I have a main form with a lot of shortcuts (Backspace, Delete, etc) and a second form with an edit box. The edit box didn't get any key actions, which are handled by the main form shortcuts.

My solution: Set the child forms OnShortCut, wich will catch the shortcuts before they get interpreted by the main form with:

procedure ChildForm.FormShortCut(var Msg: TWMKey; var Handled: Boolean);
begin
  Handled := True;
  Self.DefaultHandler(Msg);
end;

That did the trick for me, the child form catches the shortcuts and handles them as common key messages. The edit box can be used as intended.


If you have many menu items, or many controls, could be very difficult to threat the problem for each of them. Instead, you could use a function in FormActivate() and FormDeActivate() methods of main window in order to clean and restore all shortcuts in a easy and simple way:

var sstore : TStrings;

procedure Tmain_form.FormActivate(Sender: TObject);
begin
    if (sstore <> NIL) then tratta_shortcuts_menu(main_menu, {read_shortcuts}FALSE, sstore)
end;

procedure Tmain_form.FormDeactivate(Sender: TObject);
begin
    tratta_shortcuts_menu(main_menu, {read_shortcuts}TRUE, sstore)
end;

procedure tratta_shortcuts_menu(menu : TMainMenu;bo_read_shortcuts : boolean;var sstore : TStrings);
{ if BO_READ_SHORTCUTS then 1) read shortcuts 2) save them on SSTORE (Shortcuts STORE) 3) delete them from menu;
ELSE restore all shortcuts from SSTORE  }

procedure sostituisci(im : TMenuItem);
const INDICATORE_SHORTCUT = '~ ';
begin
    if bo_read_shortcuts then begin
        if (im.ShortCut <> 0) then begin
            sstore.Add(im.name);
            sstore.Add(INDICATORE_SHORTCUT + menus.ShortCutToText(im.ShortCut));    
            im.ShortCut := 0
        end
    end
    else begin
        var i : smallint := sstore.indexof(im.Name);
        if (i <> -1) then begin
            im.ShortCut := menus.TextToShortCut(copy(sstore[i + 1], length(INDICATORE_SHORTCUT) + 1, MAXINT))
        end
    end
end;

procedure tratta(im : TMenuItem);
begin
    sostituisci(im);
    for var i : smallint := 0 to im.Count-1 do tratta(im.Items[i])
end;

begin
    if (menu = NIL) then exit;

    if bo_read_shortcuts then begin if (sstore = NIL) then sstore := TStringList.Create else sstore.Clear end;
    for var i : smallint := 0 to menu.Items.Count-1 do tratta(menu.Items[i]);
    if NOT bo_read_shortcuts then begin sstore.Free;sstore := NIL end
end;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜