2

I have a form with many controls (treeview , memo ,listbox ,panels etc ).

i want to move the scrollbars of these controls automatically when the mouse is over the components and the wheel is scrolled.

Just as how rad studios inspector bar , tool box , project manger works.

And it is impassible to type the same code on each and every controls(more than 11 controls up to now)

[Edited]

Thanks for all of your answers but

controls like buttons don't have scroll-bars so their parents (like panels , frames ) must be moved when mouse wheel is moved over the buttons (child controls)

Vibeeshan Mahadeva
  • 7,147
  • 8
  • 52
  • 102
  • 1
    So you want to override the default behaviour (which, most often, is that the control also needs to have keyboard focus)? – Andreas Rejbrand Apr 09 '11 at 17:38
  • 1
    Duplicate: http://stackoverflow.com/questions/2251019/how-to-direct-the-mouse-wheel-input-to-control-under-cursor    Possible duplicate: http://stackoverflow.com/questions/4172307/wmmousewheel-not-working-in-delphi – Sertac Akyuz Apr 10 '11 at 03:04
  • Also i want to change the keyboard focus to the mouse over control – Vibeeshan Mahadeva Apr 10 '11 at 09:39
  • that sounds like a bad idea but if you do it you don't have to play with wheel messages. Just call SetFocus in MouseEnter I guess. Still a bad idea! – David Heffernan Apr 10 '11 at 10:52
  • @PIGP - As @David says, a really bad idea. Users might have a habit of moving the pointer aside when typing, they won't be able to type if the focus is lost then... – Sertac Akyuz Apr 10 '11 at 12:54
  • @David, @Sertac: As an example, both Mozilla Firefox and Mozilla Thunderbird behave like that, and probably those of the SeaMonkey's set too (not sure). That is, the wheel scrolls the control directly under the cursor. When the cursor is not over any scrollable part of the application, it scrolls nothing at all. And the focus isn't changed when the scrolling occurs. – Andriy M Apr 10 '11 at 14:24
  • @andriy mozilla gets this wrong. Wheel really best thought of as equivalent to arrow keys. – David Heffernan Apr 10 '11 at 14:28
  • @David: There may be quite a bunch of users who share just the opposite opinion. I mean, in particular, the users of various Linux systems, where such a behaviour of the mouse wheel in the graphical environment seemed to be prevalent just a few years ago (the last time I was actively using the platform) and quite probably is so till now. – Andriy M Apr 10 '11 at 14:44
  • @andriy that would likely be a tiny proportion then ;-) – David Heffernan Apr 10 '11 at 14:47
  • @Andriy - I was talking about the keyboard focus.. I like it when the window under the pointer scrolls even if it doesn't have the focus. In fact the mice I use behaves that way unless MS compatibility mode is chosen. I don't think MS should have a word in what should be scrolled at all, that should be a user choice. – Sertac Akyuz Apr 10 '11 at 14:51
  • @Sertac: The touchpad on my notebook has a similar selection of behaviour through the driver. I agree about the choice belonging on the user's side, which leads me to the idea that app makers should probably be mindful of that too... – Andriy M Apr 10 '11 at 15:31

1 Answers1

4

Add a TApplicationEvents to your form, and add a OnMessage handler:

procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
  var Handled: Boolean);
var
  pnt: TPoint;
  ctrl: TWinControl;
begin
  if Msg.message = WM_MOUSEWHEEL then
  begin
    if not GetCursorPos(pnt) then Exit;
    ctrl := FindVCLWindow(pnt);
    if Assigned(ctrl) then
    begin
      SendMessage(ctrl.Handle, Msg.message, Msg.wParam, Msg.lParam);
      Handled := true; // or maybe Msg.message := WM_NULL;
    end;
  end;
end;

Update

David Heffernan [see the comments] came up with a smart way of improving this code:

procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
  var Handled: Boolean);
var
  pnt: TPoint;
  ctrl: TWinControl;
begin
  if Msg.message = WM_MOUSEWHEEL then
  begin
    if not GetCursorPos(pnt) then Exit;
    ctrl := FindVCLWindow(pnt);
    if Assigned(ctrl) then
      Msg.hwnd := ctrl.Handle;
  end;
end;
Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
  • mouse wheel events go to the window with input focus not the window under the cursor. – David Heffernan Apr 09 '11 at 22:32
  • 1
    @David: Yes, we all know that. That is also why the OP did ask his question in the first place. (If the converse had been true, the OP would never have asked his question.) I don't say it is a good idea to alter this behaviour, but merely gave the technical details about how to do it, since that was the exact point of the question. If you want to downvote, I suggest you downvote the OP's question instead of a (strictly speaking) correct answer to the question. – Andreas Rejbrand Apr 09 '11 at 22:48
  • (The Delphi 2009 IDE do behave like this: the control beneath the cursor is scrolled when the wheel is spun, irrespective of the keyboard focus.) – Andreas Rejbrand Apr 09 '11 at 22:50
  • If you want to do this, and I hadn't understood the nuances of the question, it is neater to change msg.hwnd to ctrl, not call SendMessage and leave handled as false. – David Heffernan Apr 10 '11 at 07:31