views:

1857

answers:

4

I have created a delphi component which descends from TGraphicControl. Is it possible to add support for mouse wheels?

--- Edit ---

I've exposed the MouseWheel events as shown below but they aren't called.

TMyComponent = class(TGraphicControl)
published
  property OnMouseWheel;
  property OnMouseWheelDown;
  property OnMouseWheelUp;
end;

--- Edit ---

As suggested below, I've tried to trap the WM_MOUSEWHEEL and CM_MOUSEWHEEL messages, but it doesn't seem to work. However I've managed to trap the CM_MOUSEENTER message. I don't understand why i can trap one type of message, but not the other.

A: 

Trap the WM_MOUSEWHEEL message.

François
I tried this, but my control wouldn't trap the WM_MOUSEWHEEL or CM_MOUSEWHEEL message. But it worked as expected when attempting to trap the CM_MOUSEENTER message.
Shannon
+4  A: 

TGraphicControl descends from TControl, which already has mouse-wheel support. See the wm_MouseWheel message, the DoMouseWheel, DoMouseWheelDown, DoMouseWheelUp, and MouseWheelHandler methods, and the WheelAccumulator property.

Rob Kennedy
Something is still missing, after re-declaring the MouseWheel events as shown above, they still aren't called.
Shannon
Looks like this is more complicated than I thought. I'll try writing some code to figure this out. Try back in a couple of days.
Rob Kennedy
+1  A: 

Only TWinControl descendants can receive mouse wheel messages. TGraphicControl is not a Window based control and therefore can not. It could work if the VCL routes the messages to the TGraphicControl, but apparently does not. You could descend from TCustomControl and then it would work.

Lars Truijens
TGraphicControl gets messages all the time, just not directly from the OS. The parent control catches and forwards them. Sometimes, they arrive as CM_ messages instead of WM_. It looks like TControl.MouseWheelHandler forwards wheel messages to the form, though, so Shannon may need to override that.
Rob Kennedy
I tried overriding the MouseWheelHandler method, but that wasn't being called consistently. Sometimes the messages would still be passed on to the underlying form.
Shannon
I changed my component to descend from TCustomControl (my control needs a canvas to draw on) but the MouseWheel event handlers were still ignored. (I'm starting to feel a bit dumb here. lol) – Shannon (0 secs ago)
Shannon
+1  A: 

I have the same problem. No luck finding solution yet, but maybe this will be helpful:

I suspect the other component is calling the Win API method SetCapture, which according to the API help:

"The SetCapture function sets the mouse capture to the specified window belonging to the current thread. Once a window has captured the mouse, all mouse input is directed to that window, regardless of whether the cursor is within the borders of that window. Only one window at a time can capture the mouse. "

As a new user I can not post a link to the full thread.

EDITED

If you create your component as a descendant from TCustomControl you can solve your problem as described below:

  1. Use OnMouseEnter event to detect when mouse enters your component.
  2. In OnMouseEnter call SetFocus method to make your component focused. Now your component can receive WM_MOUSEWHEEL message
Wodzu
I've experimented a bit more and the problem is that mine (and probably yours) component doesn't have a focus. if you call a SetFocusedControl(YourComponent) method, then your component will start receiving messages from the mouse wheel.
Wodzu
Solution for this problem could be like this:1. Use OnMouseEnter event to detect when mouse enters your component.2. In OnMouseEnter call SetFocus method to make your component focused.Now your component can receive WM_MOUSEWHEEL message.
Wodzu
@Wodzu: A TGraphicControl can not receive focus, as it has no window handle.
mghie
@mghie: Shannon mentioned that he changed parent class to TCustomControl so it shouldn't be a problem.
Wodzu
+1, looks like focus is needed to receive mousewheel events (I've just tried)