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;
精彩评论