Как зафиксировать мерцание в Пользовательских элементах управления

В моем приложении я постоянно перемещаюсь от одного управления до другого. Я создал нет. из пользовательских элементов управления, но во время навигации мои средства управления получает мерцание. требуются 1 или 2 секунды для обновления. Я пытался установить это

SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
or
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true); 
SetStyle(ControlStyles.DoubleBuffer, true);

но это не помогло... Каждое управление имеет то же фоновое изображение с различными средствами управления. Таким образом, каково решение для него..
Спасибо.

105
задан Royson 10 April 2010 в 06:24
поделиться

4 ответа

Двойная буферизация не решает проблему мерцания. Ни BeginUpdate, ни SuspendLayout. У вас слишком много элементов управления, BackgroundImage может сделать его намного хуже.

Он запускается, когда UserControl рисует себя. Он рисует BackgroundImage, оставляя дыры там, где находятся окна дочерних элементов управления. Затем каждый дочерний элемент управления получает сообщение, которое нужно нарисовать, и они заполняют отверстие содержимым своего окна. Когда у вас много элементов управления, эти дыры какое-то время видны пользователю. Обычно они белые и плохо контрастируют с BackgroundImage в темноте. Или они могут быть черными, если для формы задано свойство Opacity или TransparencyKey, что плохо контрастирует практически с чем угодно.

Это довольно фундаментальное ограничение Windows Forms, оно связано с тем, как Windows отображает окна. Исправлено WPF, кстати, он не использует окна для дочерних элементов управления. Вам нужна двойная буферизация всей формы, включая дочерние элементы управления. Это возможно, проверьте мой код в этой ветке для решения. Однако у него есть побочные эффекты и на самом деле скорость рисования не увеличивается. Код прост, вставьте его в свою форму (не в пользовательский элемент управления):

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

Есть много вещей, которые вы можете сделать, чтобы улучшить скорость рисования до такой степени, что мерцание больше не будет заметно. Начните с решения BackgroundImage. Они могут быть действительно дорогими, когда исходное изображение велико и его необходимо уменьшить, чтобы соответствовать элементу управления.Измените свойство BackgroundImageLayout на «Плитка». Если это дает заметное ускорение, вернитесь в свою программу рисования и измените размер изображения, чтобы оно лучше соответствовало типичному контрольному размеру. Или напишите код в методе OnResize () UC, чтобы создать копию изображения нужного размера, чтобы его не приходилось изменять каждый раз при перерисовке элемента управления. Используйте для этой копии формат пикселей Format32bppPArgb, он отображается примерно в 10 раз быстрее, чем любой другой формат пикселей.

Следующее, что вы можете сделать, это сделать так, чтобы дыры не были такими заметными и не контрастировали с изображением. Вы можете отключить флаг стиля WS_CLIPCHILDREN для UC, флаг, который предотвращает рисование UC в области, где находятся дочерние элементы управления. Вставьте этот код в код UserControl:

protected override CreateParams CreateParams {
  get {
    var parms = base.CreateParams;
    parms.Style &= ~0x02000000;  // Turn off WS_CLIPCHILDREN
    return parms;
  }
}

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

И последнее, но не менее важное: сокращение количества дочерних элементов управления всегда является хорошим подходом к решению проблем с медленным рисованием. Переопределите событие OnPaint () UC и нарисуйте то, что теперь отображается в дочернем элементе. Особые ярлыки и PictureBox очень расточительны. Удобно указывать и щелкать, но их легкая альтернатива (рисование строки или изображения) требует только одной строки кода в вашем методе OnPaint ().

300
ответ дан 24 November 2019 в 03:54
поделиться

Вы пробовали Свойство Control.DoubleBuffered ?

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

Также могут помочь это и это .

-2
ответ дан 24 November 2019 в 03:54
поделиться

Если вы выполняете какое-либо настраиваемое рисование в элементе управления (т. Е. Переопределяете OnPaint), вы можете попробовать двойную буферизацию самостоятельно.

Image image;
protected override OnPaint(...) {
    if (image == null || needRepaint) {
        image = new Bitmap(Width, Height);
        using (Graphics g = Graphics.FromImage(image)) {
            // do any painting in image instead of control
        }
        needRepaint = false;
    }
    e.Graphics.DrawImage(image, 0, 0);
}

И аннулируйте свой элемент управления с помощью свойства NeedRepaint

В противном случае ответ с SuspendLayout и ResumeLayout, приведенный выше, вероятно, будет тем, что вам нужно.

6
ответ дан 24 November 2019 в 03:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: