I have a form in Delphi with some panels. The panels do contain controls which can receive text input (like tEdit
and tMemo
), and also other controls which do not normally receive text input (like tButton
). The main form also has a shortcut defined when the "A" character key is pressed, using the tActionList
component.
When the "A" key is pressed, it will always trigger the shortcut. I can override the IsShortCut
method in my form, and manually check whether the current focus is on one of the input controls. But this has the backside that I need to go through each of them explicitly (there are a lot of them), and as some of the components can have inner controls (like the finder in a grid) it is difficult to cover them all.
Is there some generic way to check whether the control that has focus on a form is some text input control?
Typically, if your form has controls that accept character input, you don't use plain characters as action shortcuts.
Instead, you use modifiers, like Ctrl+S, or function keys, like F7.
It might also be worth recalling that all buttons (except default OK and cancel Cancel buttons) should have access keys, like &Save
. If a button's caption is &Save
, the S will be underlined and pressing S when the form is focused will "click" the &Save
button, even if it isn't focused itself -- as long as the currently focused control doesn't accept character input (like a TEdit
), of course.
Having said this, I'm not sure if you are aware of the possibility to test the class of the focused control?
function TForm1.FocusedControlAcceptsChars: Boolean;
begin
var LCtl := ActiveControl;
Result := (LCtl is TCustomEdit) {or (LCtl is TCustomRichEdit) or (LCtl is TCustomListView) or ...};
end;
This way, you don't need to test against 132 child controls, say, but against 3 or 4 control classes.
If this is still not good enough, you may want to ask the focused control itself if it does accept character input:
function TForm1.FocusedControlAcceptsChars2: Boolean;
begin
var LCtl := ActiveControl;
if LCtl = nil then
Exit(False);
Result := LCtl.Perform(WM_GETDLGCODE, 0, 0) and DLGC_WANTCHARS <> 0;
end;
Obviously, these two approaches can be combined.