double arrow

Устранение мерцания: двойная буферизация

Часы будут перерисовываться только при перерисовке окна (например, если менять его размер). Ниже мы научимся вызывать перерисовку окна несколько раз в секунду по таймеру.

Вы заметили, что изображение мерцает при перерисовке. Это происходит потому, что мы рисуем сразу на экран. Устранить мерцание поможет двойная буферизация. Это когда изображение сначала готовится "за кадром", а затем мгновенно (ну, почти мгновенно) переносится на экран, устраняя досадное мерцание при анимации.

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

 

RECTrect = {0, 0, 600, 600};// Размер буфера в пикселах

HDChdc = 0;// Контекст рисования на экране

HDChdc_mem = 0;// Контекст рисования во временном буфере

HBITMAPbuffer = 0;// Указатель на временный буфер

 

 

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

int wmId, wmEvent;

PAINTSTRUCT ps;

 

switch (message)

{

case WM_CREATE: // Это событие срабатывает в начале работы программы

// Создаем временный буфер, в который будем рисовать наше изображение

hdc = BeginPaint(hWnd, &ps);

   hdc_mem = CreateCompatibleDC(hdc);

   buffer = CreateCompatibleBitmap(hdc, rect.right, rect.bottom);

EndPaint(hWnd, &ps);

 

// Сразу закрасим временный буфер белым цветом

SelectObject(hdc_mem, buffer);

Graphics graphics(hdc_mem);

   SolidBrush brush(Color(255, 255, 255, 255));

    graphics.FillRectangle(&brush, Rect(rect.left, rect.top,

                                         rect.right, rect.bottom));

 

// Устанавливаем таймер, который будет срабатывать каждые 50 милисекунд

   SetTimer(hWnd, 1, 50, 0);

break;     

case WM_TIMER: // Событие срабатывания таймера

           

   myDraw(hdc_mem);                 // Рисуем в буфере

  ::InvalidateRect(hWnd, &rect, false); // Говорим окну, что нужно перерисовать выбранную область

break;

case WM_PAINT: // Событие перерисовки окна

// Выводим отрисованный буфер в окно программы

hdc = BeginPaint(hWnd, &ps);

   BitBlt(hdc, rect.left, rect.top, rect.right, rect.bottom, hdc_mem, rect.left, rect.top, SRCCOPY);

EndPaint(hWnd, &ps);

 

break;

case WM_DESTROY: // Это событие вызывается при завершении работы программы

// Очистка памяти, удаление созданных объектов

DeleteObject(buffer);

ReleaseDC(hWnd, hdc);

 

PostQuitMessage(0);

break;

 

case WM_COMMAND:

   wmId = LOWORD(wParam);

   wmEvent = HIWORD(wParam);

// Parse the menu selections:

switch (wmId)

   {

case IDM_ABOUT:

       DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);

break;

case IDM_EXIT:

       DestroyWindow(hWnd);

break;

default:

return DefWindowProc(hWnd, message, wParam, lParam);

   }

break;

default:

return DefWindowProc(hWnd, message, wParam, lParam);

}

return 0;

}

 

Теперь мерцания не наблюдается, а стрелки сами меняют свое положение.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



Сейчас читают про: