. 글꼴 미리 생성

CApiEdit::OnPaint 함수의 그리기 코드는 다음과 같이 작성되어 있다.

 

void CApiEdit::OnPaint(HWND hWnd)

{

     ....

     if (logfont.lfHeight != 0) {

          hFont=CreateFontIndirect(&logfont);

          hOldFont=(HFONT)SelectObject(hMemDC,hFont);

     }

     ==== 그리기 코드 ====

     if (logfont.lfHeight != 0) {

          DeleteObject(SelectObject(hMemDC,hOldFont));

     }

 

현재 선택된 글꼴이 시스템 글꼴이 아니면 글꼴을 생성하여 DC에 선택해놓고 그리기 작업을 한다. 작업이 모두 완료되면 글꼴을 선택해제하고 파괴하는데 이렇게 하다 보니 OnPaint 메시지를 받을 때마다 글꼴을 만들었다 파괴했다를 반복하고 있는 셈이다. 글꼴은 자주 변하는 것도 아니므로 SetFont에서 미리 만들어 놓아 그리기 속도를 높여 보도록 하자. 폰트 핸들을 기억할 멤버를 추가하고 SetDefaultSetting에서 NULL로 초기화한다.

 

class CApiEdit

{

     ....

     HFONT hMainFont;

 

void CApiEdit::SetDefaultSetting()

{

     ....

     logfont.lfHeight=0;

     hMainFont=NULL;

     ....

 

SetFont에서 글꼴이 변경될 때 글꼴을 직접 생성한다.

 

void CApiEdit::SetFont(LOGFONT *alogfont)

{

     HDC hdc;

     TEXTMETRIC tm;

    HFONT hOldFont=NULL;

 

    if (hMainFont) {

        DeleteObject(hMainFont);

        hMainFont=NULL;

    }

 

     logfont=*alogfont;

     hdc=GetDC(hWnd);

     if (logfont.lfHeight != 0) {

        hMainFont=CreateFontIndirect(&logfont);

        hOldFont=(HFONT)SelectObject(hdc,hMainFont);

     }

     PrepareCharWidth(hdc);

     GetTextMetrics(hdc,&tm);

     FontHeight=tm.tmHeight;

     LineHeight=int(FontHeight*LineRatio/100);

     yPos=yPos-(yPos % LineHeight);

     FontWidth=tm.tmAveCharWidth;

     if (bCalcTabWithAvg) {

          TabSize=FontWidth*TabWidth;

     } else {

          TabSize=arChWidth[‘ ‘]*TabWidth;

     }

     if (hOldFont) {

        SelectObject(hdc,hOldFont);

     }

     ReleaseDC(hWnd,hdc);

     ....

 

지역 변수 hFont는 더 이상 필요가 없으며 시스템 글꼴이 아니면 hMainFont에 생성한 글꼴을 직접 대입하였다. 그전에 이미 생성되어 있는 글꼴이 있다면 이 글꼴은 파괴해야 한다. 글꼴로부터 원하는 정보를 얻고 난 후에도 이 글꼴을 파괴하지 않았으므로 이후 OnPaint에서는 hMainFont를 바로 선택해서 사용할 수 있다. OnPaint는 다음과 같이 수정한다.

 

void CApiEdit::OnPaint(HWND hWnd)

{

     ....

    HFONT hOldFont;

     ....

    if (hMainFont) {

        hOldFont=(HFONT)SelectObject(hMemDC,hMainFont);

    }

 

     ....

    if (hMainFont) {

        SelectObject(hMemDC,hOldFont);

    }

     DeleteObject(hBrush);

     SelectObject(hMemDC,OldBitmap);

     DeleteDC(hMemDC);

     EndPaint(hWnd,&ps);

}

 

hMainFont NULL이 아니면, 즉 시스템 글꼴이 아니면 이 글꼴을 현재 DC에 선택한 후 그리기를 한다. 그리기를 완료한 후에도 글꼴을 파괴할 필요는 없다. 이렇게 사용한 글꼴은 OnDestroy에서 종료 직전에 파괴하면 된다.

 

void CApiEdit::OnDestroy(HWND hWnd)

{

     ....

     if (hMainFont) {

          DeleteObject(hMainFont);

     }

}

 

이제 그리기를 할 때마다 글꼴을 만들었다 파괴했다 하지 않으므로 그리기 속도가 조금 빨라질 것이다. 글꼴을 생성하는 작업은 시간이 오래 걸리기 때문에 최적화 효과가 상당할 것으로 기대했으나 정밀하게 측정해보면 1/1000초 미만의 차이밖에 나지 않았다. DrawLine, DrawSegment 함수들이 워낙 많은 연산을 하기 때문에 글꼴 미리 생성에 의한 최적화 효과는 거의 없는 셈이다.