How to properly handle single-key shortcuts on a form with multiple input controls?
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?
Answers
In Delphi, you can use the TWinControl
class to check whether a control is capable of receiving text input. The TWinControl
class is the base class for all controls that have a window handle (HWND), including input controls like TEdit
and TMemo
.
You can write a recursive function to iterate through all the controls on the form and its child controls, checking whether each control is a TWinControl
and whether it can receive text input. Here's an example of how you can implement such a function:
function IsTextInputControl(Control: TControl): Boolean;
var
I: Integer;
begin
Result := (Control is TCustomEdit) or (Control is TCustomMemo);
if not Result and (Control is TWinControl) then
begin
for I := 0 to TWinControl(Control).ControlCount - 1 do
begin
if IsTextInputControl(TWinControl(Control).Controls[I]) then
begin
Result := True;
Exit;
end;
end;
end;
end;
You can then call this function in your IsShortCut
method to determine whether the current focused control is a text input control:
function TForm1.IsShortCut(var Message: TWMKey): Boolean;
var
FocusedControl: TWinControl;
begin
Result := inherited IsShortCut(Message);
// Check if the focused control is a text input control
if (Message.CharCode = Ord('A')) and (ssCtrl in KeyDataToShiftState(Message.KeyData)) then
begin
FocusedControl := Screen.ActiveControl as TWinControl;
Result := not IsTextInputControl(FocusedControl);
end;
end;
This approach should provide a generic way to check whether the focused control is capable of receiving text input, without needing to explicitly handle each individual input control.