3

System.Windows.Forms.ScrollableControl非常に大きくなる可能性のあるコントロール ( ) があります。カスタムOnPaintロジックがあります。そのため、ここで説明する回避策を使用しています。

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 は表示領域全体をスクロールと反対の方向に移動します。通常、これは理にかなっています。スクロールがスムーズで応答性が高いように見えるためです (そして、新しい部分のみを再描画する必要があります)。ただし、静的な部分もこの変換の影響を受けます (したがって、this.Invalidate()OnScroll)。次のOnPaint呼び出しでサーフェスが正常に再描画されるまで、静的部分はわずかにずれています。これにより、スクロール時に非常に顕著な「揺れ」効果が発生します。

静的パーツでこの問題が発生しないスクロール可能なカスタム コントロールを作成する方法はありますか?

4

2 に答える 2

3

スクロールを完全に制御することでこれを行うことができます。現時点では、ロジックを実行するためにイベントに接続しているだけです。以前にスクロールの問題に直面したことがありますが、すべてをスムーズに機能させる唯一の方法は、WndProc をオーバーライドして Windows メッセージを実際に処理することです。たとえば、複数の ListBox 間でスクロールを同期する次のコードがあります。

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 が発生するまでスクロールを一時停止します。見た目は滑らかではありませんが、静的オブジェクトの移動に問題はありません。

于 2013-05-11T21:34:57.633 に答える