Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2008-06

OnMouseWheel[Down/Up] support in TControl (patch included)

22 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Kostas Michalopoulos

I'm making a 3D design program and i use TPaintBox to draw the 2D viewports. I want to make the program zoom in/out using the wheel, however although all other mouse events are supported OnMouseWheelUp/Down are not. I noticed that the TPaintBox is a descendant of TGraphicControl, which doesn't provide these events and TWinControl is where the code for these is written. So i tried to move the code from TWinControl up to TControl so all controls can receive them, much like they receive OnMouseDown/Up etc. But it didn't worked, because after some checks i figured out that the message wasn't sent to the correct control (there wasn't done proper translation of the mouse coordinates from screen to client space). So i added a couple of lines in WMMouseWheel function in TControl (moved from TWinControl) that re-checks for the proper control under mouse using FindLCLControl and calls the DoMouseWheel function of that control (or the Self control if FindLCLControl returns nil).

This solved the problem and now all TControls can use OnMouseWheel* events. However while doing my tests i saw that calling ScreenToClient in a TForm the coordinates remain intact. I am not sure if this is the original issue of improper translations, since right now i'm way too tired (spent around four hours trying to fix this) to check, but i might check it tomorrow (well, also i don't know if this is a bug or a design decision).

In any case since i have a properly working (although a little hacky) patch for making wheel events usable for non-TWinControls, i'm attaching it. The patch is against SVN revision 15308.

Kostas
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.lazarus.freepascal.org/pipermail/lazarus/attachments/20080605/755e75ef/attachment.html

Reply by email

Kostas Michalopoulos
to Kostas Michalopoulos

And, um, the patch :-P

Earlier message 20 lines
----- Original Message ----- From: Kostas Michalopoulos To: General mailing list Sent: Thursday, June 05, 2008 3:00 AM Subject: [Lazarus] OnMouseWheel[Down/Up] support in TControl (patch included) I'm making a 3D design program and i use TPaintBox to draw the 2D viewports. I want to make the program zoom in/out using the wheel, however although all other mouse events are supported OnMouseWheelUp/Down are not. I noticed that the TPaintBox is a descendant of TGraphicControl, which doesn't provide these events and TWinControl is where the code for these is written. So i tried to move the code from TWinControl up to TControl so all controls can receive them, much like they receive OnMouseDown/Up etc. But it didn't worked, because after some checks i figured out that the message wasn't sent to the correct control (there wasn't done proper translation of the mouse coordinates from screen to client space). So i added a couple of lines in WMMouseWheel function in TControl (moved from TWinControl) that re-checks for the proper control under mouse using FindLCLControl and calls the DoMouseWheel function of that control (or the Self control if FindLCLControl returns nil). This solved the problem and now all TControls can use OnMouseWheel* events. However while doing my tests i saw that calling ScreenToClient in a TForm the coordinates remain intact. I am not sure if this is the original issue of improper translations, since right now i'm way too tired (spent around four hours trying to fix this) to check, but i might check it tomorrow (well, also i don't know if this is a bug or a design decision). In any case since i have a properly working (although a little hacky) patch for making wheel events usable for non-TWinControls, i'm attaching it. The patch is against SVN revision 15308. Kostas ------------------------------------------------------------------------------

Reply by email

Kostas Michalopoulos
to Kostas Michalopoulos: I'm making a 3D design program and i use TPaintBox to draw the 2D viewports. I want to…

This solved the problem and now all TControls can use OnMouseWheel* events. However while doing my tests i saw that calling ScreenToClient in a TForm the coordinates remain intact. I am not sure if this is the original issue of improper translations, since right now i'm way too tired (spent around four hours trying to fix this) to check, but i might check it tomorrow (well, also i don't know if this is a bug or a design decision). -------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.lazarus.freepascal.org/pipermail/lazarus/attachments/20080605/0853593f/attachment.html

Reply by email

Kostas Michalopoulos
to Kostas Michalopoulos: I'm making a 3D design program and i use TPaintBox to draw the 2D viewports. I want to…

Ok, i did the tests and it came up that i was just misusing ClientToScreen and ScreenToClient in TForm in my test (i expected it to modify the point i was passing instead of returning a new point), so that wasn't the reason the message isn't sent to the correct control.

Earlier message 20 lines
----- Original Message ----- From: Kostas Michalopoulos To: General mailing list Sent: Thursday, June 05, 2008 3:00 AM Subject: [Lazarus] OnMouseWheel[Down/Up] support in TControl (patch included) I'm making a 3D design program and i use TPaintBox to draw the 2D viewports. I want to make the program zoom in/out using the wheel, however although all other mouse events are supported OnMouseWheelUp/Down are not. I noticed that the TPaintBox is a descendant of TGraphicControl, which doesn't provide these events and TWinControl is where the code for these is written. So i tried to move the code from TWinControl up to TControl so all controls can receive them, much like they receive OnMouseDown/Up etc. But it didn't worked, because after some checks i figured out that the message wasn't sent to the correct control (there wasn't done proper translation of the mouse coordinates from screen to client space). So i added a couple of lines in WMMouseWheel function in TControl (moved from TWinControl) that re-checks for the proper control under mouse using FindLCLControl and calls the DoMouseWheel function of that control (or the Self control if FindLCLControl returns nil). This solved the problem and now all TControls can use OnMouseWheel* events. However while doing my tests i saw that calling ScreenToClient in a TForm the coordinates remain intact. I am not sure if this is the original issue of improper translations, since right now i'm way too tired (spent around four hours trying to fix this) to check, but i might check it tomorrow (well, also i don't know if this is a bug or a design decision). In any case since i have a properly working (although a little hacky) patch for making wheel events usable for non-TWinControls, i'm attaching it. The patch is against SVN revision 15308. Kostas ------------------------------------------------------------------------------

Reply by email

Mattias Gaertner
to Kostas Michalopoulos: I'm making a 3D design program and i use TPaintBox to draw the 2D viewports. I want to…
Show quoted text 27 lines
I'm making a 3D design program and i use TPaintBox to draw the 2D viewports. I want to make the program zoom in/out using the wheel, however although all other mouse events are supported OnMouseWheelUp/Down are not. I noticed that the TPaintBox is a descendant of TGraphicControl, which doesn't provide these events and TWinControl is where the code for these is written. So i tried to move the code from TWinControl up to TControl so all controls can receive them, much like they receive OnMouseDown/Up etc. But it didn't worked, because after some checks i figured out that the message wasn't sent to the correct control (there wasn't done proper translation of the mouse coordinates from screen to client space). So i added a couple of lines in WMMouseWheel function in TControl (moved from TWinControl) that re-checks for the proper control under mouse using FindLCLControl and calls the DoMouseWheel function of that control (or the Self control if FindLCLControl returns nil). This solved the problem and now all TControls can use OnMouseWheel* events. However while doing my tests i saw that calling ScreenToClient in a TForm the coordinates remain intact. I am not sure if this is the original issue of improper translations, since right now i'm way too tired (spent around four hours trying to fix this) to check, but i might check it tomorrow (well, also i don't know if this is a bug or a design decision). In any case since i have a properly working (although a little hacky) patch for making wheel events usable for non-TWinControls, i'm attaching it. The patch is against SVN revision 15308.

Thanks. Applied.

Mattias

Reply by email

Kostas Michalopoulos
to Mattias Gaertner
Thanks. Applied. Mattias

No, not really. The part of the code that does the trick of sending the message to the correct control is this (in procedure TControl.WMMouseWheel, in file control.inc):
---

RealControl:=FindLCLControl(MousePos);
if not Assigned(RealControl) then RealControl:=Self;

if RealControl.DoMouseWheel(Message.State, Message.WheelDelta, MousePos) then

---
which was not applied (although the rest seems to be moved). Without this, TPaintBox and other non TWinControls do not receive the wheel messages.

I'm attaching a new patch against revision 15345 which adds these lines. I have tested it and it works as supposed.

Kostas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: tcontrol-fixed-wmmousewheel-procedure.patch
Type: application/octet-stream
Size: 794 bytes
Desc: not available
Url : http://www.lazarus.freepascal.org/pipermail/lazarus/attachments/20080607/eef702c3/attachment.obj

Reply by email

Mattias Gaertner
to Kostas Michalopoulos
Show quoted text 7 lines
> Thanks. Applied. > > Mattias No, not really. The part of the code that does the trick of sending the message to the correct control is this (in procedure TControl.WMMouseWheel, in file control.inc):

For all mouse messages the delegation to the controls is done in TWinControl.IsControlMouseMsg.

Do you receive OnMouseDown events for the TPaintBox?

Show quoted text 15 lines
--- RealControl:=FindLCLControl(MousePos); if not Assigned(RealControl) then RealControl:=Self; if RealControl.DoMouseWheel(Message.State, Message.WheelDelta, MousePos) then --- which was not applied (although the rest seems to be moved). Without this, TPaintBox and other non TWinControls do not receive the wheel messages. I'm attaching a new patch against revision 15345 which adds these lines. I have tested it and it works as supposed.

It already works here. Can you provide an example, where it does not work?

Mattias

Reply by email

Kostas Michalopoulos
to Mattias Gaertner
For all mouse messages the delegation to the controls is done in TWinControl.IsControlMouseMsg.

I'm not sure i understand what this function does. I'll check it later. However there seems to be too much checking for TWinControls there :-).

Do you receive OnMouseDown events for the TPaintBox?

Yes.

It already works here. Can you provide an example, where it does not work?

Yes, i'm attaching the program i used to test my patch. Note that it might not be needed under interfaces which send the wheel messages to the correct control themselves (such as GTK+, GTK+2, Qt, etc) but it is needed under interfaces which send the wheel messages to the window (such as Win32).

Kostas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: wheel-test.zip
Type: application/x-zip-compressed
Size: 3201 bytes
Desc: not available
Url : http://www.lazarus.freepascal.org/pipermail/lazarus/attachments/20080607/5104b082/attachment.bin

Reply by email

Mattias Gaertner
to Kostas Michalopoulos
Show quoted text 6 lines
> For all mouse messages the delegation to the controls is done in > TWinControl.IsControlMouseMsg. I'm not sure i understand what this function does. I'll check it later. However there seems to be too much checking for TWinControls there :-).

If a TWinControl receives a MouseDown or MouseWheel it delegates it to its controls.

Show quoted text 12 lines
> Do you receive OnMouseDown events for the TPaintBox? Yes. > It already works here. Can you provide an example, > where it does not work? Yes, i'm attaching the program i used to test my patch. Note that it might not be needed under interfaces which send the wheel messages to the correct control themselves (such as GTK+, GTK+2, Qt, etc) but it is needed under interfaces which send the wheel messages to the window (such as Win32).

In your example the gtk sends the message to Form1 and TWinControl.IsControlMouseMsg sends it further to TPaintBox.

Where does the win32 interface send the wheel messages to?

Mattias

Reply by email

Kostas Michalopoulos
to Mattias Gaertner
In your example the gtk sends the message to Form1 and TWinControl.IsControlMouseMsg sends it further to TPaintBox. Where does the win32 interface send the wheel messages to?

Ok, after this discussion i think i figured out whats wrong: Win32 does indeed send the message to TForm (much like GTK does, as you say) *but* the coordinates are in screen space, not client space (which explains the incorrect translation i mentioned in my original post), so the IsControlMouseMsg thinks that the message is for TForm instead of TPaintBox because it gets incorrect coordinates (the rest of LCL seems to think that wheel messages are always in client space). Bringing them in client space when the WM_MOUSEWHEEL event decides that this is a message for us (at the end of the message handling in 'case') produces the correct behaviour for the test program (and my 3D app) under Windows. Also the received coordinates are in the same space with the rest of the mouse events.

I attached a patch against revision 15355 that does exactly that. This patch is in the Windows callback function, so the problem is probably now fixed where it began from.

Kostas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: win32-mousewheel-event-coords-fix.patch
Type: application/octet-stream
Size: 579 bytes
Desc: not available
Url : http://www.lazarus.freepascal.org/pipermail/lazarus/attachments/20080607/780ce10a/attachment.obj

Reply by email

Mattias Gaertner
to Kostas Michalopoulos
Show quoted text 21 lines
> In your example the gtk sends the message to Form1 and > TWinControl.IsControlMouseMsg sends it further to TPaintBox. > > Where does the win32 interface send the wheel messages to? Ok, after this discussion i think i figured out whats wrong: Win32 does indeed send the message to TForm (much like GTK does, as you say) *but* the coordinates are in screen space, not client space (which explains the incorrect translation i mentioned in my original post), so the IsControlMouseMsg thinks that the message is for TForm instead of TPaintBox because it gets incorrect coordinates (the rest of LCL seems to think that wheel messages are always in client space). Bringing them in client space when the WM_MOUSEWHEEL event decides that this is a message for us (at the end of the message handling in 'case') produces the correct behaviour for the test program (and my 3D app) under Windows. Also the received coordinates are in the same space with the rest of the mouse events. I attached a patch against revision 15355 that does exactly that. This patch is in the Windows callback function, so the problem is probably now fixed where it began from.

I created a bug report for this:
http://bugs.freepascal.org/view.php?id=11442

Mattias

Reply by email

Vincent Snijders
to Mattias Gaertner
Mattias Gaertner wrote 12 lines
On Mon, 9 Jun 2008 02:38:30 +0300 "Kostas Michalopoulos" wrote: >> I created a bug report for this: >> http://bugs.freepascal.org/view.php?id=11442 >> >> Mattias > Ok, i hope it'll enter in trunk soon. I suppose someone familiar with > Win32 and/or responsible for the Win32 interface should check it > first, right? Right.

As can be seen on that report, it introduces a Delphi incompatibility. Do we what that? Or should the LCL (and other widgetsets) be adjusted.

Vincent

Reply by email

Mattias Gaertner
to Vincent Snijders
Show quoted text 16 lines
Mattias Gaertner schreef: > On Mon, 9 Jun 2008 02:38:30 +0300 > "Kostas Michalopoulos" wrote: > >>> I created a bug report for this: >>> http://bugs.freepascal.org/view.php?id=11442 >>> >>> Mattias >> Ok, i hope it'll enter in trunk soon. I suppose someone familiar >> with Win32 and/or responsible for the Win32 interface should check >> it first, right? > > Right. As can be seen on that report, it introduces a Delphi incompatibility.

It's not a Delphi, but a winapi incompatibility.

Do we what that? Or should the LCL (and other widgetsets) be adjusted.

It's an easy change, so IMO in this case we can follow winapi.

Mattias

Reply by email

Luiz Americo Pereira Camara
to Mattias Gaertner
Mattias Gaertner wrote 6 lines
> As can be seen on that report, it introduces a Delphi > incompatibility. > It's not a Delphi, but a winapi incompatibility.

No, it's a Delphi compatibility. I tested CM_MOUSEWHEEL, the equivalent message of LM_MOUSEWHEEL. Under Delphi XPos and YPos fields returns screen coordinates.
Furthermore, OnMouseWheel MousePos also is at screen coordinates.

Luiz

Reply by email

Mattias Gaertner
to Luiz Americo Pereira Camara
Show quoted text 12 lines
Mattias Gaertner wrote: >> As can be seen on that report, it introduces a Delphi >> incompatibility. >> > > It's not a Delphi, but a winapi incompatibility. > No, it's a Delphi compatibility. I tested CM_MOUSEWHEEL, the equivalent message of LM_MOUSEWHEEL. Under Delphi XPos and YPos fields returns screen coordinates. Furthermore, OnMouseWheel MousePos also is at screen coordinates.

The VCL sends OnMouseWheel to the right child control, but it sends screen coords? That would be very inconsistent.

Mattias

Reply by email

Kostas Michalopoulos
to Luiz Americo Pereira Camara: No, it's a Delphi compatibility. I tested CM_MOUSEWHEEL, the equivalent message of…
Show quoted text 6 lines
No, it's a Delphi compatibility. I tested CM_MOUSEWHEEL, the equivalent message of LM_MOUSEWHEEL. Under Delphi XPos and YPos fields returns screen coordinates. Furthermore, OnMouseWheel MousePos also is at screen coordinates. Luiz

I assume you mean *in*compatibility :-).

Anyway i'm not sure if it is so important to bring this in screen coordinates (what is the behavior in other toolkits btw? GTK reports it in screen or client coordinates?). Personally i see this as a Delphi bug (even if its actually Windows who report it in screen coords) and i would suggest it to be in client coordinates so the behavior is consistent for all mouse events and put a note in the wiki page about converting Delphi code to Lazarus. So the options are:

1. Keep the patch as-is. Report it in client coords, be consistent with other mouse events and introduce a small Delphi incompatibility. I prefer this.
2. Modify LCL so that it brings the client coords to screen after the control is found for a LM_MOUSEWHEEL message so that is Delphi compatible (note: the screen-to-client convertion i made in WM_MOUSEWHEEL handler is still needed for LCL to figure out the correct control to send the message - unless, of course, LCL is further modified to accept screen coords from Win32 and client coords from other toolkits).

Kostas

Reply by email

Mattias Gaertner
to Kostas Michalopoulos
Show quoted text 27 lines
> No, it's a Delphi compatibility. I tested CM_MOUSEWHEEL, the > equivalent message of LM_MOUSEWHEEL. Under Delphi XPos and YPos > fields returns screen coordinates. > Furthermore, OnMouseWheel MousePos also is at screen coordinates. > > Luiz I assume you mean *in*compatibility :-). Anyway i'm not sure if it is so important to bring this in screen coordinates (what is the behavior in other toolkits btw? GTK reports it in screen or client coordinates?). Personally i see this as a Delphi bug (even if its actually Windows who report it in screen coords) and i would suggest it to be in client coordinates so the behavior is consistent for all mouse events and put a note in the wiki page about converting Delphi code to Lazarus. So the options are: 1. Keep the patch as-is. Report it in client coords, be consistent with other mouse events and introduce a small Delphi incompatibility. I prefer this. 2. Modify LCL so that it brings the client coords to screen after the control is found for a LM_MOUSEWHEEL message so that is Delphi compatible (note: the screen-to-client convertion i made in WM_MOUSEWHEEL handler is still needed for LCL to figure out the correct control to send the message - unless, of course, LCL is further modified to accept screen coords from Win32 and client coords from other toolkits).

Does someone know, if the newer Delphi flavors still have this inconsistency? Even Delphi .net?

Mattias

Reply by email

Luiz Americo Pereira Camara
to Mattias Gaertner: On Tue, 10 Jun 2008 18:27:45 -0300 The VCL sends OnMouseWheel to the right child control,…
Mattias Gaertner wrote 12 lines
>> >> > No, it's a Delphi compatibility. I tested CM_MOUSEWHEEL, the > equivalent message of LM_MOUSEWHEEL. Under Delphi XPos and YPos > fields returns screen coordinates. > Furthermore, OnMouseWheel MousePos also is at screen coordinates. > The VCL sends OnMouseWheel to the right child control, but it sends screen coords? That would be very inconsistent.

The test i done was with a TWinControl.
I tested with a TControl and Delphi does not send OnMouseWheel for TControl

Luiz

Reply by email

Luiz Americo Pereira Camara
to Kostas Michalopoulos: I assume you mean *in*compatibility :-). Anyway i'm not sure if it is so important to…
Kostas Michalopoulos wrote
1. Keep the patch as-is. Report it in client coords, be consistent with other mouse events and introduce a small Delphi incompatibility. I prefer this.

I also prefer this.

In general, if is a better behavior or difficult to implement cross platform/cross widgetset than introduce a Delphi incompatibility and document somewhere.

BTW: I have a list of "differences" that a Delphi developer find when porting components an plan to document it. Someday.

Luiz

Reply by email