FireMonkey equivalent to Application.OnMessage? - delphi

With Delphi Win32 (VCL) I use:
Application.OnMessage := MyAppMessage;
What is the equivalent in FireMonkey?
I have a routine that needs to catch all the keyboard and mouse events in the application (on all the active form controls) and handle them.

I don't know of a way in FireMonkey to capture mouse and keyboard events at the application level in a platform agnostic way. I don't think that has been implemented yet, as of Delphi XE 2 Update 2.
However, by default FireMonkey forms get all of the MouseDown and KeyDown events before the controls do.
If you simply override the MouseDown and KeyDown events on your form, you'll accomplish the same thing.
type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
private
{ Private declarations }
public
{ Public declarations }
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Single); override;
procedure KeyDown(var Key: Word; var KeyChar: System.WideChar; Shift: TShiftState); override;
end;
{ TForm1 }
procedure TForm1.KeyDown(var Key: Word; var KeyChar: System.WideChar;
Shift: TShiftState);
begin
// Do what you need to do here
ShowMessage('Key Down');
// Let it pass on to the form and control
inherited;
end;
procedure TForm1.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
Y: Single);
begin
// Do what you need to do here
ShowMessage('Mouse Down');
// Let it pass on to the form and control
inherited;
end;
If you want, you can keep going with MouseMove, MouseUp, MouseWheel, MouseLeave, KeyUp, DragEnter, DragOver, DragDrop, and DragLeave.

FireMonkey is cross platform and runs on Windows, Mac OSX, iOS and no doubt many other platforms in due course. Therefore there are no Windows messages exposed by FireMonkey.
Whatever it is you are used to doing with OnMessage in the VCL most likely has an equivalent in FireMonkey. Exactly what that equivalent is depends very much on what your OnMessage handler is trying to achieve.

These answers are fine for exposed events, but for other obscure system events it's more tricky. At the time of writing this link isn't answered:
capturing-usb-plug-unplug-events-in-firemonkey
but it will help with solving the general problem.
I would have posted this as a comment not an answer, but the previous answers were not accepting further comments.

Related

How to disable FMX ComboBox Mouse Wheel scroll

How can I disable the mouse wheel scroll on a FMX TComboBox when hovering over it?
I've tried overriding the MouseWheel method without any luck. I'm most likely doing it wrong as I'm not experienced with overriding. REF: MouseWheel
I've gone ahead and removed Inherited:
type
TComboBoxOverride = class(TComboBox)
procedure MouseWheel(Shift: TShiftState; WheelDelta: Integer; var Handled: Boolean); override;
end;
// I've tried changing the control on the class overriding the method. No luck
cbbServerMap: TComboBoxOverride;
{ TComboBoxOverride }
procedure TComboBoxOverride.MouseWheel(Shift: TShiftState; WheelDelta: Integer;
var Handled: Boolean);
begin
Handled := True;
end;
I've found the following SO post for VCL and DevEx but I'm struggling to convert it to FMX, Ref: How to suppress mouse wheel in TcxComboBox
When setting a breakpoint on the TCustomComboBox.MouseWheel method I can see that it ignores my override.
In the OnMouseWheel event, simply put Abort;.
For example:
procedure TfrmMinorInjury.cboDischargetypeMouseWheel(Sender: TObject;
Shift: TShiftState; WheelDelta: Integer; var Handled: Boolean);
begin
Abort;
end;
I solved the same task but for memos in scrollbox.
My solution is
handle mouse wheel in scrollbox.OnMouseWheel. Set Handle := true there.
call directly scrollbox.OnMouseWheel in memo's OnMouseWheel

How change characters to asterisk on TEdit onkeyup event?

my client requested to me for make a "effect" where each time that release any key of keyboard, change this character to asterisk on field.
How do this in Delphi?
I have in Html + Javascript like this. .js code can be found here.
There is no way to achieve what you want with the standard Delphi controls.
The VCL edit control uses the feature of the underlying Windows EDIT control to mask input characters for "Password" type edit controls. The behaviour is therefore determined by the Windows (OS) control, not Delphi itself.
You could try to get the effect you need by using a non-password field and handling key events to replace characters as required with asterisks or any other masking character, but you would also need to separately maintain the intended content of the edit control.
This would almost certainly be easier to implement as a custom edit control, rather than trying to customize the behaviour of a standard edit control with events.
I suspect that the implementation of a custom control is not the solution you are after however.
The below simulates the behavior of the js code with the difference backspace is also handled.
type
TForm2 = class(TForm)
Edit1: TEdit;
procedure Edit1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure Edit1KeyPress(Sender: TObject; var Key: Char);
private
FEditText: string;
procedure TForm2.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
if Key = ^H then
SetLength(FEditText, Length(FEditText) - 1)
else
FEditText := FEditText + Key;
end;
procedure TForm2.Edit1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
Edit1.Text := StringOfChar('*', Length(Edit1.Text));
Edit1.SelStart := Length(Edit1.Text);
end;
FEditText is the equivalent of df[0].Value in js code, the actual value that is typed.
Note that there's no option to reset the text, as there is none in the js code.

Delphi how to implement baseclass event?

I have an abstract Delphi XE form that acts as base class for a family of forms used in my application. I am trying to figure out the best way to make a help function (on F1 keypress) that opens a wiki-page for the active form.
I'd very much like this function to be implemented at base-class level and to call when the user presses F1 but I need some advice on how to do this in a smart way. Currently I just put a KeyDown-event on the base form but this gets overwritten if the subform receives its own KeyDown, at which point I have to manually call the baseKeyDown. Obviously, this is not optimal.. Is there a way to ensure I catch the F1 keypress at baseclass level, random overloads nonwithstanding?
I am running Delphi XE on Windows 7
The straight answer to your question is that a library writer should not assign to event handlers. That's because doing so makes it hard for library consumers to also consume those events. And when you are writing a base class, you are taking the role of the library author.
So, instead of implementing the handler in the OnKeyDown event, override the KeyDown method.
type
TBaseForm = class(TForm)
protected
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
end;
....
procedure TBaseForm.KeyDown(var Key: Word; Shift: TShiftState);
begin
inherited; // this will fire the OnKeyDown event
// your processing for F1 goes here
end;
However, I wonder if you would not be better off using the built in help system. Personally I'd add an OnHelp event for the Application object and place the centralised logic there.
You should override KeyDown method in your base form class.
type
TBaseForm = class(TForm)
protected
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
end;
procedure TBaseForm.KeyDown(var Key: Word; Shift: TShiftState);
begin
// do your processing here
// ...
inherited; // call inherited method that will call OnKeyDown if assigned
end;
This is default implementation of KewDown method that calls OnKeyDown events
procedure TWinControl.KeyDown(var Key: Word; Shift: TShiftState);
begin
if Assigned(FOnKeyDown) then FOnKeyDown(Self, Key, Shift);
end;

Changing default behaviour for TCombobox

I have a project with multiple forms that use TCombobox and i would like to remove the default behavior when a focused combobox receives a Return stroke:
In the Keydown of TCustomCombobox:
vkF4, vkReturn:
DropDown;
Q: How could i remove the functionality for all my forms?
Creating a new custom control that overrides this would mean to much work to recreate all the comboboxes.
A: Make an "imposter" subclass :
Found a Duplicate question : Delphi subclass visual component and use it
I put this code in a unit, and put that unit in the interface/uses of my forms.
TCombobox = class(FMX.ListBox.TComboBox)
protected
procedure KeyDown(var Key: Word; var KeyChar: System.WideChar; Shift: TShiftState);override;
end;
procedure TCombobox.KeyDown(var Key: Word; var KeyChar: System.WideChar;
Shift: TShiftState);
begin
if key=vkReturn then exit;
inherited;
end;

Filter(disabling) mouse wheel messages in a VisualCLX Form

I have inherited a Delphi 7 (VisualCLX) application to maintain and I want to filter some windows message like the mouse wheel (WM_MOUSEWHEEL) on the main form(TForm) of the application, is it possible on the Visual CLX ? How ?
I know that is possible on the VCL, but I'm looking for some solutions on the old Cross-Platform (CLX) ...
Note
I need to disable the mousewheel event because it keeps changing the active page(TPageControl) and this is very annoying in Delphi with Component Library for Cross-Platform (CLX), so any other workaround that solve the problem is welcome ...
Filtering input messages in CLX is not simple. There appears to be nothing like the VCL's OnMessage.
You can stop mouse wheel events being handled by CLX page controls with a simple interposer. Add this code to your main form, before the declaration of your main form class.
type
TPageControl = class(QComCtrls.TPageControl)
protected
function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
const MousePos: TPoint): Boolean; override;
end;
And then in the implementation section of the unit, add this:
function TPageControl.DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
const MousePos: TPoint): Boolean;
begin
Result := True;
end;
If you have a number of page controls on different forms then you should declare the interposer in a unit that can be shared by all the forms in your app. Or maybe even derive a proper grown-up sub-class.

Resources