C# 4.0 仅更新usercontrol的一部分

C# 4.0 仅更新usercontrol的一部分,c#-4.0,user-controls,onpaint,C# 4.0,User Controls,Onpaint,我正在开发一个用于视频使用的时间轴用户控件。这是我工作的照片: 这是我的问题。当currentTime更改时,我必须更新UI。但是当我使用这个时。Invalidate();它刷新整个控件。但我只想更新指针(灰色背景中的白线)。因为它会导致控件在非常微小的时间变化上反复闪烁。 如何只更新指针? 这是我的onPaint方法 private void OnPaint(object sender, System.Windows.Forms.PaintEventArgs e) {

我正在开发一个用于视频使用的时间轴用户控件。这是我工作的照片:

这是我的问题。当currentTime更改时,我必须更新UI。但是当我使用这个时。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);
    }
private void OnPaint(对象发送方,System.Windows.Forms.PaintEventArgs e)
{
int width=这个.width;
int height=这个.height;
内部楼层=高度-楼层高度;
笔SecPen=新笔(SecColor);
Pen MinPen=新笔(MinColor);
SolidBrush TimeLineBrush=新的SolidBrush(颜色为灰色);
StringFormat StringFormat=新的StringFormat();
SolidBrush TimesolidBrush=新的SolidBrush(TimeColor);
SolidBrush BackBrush=新的SolidBrush(TimlineBackColor);
SolidBrush PointerBrush=新的SolidBrush(指针颜色);
stringFormat.FormatFlags=StringFormatFlags.DirectionVertical;
开关(缩放)
{
案例ZoomLEvel.季度:
宽度=(整数)数学上限((总持续时间/900))*厚度距离;
打破
案例ZoomLEvel.分钟:
宽度=(整数)数学上限((总持续时间/60))*厚度距离;
打破
案例ZoomLEvel.Secound:
宽度=(整数)数学上限(总持续时间)*厚度距离;
打破
case ZoomLEvel.MiliSecound:
宽度=(整数)数学上限(总持续时间*10)*厚度距离;
打破
}
宽度+=11;
这个。宽度=宽度;
e、 图形。填充矩形(TimeLineBrush,0,地板,宽度,3);
e、 图形。填充矩形(后冲线,0,0,宽度,高度-楼板间距);
int x=距离;
int步长=0;

而(xInvalidate()
方法的重载采用了一个定义要刷新的区域的
Rectangle
类型参数,称为剪裁矩形。您应该传递指针的边界矩形(白线,两边可能有10个像素的填充)。在
OnPaint()中
方法,您应该检查需要重新绘制的区域的
e.ClipRectangle
属性。现在对于所有绘图逻辑(e.Graphics.DrawX()调用),您应该首先确认该元素是否与剪裁区域相交(可以使用
Rectangle.IntersectsWith()轻松完成)。如果是,则应调用DrawX方法,否则不应调用

为了避免闪烁,您应该将控件的
双缓冲
属性启用为
True
。这对于实现真正平滑的渲染有很大帮助

此外,我看到您在
OnPaint
方法中声明了许多画笔和画笔,并且在使用后没有对它们进行处理。我假设这些画笔和画笔中的许多画笔和画笔将被反复使用,因此您可能希望在类级别声明它们,然后在
dispose()中对它们进行处理
控制方法。考虑到这是一个与视频相关的应用程序,这将节省一些处理

希望有帮助