How to properly handle single-key shortcuts on a form with multi

ghz 7months ago ⋅ 119 views

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.