Windows Forms: capturing MouseWheel
Asked Answered
A

2

6

I have a Windows Form (working in C#.NET).

The form has a couple of panels top-side and some ComboBoxes and DataGridViews bottom-side.

I want to use the scroll events on the top-side panels, but if selecting a e.g. ComboBox the focus is lost. The panels contain various other controls.

How could I always receive the mouse wheel events when the mouse is over any of the panels ? So far I tried to use the MouseEnter / MouseEnter events but with no luck.

Alenaalene answered 22/1, 2011 at 18:53 Comment(0)
H
13

What you describe sounds like you want to replicate the functionality of for example Microsoft Outlook, where you don't need to actually click to focus the control to use the mouse wheel on it.

This is a relatively advanced problem to solve: it involves implementing the IMessageFilter interface of the containing form, looking for WM_MOUSEWHEEL events and directing them to the control that the mouse is hovering over.

Here's an example (from here):

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsApplication1 {
  public partial class Form1 : Form, IMessageFilter {
    public Form1() {
      InitializeComponent();
      Application.AddMessageFilter(this);
    }

    public bool PreFilterMessage(ref Message m) {
      if (m.Msg == 0x20a) {
        // WM_MOUSEWHEEL, find the control at screen position m.LParam
        Point pos = new Point(m.LParam.ToInt32());
        IntPtr hWnd = WindowFromPoint(pos);
        if (hWnd != IntPtr.Zero && hWnd != m.HWnd && Control.FromHandle(hWnd) != null) {
          SendMessage(hWnd, m.Msg, m.WParam, m.LParam);
          return true;
        }
      }
      return false;
    }

    // P/Invoke declarations
    [DllImport("user32.dll")]
    private static extern IntPtr WindowFromPoint(Point pt);
    [DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
  }
}

Note that this code is active for all the forms in your application, not just the main form.

Hetman answered 22/1, 2011 at 19:11 Comment(9)
Thanks, seen it there but I am not sure why handling of WM_MOUSEWHEEL isn't very desirable.Alenaalene
Hey, that's my code! Not so sure if attribution required is appropriate here, it ought to be.Lunate
The comment the poster makes is "Windows' handling of MouseWheel events isn't very desirable", meaning the default Windows implementation of the mouse wheel means that it sends the events to the control with focus, not the control that the mouse is hovering over, as most people would expect or desire.Hetman
@Hans Passant, @Jon Grant Thanks... BTW: can I make it work only over certain controls ? i.e. not scroll combobox if not focused ?Alenaalene
You save my day. Best solution for scrolling without focus!Rucker
Just implemented something similar, but with an additional test: "Control.FromHandle(hWnd).FindForm() == this" to ensure it only works for messages to controls on the same form.Auxiliaries
Thanks for this great piece of code! I understand all except this test: hWnd != m.HWnd. What is its purpose?Richia
@KevinVuilleumier hWnd contains the window handle of the control under the mouse location. It is checking if the WM_MOUSEWHEEL message is already destined for the control. If it isn't, then we send the message to it (if it is, then we don't need to do anything).Hetman
I wonder why none of the AddMessageFilter samples contains the corresponding call to RemoveMessageFilter. If this is the main window of the application, there's no problem. If multiple new instances of the window can be created throughout the runtime of the application however, leaving out RemoveMessageFilter will mean you'll accumulate message filters. Which, if nothing else, will mean you leak memory and slow down the application.Amblyoscope
S
0

Every control has a mousewheel event that occurs when the mouse wheel moves while the control has focus.

Check this out for more info: Control.MouseWheel Event

Satisfaction answered 22/1, 2011 at 19:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.