더블 버퍼링 깜빡임 없는 화면 그리기
더블 버퍼링 화면에 바로 그리지 않고, 메모리 공간에 먼저 그린 뒤 한 번에 출력하는 구조를 사용하면 깜빡임을 거의 완전히 제거할 수 있습니다.
화면에 도형을 그리기 시작하면 바로 눈에 들어오는 문제가 있습니다. 바로 화면이 번쩍이며 깜빡이는 현상입니다. 특히 마우스로 계속 그리거나 자주 갱신할수록 더 두드러지게 나타납니다.
왜 화면이 깜빡이는가
깜빡임의 원인은 단순합니다. 화면을 지우고 다시 그리기 때문입니다.
기본 흐름은 다음과 같습니다.
- 배경 지우기 (WM_ERASEBKGND)
- WM_PAINT에서 다시 그림
이 과정이 반복되면서 사용자에게는 깜빡임으로 보이게 됩니다.
흔한 오해: 코드를 줄이면 해결될까
코드를 줄이거나 그리기 횟수를 줄이는 방법은 근본적인 해결이 되지 않습니다.
- 일부 상황에서만 완화됨
- 구조가 그대로라면 깜빡임 유지
문제는 “얼마나 많이 그리느냐”가 아니라 “어떻게 그리느냐”입니다.
해결 방법: 더블 버퍼링 구조 이해하기
더블 버퍼링은 보이지 않는 메모리 공간에 먼저 그림을 완성한 뒤, 결과만 화면에 한 번에 출력하는 방식입니다.
핵심 흐름은 다음과 같습니다.
- 메모리 DC 생성
- 메모리 DC에 전체 화면 그리기
- BitBlt로 한 번에 출력
이 방식은 중간 과정이 화면에 보이지 않기 때문에 깜빡임이 사라집니다.
실제 구현: 더블 버퍼링 적용하기
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
RECT rc;
GetClientRect(hwnd, &rc);
HDC memDC = CreateCompatibleDC(hdc);
HBITMAP memBitmap = CreateCompatibleBitmap(hdc, rc.right, rc.bottom);
HBITMAP oldBitmap = (HBITMAP)SelectObject(memDC, memBitmap);
// 배경 채우기
FillRect(memDC, &rc, (HBRUSH)(COLOR_WINDOW+1));
// 실제 그리기
Ellipse(memDC, g_x - 20, g_y - 20, g_x + 20, g_y + 20);
// 화면에 출력
BitBlt(hdc, 0, 0, rc.right, rc.bottom, memDC, 0, 0, SRCCOPY);
// 리소스 복구
SelectObject(memDC, oldBitmap);
DeleteObject(memBitmap);
DeleteDC(memDC);
EndPaint(hwnd, &ps);
}
return 0;
추가로 깜빡임을 완전히 줄이려면 다음도 함께 적용하는 것이 좋습니다.
- WM_ERASEBKGND에서
return 1처리 - 배경을 한 번만 그리도록 통제
이 두 가지를 적용하면 이중으로 지워지는 문제를 방지할 수 있습니다.
마무리
이 단계까지 오면 WinAPI의 핵심 흐름을 모두 경험한 상태입니다.
- 창 생성
- 메시지 처리
- 입력 처리
- GDI 그리기
- UI 컨트롤
- 구조 개선
- 렌더링 최적화
이제 단순 예제가 아니라, 실제 프로그램을 만들 수 있는 기반이 완성되었습니다