자료 저장소

::중요한 부분인듯 하여 요약정리함!
:: 2008 MFC 윈도우프로그래밍 (최호성 저) 내용


# 더블 버퍼링(Double Buffering)

더블버퍼링이란 화면 DC에 직접 출력하는 것이 아니라, 화면 DC와 호환되는 메모리 DC(버퍼 DC)를 만들어서 모든 그리기
작업을 수행한 후, 메모리 DC의 내용을 화면 DC로 복사하는 기법이다. 이렇게 화면을 하얗게 칠해서 지웠다가 다시 검게 그리는
코드를 아무리 반복하더라도 그리는 과정이 화면에 출력되지 않으므로 깜빡임이 없어진다.
더블 버퍼링의 핵심은 복잡한 그리기 과정을 사용자가 보지 못하게 메모리 DC(버퍼 DC)에서 처리하고, 화면 DC에는 이렇게
완성된 이지미 하나만 출력하는(BitBlt())하는 것으로 요약된다.

[더블버퍼링 구현을 위해서 만든 CBufferDC 클래스]

class CBufferDC : public CDC 
{
private:
CBufferDC() {}
CBufferDC(const CBufferDC &src) {}
CBufferDC& operator=(const CBufferDC &src) {}

protected:
BOOL Attach(HDC hDC);
HDC Detach();

private:
CWnd* m_pParent; // 대상 윈도우에 대한 포인터
CDC* m_pTarget; // 대상 윈도우 DC에 대한 포인터
PAINTSTRUCT m_PaintStruct; // 화면을 그리기 위한 정보를 담는 구조체
CRect m_RcClient, m_RcWindow; // 대상 윈도우의 크기 정보

CDC m_MemoryDC; // 메모리 DC(버퍼 DC)
CBitmap m_MemoryBmp, *m_pOldMemoryBmp; // 버퍼링을 위한 비트맵
};

CBufferDC::CBufferDC(CWnd *pParent) 
: m_pParent(pParent)
{
ASSERT(pParent);

//대상 윈도우에 대한 정보를 수집한다.
m_pTarget = m_pParent->BeginPaint(&m_PaintStruct);
m_pParent->GetClientRect(&m_RcClient);
m_pParent->GetWindowRect(&m_RcWindow);

//대상 윈도우에 대한 DC를 생성한다.
m_MemoryDC.CreateCompatibleDC(m_pTarget);
//대상 DC에 대한 메모리 비트맵을 생성하여 Select 한다.
m_MemoryBmp.CreateBitmap(m_RcClient.Width(), m_RcClient.Height(),
m_MemoryDC.GetDeviceCaps(PLANES),
m_MemoryDC.GetDeviceCaps(BITSPIXEL), 0);
m_pOldMemoryBmp = m_MemoryDC.SelectObject(&m_MemoryBmp);

//메모리 버퍼에 Attach한다.
Attach(m_MemoryDC);
}

//////////////////////////////////////////////////////////////////////
CBufferDC::~CBufferDC()
{
//메모리 DC의 내용을 대상 윈도우에 출력한다.
//내부적으로 비트맵에 출력한 것이므로 해당 비트맵을 1:1로 복사한다.
m_pTarget->BitBlt(
m_PaintStruct.rcPaint.left,
m_PaintStruct.rcPaint.top,
m_PaintStruct.rcPaint.right - m_PaintStruct.rcPaint.left,
m_PaintStruct.rcPaint.bottom - m_PaintStruct.rcPaint.top,
&m_MemoryDC,
m_PaintStruct.rcPaint.left,
m_PaintStruct.rcPaint.top, SRCCOPY);

m_MemoryDC.SelectObject(m_pOldMemoryBmp);
m_pParent->EndPaint(&m_PaintStruct);

Detach();
}

//////////////////////////////////////////////////////////////////////
BOOL CBufferDC::Attach(HDC hDC)
{
return CDC::Attach(hDC);
}

생성자의 인자로 전달받은 윈도우 객체의 BeginPaint()메서드를 호출하여 윈도우 그리기가 시작되었음을 알리고 화면 DC와
호완되는 메모리 DC를 생성한 후 CBitmap 클래스 객체의 CreateBitmap() 메서드를 호출하여 DC에 대한 비트맵을 생성한다.

생성자보다 소멸자가 더욱 중요하다. 메모리 DC에 수행하여 그린 결과를 화면 DC로 출력하는 결과는 소멸자에 들어있다.
CBitmap 클래스 객체를 선택한(SelecteObject()) 메모리 DC의 내용을 연결된 화면 DC에 SRCCOPY 모드로 출력(BitBlt()한 후
자원을 반납하고 처리를 완료한다.

화면 DC에 직접 그리는 것도 좋지만 중간 단계를 거쳐서 출력하면 출력 전 과정이 화면에 나타나지 않으므로 깜빡임이 없어진다.

WM_ERASERBKGND 메시지 핸들러 함수를 등록하여 아무런 처리도 하지 않도록 코드를 수정하고 OnPaint() 함수에서
CBufferDC 클래스를 활용하여 더블 버퍼링을 구현한다면 화면 깜빡임을 완벽히 해결 할 수 있다.

댓글 로드 중…

최근에 게시된 글