How to disable FMX ComboBox Mouse Wheel scroll - delphi

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

Related

Unintended tStringGrid.OnFixedCellClick firing behind tOpenDialog

I use Delphi Berlin on Windows 10. I need to use tOpenDialog on a tStringGrid based tForm.
When I double click a file which overlaps a fixed column or row on an open dialog onFixedCellClick event fires automatically right after the disapperance of the open dialog. In the following image the file is on the same position of fixed row which is the first line.
type
TForm1 = class(TForm)
StringGrid1: TStringGrid;
OpenDialog1: TOpenDialog;
procedure FormClick(Sender: TObject);
procedure StringGrid1FixedCellClick(Sender: TObject; ACol, ARow: Integer);
procedure FormCreate(Sender: TObject);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
StringGrid1.Options := StringGrid1.Options + [goFixedColClick, goFixedRowClick];
end;
procedure TForm1.FormClick(Sender: TObject);
begin
OpenDialog1.Execute;
end;
procedure TForm1.StringGrid1FixedCellClick(Sender: TObject; ACol, ARow: Integer);
begin
Caption := '';
end;
In most cases I can handle this by moving the dialog window or clicking the file once and clicking open button but I can't guarantee that other people who will use this would do that.
What is the reason and how can I solve this problem?
I believe this is a problem in how TCustomGrid triggers its OnFixedCellClick event on a mouse-up message (in its overriden MouseUp method) without checking if there was a corresponding mouse-down message (FHotTrackCell.Pressed). A quick fix (if you can copy and modify Vcl.Grids): on line 4564 in Berlin (in TCustomGrid.MouseUp method add another condition to check, leading to the call to FixedCellClick):
if ... and FHotTrackCell.Pressed then
FixedCellClick(Cell.X, Cell.Y);
In other words, don't call FixedCellClick if a mouse-up comes without a prior corresponding mouse-down.

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;

FireMonkey equivalent to Application.OnMessage?

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.

How to hide caret in Delphi TEdit?

I want to remove the caret from a TEdit control in Delphi. I have made the component Enabled := False but the caret still appears.
My question is how to remove the caret from a disabled TEdit control?
I assume that you mean TEdit control.
The solution is HideCaret function, the only problem is where to call it. The 2 event handlers below worked fine for me:
procedure TForm18.Edit1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
HideCaret(Edit1.Handle);
end;
procedure TForm18.Edit1MouseEnter(Sender: TObject);
begin
HideCaret(Edit1.Handle);
end;
Place a TApplicationEventscontrol on the form and in the OnIdle event, hide the caret, as follows. Set the event to nil so it only fires once.
procedure TFormMain.AppEventsIdle(Sender: TObject; var Done: Boolean);
begin
AppEvents.OnIdle := nil;
HideCaret(Memo1.Handle);
end;

Is mouse over Form?

This code is not working for me on Delphi XE:
http://delphi.about.com/cs/adptips2000/a/bltip0800_5.htm
procedure TForm1.FormDeactivate(Sender: TObject) ;
begin
ReleaseCapture;
end;
procedure TForm1.FormMouseMove
(Sender: TObject; Shift: TShiftState; X,Y: Integer) ;
begin
If GetCapture = 0 then
SetCapture(Form1.Handle) ;
if PtInRect(Rect(Form1.Left,
Form1.Top,
Form1.Left + Form1.Width,
Form1.Top + Form1.Height),
ClientToScreen(Point(x, y))) then
Form1.Caption := 'Mouse is over form' else
Form1.Caption := 'Mouse is outside of form';
end;
No errors - it just has no effect.
Please help.
EDIT 1
It turned out the problem is not with the code, even mouse FormMouseEnter and FormMouseLeave are not working because I'm passing the form to a Unit I created with a function like this:
procedure Slide(Form: TForm; Show: Boolean);
I'm calling the Show method from inside this procedure. How can I overcome this problem?
Thanks.
EDIT 2
I don't want to use the function I posted now. I want to use what the people suggested below (FormMouseEnter and FormMouseLeave) but it's not working in my case as well.
You could use OnMouseEnter and OnMouseLeave events to keep track of whether the mouse is over the form or not without capturing the mouse cursor.
This is just a matter of entering the necessary code in the OnMouseEnter and OnMouseLeave events of the corresponding form. In my case, all I did was :
Create a new project in Delphi
Select the form you are working with
Go to the Object Inspector
Switch to the Events tab in the object inspector if necessary
Scroll down to the OnMouseEnter event, double click in the white space next to it which will generate an EventHandler. Make sure you end up with the following code in the event handler :
procedure TForm1.FormMouseEnter(Sender: TObject);
begin
Self.Caption := 'Mouse in form';
end;
Go to the Object Inspector again
Find the OnMouseLeave event and double click in the white area to the right of it to generate a new event handler, and add the following code to it
procedure TForm1.FormMouseLeave(Sender: TObject);
begin
Self.Caption := 'Mouse outside form';
end;
Run the app ... move your mouse over the form and the caption will change to 'Mouse inside form', move it outside the form and the caption will say 'Mouse outside form'
Works as a charm (Tested in Delphi 2010)
As far as I understand, using SetCapture for this is a bad idea. If it functioned like you wish, you would be robbing everyone else of the mouse messages just because you don't know a better way to track mouse.
But MSDN says (http://msdn.microsoft.com/en-us/library/ms646262(VS.85).aspx) that even with SetCapture, mouse messages from outside would not be redirected to your window unless mouse button is down (probably a measure to prevent exactly what are you trying to achieve: stealing mouse without a valid reason).
It doesn't matter where are you calling Show() from, so your problem is not in that.
I needed a form (frmTasks) with a heavily modified Caption. So I created a form with a hidden Caption. I simulate the Caption with a TImage (imgRedLogo) on which I draw the stuff I need.
This code lets the user to click the fake caption (the image) and move the form around. Works like a charm WITHOUT capturing the mouse. It works even with the right mouse button (you have to test the 'Button' parameter in imgRedLogoMouseDown if you want to disable this 'feature').
FULL WORKING CODE:
VAR
Dragged : Boolean= FALSE;
IsOverImg: Boolean= FALSE; { True if mouse if over the image }
OldPos : TPoint;
procedure TfrmTasks.imgRedLogoMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
Dragged:= True;
GetCursorPos(OldPos);
end;
procedure TfrmTasks.imgRedLogoMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
VAR NewPos: TPoint;
begin
if Dragged AND IsOverImg then
begin
GetCursorPos(NewPos);
frmTasks.Left:= frmTasks.Left- OldPos.X + NewPos.X;
frmTasks.Top := frmTasks.Top - OldPos.Y + NewPos.Y;
OldPos:= NewPos;
end;
end;
procedure TfrmTasks.imgRedLogoMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if Dragged
then Dragged:= False;
end;
procedure TfrmTasks.imgRedLogoMouseEnter(Sender: TObject);
begin
IsOverImg:= TRUE;
end;
procedure TfrmTasks.imgRedLogoMouseLeave(Sender: TObject);
begin
IsOverImg:= FALSE;
end;
Enjoy.

Resources