winforms 用鼠标拖动滚动

yqyhoc1h  于 2023-10-23  发布在  其他
关注(0)|答案(3)|浏览(125)

我试图使一个可滚动的面板,但没有滚动条和滚动拖动鼠标垂直.这是到目前为止有人帮助我做的事情。:

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中此行var max = (from Control control in Controls select control.Top + control.Height + padding).Concat(new[] { int.MinValue }).Max();处发生类型为“System.StackOverflowException”的未处理异常

yws3nbqq

yws3nbqq1#

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

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倍的移动距离也是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..?
col17t5w

col17t5w2#

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

oaxa6hgo3#

我测试了这里发布的所有解决方案,但没有一个对我有效。
我的情况是,我正在开发一个打印设计器在不同的打印机应用程序。这个打印设计器提供了缩放打印机和拖动打印机上的打印元素。我想提供拖动鼠标本身时,按下鼠标左键的空白空间的鼠标。
我的表单上有一个面板(pnlWorkspace),AutoScroll = true。我展示了多个嵌板

  1. pnlBorder with BackgroundColor = Black比纸张大小大2个像素
  2. pnlReceipt位于pnlBorder内,位置1,1,大小比pnlBorder小2 px,且BackgroundColor = Gainsboro
    1.根据真实的打印机边距和BackgroundColor =白色设置位置和大小的pnlPrintArea;
    由于纸张大小和缩放的原因,面板可能会大于自动滚动设置为True的包含面板。
    我的非常简单的工作解决方案没有任何问题(甚至鼠标的滚动轮仍然工作)只使用了很少的几行代码。首先,我直接在From中创建了一个变量:
private Boolean dragScroll = false;

然后我添加了三个步骤:

private void Panel_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            clickPos = PointToClient(MousePosition);
            clickPos.X -= pnlWorkspace.AutoScrollPosition.X;
            clickPos.Y -= pnlWorkspace.AutoScrollPosition.Y;
            dragScroll = true;
            pnlBorder.Cursor = pnlReceipt.Cursor = pnlPrintArea.Cursor = Cursors.SizeAll;
        }
    }

    private void Panel_MouseMove(object sender, MouseEventArgs e)
    {
        if ((e.Button == MouseButtons.Left) && (dragScroll))
        {
            mousePos = PointToClient(MousePosition);
            pnlWorkspace.AutoScrollPosition = new Point((clickPos.X - mousePos.X), (clickPos.Y - mousePos.Y));
        }
    }

    private void Panel_MouseUp(object sender, MouseEventArgs e)
    {
        dragScroll = false;
        pnlBorder.Cursor = pnlReceipt.Cursor = pnlPrintArea.Cursor = Cursors.Default;
    }

然后,我通过在“属性”窗口中选择面板pnlBorder、pnlReceipt和pnlPrintArea,将这些行连接到它们。这就是它的全部:)
下面是一段视频,展示了Print Designer的功能:https://youtu.be/frjWn5bOyo8

相关问题