2012-04-23 252 views
6

我有一个自定义控件,可以在自定义绘制文档画布上进行缩放。如何将ScrollableControl与AutoScroll设置为false

我试过使用AutoScroll,但没有给出令人满意的结果。当我将AutoScrollPosition和AutoScrollMinSize背对背(以任何顺序)时,它会在每次缩放更改时强制绘制并导致抖动。我认为这是因为它调用了更新而不是无效当我修改这两个属性。

我现在手动设置与的AutoScroll集Horizo​​ntalScroll和VerticalScroll属性设置为false所以每次像缩放级别或客户端大小的变化:

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结构保存用户关注的位图中的坐标(例如,当鼠标滚轮放大时,他们将焦点放在当时的鼠标位置上)。该功能大部分适用。

什么不行的是滚动条。如果用户尝试通过单击滚动条来手动滚动,则它们都会返回0.我不会在代码中的其他位置设置它们。我试图写在OnScroll()方法如下:

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

Invalidate(); 

但这会导致一些非常古怪的行为,包括弹和滚动出界。

我该如何编写OnScroll的代码?我试过了base.OnScroll,但AutoScroll设置为false时并没有做任何事情。

+0

我觉得你第一次就对了。首先设置AutoScrollMinSize,然后调用AutoScrollPosition。使用双缓冲面板来控制闪烁。 – LarsTech 2012-04-23 18:50:27

+0

我的控件是双缓冲的。除非我同时更改AutoScrollMinSize和AutoScrollPosition,否则它不会闪烁。 – 2012-04-23 18:58:45

回答

3

我最终通过创建3个子控件来实现我自己的自定义滚动:HScrollBar,VScrollBar和Panel。

我隐藏ClientSize和ClientRectangle像这样:

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完成:

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

每个滚动条均有其滚动事件订阅以下:

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

最后我们可以让鼠标滚轮事件与下面的滚动:

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

对于风俗画,你可以使用下面的语句:

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

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

相关问题