Мерцание при отрисовке

seekBar это Panel. По таймеру вызывается seekBar.Refresh() и перерисовывается

        private void seekBar_Paint(object sender, PaintEventArgs e)
        {
            Bitmap bitmap = new Bitmap(seekBar.Width, seekBar.Height);
            Graphics g = System.Drawing.Graphics.FromImage(bitmap);
            Brush brush = new SolidBrush(seekBar.BackColor);
            g.FillRectangle(brush, seekBar.ClientRectangle);
            brush.Dispose();
            if (player != null && player.State != PLAYER_STATE.Null && player.Duration > 0.0)
            {
                int x = (int)(seekBar.Width / player.Duration * player.Position);
                Rectangle r = new Rectangle(0, 0, x, seekBar.Height);
                g.FillRectangle(Brushes.Blue, r);

                string elapsedString = new DateTime(TimeSpan.FromSeconds(player.Position).Ticks).ToString("H:mm:ss");
                string remainingString = new DateTime(TimeSpan.FromSeconds(player.Duration - player.Position).Ticks).ToString("H:mm:ss");

                Font fnt = new Font("Tahoma", 11.0f);
                SizeF size = g.MeasureString(elapsedString, fnt);

                int y = (int)(seekBar.Height / 2 - size.Height / 2);
                g.DrawString(elapsedString, fnt, Brushes.White, x - size.Width - 2, y);
                g.DrawString(remainingString, fnt, Brushes.Black, x + 2, y);

                fnt.Dispose();
            }
            e.Graphics.DrawImage(bitmap, 0, 0);
            g.Dispose();
            bitmap.Dispose();
        }

Почему эта фигня мерцает? Тут же двойная буферизация

А она включена у формы?

Пробовал и включать и выключать - ничего не меняется.
нашел, что можно вот так:

        private void seekBar_Paint(object sender, PaintEventArgs e)
        {
            Bitmap bitmap = new Bitmap(seekBar.Width, seekBar.Height);
            Graphics g = Graphics.FromImage(bitmap);
            BufferedGraphicsContext bufferedGraphicsContext = BufferedGraphicsManager.Current;
            BufferedGraphics bg = bufferedGraphicsContext.Allocate(g, seekBar.ClientRectangle);
            Brush brush = new SolidBrush(seekBar.BackColor);
            bg.Graphics.FillRectangle(brush, seekBar.ClientRectangle);
            brush.Dispose();

            bg.Graphics.FillRectangle(...); 

            bg.Render(e.Graphics);
            bg.Dispose();
            g.Dispose();
            bitmap.Dispose();
        }

Но оно всё-равно мерцает. Зачем тогда эти буфера создавать?

Вроде бы надо так How to: Manually Render Buffered Graphics - Windows Forms .NET Framework | Microsoft Docs

У панели оно отключено. Надо либо взять PictureBox, либо создать наследника https://stackoverflow.com/a/7569645 (либо включить другими способами https://stackoverflow.com/a/31562892).

Пока вы это писали, я погуглил. Как только начал писать, смотрю и вы отвечаете :slightly_smiling_face:
Похоже на то, что перед приходом события Paint компонент Panel себя перерисовывает. Отсюда и мерцание.
Предлагается либо писать наследника от Panel, либо юзать рефлексию:

            typeof(Control).InvokeMember("DoubleBuffered",
                BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
                null, seekBar, new object[] { true });