Мерцание в приложении Windows Forms

У меня есть приложение, в котором есть множество элементов управления. И он имеет огромное количество мерцания, особенно при запуске.

Я применил это исправление к нему.

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

Это работало отлично - мерцание было уменьшено на довольно невероятную величину. Тем не менее, побочным эффектом является то, что кнопки "Свернуть", "Развернуть" и "Закрыть" в правом верхнем углу окна не анимируются, когда я перемещаю указатель мыши или нажимаю на них (они все же работают). Это дает приложению ощущение зависания.

Как сохранить WS_EX_COMPOSITED, сохранив удобство использования кнопок "Развернуть", "Свернуть" и "Закрыть"?

Это происходит в Windows XP. Как отметил @fallenidol, это не проблема для Windows 7.

5 ответов

Решение

Я понял. Хитрость заключается в том, чтобы убрать флаг WS_EX_COMPOSITED после показа формы. Полное объяснение и код на моем блоге:

Как избавиться от мерцания в приложениях Windows Forms

Я знаю, что этот вопрос немного старый, но лучше поздно, чем никогда. Я использовал ваш исходный пример, который вы связали, чтобы придумать тот, который включает его при изменении размера, а затем переключает его обратно, чтобы нарисовать все остальное идеально. Надеюсь, это поможет другим, ищущим решение этой проблемы. Как известно оператору, только свойства DoubleBuffering не решают проблемы мерцания.

Вот обходной путь, чтобы прекратить мерцание, когда пользователь изменяет размеры формы, но не путаясь при рисовании элементов управления, таких как DataGridView, NumericUpDown и т. Д. При условии, что ваше имя формы - "Form1":

int intOriginalExStyle = -1;
bool bEnableAntiFlicker = true;

public Form1()
{
    ToggleAntiFlicker(false);
    InitializeComponent();
    this.ResizeBegin += new EventHandler(Form1_ResizeBegin);
    this.ResizeEnd += new EventHandler(Form1_ResizeEnd);
}

protected override CreateParams CreateParams
{
    get
    {
        if (intOriginalExStyle == -1)
        {
            intOriginalExStyle = base.CreateParams.ExStyle;
        }
        CreateParams cp = base.CreateParams;

        if (bEnableAntiFlicker)
        {
            cp.ExStyle |= 0x02000000; //WS_EX_COMPOSITED
        }
        else
        {
            cp.ExStyle = intOriginalExStyle;
        }

        return cp;
    }
} 

private void Form1_ResizeBegin(object sender, EventArgs e)
{
    ToggleAntiFlicker(true);
}

private void Form1_ResizeEnd(object sender, EventArgs e)
{
    ToggleAntiFlicker(false);
}

private void ToggleAntiFlicker(bool Enable)
{
    bEnableAntiFlicker = Enable;
    //hacky, but works
    this.MaximizeBox = true;
}

Попробуйте следующий код. Это должно войти в основную форму и любые другие пользовательские элементы управления, которые у вас есть.

        // Enable double duffering to stop flickering.
        this.SetStyle(ControlStyles.DoubleBuffer, true);
        this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        this.SetStyle(ControlStyles.UserPaint, true);
        this.SetStyle(ControlStyles.SupportsTransparentBackColor, false);
        this.SetStyle(ControlStyles.Opaque, false);
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        this.SetStyle(ControlStyles.ResizeRedraw, true);

Вам следует попробовать стандартное свойство управления окнами формы, которое называется DoubleBuffered. http://msdn.microsoft.com/en-us/library/system.windows.forms.control.doublebuffered.aspx

Я только что наткнулся на этот пост и понял, что он немного старый. Тем не менее, у меня возникла та же проблема с моей формой, и я обнаружил (для XP, в любом случае), что не элегантное решение, похоже, не включает визуальные стили.

Другие вопросы по тегам