. 줄단위 더블 버퍼링

더블 버퍼링의 단위를 화면으로 하지 말고 줄단위로 바꾸어 보자. 한 줄씩 비트맵에 출력한 후 이 비트맵을 화면으로 전송하는 방식이다.

 

void OnPaint(HWND hWnd)

{

     HDC hdc, hMemDC;

     PAINTSTRUCT ps;

     int l;

     RECT crt;

     int s,e;

     HBRUSH hBrush;

     HBITMAP OldBitmap;

    RECT lrt;

 

     hdc=BeginPaint(hWnd,&ps);

     GetClientRect(hWnd,&crt);

 

     s=yPos/LineHeight;

     e=s+crt.bottom/LineHeight;

    e=min(e,TotalLine-1);

 

     hMemDC=CreateCompatibleDC(hdc);

     if (hBit == NULL) {

        hBit=CreateCompatibleBitmap(hdc,crt.right,LineHeight);

     }

     OldBitmap=(HBITMAP)SelectObject(hMemDC,hBit);

 

     hBrush=GetSysColorBrush(COLOR_WINDOW);

     SetRect(&lrt,0,0,crt.right,LineHeight);

 

     for (l=s;l<=e;l++) {

        FillRect(hMemDC,&lrt,hBrush);

        DrawLine(hMemDC,l);

        BitBlt(hdc,0,(l-s)*LineHeight,crt.right,(l-s)*LineHeight+LineHeight,

            hMemDC,0,0,SRCCOPY);

     }

 

    SetRect(&lrt,0,(l-s)*LineHeight,crt.right,crt.bottom);

    FillRect(hdc,&lrt,hBrush);

 

     DeleteObject(hBrush);

     SelectObject(hMemDC,OldBitmap);

     DeleteDC(hMemDC);

     EndPaint(hWnd,&ps);

}

 

출력 시작줄은 화면상의 첫 줄이고 끝줄은 화면의 제일 아래줄이되 단 문서의 제일 끝줄보다 커지지 않도록 조정하였다. 비트맵의 폭은 여전히 작업영역의 폭과 같지만 높이는 작업영역의 높이가 아니라 줄간을 사용한다. 각 줄마다 비트맵을 배경색으로 채우고 DrawLine으로 출력한 후 그 줄의 y 좌표에 비트맵을 전송하였다. 이때 마지막 줄인 e는 문서의 마지막 줄보다 크지 않으므로 DrawLine의 리턴값은 더 이상 점검할 필요가 없어졌다.

정확하게 문서의 끝까지만 출력하도록 루프의 범위를 설정했기 때문에 문서 이후의 여백 부분이 삭제되지 않는 문제가 있다. 그래서 루프가 끝난 후에 혹시라도 남아 있을지 모르는 문서 뒷부분을 삭제하는 코드가 있어야 한다. for 루프를 탈출한 후 최후 출력한 줄의 다음 줄에서부터 화면의 끝까지는 배경색으로 채워서 지워 주었다. 이 처리를 생략하면 아래로 스크롤할 때(문서가 위로 올라갈 때) 화면 아래쪽에 있던 문서 끝 부분이 그대로 남아 있게 된다.

더블 버퍼링의 단위가 화면이 아니라 줄로 바뀌었다고 해서 OnSize OnDestroy의 코드를 수정할 필요는 없다. 이 함수들은 어차피 비트맵을 무효화시키기만 할 뿐이지 비트맵의 크기 따위에는 관심이 없기 때문이다. 대신 비트맵에 문자열을 출력하는 DrawLine 함수가 조금 바뀌어야 한다.

 

int DrawLine(HDC hdc, int Line)

{

          ....

          DrawSegment(hdc,x,0,nowoff,len,

               (nowoff+len==pLine[Line].End),fore,back);

 

이전에는 DrawSegment를 호출할 때 줄의 y 좌표를 전달했지만 이제 한 줄에 대한 출력이 직접 화면으로 나가는 것이 아니라 줄단위의 비트맵으로 나가게 되므로 y 좌표는 무조건 0이다. 이 비트맵을 줄의 y 좌표에 출력하는 책임은 OnPaint가 맡게 되었으며 y 좌표 계산식은 BliBlt문으로 옮겨졌다.

이제 화면상의 깜박임은 전혀 없다. 하지만 출력 과정에서 메모리 비트맵을 경유해서 화면으로 나가기 때문에 속도는 조금 느려진다. 정밀하게 측정해보면 확실하게 더블 버퍼링으로 인한 속도 감소를 확인할 수 있다. 그러나 다행히 사용자는 깜박거리지 않음으로 인해 더 빨라진 것으로 느끼게 된다.