Jump to content
dmitrybv

How can you track that the mouse is over a certain control or over any of its Child controls.

Recommended Posts

Posted (edited)

How can you track that the mouse is over within the boundaries of the control, regardless of the Child controls?


If the mouse inside the Parent control moves to the Child control, then the OnMouseLeave event is triggered for the Parent control, although we are still within the boundaries of the Parent control.


For example, I created a project in which I try to highlight the Parent control in red while we are within the boundaries of the Parent control. But as soon as the mouse moves to any Child control, the Parent control loses the mouse and the shading disappears.

 

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Objects, FMX.Controls.Presentation, FMX.StdCtrls;

type
  TForm1 = class(TForm)
    ParentPanel: TRectangle;
    Button1: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Rectangle2: TRectangle;
    Label3: TLabel;
    procedure ParentPanelMouseEnter(Sender: TObject);
    procedure ParentPanelMouseLeave(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.ParentPanelMouseEnter(Sender: TObject);
begin
  ParentPanel.Fill.Color := TAlphaColorRec.Red;
end;

procedure TForm1.ParentPanelMouseLeave(Sender: TObject);
begin
  ParentPanel.Fill.Color := $FFE0E0E0;
end;

end.

image.thumb.png.6228cc668921530cb1b3dba9b5035ae9.png

 

image.thumb.png.b264e6bc07567ed92981af9fd709da24.png

FmxDemo.zip

Edited by dmitrybv

Share this post


Link to post
43 minutes ago, dmitrybv said:

How can you track that the mouse is over within the boundaries of the control, regardless of the Child controls?

You could use GetMousePos to check if the mouse is inside of it, like this:

uses
  FMX.Platform;

procedure TForm1.ParentPanelMouseLeave(Sender: TObject);
var
  LService: IFMXMouseService;
  LPoint: TPointF;
begin
  if TPlatformServices.Current.SupportsPlatformService(IFMXMouseService, LService) then
  begin
    LPoint := ScreenToClient(LService.GetMousePos);
    if not ParentPanel.AbsoluteRect.Contains(LPoint) then
      ParentPanel.Fill.Color := $FFE0E0E0;
  end;
end;

 

Share this post


Link to post

Dave, thanks for the advice.

But this doesn't work when:
- One of the boundaries of the Child control is on the boundary of the Parent control. In this case, if the mouse cursor leaves the Child control at this boundary, it does not trigger the MouseLeave event for the Parent control.
- If the mouse cursor moves fast enough, then the MouseLeave event does not have time to arrive in the Parent control, the event goes to some other external control.

image.thumb.png.21bc41f512eee67aaa23118e35da6d81.png

Share this post


Link to post
Posted (edited)

Assign the same mouse enter and mouse leave event for each of the controls in question.

 

Looking at the .dfm as text we can see that the same mouse enter / leave event was manually set.

 

  object Rectangle1: TRectangle
    Position.X = 80.000000000000000000
    Position.Y = 232.000000000000000000
    Size.Width = 489.000000000000000000
    Size.Height = 177.000000000000000000
    Size.PlatformDefault = False
    OnMouseEnter = Panel1MouseEnter
    OnMouseLeave = Panel1MouseLeave
    object Button1: TButton
      Position.X = 128.000000000000000000
      Position.Y = 74.000000000000000000
      TabOrder = 2
      Text = 'Button1'
      TextSettings.Trimming = None
      OnMouseEnter = Panel1MouseEnter
      OnMouseLeave = Panel1MouseLeave
    end
    object Button2: TButton
      Position.X = 352.000000000000000000
      Position.Y = 70.000000000000000000
      Size.Width = 89.000000000000000000
      Size.Height = 27.000000000000000000
      Size.PlatformDefault = False
      TabOrder = 1
      Text = 'Button2'
      TextSettings.Trimming = None
      OnMouseEnter = Panel1MouseEnter
      OnMouseLeave = Panel1MouseLeave
    end
  end

The following is assigned event.

 

procedure TForm8.Panel1MouseEnter(Sender: TObject);
begin
  Caption := 'Hovering over ' + TControl(Sender).name;
  Rectangle1.Fill.Color := TAlphaColorRec.Red;
end;

procedure TForm8.Panel1MouseLeave(Sender: TObject);
begin
  Caption := 'Not hovering over ' + Rectangle1.Name;
  Rectangle1.Fill.Color := TAlphaColorRec.Green;
end;

 

Edited by Pat Foley
expand answer

Share this post


Link to post
Posted (edited)

Another approach: Code like that suggested by Dave but in the form's MouseMove and leave MouseLeave for the panel blank.

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y:
    Single);
var
  LPoint: TPointF;
begin
  if (ParentPanel.Fill.Color = TAlphaColorRec.Red) then
  begin
    LPoint.X := X;
    LPoint.Y := Y;
    if not ParentPanel.AbsoluteRect.Contains(LPoint) then
      ParentPanel.Fill.Color := $FFE0E0E0;
  end;
end;

procedure TForm1.ParentPanelMouseEnter(Sender: TObject);
begin
  ParentPanel.Fill.Color := TAlphaColorRec.Red;
end;

procedure TForm1.ParentPanelMouseLeave(Sender: TObject);
begin
 // ParentPanel.Fill.Color := $FFE0E0E0;
end;

 

Edited by Brian Evans

Share this post


Link to post

This feature must be used in a separate component.
A component must not assign events to other external Components (Controls) or Forms.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×