1
votes

Something is fishy with the mouse wheel / middle mouse button in my C# Windows Forms application, and in other applications.

How can I detect that the middle mouse button is being held down in the following scenario? (because Control.MouseButtons lies!)

If I scroll the mouse wheel, then quickly press the wheel button (which is set to produce a Middle-click in the control panel), then this code does not detect a MouseDown event for the middle mouse button. Furthermore, if I continue to hold the wheel button down, and simultaneously scroll the wheel while the button is held down, then I get MouseWheel events but Control.MouseButtons does not indicate that the middle button is held down. This seems like an egregious flaw. The wheel button is now physically held down, but there seems to be no way to detect that it is down.

In contrast to this, if I press the wheel button down first (without scrolling the wheel), and hold it down, then the scroll wheel event correctly indicates that the middle mouse button is down as one would expect.

This seems like I may be wrestling with some secret cleverness that Microsoft has implemented to try to prevent accidental wheel button clicks while using the mouse wheel. But really what it means is that the middle mouse button (wheel button) is not correctly detected to be down if the wheel is scrolled slightly just before being depressed. I don't actually know if this cleverness is implemented at the hardware level or driver level or application level or what. I'm not entirely certain if there's anything that can be done.

I'm particularly worried because I tried to reproduce this phenomenon in other apps and I was able to reproduce the problem in Blender, for example. So maybe there isn't anything that can be done in C#. Or maybe there's a control panel setting or something that will overcome this. I'm not sure if this is a hardware problem, but I suspect it might be something with the mouse driver - and that it likely seems to be intentional. I don't know the extent to which this behaviour occurs with other kinds of mouse devices by other vendors, or if it's just this mouse. I haven't checked to see if it happens with the same mouse on other operating systems.

I'm hoping someone can tell me a way to detect that the middle mouse button is down in this scenario. If not, then I would also be curious to know if this is a bug that can be corrected with a software (driver?) update or if it's a hardware limitation of this mouse (or maybe all mouse devices).

Here is code that can be used to detect this phenomenon.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        MouseDown += Form1_MouseDown;
        MouseWheel += Form1_MouseWheel;
    }

    private void Form1_MouseWheel(object sender, MouseEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("MouseWheel {0}", MouseButtons);
    }

    private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("MouseDown");
    }
}

Again, the magic steps to reproduce the problem are:

  • scroll the mouse wheel a little
  • immediately depress the mouse wheel button (which is configured to deliver a middle mouse button click, according to the mouse properties / control panel.)
  • (we are already in a bad state because we did not receive a middle mouse down event.)
  • continue to hold the button and scroll the wheel, which will cause the code above to indicate that the mouse button is not down. (Control.MouseButtons has been fooled into thinking the middle mouse button is not down.)

In case any of these details matter:

  • Microsoft IntelliMouse Optical USB
    • Driver Date: 2011-05-18
    • Driver Version 8.20.409.0
  • Windows 10 1909 (18363.900)
  • Visual Studio 2019
  • .NET Framework 4.7.2

Screenshot of Mouse Properties in Control Panel

1
For what it's worth, my finding is that after pressing and holding down the mouse wheel, and then scrolling, a few scroll events might be detected, but then stop, after which no more scroll events are dispatched, even though I am rolling the wheel.Loathing
Further, if scrolling the mouse wheel and then pressing down the wheel, after that no more scroll events are dispatched. So it seems like it is not a good idea to expect the mouse wheel to behave consistently, i.e. it's not something that can be depended on to function the same way across different computers.Loathing

1 Answers

1
votes

MouseDown detects when any mouse buttons are pressed - meanwhile MouseClick detects when the button is released. Giving that you could capture the following events:

    public Form1()
    {
        InitializeComponent();
        MouseDown += Form1_MouseDown;
        MouseClick += Form1_Click;
        MouseWheel += Form1_MouseWheel;
    }

    private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Button pressed {0}", e.Button);
    }

    private void Form1_MouseWheel(object sender, MouseEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Wheel in action....");
    }

    private void Form1_Click(object sender, MouseEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Button Released {0}", e.Button);
    }

enter image description here

Edit

Screenshot with time stamp enter image description here

The time difference between Wheel in action and Button pressed Middle is 32ms.

Let me know if the above is what you are looking for.