如何使用ScrollableControl与自动滚屏设置为false [英] How to use ScrollableControl with AutoScroll set to false

查看:394
本文介绍了如何使用ScrollableControl与自动滚屏设置为false的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个自定义绘制的文档画布放大自定义控件。

I have a custom control that zooms on a custom drawn document canvas.

我试图使用自动滚屏但它没有给出令人满意的结果。当我设置AutoScrollPosition和AutoScrollMinSize背靠背(以任意顺序),这将迫使涂料,导致抖动每一次变焦的变化。我想这是因为它被调用一个更新,而不是无效,当我修改这两个属性。

I tried using AutoScroll but it was not giving satisfactory results. When I would set AutoScrollPosition and AutoScrollMinSize back to back (in any order) it would force a paint and cause jitter each time the zoom changes. I assume this was because it was calling an Update and not Invalidate when I modified both properties.

我现在手动设置是的AutoScroll集Horizo​​ntalScroll和VerticalScroll性能为false 像这样每一次的缩放级别或客户端大小的变化:

I am now manually setting the HorizontalScroll and VerticalScroll properties with AutoScroll set to false like so each time the Zoom level or the client size changes:

int canvasWidth = (int)Math.Ceiling(Image.Width * Zoom) + PageMargins.Horizontal;
int canvasHeight = (int)Math.Ceiling(Image.Height * Zoom) + PageMargins.Vertical;

HorizontalScroll.Maximum = canvasWidth;
HorizontalScroll.LargeChange = ClientSize.Width;

VerticalScroll.Maximum = canvasHeight;
VerticalScroll.LargeChange = ClientSize.Height;

if (canvasWidth > ClientSize.Width)
{
    HorizontalScroll.Visible = true;
}
else
{
    HorizontalScroll.Visible = false;
    HorizontalScroll.Value = 0;
}

if (canvasHeight > ClientSize.Height)
{
    VerticalScroll.Visible = true;
}
else
{
    VerticalScroll.Visible = false;
    VerticalScroll.Value = 0;
}

int focusX = (int)Math.Floor((FocusPoint.X * Zoom) + PageMargins.Left);
int focusY = (int)Math.Floor((FocusPoint.Y * Zoom) + PageMargins.Top);

focusX = focusX - ClientSize.Width / 2;
focusY = focusY - ClientSize.Height / 2;

if (focusX < 0)
    focusX = 0;
if (focusX > canvasWidth - ClientSize.Width)
    focusX = canvasWidth - ClientSize.Width;

if (focusY < 0)
    focusY = 0;
if (focusY > canvasHeight - ClientSize.Height)
    focusY = canvasHeight - ClientSize.Height;

if (HorizontalScroll.Visible)
    HorizontalScroll.Value = focusX;

if (VerticalScroll.Visible)
    VerticalScroll.Value = focusY;

在这种情况下, FocusPoint 是持有坐标中的PointF结构其中用户集中于(例如,当它们鼠标滚轮来放大它们集中在当前鼠标位置当时)的位图。此功能适用于大部分。

In this case, FocusPoint is a PointF structure that holds the coordinates in the bitmap which the user is focused on (for example, when they mouse wheel to zoom in they are focusing on the current mouse location at that time). This functionality works for the most part.

什么不工作是滚动条。如果用户试图手工通过单击滚动条滚动上,他们都回头率0我不设置这些其他地方在我的代码。我试图写在OnScroll()方法如下:

What does not work is the scroll bars. If the user tries to manually scroll by clicking on either scroll bar, they both keep returning to 0. I do not set them anywhere else in my code. I have tried writing the following in the OnScroll() method:

if (se.ScrollOrientation == ScrollOrientation.VerticalScroll)
{
    VerticalScroll.Value = se.NewValue;
}
else
{
    HorizontalScroll.Value = se.NewValue;
}

Invalidate();



不过,这会导致一些非常不稳定的行为,包括弹和滚动出界。

But this causes some very erratic behavior including flicking and scrolling out of bounds.

我怎么写的OnScroll代码?我已经试过base.OnScroll但它没有做任何事情,而自动滚屏设置为false。

How am I supposed to write the code for OnScroll? I've tried the base.OnScroll but it didn't do anything while AutoScroll is set to false.

推荐答案

我结束了创建3子控件实现我自己的自定义滚动:一个HScrollBar控件,一个VScrollBar和面板

I ended up implementing my own custom scrolling by creating 3 child controls: an HScrollBar, a VScrollBar, and a Panel.

我隐藏ClientSize和ClientRectangle像这样:

I hide ClientSize and ClientRectangle like so:

public new Rectangle ClientRectangle
{
    get
    {
        return new Rectangle(new Point(0, 0), ClientSize);
    }
}

public new Size ClientSize
{
    get
    {
        return new Size(
            base.ClientSize.Width - VScrollBar.Width,
            base.ClientSize.Height - HScrollBar.Height
        );
    }
}



布局在OnClientSizeChanged完成:

The layout is done in OnClientSizeChanged:

protected override void OnClientSizeChanged(EventArgs e)
{
    base.OnClientSizeChanged(e);

    HScrollBar.Location = new Point(0, base.ClientSize.Height - HScrollBar.Height);
    HScrollBar.Width = base.ClientSize.Width - VScrollBar.Width;

    VScrollBar.Location = new Point(base.ClientSize.Width - VScrollBar.Width, 0);
    VScrollBar.Height = base.ClientSize.Height - HScrollBar.Height;

    cornerPanel.Size = new Size(VScrollBar.Width, HScrollBar.Height);
    cornerPanel.Location = new Point(base.ClientSize.Width - cornerPanel.Width, base.ClientSize.Height - cornerPanel.Height);
}

每个滚动条都有自己的滚动事件订阅以下内容:

Each ScrollBar has their Scroll event subscribed to the following:

private void ScrollBar_Scroll(object sender, ScrollEventArgs e)
{
    OnScroll(e);
}



最后,我们可以让鼠标滚轮事件有以下滚动:

And finally we can allow MouseWheel events to scroll with the following:

protected override void OnMouseWheel(MouseEventArgs e)
{
    int xOldValue = VScrollBar.Value;

    if (e.Delta > 0)
    {
        VScrollBar.Value = (int)Math.Max(VScrollBar.Value - (VScrollBar.SmallChange * e.Delta), 0);
        OnScroll(new ScrollEventArgs(ScrollEventType.ThumbPosition, xOldValue, VScrollBar.Value, ScrollOrientation.VerticalScroll));
    }
    else
    {
        VScrollBar.Value = (int)Math.Min(VScrollBar.Value - (VScrollBar.SmallChange * e.Delta), VScrollBar.Maximum - (VScrollBar.LargeChange - 1));
        OnScroll(new ScrollEventArgs(ScrollEventType.ThumbPosition, xOldValue, VScrollBar.Value, ScrollOrientation.VerticalScroll));
    }
}

有关风俗画,你可以使用如下语句:

For custom painting, you would use the following statement:

e.Graphics.TranslateTransform(-HScrollBar.Value, -VScrollBar.Value);

这工作完全不存在的毛刺使用自动滚屏时。

This worked perfectly without the glitches present when using AutoScroll.

这篇关于如何使用ScrollableControl与自动滚屏设置为false的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆