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.