Prevent Scrolling with Mouse Wheel in Windows Forms
Asked Answered
J

1

5

I want to prevent a panel from scrolling when the mousewheel is used. I've tried setting the flag Handled on the HandledMouseEventArgs to false, but that doesn't work.

In this repro code, we have one panel and one button.

using (var scrollTestForm=new Form())
{
    var panel = new Panel() { Dock = DockStyle.Fill };
    scrollTestForm.Controls.Add(panel);
    var buttonOutsideArea = new Button();
    buttonOutsideArea.Location = new System.Drawing.Point(panel.Width * 2, 100);
    panel.Controls.Add(buttonOutsideArea);
    panel.AutoScroll = true;
    panel.MouseWheel += delegate (object sender, MouseEventArgs e)
    {
        ((HandledMouseEventArgs)e).Handled = false;
    };
    scrollTestForm.ShowDialog();
}

When using the mouse wheel, the panel scrolls. How can I prevent it from scrolling?

Jumper answered 17/12, 2019 at 8:37 Comment(0)
F
8

You need to create your custom control and WM_MOUSEWHEEL message

So first create a new panel

    public class PanelUnScrollable : Panel
    {       
        protected override void WndProc(ref Message m)
        {           
            if(m.Msg == 0x20a) return; 
            base.WndProc(ref m);
        }
    }

Edit, or if you want to control is scrollable or not(and then in your main panel you can call panel.ScrollDisabled = true);

    public class PanelUnScrollable : Panel
    {
        public bool ScrollDisabled { get; set; }
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == 0x20a && ScrollDisabled) return;             
            base.WndProc(ref m);
        }
    }

Then use it in your original form

        public Form2()
        {
            InitializeComponent();

            CreateNewUnscrollablePanel();            
        } 

        public void CreateNewUnscrollablePanel()
        {
           using (var unScrollablePanel = new UnScrollablePanel() { Dock = DockStyle.Fill })
            {                     
                this.Controls.Add(unScrollablePanel);
                var buttonOutsideArea = new Button();
                buttonOutsideArea.Location = new System.Drawing.Point(unScrollablePanel.Width * 2, 100);
                unScrollablePanel.Controls.Add(buttonOutsideArea);
                unScrollablePanel.AutoScroll = true;
                unScrollablePanel.ScrollDisabled = true; //-->call the panel propery
                unScrollablePanel.MouseWheel += delegate(object sender, MouseEventArgs e) //--> you dont need this
                {
                    ((HandledMouseEventArgs)e).Handled = true;
                };

                this.ShowDialog();
            }
        }
Fleeman answered 17/12, 2019 at 9:41 Comment(3)
To be precise, you should set m.WParam = IntPtr.Zero; m.Result = IntPtr.Zero; and let base.WndProc get through.Swifter
@Swifter can you explain why?Fleeman
WParam set to IntPtr.Zero will change the carrier content, saying no wheel rotation happened. m.Result = IntPtr.Zero is the standard result when this message has been processes. Letting base.WndProc through preserves the mouse location that lParam is referencing.Swifter

© 2022 - 2024 — McMap. All rights reserved.