I want to set limit scrolling to a scrollable panel

Question

I made a scrollable panel like this:

private void button3_Click(object sender, EventArgs e)
{
    Form f2 = new Form();
    f2.Size = new Size(400, 300);
    f2.AutoScroll = false;
    Panel pan = new Panel();
    pan.Size = new Size(600, 100);
    pan.AutoScroll = false;
    for (int i = 1; i <= 10; i++)
    {
        Button b = new Button();
        b.Text = "B" + (i);
        b.Name = "button_" + (i);
        b.Left = (b.Width + 12) * (i - 1);
        b.Parent = pan;
        pan.Parent = f2;
        f2.Show();
    }
}

private void panel1_MouseWheel(object sender, MouseEventArgs e)
{
        Form2 frm = new Form2();
        panel1.Top += e.Delta > 0 ? 10 : -10;
        if (panel1.Top > 0) 
            panel1.Top = 0;
        else if (panel1.Top <= panel1.Parent.Height) 
            panel1.Top = panel1.Parent.Height;
        Console.WriteLine("panel2.top:" + panel1.Top);

    }

This is the full code of that panel, panel1 = pan...

private void panel1_MouseDown(object sender, MouseEventArgs e)
{
    pPt = e.Location;
}
public void panel1_MouseMove(object sender, MouseEventArgs e)
{
    Console.WriteLine("panel2.top:" + panel1.Top);
    if (e.Button.HasFlag(MouseButtons.Left))
    {
        Form2 frm = new Form2();
        panel1.Top += e.Y - pPt.Y;
        if (panel1.Top > 0) 
            panel1.Top = 0;
        else if (panel1.Top <= panel1.Parent.Height) 
            panel1.Top = panel1.Parent.Height;
    }
}

And you can scroll it by dragging the panel with the mouse but the problem is it looks like this:

And I want to don't go higher than button1 or lower than the last button.


Show source
| c#   | winforms   2016-12-04 18:12 2 Answers

Answers ( 2 )

  1. 2016-12-04 18:12

    We can Get or set the upper limit of values of the scrollable range with

    ScrollBar.Maximum Property

    An example is as follows.

    The following example assumes that you have created a Form, added a PictureBox to the Form, and added a horizontal HScrollBar and a vertical VScrollBar to the PictureBox. This code example is part of a larger example provided for the ScrollBar class overview. In this example, the Maximum property is set to the size of the Image plus the size of the scrollbar if it is visible plus an adjustment factor of the size of the LargeChange property. You must add references to the System.Drawing and System.Windows.Forms namespaces to run this example.

    public void SetScrollBarValues()
        {
            //Set the following scrollbar properties:
    
            //Minimum: Set to 0
    
            //SmallChange and LargeChange: Per UI guidelines, these must be set
            //    relative to the size of the view that the user sees, not to
            //    the total size including the unseen part.  In this example,
            //    these must be set relative to the picture box, not to the image.
    
            //Maximum: Calculate in steps:
            //Step 1: The maximum to scroll is the size of the unseen part.
            //Step 2: Add the size of visible scrollbars if necessary.
            //Step 3: Add an adjustment factor of ScrollBar.LargeChange.
    
    
            //Configure the horizontal scrollbar
            //---------------------------------------------
            if (this.hScrollBar1.Visible)
            {
                this.hScrollBar1.Minimum = 0;
                this.hScrollBar1.SmallChange = this.pictureBox1.Width / 20;
                this.hScrollBar1.LargeChange = this.pictureBox1.Width / 10;
    
                this.hScrollBar1.Maximum = this.pictureBox1.Image.Size.Width - pictureBox1.ClientSize.Width;  //step 1
    
                if (this.vScrollBar1.Visible) //step 2
                {
                    this.hScrollBar1.Maximum += this.vScrollBar1.Width;
                }
    
                this.hScrollBar1.Maximum += this.hScrollBar1.LargeChange; //step 3
            }
    
            //Configure the vertical scrollbar
            //---------------------------------------------
            if (this.vScrollBar1.Visible)
            {
                this.vScrollBar1.Minimum = 0;
                this.vScrollBar1.SmallChange = this.pictureBox1.Height / 20;
                this.vScrollBar1.LargeChange = this.pictureBox1.Height / 10;
    
                this.vScrollBar1.Maximum = this.pictureBox1.Image.Size.Height - pictureBox1.ClientSize.Height; //step 1
    
                if (this.hScrollBar1.Visible) //step 2
                {
                    this.vScrollBar1.Maximum += this.hScrollBar1.Height;
                }
    
                this.vScrollBar1.Maximum += this.vScrollBar1.LargeChange; //step 3
            }
        }
    

    Hope you can change the code accordingly to set the maximum scrollable space.:)

  2. 2016-12-04 19:12

    Tweak this method: you need to "pin" the panel so it doesn't move below the top and above the bottom - because mouse wheel deltas are events you will continuously receive. You have to manually decide when to ignore them

    private void panel1_MouseWheel(object sender, MouseEventArgs e)
    {
            Form2 frm = new Form2();
            panel1.Top += e.Delta > 0 ? 10 : -10;
    
            // tweak this
            if (panel1.Top > 0) panel1.Top = 0;
            else if (panel1.Bottom <= panel1.Parent.Height) panel1.Bottom = panel1.Parent.Height;
    
            Console.WriteLine("panel2.top:" + panel1.Top);
    
    }
    

    Also, the above will work when the panel you are scrolling is "Taller" than the viewport (the form itself). You might need to tweak further when the panel is smaller than the form - so just test a few cases.

    You also need to pay attention to the Resize event so your panel has the correct Top property when someone expands the container form.

◀ Go back