“Hooking” KeyDown in a Firemonkey form

  

As said in my last post: " The hard part is hooking the form in a way so all I need to do is call TForm_ActivatePositioning as in the VCL."
As it turns out, that’s even easier to do than in the VCL. No subclassing of the window, just adding a new control is sufficient. As this StackOverflow answer points out, a Firemonkey form calls the DialogKey method of all its child controls when a key is pressed, starting with the one that has got the focus. So, all we’ve got to do is creating a control that handles the keys we want to intercept and add it to the form.
Here is the code:

type
TFormPositioningActivator = class(TControl)
private
FModifier: TShiftState;
protected
procedure DialogKey(var Key: Word; Shift: TShiftState); override;
public
constructor Create(_Form: TCustomForm; _Modifier: TShiftState); reintroduce;
end;

{ TFormHookChild }

constructor TFormPositioningActivator.Create(_Form: TCustomForm; _Modifier: TShiftState);
begin
inherited Create(_Form);
FModifier := _Modifier;
Parent := _Form;
end;

procedure TFormPositioningActivator.DialogKey(var Key: Word; Shift: TShiftState);
begin
inherited;
if Shift = FModifier then begin
case Key of
vkLeft: TForm_MoveTo(self.Parent as TForm, dwpLeft);
vkRight: TForm_MoveTo(self.Parent as TForm, dwpRight);
vkUp: TForm_MoveTo(self.Parent as TForm, dwpTop);
vkDown: TForm_MoveTo(self.Parent as TForm, dwpBottom);
vkHome: TForm_MoveTo(self.Parent as TForm, dwpTopLeft);
vkEnd: TForm_MoveTo(self.Parent as TForm, dwpBottomLeft);
vkPrior: TForm_MoveTo(self.Parent as TForm, dwpTopRight);
vkNext: TForm_MoveTo(self.Parent as TForm, dwpBottomRight);
else
Exit; // so Key doesn’t get set to 0
end;
Key := 0;
end;

end;

function TForm_ActivatePositioning(_Form: TForm; _Modifier: TShiftState = [ssCtrl, ssAlt]): TObject;
begin
Result := TFormPositioningActivator.Create(_Form, _Modifier);
end;

All you have to do is call TForm_ActivatePositioning(Self) in the form’s constructor and be done.

Comments are closed.