簡體   English   中英

在C#中使用Graphics.DrawString時,如何減少閃爍?

[英]How to reduce flickering when using Graphics.DrawString in C#, for a timer?

下面是將文本繪制到進度條的C#代碼。 它用於向進度條添加文本,顯示剩余時間倒計時。 我使用Graphics類繪制字符串而不是Windows窗體標簽,因為放置在進度條上時標簽背景無法設置為透明。

但是,使用此代碼,文本每次更新時都會閃爍(此方法在每秒鍾滴答一次的計時器內調用),因此它會不斷閃爍並且無法使用。

/// <summary>
    /// Adds time remaining text into a System.Windows.Forms.ProgressBar
    /// </summary>
    /// <param name="target">The target progress bar to add text into</param>
    /// <param name="remainingTimeText">The text to add into the progress bar.</param>
    private void set_progress_bar_text( System.Windows.Forms.ProgressBar target, string remainingTimeText )
    {
        // Make sure we do not have a null progress bar.
        if( target == null )
        {
            throw new ArgumentException( "Null Target" );
        }

        // Use the progress bar label font and size.
        Font textFont = new Font( labelProgress.Font.Name, labelProgress.Font.Size );

        // gr will be the graphics object we use to draw on the progress bar.
        using( Graphics gr = target.CreateGraphics() )
        {
            gr.DrawString( remainingTimeText,
                textFont,
                new SolidBrush( Color.Black ), // The brush we will use to draw the string, using a black colour.

                // The position on the progress bar to put the text.
                new PointF(
                // X location of text, to be placed at the centre of the progress bar.
                    progressBar.Width / 2 - ( gr.MeasureString( remainingTimeText,
                    textFont ).Width / 2.0F ),
                // Y Location
                progressBar.Height / 2 - ( gr.MeasureString( remainingTimeText,
                    textFont ).Height / 2.0F ) ) );
        }
    }

我已嘗試在此方法中設置DoubleBuffered = true ,如Stack Overflow上的相關問題所示,但它不會阻止閃爍。 我不能減少文本更新的次數,因為文本是必須每秒更新一次的倒計時時鍾。 有沒有辦法防止雙緩沖閃爍,還是有其他潛在的解決方案?

ProgressBar似乎是試圖隱藏繪畫的控件之一。 所以我們需要自己動手。 只需將ProgressBar與此進行交換即可。

添加了CreateParams覆蓋以減少評論中提到的閃爍。

public class MyLovelyProgressBar : ProgressBar
{
    public MyLovelyProgressBar()
    {
        SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
    }

    private string foregroundText;
    public string ForegroundText 
    {
        get { return foregroundText;  }
        set 
        {
            if (foregroundText != value)
            {
                Invalidate();
                foregroundText = value;
            }
        } 
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams result = base.CreateParams;
            result.ExStyle |= 0x02000000; // WS_EX_COMPOSITED 
            return result;
        }
    }

    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        switch (m.Msg)
        {
            case 15: //WmPaint
                using (var graphics = Graphics.FromHwnd(Handle))
                    PaintForeGroundText(graphics);
                break;
        }
    }

    private void PaintForeGroundText(Graphics graphics)
    {
        if (!string.IsNullOrEmpty(ForegroundText))
        {
            var size = graphics.MeasureString(ForegroundText, this.Font);
            var point = new PointF(Width / 2.0F - size.Width / 2.0F, Height / 2.0F - size.Height / 2.0F);
            graphics.DrawString(ForegroundText, this.Font, new SolidBrush(Color.Black), point);
        }
    }
}

然后只需在Timer事件中更改ProgressBar的ForegroundText。

myLovelyProgressBar1.ForegroundText = "A constantly changing lovely text";

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM