У меня есть две проблемы с собственным пользовательским элементом управления, использующим растровые изображения:
Элемент управления состоит из трех растровых изображений:
Все используемые растровые изображения имеют разрешение 500x500 пикселей. Управление работает так: https://www.dropbox.com/s/t92gucestwdkx8z/StatorAndRotor.gif(это gif-анимация)
Пользовательский элемент управления должен отрисовываться каждый раз, когда он получает новый угол ротора. Поэтому у него есть общедоступное свойство RotorAngle, которое выглядит следующим образом:
public double RotorAngle
{
get { return mRotorAngle; }
set
{
mRotorAngle = value;
Refresh();
}
}
Refresh
вызывает событие Paint
. Обработчик события OnPaint
выглядит следующим образом:
private void StatorAndRotor2_Paint(object sender, PaintEventArgs e)
{
// Draw the three bitmaps using a rotation matrix to rotate the rotor bitmap.
Draw((float)mRotorAngle);
}
Но когда я использую этот код, который хорошо работает в других собственных пользовательских элементах управления, пользовательский элемент управления вообще не рисуется, если элемент управления имеет двойную буферизацию через SetStyle(ControlStyles.OptimizedDoubleBuffer, true)
. Если я не установлю для этого флага значение true, элемент управления мерцает при перерисовке.
В конструкторе элемента управления я установил:
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.ContainerControl, false);
// User control is not drawn if "OptimizedDoubleBuffer" is true.
// SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
Сначала я подумал, что он мерцает, потому что фон очищается каждый раз, когда элемент управления рисуется. Поэтому я установил SetStyle(ControlStyles.AllPaintingInWmPaint, true)
. Но это не помогло.
Итак, почему он мерцает? Другие элементы управления работают очень хорошо с этой настройкой. И почему элемент управления не рисуется, если SetStyle(ControlStyles.OptimizedDoubleBuffer, true)
.
Я обнаружил, что элемент управления не мерцает, если я вызываю метод Draw
сразу после изменения свойства RotorAngle
:
public float RotorAngle
{
get { return mRotorAngle; }
set
{
mRotorAngle = value;
Draw(mRotorAngle);
}
}
Но это приводит к очень плохой производительности, особенно в полноэкранном режиме. Невозможно обновлять элемент управления каждые 20 миллисекунд. Вы можете попробовать сами. Ниже я прикреплю полное решение Visual Studio 2008.
Итак, почему такое плохое выступление? Не проблема обновлять другие (собственные) элементы управления каждые 20 миллисекунд. Это действительно только из-за растровых изображений?
Я создал простое визуальное решение Visual Studio 2008, чтобы продемонстрировать две проблемы: https://www.dropbox.com/s/mckmgysjxm0o9e0/WinFormsControlsTest.zip(289,3 КБ)
В каталоге bin\Debug
находится исполняемый файл.
Спасибо за помощь.