Recent

Author Topic: TForm.OnMouseLeave not working  (Read 9803 times)

Handoko

  • Hero Member
  • *****
  • Posts: 4087
  • My goal: build my own game engine using Lazarus
Re: TForm.OnMouseLeave not working
« Reply #15 on: May 30, 2017, 09:03:39 am »
Just installed Lazarus 1.8.0RC1 2017-05-15 FPC 3.0.3 x86_64-linux-gtk2 and tested the code. The result is same.

If I move fast enough, the issue is always reproducible.

Handoko

  • Hero Member
  • *****
  • Posts: 4087
  • My goal: build my own game engine using Lazarus
Re: TForm.OnMouseLeave not working
« Reply #16 on: June 03, 2017, 10:00:42 am »
I checked the Lazarus Bugtracker and I found this issue may be related with these:

- 0031511: MouseLeave not called ... gtk2, 2017-03-09
https://bugs.freepascal.org/view.php?id=31511

- 0031510: MouseLeave isn't executed ..., 2017-03-08
https://bugs.freepascal.org/view.php?id=31510

- 0022098: MouseLeave not always fired, 2012-05-22
https://bugs.freepascal.org/view.php?id=22098

Handoko

  • Hero Member
  • *****
  • Posts: 4087
  • My goal: build my own game engine using Lazarus
Re: TForm.OnMouseLeave not working
« Reply #17 on: February 02, 2020, 10:38:54 am »
IIRC, I fixed this in 1.7. Please retest in 1.8 RC1.

I retested the issue again today on Lazarus 2.0.6 GTK2 Ubuntu 19.10, it's still not fixed yet.

jamie

  • Hero Member
  • *****
  • Posts: 4210
Re: TForm.OnMouseLeave not working
« Reply #18 on: February 05, 2020, 02:19:27 am »
Mouse movements of that nature in windows is a low priority..

a message is sent via the OS but it can get delayed and it can also get trashed.

on my system it seems to work ok but on slower systems the mouse may skip outside the form and if the system is busy it won't get sent.

 maybe the onActivate and OnDeActivate form is what you can use
The only true wisdom is knowing you know nothing

Handoko

  • Hero Member
  • *****
  • Posts: 4087
  • My goal: build my own game engine using Lazarus
Re: TForm.OnMouseLeave not working
« Reply #19 on: February 05, 2020, 02:47:46 am »
Yes, just like you said if I move the move away slowly there will be no problem. Unfortunately users do not always move the mouse slowly.  :D

On activate/deactive may work but not suitable for the case I want to do.

jamie

  • Hero Member
  • *****
  • Posts: 4210
Re: TForm.OnMouseLeave not working
« Reply #20 on: February 05, 2020, 10:40:48 pm »
I am not exactly sure what it is  you are doing but I can only assume you are jumping between windows and need to know this information ?

 What I do when using mouse as a free hand drawing or dragging tool I always record the last mouse position I processed and there for I use a Lineto call for free hand drawing instead of a point draw.

 This will guarantee that I do not have any broken lines sections ..

 In your case what you should be doing is recording the MouseMove Plots in a global location so that each time a mouse move is received you can first test to see what the last one was. If the last one was in a different form then you can execute the OnMouseEnter yourself in code.

 When doing such a practice you always record the current location for the next time you receive the message and thus can test for this..

 So basically you need to use the Mouse Move event and do your own Enter and Exit where by you can check the last control it was over.
The only true wisdom is knowing you know nothing

winni

  • Hero Member
  • *****
  • Posts: 2214
Re: TForm.OnMouseLeave not working
« Reply #21 on: February 05, 2020, 11:25:29 pm »
Maybe I don't understand how the Mouse Leave works. But I think it has 2 issues:

- If we move the mouse pointer to other controls (for example a button), that is still inside the form the OnMouseLeave will be triggered. I think it is wrong because that control is inside the form. Correct me if I'm wrong.

- If we move the mouse pointer from inside to the outside of the form, the OnMouseLeave will not be triggered. It is definitely wrong. (Actually, it will be triggered but at very low chances, perhaps 1% only)

Any test from others, maybe Windows?

Hi!

In your first szenario the behaviour is correct. The enter/leave event depends on the z-axis : The highest component is triggerd and get the focus - if possible.

OneMouseLeave for a form is not usable. You have to check if it is the Form is active or take the screen coordinates via application.OnMouseMove.

If the MouseLeave/MouseEnter inside an app gets lost you can  use the internal logic:

If the MouseMove of a component is triggered there must definitly  an Enter happend.

If  a MouseMove of anonother neighbour or parent component is triggered, then there must be a mouseleave for the first component.

This problem exists since the last millenium.
And I never had those problems with Delphi

Winni

Handoko

  • Hero Member
  • *****
  • Posts: 4087
  • My goal: build my own game engine using Lazarus
Re: TForm.OnMouseLeave not working
« Reply #22 on: November 09, 2020, 05:19:55 pm »
Hello, I'm back again.
Now with more detailed information.

I am not exactly sure what it is  you are doing ...

Look at the picture below.

I'm designing a form that lets users to select an item from a list. On the right bottom corner, there is an image 'F1', which means users can press F1 or click on the image.

To let user know that image is clickable, I want it to change color (or perhaps change the image to 'click me') when the mouse pointer is hovering on it. So I need to use OnMouseEnter and OnMouseLeave. Unfortunately OnMouseLeave is not 100% triggered. I tested on Lazarus 2.0.10 GTK2 Ubuntu Mate 20.04.

You have to check if it is the Form is active or take the screen coordinates via application.OnMouseMove.

I can't find TApplication.OnMouseMove. Where to find it?





Changing image is not simple so I wrote a demo that use a TButton instead.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, Forms, Controls, Graphics, ExtCtrls, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     Shape1: TShape;
  17.     procedure Button1MouseEnter(Sender: TObject);
  18.     procedure Button1MouseLeave(Sender: TObject);
  19.   end;
  20.  
  21. var
  22.   Form1: TForm1;
  23.  
  24. implementation
  25.  
  26. {$R *.lfm}
  27.  
  28. { TForm1 }
  29.  
  30. procedure TForm1.Button1MouseEnter(Sender: TObject);
  31. begin
  32.   Shape1.Brush.Color := clBlue;
  33. end;
  34.  
  35. procedure TForm1.Button1MouseLeave(Sender: TObject);
  36. begin
  37.   Shape1.Brush.Color := clWhite;
  38. end;
  39.  
  40. end.

Any solution? Workaround? Or maybe suggestion to use other component?

winni

  • Hero Member
  • *****
  • Posts: 2214
Re: TForm.OnMouseLeave not working
« Reply #23 on: November 09, 2020, 06:00:21 pm »
Hi Handoko!

To call the mouse from the application you have to use the hook called
Application.AddOnUserInputHandler.

Why ever they hide the word "mouse".

A little example is here:

https://forum.lazarus.freepascal.org/index.php/topic,22815.msg135328.html#msg135328

Winni

Handoko

  • Hero Member
  • *****
  • Posts: 4087
  • My goal: build my own game engine using Lazarus
Re: TForm.OnMouseLeave not working
« Reply #24 on: November 09, 2020, 07:39:50 pm »
I tried you suggestion and wrote a demo using it. Unfortunately the result is the same as using OnMouseLeave. I'm not sure on Windows, but on Linux GTK2 if I move the mouse quickly, it cannot 100% detect mouse outside button positions.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, sysutils, Forms, Controls, Graphics, ExtCtrls, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     RadioGroup1: TRadioGroup;
  17.     Shape1: TShape;
  18.     procedure MouseInput(Sender: TObject; Msg: Cardinal);
  19.     procedure Button1MouseEnter(Sender: TObject);
  20.     procedure Button1MouseLeave(Sender: TObject);
  21.     procedure FormCreate(Sender: TObject);
  22.   end;
  23.  
  24. var
  25.   Form1: TForm1;
  26.  
  27. implementation
  28.  
  29. {$R *.lfm}
  30.  
  31. { TForm1 }
  32.  
  33. procedure TForm1.MouseInput(Sender: TObject; Msg: Cardinal);
  34. var
  35.   LeftTop, RightBottom: TPoint;
  36.   inRange: Boolean;
  37. begin
  38.   if not(RadioGroup1.ItemIndex = 0) then Exit;
  39.  
  40.   // Button Position
  41.   LeftTop     := Point(Button1.Left, Button1.Top);
  42.   RightBottom := Point(Button1.Left+Button1.Width, Button1.Top+Button1.Height);
  43.   // Convert to screen coordinate
  44.   LeftTop     := ClientToScreen(LeftTop);
  45.   RightBottom := ClientToScreen(RightBottom);
  46.   // Is mouse position in the range of button?
  47.   with Mouse.CursorPos do
  48.     inRange := (X > LeftTop.X) and (X < RightBottom.X) and
  49.       (Y > LeftTop.Y) and (Y < RightBottom.Y);
  50.   // Change color
  51.   case inRange of
  52.     True:  Shape1.Brush.Color := clGreen;
  53.     False: Shape1.Brush.Color := clWhite;
  54.   end;
  55. end;
  56.  
  57. procedure TForm1.Button1MouseEnter(Sender: TObject);
  58. begin
  59.   if not(RadioGroup1.ItemIndex = 1) then Exit;
  60.   Shape1.Brush.Color := clBlue;
  61. end;
  62.  
  63. procedure TForm1.Button1MouseLeave(Sender: TObject);
  64. begin
  65.   if not(RadioGroup1.ItemIndex = 1) then Exit;
  66.   Shape1.Brush.Color := clWhite;
  67. end;
  68.  
  69. procedure TForm1.FormCreate(Sender: TObject);
  70. begin
  71.   Application.AddOnUserInputHandler(@MouseInput, True);
  72.   RadioGroup1.ItemIndex := 0;
  73. end;
  74.  
  75. end.
« Last Edit: November 09, 2020, 07:57:50 pm by Handoko »

jamie

  • Hero Member
  • *****
  • Posts: 4210
Re: TForm.OnMouseLeave not working
« Reply #25 on: November 09, 2020, 11:39:26 pm »
use a borderless control and set the cursor shape to a custom shape? at least it will change to a different shape as you pass over it.
The only true wisdom is knowing you know nothing

winni

  • Hero Member
  • *****
  • Posts: 2214
Re: TForm.OnMouseLeave not working
« Reply #26 on: November 10, 2020, 12:44:44 am »
Hi Handoko!

I tested your code: Everything works fine. With a quick mouse. With a very slow mouse.
Everything is ok.

Perhaps you moan about the 1 Pixel in X and one Pixel in Y:

Always the same  with the TRect:

TopLeft is INSIDE the button.
BottomRight is OUTSIDE the button.

So your code has to be:

with Mouse.CursorPos do
    inRange := (X >= LeftTop.X) and (X < RightBottom.X) and
      (Y >= LeftTop.Y) and (Y < RightBottom.Y);

Now the last pixels are found:

System: Lin64, fpc 3.04 Lazarus 2.0.10 gtk2

Winni
 
« Last Edit: November 10, 2020, 12:46:46 am by winni »

jamie

  • Hero Member
  • *****
  • Posts: 4210
Re: TForm.OnMouseLeave not working
« Reply #27 on: November 10, 2020, 01:50:56 am »
Reason to use the  PtInRect function  :D
The only true wisdom is knowing you know nothing

winni

  • Hero Member
  • *****
  • Posts: 2214
Re: TForm.OnMouseLeave not working
« Reply #28 on: November 10, 2020, 02:44:43 am »
Hi Jamie!

Which PtInRect  do you use?

Windows?  LCLIntf?  jedi?  types?

I swear the are some more.

But a simple const like
Code: Pascal  [Select][+][-]
  1.  
  2. HexChars=['0'..'9','a'..'f','A'..'F'];

is missing.

Winni

winni

  • Hero Member
  • *****
  • Posts: 2214
Re: TForm.OnMouseLeave not working
« Reply #29 on: November 10, 2020, 02:52:45 am »
 

Another one:

PointInRect 

in leakview

Winni

 

TinyPortal © 2005-2018