0

ビデオを使用するためのタイムライン ユーザー コントロールを開発しています。ここに私の作品の写真があります: ここに画像の説明を入力

ここで問題があります。currentTime が変更されたら、UI を更新する必要があります。しかし、私が this.Invalidate(); を使用すると コントロール全体をリフレッシュします。しかし、ポインタ(灰色の背景の白い線)を更新したいだけです。非常に小さな時間の変化でコントロールが何度も点滅するためです。ポインタを更新する方法は?これが私のonPaintメソッドです

 private void OnPaint(object sender, System.Windows.Forms.PaintEventArgs e)
    {
        int width = this.Width;
        int height = this.Height;
        int Floor = height - FloorDistance;
        Pen SecPen = new Pen(SecColor);
        Pen MinPen = new Pen(MinColor);
        SolidBrush TimeLineBrush = new SolidBrush(Color.Gray);
        StringFormat stringFormat = new StringFormat();
        SolidBrush TimesolidBrush = new SolidBrush(TimeColor);
        SolidBrush BackBrush = new SolidBrush(TimlineBackColor);
        SolidBrush PointerBrush = new SolidBrush(PointerColor);
        stringFormat.FormatFlags = StringFormatFlags.DirectionVertical;
        switch (Zoom)
        {
            case ZoomLEvel.Quarter:
                width = (int)Math.Ceiling((TotalDuration / 900)) * ThickDistance;
                break;
            case ZoomLEvel.Minute:
                width = (int)Math.Ceiling((TotalDuration / 60)) * ThickDistance;
                break;
            case ZoomLEvel.Secound:
                width = (int)Math.Ceiling(TotalDuration) * ThickDistance;
                break;
            case ZoomLEvel.MiliSecound:
                width = (int)Math.Ceiling(TotalDuration * 10) * ThickDistance;
                break;
        }
        width += 11;
        this.Width = width;

        e.Graphics.FillRectangle(TimeLineBrush, 0, Floor, width, 3);
        e.Graphics.FillRectangle(BackBrush, 0, 0, width, height - FloorDistance);

        int x = ThickDistance;
        int step = 0;
        while (x <= width - ThickDistance)
        {
            if (step % 5 == 0)
            {
                e.Graphics.DrawLine(MinPen, x, Floor, x, Floor - _MinHeight);
                // print time
                string time = "";
                double totalSecounds = 0;
                PointF pointF = new PointF(x - 8, Floor + 5);


                switch (Zoom)
                {
                    case ZoomLEvel.Quarter:
                        totalSecounds = step * 900;
                        break;
                    case ZoomLEvel.Minute:
                        totalSecounds = step * 60;
                        break;
                    case ZoomLEvel.Secound:
                        totalSecounds = step;
                        break;
                    case ZoomLEvel.MiliSecound:
                        totalSecounds = step / 10d;
                        break;
                }

                time = (new TimeSpan(0, 0, 0, (int)totalSecounds, (int)(step % 10) * 100)).ToString(@"hh\:mm\:ss\:fff");
                e.Graphics.DrawString(time, this.Font, TimesolidBrush, pointF, stringFormat);

            }
            else
                e.Graphics.DrawLine(SecPen, x, Floor, x, Floor - _SecHeight);
            x += ThickDistance;
            step++;
        }
        int PointerTime = 0;//(int)Math.Floor(CurrentTime);
        int pointerX = 0;
        switch (Zoom)
        {
            case ZoomLEvel.Quarter:

                PointerTime = (int)Math.Floor(CurrentTime / 900);
                pointerX = PointerTime * ThickDistance;
                break;
            case ZoomLEvel.Minute:
                PointerTime = (int)Math.Floor(CurrentTime / 60);
                pointerX = PointerTime * ThickDistance;
                break;
            case ZoomLEvel.Secound:
                PointerTime = (int)Math.Floor(CurrentTime);
                pointerX = PointerTime * ThickDistance;
                break;
            case ZoomLEvel.MiliSecound:
                PointerTime = (int)Math.Floor(CurrentTime * 10);
                pointerX = PointerTime * ThickDistance;
                break;
        }
        pointerX += 5;
        e.Graphics.FillRectangle(PointerBrush, pointerX, 0, 2, height - FloorDistance);
    }
4

1 に答える 1

2

Invalidate()メソッドのオーバーロードは、クリッピング四角形Rectangleと呼ばれる、更新する領域を定義する型パラメーターを受け取ります。ポインターの境界の四角形を渡す必要があります (白い線、おそらくすべての辺に 10 ピクセルのパディングがあります)。メソッドでは、再描画が必要な領域のプロパティを確認する必要があります。ここで、すべての描画ロジック (e.Graphics.DrawX ()呼び出し) について、その要素がクリッピング領域と交差するかどうかを最初に確認する必要があります (を使用して簡単に実行できます)。そうでない場合は、 DrawXメソッドを呼び出す必要があります。OnPaint()e.ClipRectangleRectangle.IntersectsWith()

DoubleBufferedちらつきを避けるには、コントロールのプロパティを にオンにする必要がありますTrue。は、真にスムーズなレンダリングを実現するのに大いに役立ちます。

さらに、OnPaintメソッドで多くのブラシとペンを宣言しており、使用後にそれらを破棄していないようです。これらの多くは何度も必要になると思いますので、それらをクラス レベルで宣言してからDispose()、コントロールのメソッドで破棄することをお勧めします。これはビデオ関連のアプリケーションであることを考えると、これにより処理が節約されます。

それが役立つことを願っています。

于 2013-04-28T09:05:56.967 に答える