如何实现自定义控件的滚动?

问题描述:

如何实现自定义控件的滚动?我的控件是完全自定义绘制的,其高度是可变的,并且控件的一部分包含一个菜单,所以如果控件中有很多项目,我需要能够将滚动条放在那里。我没有真正能够找到任何有关如何做到这一点的线索。我确实看到了一些关于ScrollableControl的内容,但我仍然不确定这是否是我需要的。如何实现自定义控件的滚动?

此外,我的控件如何知道何时需要显示滚动条?因为我的控件完全是自定义绘制的,所以在那里没有真正的“控件”,它只是一堆像素被绘制到它上面,所以它不像我可以将AutoScroll设置为true,我不能那样做,因为它不是需要滚动的控件的主要部分,它是控件上需要滚动条的特定位置。

您可以使用PanelAutoScroll = true。之后,如果您将任何控件放入其中,只要它们的尺寸大于面板的尺寸,面板就会自动显示滚动条。只要您将位置调整为任何自定义控件,该技巧都可以使用它位于AutoScroll面板内部,并根据需要调整它的大小。

您有两种选择。

好的新的是它是可能的,两者都不是很难。

  • 的坏消息是,对于一个选项,您将不得不适应所有的绘制代码:

首先让你的控制,我用一个Panel,有Autoscroll=true;

然后,你需要添加一个虚拟控制,我使用另一个Panel,也许这样,远远到右边和底部,迫使ScrollBars显示:

public Form1() 
{ 
    InitializeComponent(); 

    Panel panelDummy = new Panel(); 
    panelDummy.Size = new Size(1,1); 
    panelDummy.Location = new Point(yourMaxX,yourMaxY); 
    panel1.Controls.Add(panelDummy); 
} 

然后你需要调整你的绘图代码。这里是如何:

private void panel1_Paint(object sender, PaintEventArgs e) 
{ 
    int xx = panel1.HorizontalScroll.Value; 
    int yy = panel1.VerticalScroll.Value; 

    e.Graphics.FillRectangle(Brushes.Wheat, new Rectangle(11 - xx, 22 - yy, 22, 311)); 
    e.Graphics.FillRectangle(Brushes.RosyBrown, new Rectangle(11 - xx, 280 - yy, 22, 3)); 
} 

private void panel1_Scroll(object sender, ScrollEventArgs e) 
{ 
    panel1.Invalidate(); 
} 

我增加了一个InvalidateScroll事件,以避免弄乱了绘画的效果。

  • 另一种选择是简单的:让你的控制大到足以容纳你所有的绘制控件和放它一个PanelAutoScroll=true;这将委托整个滚动业务,以含面板。

    this.AutoScrollMinSize = New Size(yourWidth, yourHeight); 
    

    如果你控制的ClientSize.Height比yourHeight更大:

如果您的自定义控件从Panel控件继承,你只是这个设置中设置的内容在自己的定制控件的大小,你不会得到任何滚动条。如果它更少,那么你会得到一个滚动条。

在你的paint方法,这在前面加上:

protected override void OnPaint(PaintEventArgs e) { 
    e.Graphics.TranslateTransform(this.AutoScrollPosition.X, 
           this.AutoScrollPosition.Y); 

你画现在一切都被自动转换到滚动坐标。

+0

谢谢,但它不是需要滚动的控件的整个大小,它只是需要滚动条的控件的大约四分之一。 (用按钮思考一个面板控件;你点击按钮,然后弹出一个可滚动菜单)尽管如此,整个控件会滚动,正确吗? – 2014-10-13 14:28:41

+0

@ jay_t55我将注意力集中在你的陈述上:'我的控件完全是自定义绘制的......'滚动的部分需要有它自己的容器。 – LarsTech 2014-10-13 14:29:17

+0

你解决了你的问题吗?如果有任何答案被使用,你可能想要接受它。 – TaW 2014-10-17 15:50:40

我已经部分解决了这个问题,通过创建一个自定义控件继承自Control并完全绘制在OnPaint中。到目前为止,我的解决方案是使用ScrollBarRenderer绘制滚动按钮,然后为可滚动区域定义一个Rectangle。然后我创建一个Image来绘制我的可滚动内容,并使用TranslateTransform在使用DrawImage绘制到我创建的可滚动内容矩形之前,将该图像滚动到位。它显示了承诺,尽管我还没有完全使用它,因为我必须自己处理所有的MouseOver和Click事件。