我有一个控件(System.Windows.Forms.ScrollableControl),它可能非常大。它有自定义的OnPaint逻辑。出于这个原因,我使用所描述的here解决方法。
public class CustomControl : ScrollableControl
{
public CustomControl()
{
this.AutoScrollMinSize = new Size(100000, 500);
this.DoubleBuffered = true;
}
protected override void OnScroll(ScrollEventArgs se)
{
base.OnScroll(se);
this.Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
var graphics = e.Graphics;
graphics.Clear(this.BackColor);
...
}
}绘画代码主要绘制滚动时移动的“普通”物体。绘制的每个形状的原点由this.AutoScrollPosition偏移。
graphics.DrawRectangle(pen, 100 + this.AutoScrollPosition.X, ...);但是,该控件还包含“静态”元素,这些元素始终绘制在相对于父控件相同的位置。为此,我只是不使用AutoScrollPosition并直接绘制形状:
graphics.DrawRectangle(pen, 100, ...);当用户滚动时,Windows在与滚动相反的方向上平移整个可见区域。通常这是有意义的,因为滚动看起来流畅且响应迅速(只有新的部分需要重绘),但是静态部分也会受到这种转换的影响(因此OnScroll中的this.Invalidate() )。在下一次OnPaint调用成功重绘曲面之前,静态部分会稍微关闭。这会在滚动时产生非常明显的“抖动”效果。
有没有一种方法可以创建一个可滚动的自定义控件,而不存在静态部件的这个问题?
发布于 2013-05-12 05:34:58
你可以通过完全控制滚动来做到这一点。目前,您只需连接到事件来执行您的逻辑。我以前遇到过滚动的问题,唯一能让一切顺利运行的方法就是通过重写WndProc来处理Windows消息。例如,我使用以下代码在多个ListBoxes之间同步滚动:
protected override void WndProc(ref Message m) {
base.WndProc(ref m);
// 0x115 and 0x20a both tell the control to scroll. If either one comes
// through, you can handle the scrolling before any repaints take place
if (m.Msg == 0x115 || m.Msg == 0x20a)
{
//Do you scroll processing
}
}使用WndProc将在重新绘制任何内容之前获得滚动消息,因此您可以适当地处理静态对象。我会用它来暂停滚动,直到发生OnPaint。它看起来不会那么平滑,但你不会遇到静态对象移动的问题。
https://stackoverflow.com/questions/16501557
复制相似问题