用鼠标拖动滚动

C. *_*sti 4 c# winforms

我试图制作一个可滚动的面板但没有滚动条并通过垂直拖动滚动...这是有人帮助我做到目前为止...:

 private void panel1_MouseEnter(object sender, EventArgs e)
    {
        panel1.AutoScroll = false;
    }

    private int ValidateChange(int change)
    {
        var padding = -1;
        if (change < 0)
        {
            var max = (from Control control in Controls select control.Top + control.Height + padding).Concat(new[] { int.MinValue }).Max();

            if (max < Height + Math.Abs(change))
            {
                return Height - max;
            }
        }
        else
        {
            var min = (from Control control in Controls select control.Top).Concat(new[] { int.MaxValue }).Min();

            if (min > padding - Math.Abs(change))
            {
                return padding - min;
            }
        }
        return change;
    }

    private void HandleDelta(int delta)
    {
        var change = ValidateChange(delta);

        foreach (Control control in Controls)
        {
            control.Top += change;
        }

    }

    private void panel1_MouseWheel(object sender, MouseEventArgs e)
    {
        HandleDelta(e.Delta);
        base.OnMouseWheel(e);
    }

    private Point _mouseLastPosition;

    private void panel1_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            _mouseLastPosition = e.Location;
        }
        base.OnMouseDown(e);
    }

    public void panel1_MouseMove(object sender, MouseEventArgs e)
    {            
            if ((MouseButtons & MouseButtons.Left) != 0)
            {
                var delta = e.Y - _mouseLastPosition.Y;
                HandleDelta(delta);
                _mouseLastPosition = e.Location;
            }
            base.OnMouseMove(e);

    }
Run Code Online (Sandbox Code Playgroud)

但是它太快了..编辑:鼠标拖动看起来有点奇怪我不知道为什么当我尝试使用鼠标滚轮时它会出现错误并给我这个错误:发生了'System.StackOverflowException'类型的未处理异常在此行的System.Core.dll中 var max = (from Control control in Controls select control.Top + control.Height + padding).Concat(new[] { int.MinValue }).Max();

TaW*_*TaW 5

发布的代码仅"滚动"或更确切地水平移动面板.对于垂直滚动效果,请更改:

   Panel pa = ss as Panel; pa.Left = pa.Left + ee.X - pPt.X;
Run Code Online (Sandbox Code Playgroud)

对此:

   Panel pa = ss as Panel; pa.Top = pa.Top + ee.Y - pPt.Y;
Run Code Online (Sandbox Code Playgroud)

要理解"滚动"或"移动"面板也应该高于封闭形式,因此更改尺寸,可能是这样的:

    f2.Size = new Size(400, 300);
    ..
    pan.Size = new Size(400, 600);
Run Code Online (Sandbox Code Playgroud)

并且按钮也应垂直放置,因此更改:

    b.Left = (b.Width + 12) * (i - 1);
Run Code Online (Sandbox Code Playgroud)

    b.Top= (b.Height + 12) * (i - 1);
Run Code Online (Sandbox Code Playgroud)

从评论中复制时你也犯了一个错误:这:

 pan.Parent = f2;
Run Code Online (Sandbox Code Playgroud)

应该是循环中的最后一行.在循环中添加事件处理程序意味着也MouseMove称为10倍移动距离也是十倍.

正确编码时,这是什么样子:

在此输入图像描述

为了完成这项MouseWheel工作你可以像这样编码:

 pan.MouseWheel += (ss, ee) =>
 {
      Panel pa = ss as Panel;
      pa.Top += ee.Delta > 0 ? 10 : -10;
 };
Run Code Online (Sandbox Code Playgroud)

更新看起来您还希望限制滚动,以便顶部和底部都不会移动到显示区域.这是一个实现这一目标的检查; 诀窍是首先进行检查,然后才进行移动:

            if (ee.Button.HasFlag(MouseButtons.Left))
            {
                Panel pa = ss as Panel;

                int newTop =  pa.Top + ee.Y - pPt.Y;

                if ((newTop <= pan.Top && newTop + pan.Height > f2.ClientSize.Height) ||
                    (newTop >= pan.Top && newTop <= 0))
                {
                    if (newTop <= pan.Top && newTop + pan.Height > f2.ClientSize.Height) 
                        newTop = f2.ClientSize.Height - pan.Height;
                    pa.Top = newTop;
                }
            }
Run Code Online (Sandbox Code Playgroud)

MouseWheel代码应该进行检查,并以类似的方式限制!

注意:正确的面板高度至关重要.我的原始示例没有处理,因为没有要求滚动限制.你可以动态地得到它:

int panHeight = pan.Controls.Cast<Control>().Select(x => x.Bottom).Max();
pan.Height = panHeight;  // maybe add a small gap here..?
Run Code Online (Sandbox Code Playgroud)

  • 我制作了一个视频,然后在这里发布,告诉你它是如何工作的......这是相同的代码.. https://vimeo.com/194139497 (2认同)
  • 所以,如果我把鼠标移到现场循环它应该工作? (2认同)
  • 是的它现在有效....但我已经在我的表格中有一些按钮我想要滚动它是否也适用于他们?另外,我想在顶部和下部设置最大滚动点.. (2认同)
  • 所以它只会在现有面板中滚动吗?我的意思是只从位置0到它的最大尺寸不高或成为循环滚动.. (2认同)
  • 是的,那是对的,但我当时也不能提问...也..我看到你能够向上滚动但是我希望它只能从按钮开始滚动到按钮结束的位置..不比那更多的.. (2认同)
  • 让我们[在聊天中继续讨论](http://chat.stackoverflow.com/rooms/129683/discussion-between-c-cristi-and-taw). (2认同)
  • 你看到我的留言了吗? (2认同)
  • 轮子在顶部工作完美,但在底部不是真正的pan.Top = pan.Height - f2.Height; 按钮dissapear这样的...还我怎么告诉他不要动,如果是通过拖动太高......它看起来可能是因为鼠标按下事件的怪异..但可以;吨弄清楚什么;错 (2认同)
  • 我确实为面板设置了颜色,我会试试 (2认同)
  • 我想会发生什么呢,它给了我panel1.Height - button8.Height(最后一个按钮)在面板的顶部,不能从那里滚动..我确实这样:`if(panel1.Top <panel1 .Height - button8.Bottom)panel1.Top = panel1.Height - button8.Bottom;`**这是鼠标滚轮** (2认同)
  • 现在我尝试了这样,它有点工作,但当我太"低"时,它再次将我带到顶部,我想留在底部......`if(panel1.Top> 0)panel1.Top = 0; else if(panel1.Bottom <panel1.Parent.Height)panel1.Top = panel1.Height;` (2认同)
  • 仍然不起作用..上部仍然在上面但是太低说不"直到结束"我的意思是直到面板的最大尺寸..超过最后一个按钮.. (2认同)

MrA*_*nea 3

这对我有用。它在所有控件上保持 10 像素的填充。尝试一下并根据您的需要进行修改。

如果缺少您需要的东西,请告诉我。

public class ScrollablePanel : Panel {
    private Point _mouseLastPosition;

    protected override void OnMouseDown(MouseEventArgs e) {
        if (e.Button == MouseButtons.Left) {
            _mouseLastPosition = e.Location;
        }
        base.OnMouseDown(e);
    }

    private int ValidateChange(int change) {
        var padding = -1;
        if (change < 0) {
            var max = (from Control control in Controls select control.Top + control.Height + padding).Concat(new[] { int.MinValue }).Max();

            if (max < Height + Math.Abs(change)) {
                return Height - max;
            }
        }
        else {
            var min = (from Control control in Controls select control.Top).Concat(new[] { int.MaxValue }).Min();

            if (min > padding - Math.Abs(change)) {
                return padding - min;
            }
        }
        return change;
    }

    private void HandleDelta(int delta) {
        var change = ValidateChange(delta);

        foreach (Control control in Controls) {
            control.Top += change;
        }

    }

    protected override void OnMouseMove(MouseEventArgs e) {
        if((MouseButtons & MouseButtons.Left) != 0) { 
            var delta = e.Y - _mouseLastPosition.Y;
            HandleDelta(delta);
            _mouseLastPosition = e.Location;
        }
        base.OnMouseMove(e);
    }

    protected override void OnMouseWheel(MouseEventArgs e) {
        HandleDelta(e.Delta);
        base.OnMouseWheel(e);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 从github下载代码并添加ScrollablePanel类,然后在设计模式下将Panel更改为ScrollablePanel,并从粘贴的ScrollablePanel代码中删除所有代码并放置Dock=Fill。然后测试了代码,可能还做了一些我现在不记得的更改,以确保它有效。我想,当您知道新代码时就很容易了。如果有效,请将其标记为已接受:) (2认同)