【问题标题】:Scroll by dragging with mouse用鼠标拖动滚动
【发布时间】:2021-10-02 22:09:48
【问题描述】:

我正在尝试制作一个可滚动的面板,但没有滚动条,并通过鼠标垂直拖动来滚动......这是迄今为止有人帮助我做的事情......:

 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();

【问题讨论】:

    标签: c# winforms


    【解决方案1】:

    发布的代码仅“滚动”或移动面板水平。要获得垂直滚动效果,请更改:

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

    你在从 cmets 复制时也犯了一个错误:这个:

     pan.Parent = f2;
    

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

    以下是正确编码后的样子:

    要使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..?
    

    【讨论】:

    • 我制作了一个视频并将其发布在这里,向您展示它是如何工作的。它是相同的代码..vimeo.com/194139497
    • 所以如果我把鼠标移到循环之外它应该可以工作吗?
    • 是的,它现在可以工作了....但是我的表单中已经有一些我想滚动的按钮,它们也可以工作吗?另外我想在顶部和底部设置最大滚动点..
    • 所以它只会在现有面板中滚动,对吗?我的意思是从位置 0 到它的最大尺寸不高于或成为循环滚动..
    • 是的,没错,但我当时不能问问题......也......我看到你让它也能向上滚动,但我希望它只从按钮开始的地方滚动到按钮结束的地方..不超过..
    【解决方案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);
        }
    }
    

    【讨论】:

    • mouseMove 和鼠标向下实际上通过鼠标滚动拖动是有效的......但是当我使用鼠标滚轮时它只是冻结并且在那之后不能做任何事情......我也改变了填充为 -1,因为这就是我喜欢的方式......所以鼠标滚轮无法正常工作
    • 当我尝试用鼠标滚轮滚动时,它给了我这个错误:在 System.Core.dll 在这一行 var max = (from Control control in Controls select control.Top + control.Height + padding).Concat(new[] { int.MinValue }).Max();
    • 仍然无法正常工作,出现此错误:System.Windows.Forms.dll 在此行中发生了“System.StackOverflowException”类型的未处理异常:foreach (Control control in Controls) in GetMax
    • github.com/cristicretan/OutfitPick/blob/master/Clothes%20Pick/… 这是我完整的 form2 cs 代码...得到了同样的错误,但在 Controls.Count 的 for 中
    • 从 github 下载了你的代码并添加了 ScrollablePanel 类,然后在设计模式下将 Panel 更改为 ScrollablePanel,并从粘贴的 ScrollablePanel 代码中删除了所有代码并放置 Dock=Fill。然后测试了代码,可能做了一些我现在不记得的更改,以确保它有效。当你知道我猜的新代码时很容易..如果它有效,请将其标记为已接受:)
    猜你喜欢
    • 2015-10-10
    • 1970-01-01
    • 1970-01-01
    • 2011-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多