View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0038101 | Lazarus | Packages | public | 2020-11-18 18:07 | 2021-01-09 22:46 |
Reporter | Andy Spry | Assigned To | Bart Broersma | ||
Priority | normal | Severity | minor | Reproducibility | have not tried |
Status | resolved | Resolution | fixed | ||
Product Version | 2.0.8 | ||||
Summary | 0038101: TUpDown MouseEnter and MouseLeave events are not fired when the mouse cursor is over component buttons | ||||
Description | These events are only fired when the mouse cursor is over the narrow gap between the 2 component buttons. (Thanks again, Bart) | ||||
Tags | No tags attached. | ||||
Fixed in Revision | r64151,r64369 | ||||
LazTarget | - | ||||
Widgetset | Win32/Win64 | ||||
Attached Files |
|
related to | 0038099 | resolved | Bart Broersma | TUpDown MouseDown event is not fired by left and right click on component buttons |
related to | 0038325 | new | OnMouseEnter and OnMouseLeave not firing on spinbuttons of T(Float)SpinEdit(Ex) |
|
Unfortunateley simply forwarding the buttons MouseEnter/MouseLeave is not the solution, you get MoseLeave+MouseEnter when you move the mouse from one button to the other. I don't know if that is at all fixable? |
|
Had another look at Delphi7 TUpDown. This has Enter and Leave events (rather than MouseEnter etc). Other components have MouseEnter so I'm guessing that Enter and Leave are different. They are certainly not fired by the mouse cursor anyway. Perhaps Borland found it impossible to implement MouseEnter etc. events as well. It's a shame, but thank you very much for having a go and for fixing the MouseDown/ Up events. Regards. |
|
> Had another look at Delphi7 TUpDown. This has Enter and Leave events (rather than MouseEnter etc). Are you sure? I have sources of an oldish Delphi but newer than Delphi7. It has published OnMouseEnter / OnMouseLeave events. It has also the standard OnEnter / OnExit that inherit from TWinControl. Please check again. > It's a shame, but thank you very much for having a go and for fixing the MouseDown/ Up events. What is a shame? Anyway, this issue is not fixed yet but it should be fixable. |
|
Attached is a screenshot of the D7 Object Inspector. There aren't even any MouseWheel events. Weren't Mousewheels around in 2002?? |
|
Ok, the mouse events were added to Delphi after D7 then. BTW, can TUpDown get focus? At least it makes no sense. The OnEnter / OnExit events are useless then. In my tests none of the 4 events were fired with GTK2 or Qt5 bindings, except OnEnter was fired ONCE with GTK2. |
|
Well, I thought a work around was to use the MouseMove event to check for Focus... If not updown1.Focused then updown1.Setfocus; With the cursor over either button, this fired the OnEnter event where I had the code I wanted for the MouseEnter event. This seems to work for a design time TUpDown. But I use runtime created TUpDowns and unfortunately the OnEnter event reverts to being fired only when the cursor is in that gap, even though the buttons indicate they are focussed. C'est la vie. |
|
A possible workaround is something like this: At the moment MouseLeave is fired, check the last position of the mouse over the button. If this is the side next to the other button, assume that the mouse has moved from one button to the other: don't fire TUpDown.MouseLeave. Mind you that the control cane be horizontally orientated, so that furhter complicates things. For MouseEnter check the position the mouse entered and handle similar to the above. For this we need to keep track of - the first X,Y of a mousemove of the button. - the last X,Y of a mousemove of the button. Simply checking the mouse position at the time of MouseLeave/MouseEnter migth give values that are not the position that MouseLeave/MouseEnter was fired? I don't mind having a go at implementing something like this, but it feels dodgy (to say the least). Is it really worth all the hassle? What's the use case for MouseEnter/MouseLeave of this specific control? |
|
I just checked: checkin Mouse.MousePos at the time MouseLeave is fired can be off by 100 (!) pixels. Also MouseMove trails behind, if I rapdily move the mouse out of the control, the values are of no use to determin wether or not we are moving to the other button. Unless anybody has a better sulution, I'm inclined to resolve this as "won't fix".... |
|
B.t.w. OnEnter/OnExit events never fire in D7. |
|
Delphi 10.3.3 has MouseEnter and MouseLeave working.. the OnEnter and onExit does not seem to work.. Also, Setting the TabStop to true, it never tabs over to it so I don't know what that is all about. |
|
I think I got it working in r64151. It is a modification of Bart's idea. Please test. > These events are only fired when the mouse cursor is over the narrow gap between the 2 component buttons. I am not able to reproduce that. I tested also in Windows. MouseEnter and MouseLeave are never called for the main component because the buttons cover the whole area. AFAIK there is no narrow gap. I added MouseEnter and MouseLeave to TCustomUpDown with Assert(False). If it triggers for somebody, I guess those methods can be left empty. Responding to the buttons' events is enough. GetCursorPos() appears to be fast enough. My Windows 10 is in VirtualBox and thus slow, but the events were triggered correctly there. I just realized that Bart fixed OnMouseDown and OnMouseUp just day before yesterday. Nice. |
|
> AFAIK there is no narrow gap. Yes, ther CAN be. I reproduced this just once. > GetCursorPos() appears to be fast enough No it is NOT. I tested it. It can be off by 100 pixels (and the control itself is normaly appr 15-30 pixels wide). This of course only happens if you move the mouse rather fast. The same happens with MouseDown, it simply lags. W.r.t. Delphi: maybe they implement TUpDown as a native Windows control? I really have no idea. We have it as 2 speedbuttons on a TCustomControl, the TCustomControl never sees the mouse (it cannot), so this is rather difficult to omplement. |
|
@Juha: seems to work OK now. I'ld suggest to resolve as "fixed". |
|
I don't get this thing about the gap. Please see attached. It's there whatever I do (Win10). The result sounds good, but I'm a novice. How do I access r64151, please. |
|
> W.r.t. Delphi: maybe they implement TUpDown as a native Windows control? I really have no idea. @Bart, they didn't use SpeedButtons in Delphi. I guess they draw the arrows and use MouseDown to identify button clicks. @Andy Spry : > I don't get this thing about the gap. Please see attached. It's there whatever I do (Win10). Did OnMouseEnter and OnMouseLeave actually trigger when your mouse moved over the gap? It can be verified by running with my changes, as Assert(False) should fire then. Please remember to compile with assertion enabled. All other debug flags are recommended, too. > The result sounds good, but I'm a novice. How do I access r64151, please. $ svn update or the equivalent thing with TortoiseSVN. [Edit] Your reported version is 2.0.8. You must get Lazarus trunk, the development version. See : https://wiki.freepascal.org/Getting_Lazarus#Development_version_of_Lazarus |
|
Depending on size and screen resolution ans possibly PPI you can or cannot position the mouse over the gap. On my laptop with a touchpad, I'm not able to. When testing the MousUp/MouseDown at some point I was able to do that. > How do I access r64151, That revision cahnged more than the customupdown.inc file, so you will have to use either svn (SubVersion) or git to have a checkout of Lazarus trunk. It is explained on the wiki: https://wiki.lazarus.freepascal.org/Installing_Lazarus#From_source_on_Windows It looks complicated at first, but it is in essence a rather simple process. You already have the compiler and it's sources. Make sure that fpc is in your system's path variable. Install a svn client (I use SlikSvn client, just google it) Checkout lazarus trunk to a folder of your choice In the new Lazarus folder do: make bigide OPT="-gl" (the -gl makes that the IDE is built with debug info. If you need help, you can ask on the forum (you can PM me there if you want, my username is the same) |
|
Andy Spry, can you please test with trunk. I want to know if OnMouseEnter and OnMouseLeave trigger for you over the gap. |
|
In windows target, this is working good in trunk. There are no mouse enter/leave events between the two buttons. |
|
Juha Manninen / Bart Broersma. I am sorry, but for a short while I will not have access to the PC on which Lazarus is installed . I hope that jamie philbrook's confirmation of success is a good substitute. Great job! |
|
Ok, resolving. If you experience problems later, you can reopen this issue. |
|
As it is now MoseEnter/MouseLeave now are never fired. This is a bit awkward if you want to override that in a derived component. IMO it would have been more logical to have TUpDownButton.MouseEnter/Leave call TCustomUpDown.MouseEnter/Leave and check for mouse position there and call inherited MouseEnter/Leave from there. I was trying to do a similar thing for SpinEditEx so I sat out to override MouseEnter/Leave from TUpDown, only to discover this never fires. |
|
it works fine for me in windows ? I just dropped one on a form with trunk and the enter and leave does fire. |
|
@Juha: please comment on the attached diff (don't mind all the lines I commented out). If you think this is a feasible approach I will tidy it up and commit. I deliberately left out the Assertions. The gap between buttons is there, sporadically I can acces it with my touchpadmouse, but having sporadically an extra OnMouseEnter/Leave is the (small) price to pay for implementing it at all. updown.mouseenter.diff (3,680 bytes)
Index: lcl/comctrls.pp =================================================================== --- lcl/comctrls.pp (revision 64344) +++ lcl/comctrls.pp (working copy) @@ -1904,8 +1904,8 @@ FThousands: Boolean; FWrap: Boolean; FUseWS: Boolean; - procedure CheckMouseEntering; - procedure CheckMouseLeaving; + function CheckMouseEntering: Boolean; + function CheckMouseLeaving: Boolean; function GetPosition: SmallInt; procedure BTimerExec(Sender : TObject); function GetFlat: Boolean; Index: lcl/include/customupdown.inc =================================================================== --- lcl/include/customupdown.inc (revision 64344) +++ lcl/include/customupdown.inc (working copy) @@ -53,14 +53,16 @@ procedure TUpDownButton.MouseEnter; begin - FUpDown.CheckMouseEntering; - inherited MouseEnter; + //FUpDown.CheckMouseEntering; + inherited MouseEnter; //does UpdateState o.a., so call this as well + FUpDown.MouseEnter; end; procedure TUpDownButton.MouseLeave; begin - FUpDown.CheckMouseLeaving; - inherited MouseLeave; + //FUpDown.CheckMouseLeaving; + inherited MouseLeave; //does UpdateState o.a., so call this as well + FUpDown.MouseLeave; end; procedure TUpDownButton.MouseDown(Button: TMouseButton; Shift: TShiftState; @@ -540,14 +542,22 @@ procedure TCustomUpDown.MouseEnter; begin // This should never happen because buttons cover the whole component. - Assert(False, 'TCustomUpDown.MouseEnter called!'); - CheckMouseEntering; + //Assert(False, 'TCustomUpDown.MouseEnter called!'); + if CheckMouseEntering then + begin + inherited MouseEnter; + FMouseInsideComp := True; + end; end; procedure TCustomUpDown.MouseLeave; begin // This should never happen because buttons cover the whole component. - Assert(False, 'TCustomUpDown.MouseLeave called!'); - CheckMouseLeaving; + //Assert(False, 'TCustomUpDown.MouseLeave called!'); + if CheckMouseLeaving then + begin + inherited MouseLeave; + FMouseInsideComp := False; + end; end; procedure TCustomUpDown.DoSetBounds(ALeft, ATop, AWidth, AHeight: integer); @@ -596,15 +606,17 @@ SetAssociate(nil); end; -procedure TCustomUpDown.CheckMouseEntering; +function TCustomUpDown.CheckMouseEntering: Boolean; // Mouse in entering this control. begin - if FMouseInsideComp then Exit; // Already inside, moving between 2 buttons. - inherited MouseEnter; - FMouseInsideComp := True; + //debugln(['TCustomUpDown.CheckMouseEntering: FMouseInsideComp=',FMouseInsideComp]); + Result := not FMouseInsideComp; + //if FMouseInsideComp then Exit; // Already inside, moving between 2 buttons. + //inherited MouseEnter; + //FMouseInsideComp := True; end; -procedure TCustomUpDown.CheckMouseLeaving; +function TCustomUpDown.CheckMouseLeaving: Boolean; // Mouse in leaving this control. var P: TPoint; @@ -611,11 +623,13 @@ begin GetCursorPos(P); P:=ScreenToClient(P); - if PtInRect(ClientRect, P) then - exit; // Still inside, moving between 2 buttons. - Assert(FMouseInsideComp, 'TCustomUpDown.DecMouseEnterLeaveCnt: FMouseInsideComp=False'); - FMouseInsideComp := False; - inherited MouseLeave; + Result := not PtInRect(ClientRect, P); + //debugln(['TCustomUpDown.CheckMouseLeaving: PtInRect(ClientRect, P)=',PtInRect(ClientRect, P)]); + //if PtInRect(ClientRect, P) then + // exit; // Still inside, moving between 2 buttons. + //Assert(FMouseInsideComp, 'TCustomUpDown.DecMouseEnterLeaveCnt: FMouseInsideComp=False'); + //FMouseInsideComp := False; + //inherited MouseLeave; end; function TCustomUpDown.GetPosition: SmallInt; |
|
I think TCustomUpDown.MouseEnter; and TCustomUpDown.MouseLeave; should be just empty. Mouse pointer is already on the component and those extra events must be ignored. That was in my mind already when I created the code, but the events never triggered here and I added Assertions. Please see the mailing thread discussion with wp. I understood he just emptied TCustomUpDown.MouseEnter and TCustomUpDown.MouseLeave, thus ignoring the events, and everything worked. Actually I thought he committed it to SVN but he didn't. |
|
Atached new diff, since r64357 made my diff incompatible. updown.mouseenter.2.diff (3,341 bytes)
Index: lcl/comctrls.pp =================================================================== --- lcl/comctrls.pp (revision 64344) +++ lcl/comctrls.pp (working copy) @@ -1904,8 +1904,8 @@ FThousands: Boolean; FWrap: Boolean; FUseWS: Boolean; - procedure CheckMouseEntering; - procedure CheckMouseLeaving; + function CheckMouseEntering: Boolean; + function CheckMouseLeaving: Boolean; function GetPosition: SmallInt; procedure BTimerExec(Sender : TObject); function GetFlat: Boolean; Index: lcl/include/customupdown.inc =================================================================== --- lcl/include/customupdown.inc (revision 64359) +++ lcl/include/customupdown.inc (working copy) @@ -53,14 +53,16 @@ procedure TUpDownButton.MouseEnter; begin - FUpDown.CheckMouseEntering; - inherited MouseEnter; + //FUpDown.CheckMouseEntering; + inherited MouseEnter; //does UpdateState o.a., so call this as well + FUpDown.MouseEnter; end; procedure TUpDownButton.MouseLeave; begin - FUpDown.CheckMouseLeaving; - inherited MouseLeave; + //FUpDown.CheckMouseLeaving; + inherited MouseLeave; //does UpdateState o.a., so call this as well + FUpDown.MouseLeave; end; procedure TUpDownButton.MouseDown(Button: TMouseButton; Shift: TShiftState; @@ -539,11 +541,21 @@ end; procedure TCustomUpDown.MouseEnter; -begin // This should never happen because buttons cover the whole component. +begin + if CheckMouseEntering then + begin + inherited MouseEnter; + FMouseInsideComp := True; + end; end; procedure TCustomUpDown.MouseLeave; -begin // This should never happen because buttons cover the whole component. +begin + if CheckMouseLeaving then + begin + inherited MouseLeave; + FMouseInsideComp := False; + end; end; procedure TCustomUpDown.DoSetBounds(ALeft, ATop, AWidth, AHeight: integer); @@ -592,15 +604,17 @@ SetAssociate(nil); end; -procedure TCustomUpDown.CheckMouseEntering; +function TCustomUpDown.CheckMouseEntering: Boolean; // Mouse in entering this control. begin - if FMouseInsideComp then Exit; // Already inside, moving between 2 buttons. - inherited MouseEnter; - FMouseInsideComp := True; + //debugln(['TCustomUpDown.CheckMouseEntering: FMouseInsideComp=',FMouseInsideComp]); + Result := not FMouseInsideComp; + //if FMouseInsideComp then Exit; // Already inside, moving between 2 buttons. + //inherited MouseEnter; + //FMouseInsideComp := True; end; -procedure TCustomUpDown.CheckMouseLeaving; +function TCustomUpDown.CheckMouseLeaving: Boolean; // Mouse in leaving this control. var P: TPoint; @@ -607,11 +621,12 @@ begin GetCursorPos(P); P:=ScreenToClient(P); - if PtInRect(ClientRect, P) then - exit; // Still inside, moving between 2 buttons. - Assert(FMouseInsideComp, 'TCustomUpDown.DecMouseEnterLeaveCnt: FMouseInsideComp=False'); - FMouseInsideComp := False; - inherited MouseLeave; + Result := not PtInRect(ClientRect, P); + //debugln(['TCustomUpDown.CheckMouseLeaving: PtInRect(ClientRect, P)=',PtInRect(ClientRect, P)]); + //if PtInRect(ClientRect, P) then + // exit; // Still inside, moving between 2 buttons. + //FMouseInsideComp := False; + //inherited MouseLeave; end; function TCustomUpDown.GetPosition: SmallInt; |
|
What is the bug your patch fixes? I thought it works after wp's commit. Anyway, I am not an expert with this component. Assigning to you. |
|
The patch fixes the original bug in a slightly different way, based upon your initial fix. |
|
Ok, sounds good. :) |
Date Modified | Username | Field | Change |
---|---|---|---|
2020-11-18 18:07 | Andy Spry | New Issue | |
2020-11-18 22:15 | Bart Broersma | Status | new => confirmed |
2020-11-18 22:15 | Bart Broersma | LazTarget | => - |
2020-11-18 22:15 | Bart Broersma | Note Added: 0127040 | |
2020-11-18 22:16 | Bart Broersma | Note Edited: 0127040 | View Revisions |
2020-11-19 16:25 | Andy Spry | Note Added: 0127049 | |
2020-11-19 17:36 | Juha Manninen | Note Added: 0127051 | |
2020-11-19 18:01 | Andy Spry | Note Added: 0127053 | |
2020-11-19 18:01 | Andy Spry | File Added: D7ObjectInspector.PNG | |
2020-11-19 18:43 | Juha Manninen | Note Added: 0127054 | |
2020-11-19 18:56 | Andy Spry | Note Added: 0127055 | |
2020-11-19 20:24 | Bart Broersma | Note Added: 0127056 | |
2020-11-19 20:44 | Bart Broersma | Note Added: 0127061 | |
2020-11-19 20:48 | Bart Broersma | Note Added: 0127062 | |
2020-11-19 22:50 | jamie philbrook | Note Added: 0127064 | |
2020-11-20 11:52 | Juha Manninen | Assigned To | => Juha Manninen |
2020-11-20 11:52 | Juha Manninen | Status | confirmed => assigned |
2020-11-20 12:04 | Juha Manninen | Status | assigned => feedback |
2020-11-20 12:04 | Juha Manninen | Note Added: 0127070 | |
2020-11-20 12:08 | Juha Manninen | Relationship added | related to 0038099 |
2020-11-20 12:10 | Juha Manninen | Note Edited: 0127054 | View Revisions |
2020-11-20 12:11 | Juha Manninen | Note Edited: 0127070 | View Revisions |
2020-11-20 15:00 | Bart Broersma | Note Added: 0127071 | |
2020-11-20 18:35 | Bart Broersma | Note Added: 0127072 | |
2020-11-20 19:03 | Andy Spry | Note Added: 0127073 | |
2020-11-20 19:03 | Andy Spry | File Added: mindthegap.PNG | |
2020-11-20 19:03 | Andy Spry | Status | feedback => assigned |
2020-11-20 19:33 | Juha Manninen | Note Added: 0127074 | |
2020-11-20 19:39 | Bart Broersma | Note Added: 0127075 | |
2020-11-20 19:43 | Juha Manninen | Note Edited: 0127074 | View Revisions |
2020-11-22 10:08 | Juha Manninen | Note Added: 0127091 | |
2020-11-22 10:08 | Juha Manninen | Status | assigned => feedback |
2020-11-22 12:26 | jamie philbrook | Note Added: 0127093 | |
2020-11-22 13:53 | Andy Spry | Note Added: 0127104 | |
2020-11-22 13:53 | Andy Spry | Status | feedback => assigned |
2020-11-22 14:50 | Juha Manninen | Status | assigned => resolved |
2020-11-22 14:50 | Juha Manninen | Resolution | open => fixed |
2020-11-22 14:50 | Juha Manninen | Fixed in Revision | => r64151 |
2020-11-22 14:50 | Juha Manninen | Widgetset | Win32/Win64 => Win32/Win64 |
2020-11-22 14:50 | Juha Manninen | Note Added: 0127106 | |
2021-01-07 00:50 | wp | Relationship added | related to 0038325 |
2021-01-07 22:39 | Bart Broersma | Status | resolved => assigned |
2021-01-07 22:39 | Bart Broersma | Resolution | fixed => open |
2021-01-07 22:39 | Bart Broersma | Note Added: 0128156 | |
2021-01-07 23:06 | jamie philbrook | Note Added: 0128161 | |
2021-01-07 23:08 | Bart Broersma | Note Added: 0128162 | |
2021-01-07 23:08 | Bart Broersma | File Added: updown.mouseenter.diff | |
2021-01-07 23:24 | Juha Manninen | Note Added: 0128163 | |
2021-01-09 00:26 | Bart Broersma | Note Added: 0128180 | |
2021-01-09 00:26 | Bart Broersma | File Added: updown.mouseenter.2.diff | |
2021-01-09 13:46 | Juha Manninen | Assigned To | Juha Manninen => Bart Broersma |
2021-01-09 13:50 | Juha Manninen | Note Added: 0128197 | |
2021-01-09 16:10 | Bart Broersma | Note Added: 0128200 | |
2021-01-09 20:41 | Juha Manninen | Note Added: 0128215 | |
2021-01-09 22:46 | Bart Broersma | Status | assigned => resolved |
2021-01-09 22:46 | Bart Broersma | Resolution | open => fixed |
2021-01-09 22:46 | Bart Broersma | Fixed in Revision | r64151 => r64151,r64369 |
2021-01-09 22:46 | Bart Broersma | Widgetset | Win32/Win64 => Win32/Win64 |