C ++: избегайте мерцания, используя WM_ERASEBKGND-сообщение в MFC-приложении

в методе OnDraw () — я создаю растровое изображение и добавляю его на выход каждый раз, когда изменяется размер окна:

void CmbmView::OnDraw(CDC* pDC)
{
CRect WindowSize;
HDC hdc;
BITMAPINFO pbmi;
HBITMAP hbm;
CBitmap *pBitmap;
CDC MemDC;
void* ppvBits;

GetClientRect(WindowSize);

hdc = CreateDC (TEXT ("DISPLAY"), NULL, NULL, NULL) ;

memset(&pbmi, 0, sizeof(BITMAPINFO));
pbmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi.bmiHeader.biWidth = WindowSize.Width();
pbmi.bmiHeader.biHeight = -WindowSize.Height(); // top down
pbmi.bmiHeader.biPlanes = 1;
pbmi.bmiHeader.biBitCount = 32;
pbmi.bmiHeader.biCompression = BI_RGB;

hbm = CreateDIBSection(hdc, &pbmi, DIB_RGB_COLORS, &ppvBits, NULL, NULL);
pBitmap = CBitmap::FromHandle(hbm);

MemDC.CreateCompatibleDC(pDC);
MemDC.SelectObject(pBitmap);

// "Draw" into ppvBits
GetDocument()->DrawApple(pDC, ppvBits, WindowSize.Width(), WindowSize.Height(), m_MaxIter, m_MaxBetragQuadrat, m_BW);

// Blit it to the output
pDC->BitBlt(0, 0, WindowSize.Width(), WindowSize.Height(), &MemDC, 0, 0, SRCCOPY);
}

Но каждый раз, когда приложению необходимо воссоздать растровое изображение в OnDraw (), экран становится белым, пока не перетянет растровое изображение на экран. Как я могу использовать WM_ERASEBKGND-сообщение, чтобы избежать этого мерцания?

0

Решение

Я не знаю, с MFC, но с родным Windows API вы должны обрабатывать WM_ERASEBKGND сообщение и просто return TRUE;, Это говорит оконной процедуре по умолчанию, что сообщение обрабатывается, поэтому фон окна стирается. В результате мерцание исчезает.

Кроме того, если вы используете функцию InvalidateRect(..) обязательно установите параметр bErase в FALSE, Обратите внимание, что параметр TRUE по умолчанию, если не указано явно.

2

Другие решения

В приложении, где рендеринг содержимого окна занимал нетривиальное время, я предпринял следующие шаги:

  1. когда экран нуждается в перерисовке, скопируйте его содержимое из растрового изображения
  2. если базовые данные изменяются, запускают поток, чтобы отобразить эти данные в новом растровом изображении (если этот поток уже запущен, просто установите флаг)
  3. когда поток рендеринга заканчивается, замените сохраненное растровое изображение на результат потока и аннулируйте окно (если установлен соответствующий флаг, немедленно возобновите рендеринг)
  4. при изменении размера окна запускаем рендеринг и растягиваем растровое изображение до окна
  5. когда прокручивается представление, стирайте те части, которые доступны, и запускайте рендеринг

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

  • Не запускайте одновременно несколько потоков в фоновом режиме, так как это может снизить производительность. Если вы просто растянете окно с помощью мыши, вы можете легко генерировать десятки сообщений об изменении размера, и вы не захотите тратить на это ни время, ни объем памяти.
  • Отрисовывайте только видимые части, так как при виртуальных размерах прокрутки растровое изображение может стать действительно большим. Чтобы упростить прокрутку, вы можете добавить рамку (например, 1/5 ширины / высоты), чтобы сохранить некоторые дополнительные данные при подготовке нового растрового изображения в фоновом режиме.
1

По вопросам рекламы [email protected]