Nothing Special   »   [go: up one dir, main page]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use of SystemInformation.MouseWheelScrollDelta within MouseWheel event for Zooming #8

Open
finito opened this issue Sep 11, 2016 · 3 comments
Assignees
Labels

Comments

@finito
Copy link
finito commented Sep 11, 2016

Hi,

I want to bring attention to the usage of SystemInformation.MouseWheelScrollDelta which cannot be relied upon.

It causes an issue where cannot Zoom without scrolling the mouse wheel a lot because there are mice that have a different delta constant to what is given by SystemInformation.MouseWheelScrollDelta.

The mouse I have right now has a delta of 30 but SystemInformation.MouseWheelScrollDelta is 120.

The code where issue is:

       int spins;

        // The MouseWheel event can contain multiple "spins" of the wheel so we need to adjust accordingly
        spins = Math.Abs(e.Delta / SystemInformation.MouseWheelScrollDelta);

        // TODO: Really should update the source method to handle multiple increments rather than calling it multiple times
        for (int i = 0; i < spins; i++)
        {
          this.ProcessMouseZoom(e.Delta > 0, e.Location);
        }

One way to fix the issue is to keep a remainder of delta / SystemInformation.MouseWheelScrollDelta and make sure to reset the remainder to 0 if scroll direction changes or scrolling stops (after a period of time has passed).

I have put together code changes for the above fix. The code has been tested and the fix is working.


    private const int MouseWheelScrollDeltaRemainderResetDelay = 250;
    private int _mouseWheelScrollDeltaRemainder;
    private int _mouseWheelScrollDeltaUpdateTime;

    protected override void OnMouseWheel(MouseEventArgs e)
    {
      base.OnMouseWheel(e);

      if (this.AllowZoom && this.SizeMode == ImageBoxSizeMode.Normal)
      {
        // A remainder is kept so can support mice that use a  delta value that isn't SystemInformation.MouseWheelScrollDelta
        // for the mouse wheel.
        //
        // The remainder will also be reset to 0 after a time delay to prevent it affecting future scrolling where user stops
        // scrolling and then comes back and starts scrolling again. In that case we want the remainder to start at 0 again.
        //
        // To detect the switching of scroll direction will simply just check the sign of delta and delta remainder.
        // Then can reset the remainder to 0 because do not want the scrolling in different direction to affect the current direction.
        int delta = e.Delta + this._mouseWheelScrollDeltaRemainder;

        if (Environment.TickCount - this._mouseWheelScrollDeltaUpdateTime > MouseWheelScrollDeltaRemainderResetDelay ||
            (delta < 0) != (this._mouseWheelScrollDeltaRemainder < 0))
        {
          this._mouseWheelScrollDeltaRemainder = 0;
        }

        this._mouseWheelScrollDeltaRemainder = delta % SystemInformation.MouseWheelScrollDelta;
        this._mouseWheelScrollDeltaUpdateTime = Environment.TickCount;

        int spins;

        // The MouseWheel event can contain multiple "spins" of the wheel so we need to adjust accordingly
        spins = Math.Abs(delta / SystemInformation.MouseWheelScrollDelta);

        // TODO: Really should update the source method to handle multiple increments rather than calling it multiple times
        for (int i = 0; i < spins; i++)
        {
          this.ProcessMouseZoom(e.Delta > 0, e.Location);
        }
      }
    }
@cyotek
Copy link
Owner
cyotek commented Sep 13, 2016

Hello,

Thanks for the bug report, that's something I haven't come across before.

What mouse are you using? I don't really want to add random fixes without being able to reproduce it so I'm slightly wary of this code at present. The MSDN page for WM_MOUSEWHEEL proposes a slightly different solution to what you have implemented, but regardless of the final solution I'd still like to be able to repro it first. I use similar code to the (original) delta code in other controls without custom wheel processing too.

Many thanks for taking the time to log the issue and propose a solution.

Regards;
Richard Moss

@cyotek cyotek self-assigned this Sep 13, 2016
@cyotek cyotek added the bug label Sep 13, 2016
@finito
Copy link
Author
finito commented Sep 13, 2016

Hi,

I had never come across it before either until I started using this mouse. The mouse I am using right now is a Microsoft IntelliMouse Explorer (Model: 1004) (Was previously using a Logitech Performance MX but I need to get a replacement) but as far as I know it is any mouse that has a high resolution/smooth scroll. I have found doing a search on Google for "High-resolution mouse wheel" brings up information.

That fix is for when cannot do partial or per-pixel scrolling. So another way could be to change ProcessMouseZoom so it can do smaller increments using the delta.

A crude way to reproduce the problem for testing would be to change the incoming delta values to a factor of 120 (will need to handle multiples aswell). This will simulate the problem for the mouse you are using.

This will work (I have tested it with my Logitech Performance MX and it reproduces the problem):

int delta = 30 * (e.Delta / SystemInformation.MouseWheelScrollDelta);
spins = Math.Abs(delta / SystemInformation.MouseWheelScrollDelta);

Regards,
Charles

@cyotek
Copy link
Owner
cyotek commented Sep 13, 2016

Hello,

Thanks for the follow up. I used to love my IntelliMouse Explorers, they were good mice and I still have a couple of receivers still floating around after the base units themselves gave up the ghost. I don't even think you can get them now, just as difficult getting Comfort Curve 2000 replacements.

I'll take a look at this as soon as I can - I've been working on and off on a newer version of the control for some time now, should probably do some more work on that!

Regards;
Richard Moss

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants