Delphi - Reading the Mouse ScrollWheel

I have always considered it a failing of Delphi to not provide a simple way to interface with the mouse scrollwheel .. boy was I wrong. After 10 years (or more), I finally figured it out. It is dead simple.

It turns out that the only problem is that the OnMouseWheel property is not published or in the TEdit help. If it was, I would have learned about it long ago. (It is listed in the TWinControl help as a protected event.)

Basic Processing | ReadOnly | Code Example


Basic Processing

There are 3 protected MouseWheel events defined for windows controls (in TWinControl). The available help is next to worthless. I strongly suggest reading the actual source code.

The basic procedure is

  1. A windows WM_MOUSEWHEEL message eventually calls MouseWheelHandler
  2. MouseWheelHandler bubbles the message up to the form
  3. The form's MouseWheelHandler creates a CM_MOUSEWHEEL message for the focused control
  4. The component's CMMouseWheel calls DoMouseWheel (can be overridden). If it returns false, the component creates a CM_MOUSEWHEEL message for the parent control.
  5. The default DoMouseWheel calls the three related events.

There appears to be a design problem in the Delphi code - the last line of TWinControl.WMMouseWheel() calls inherited. The problem is that TWinControl.WMMouseWheel() is neither virtual or dynamic. Actually, this is a common construct in the message processing loop. As a result, all "messages" are "virtual" (even though the implementation is not quite the same).


ReadOnly

Some components (not all) provide a ReadOnly property. However, in the case of TEdit (and other Windows-based components), this property apparently only applies to keyboard input. This actually makes sense .. it allows the user to select and copy ReadOnly text using the mouse. As a result, the default MouseWheel processing ignores this property and your code must test for it.


Code Example

This is some code I use to increment the value in a custom edit field. The wheel direction (sign) controls increment verses decrement. Rather than overriding DoMouseWheel, I could have just set OnMouseWheel to point to a similar function. However, then descendent components could not use that event.

In theory, WheelDelta can be any integer multiple of 120 (one click of the mouse wheel). Perhaps this allows windows to accelerate the counts based on speed. The default handler assumes that this is possible and repeats the inner loop an appropriate number of times. My code (above) assumes that it will always represent plus or minus a single step.


Author: Robert Clemenzi - clemenzi@cpcug.org
URL: http:// cpcug.org / user / clemenzi / technical / Languages / Delphi / ScrollWheel.html