Метод CreateParams. Как правильно пользоваться для устранения мерцания?

Есть класс CustomProgressBar, нужно было кроме прогресса отображать процент заполнения ползунка в текстовом формате, чего не делает стандартный ProgressBar:

class CustomProgressBar : ProgressBar
{
         
      
    public String CustomText { get; set; }

    public CustomProgressBar()
    {
        
        SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
        
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        Rectangle rect = ClientRectangle;
        Graphics g = e.Graphics;

        ProgressBarRenderer.DrawHorizontalBar(g, rect);
        rect.Inflate(-3, -3);
        if (Value > 0)
        {
            
            Rectangle clip = new Rectangle(rect.X, rect.Y, (int)(((float)Value / (float)Maximum) * (float)rect.Width),
                                           rect.Height);
            ProgressBarRenderer.DrawHorizontalChunks(g, clip);
        }


        
        using (Font f = new Font(FontFamily.GenericSerif, 10))
        {

            SizeF len = g.MeasureString(CustomText, f);
           
            Point location = new Point(Convert.ToInt32((Width / 2) - len.Width / 2), 
                                       Convert.ToInt32((Height / 2) - len.Height / 2));
            
            g.DrawString(CustomText, f, Brushes.Black, location);
        }
    }

    //Для устранения мерцания контрола применяем двойную буферизацию на уровне формы, а не на уровне контрола
    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams myParams = base.CreateParams;

            // Установка флага для двойной буферизации WS_EX_COMPOSITED
            myParams.ExStyle |= 0x02000000;

            return myParams; 
        }
    }
   
}

} В классе есть переопределенный метод protected override CreateParams CreateParams. Там, откуда я его взял, он был прописан в определении пользовательского контрола. https://www.codeproject.com/Articles/1082902/How-to-Paint-on-Top-of-a-ProgressBar-using-Csharp (2016 год) Пишут что в отличие от свойства DoubleBuffered, этот метод устраняет мерцание для всей формы и контролов на ней, но вот вставляют ее кто куда, то в код основной формы, то в код пользовательского контрола (как здесь)... Так где же все-таки правильно переопределять CreateParams?Будет ли она так же работать, если переопределить в кастомном контроле?


Ответы (1 шт):

Автор решения: MSDN.WhiteKnight

Говорить тут о "двойной буферизации на уровне формы" тут, строго говоря, неправильно. Это жаргон, который возник из-за того, что чаще всего двойную буферизацию включают на уровне формы. Вот, что делает WS_EX_COMPOSITED по документации:

Paints all descendants of a window in bottom-to-top painting order using double-buffering. Bottom-to-top painting order allows a descendent window to have translucency (alpha) and transparency (color-key) effects, but only if the descendent window also has the WS_EX_TRANSPARENT bit set. Double-buffering allows the window and its descendents to be painted without flicker.

Этот стиль включает двойную буферизацию для окна и всех его дочерних окон. Слово окно здесь следует понимать в терминологии Windows - то, что имеет дескриптор окна, то есть любой элемент управления Windows Forms также считается окном. То есть вполне нормально переопределить CreateParams для установки стиля окна и в элементе управления, если это работает в вашем случае. По моим тестам, все работает, и мерцание надписи устраняется.

→ Ссылка