Мерцание в приложении Windows Forms - PullRequest
22 голосов
/ 20 июля 2010

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

Я применил к нему fix .

    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 ]

12 голосов
/ 22 июля 2010

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

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

7 голосов
/ 28 июня 2011

Я знаю, что этот вопрос немного старый, но лучше поздно, чем никогда.Я использовал ваш исходный пример, который вы связали, чтобы придумать тот, который включает его при изменении размера, а затем переключает его обратно, чтобы нарисовать все остальное идеально.Надеюсь, это поможет другим, ищущим решение этой проблемы.Как известно оператору, только свойства 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;
}
4 голосов
/ 20 июля 2010

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

        // 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);
0 голосов
/ 09 декабря 2012

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

0 голосов
/ 20 июля 2010

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

...