用鼠标拖动滚动

时间:2016-11-18 17:13:22

标签: 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);

    }

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

2 个答案:

答案 0 :(得分:5)

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

   Panel pa = ss as Panel; pa.Left = pa.Left + ee.X - pPt.X;

到此:

   Panel pa = ss as Panel; pa.Top = pa.Top + ee.Y - pPt.Y;

要明白“滚动”或“移动”面板也应该高于封闭形式,所以更改大小,可能是这样的:

    f2.Size = new Size(400, 300);
    ..
    pan.Size = new Size(400, 600);

按钮也应该垂直放置,所以改变:

    b.Left = (b.Width + 12) * (i - 1);

    b.Top= (b.Height + 12) * (i - 1);

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

 pan.Parent = f2;

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

如果编码正确,以下是什么样的:

enter image description here

要使MouseWheel工作,您可以将其编码为:

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

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

            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;
                }
            }

应该以类似的方式检查和限制MouseWheel代码!

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

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

答案 1 :(得分:2)

这对我有用。它在所有控件上保持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);
    }
}