. 색상 변경

색상을 변경하는 것은 아주 쉽다. 비선택시의 전경색과 배경색 및 선택시의 전경색과 배경색을 변경할 수 있도록 해보자. 디폴트로 시스템 색상을 사용하도록 되어 있는데 이 값만 변경하면 된다. 전경색과 배경색을 기억할 변수를 각각 선언하고 OnCreate에서 시스템 색상으로 초기화한다.

 

class CApiEdit

{

     ....

     COLORREF cFore,cBack;

     COLORREF cSelFore,cSelBack;

 

BOOL CApiEdit::OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct)

{

     ....

    cBack=GetSysColor(COLOR_WINDOW);

    cFore=GetSysColor(COLOR_WINDOWTEXT);

    cSelFore=GetSysColor(COLOR_HIGHLIGHTTEXT);

    cSelBack=GetSysColor(COLOR_HIGHLIGHT);

     InitDoc();

 

시스템 색상은 사용자가 운영체제 차원에서 선택해놓은 색상이기 때문에 사실 굳이 편집기의 색상을 따로 변경하는 기능까지 제공할 필요는 없다. 실제로 색상을 바꾸는 사용자도 그리 많지 않다. 하지만 이왕 설정 변경 기능이 들어가는 김에 좀 더 많은 자유를 준다는 의미는 있다. 이 값을 사용하는 곳은 두 군데가 있는데 OnPaint에서 배경 브러시를 생성할 때 cBack 색상을 사용한다. 즉 편집기의 배경이 이 색상으로 채워진다.

 

void CApiEdit::OnPaint(HWND hWnd)

{

     ....

    hBrush=CreateSolidBrush(cBack);

     SetRect(&lrt,MarginWidth-1,0,frt.right,LineHeight);

 

DrawLine에서는 선택영역이 아닐 때의 색상을 cFore, cBack으로 설정한다. 선택영역이나 현재줄은 따로 지정되는 색상이 있다.

 

int CApiEdit::DrawLine(HDC hdc, int Line)

{

          ...

          if (bInSel && (GetFocus()==hWnd || HideSelType!=0)) {

              fore=SelFore;

              back=SelBack;

          } else {

           fore=cFore;

              if ((nShowCurLine==3 || nShowCurLine==4) && bCurLine) {

                   back=CurColor;

               } else {

               back=cBack;

              }

          }

 

선택시의 색상은 ApiEdit가 포커스를 가질 때인 OnSetFocus에서 적용되며 선택영역 숨기기 옵션이 변경될 때도 적용된다.

 

void CApiEdit::OnSetFocus(HWND hWnd, HWND hwndOldFocus)

{

     SetCaret(FALSE,FALSE);

 

    SelFore=cSelFore;

    SelBack=cSelBack;

 

     if (HideSelType != 2 && SelStart != SelEnd) {

          Invalidate(-1);

     }

}

 

void CApiEdit::SetHideSelType(int aHideSelType)

{

     HideSelType=aHideSelType;

     if (HideSelType == 1) {

          SelFore=RGB(0,0,0);

          SelBack=RGB(192,192,192);

     } else {

        SelFore=cSelFore;

        SelBack=cSelBack;

     }

     if (SelStart != SelEnd) {

          Invalidate(-1);

     }

}

 

지정된 색상을 사용하는 코드는 모두 작성했으며 호스트에서 색상을 변경할 수 있도록 조사 및 변경 함수를 작성하도록 하자. 모두 8개의 함수가 필요하다.

 

     COLORREF GetForeColor() { return cFore; }

     void SetForeColor(COLORREF acol);

     COLORREF GetBackColor() { return cBack; }

     void SetBackColor(COLORREF acol);

     COLORREF GetSelForeColor() { return cSelFore; }

     void SetSelForeColor(COLORREF acol);

     COLORREF GetSelBackColor() { return cSelBack; }

     void SetSelBackColor(COLORREF acol);

 

Get 함수는 색상값만 리턴하면 되므로 인라인으로 작성했고 Set 함수의 코드는 다음과 같이 작성한다.

 

void CApiEdit::SetForeColor(COLORREF acol)

{

     if (acol==-1) {

          cFore=GetSysColor(COLOR_WINDOWTEXT);

     } else {

          cFore=acol;

     }

     Invalidate(-1);

}

 

void CApiEdit::SetBackColor(COLORREF acol)

{

     if (acol==-1) {

          cBack=GetSysColor(COLOR_WINDOW);

     } else {

          cBack=acol;

     }

     Invalidate(-1);

}

 

void CApiEdit::SetSelForeColor(COLORREF acol)

{

     if (acol==-1) {

          cSelFore=GetSysColor(COLOR_HIGHLIGHTTEXT);

     } else {

          cSelFore=acol;

     }

     if (SelStart!=SelEnd && (HideSelType==2 || GetFocus()==hWnd)) {

          SelFore=cSelFore;

          Invalidate(-1);

     }

}

 

void CApiEdit::SetSelBackColor(COLORREF acol)

{

     if (acol==-1) {

          cSelBack=GetSysColor(COLOR_HIGHLIGHT);

     } else {

          cSelBack=acol;

     }

     if (SelStart!=SelEnd && (HideSelType==2 || GetFocus()==hWnd)) {

          SelBack=cSelBack;

          Invalidate(-1);

     }

}

 

인수로 전달된 색상값이 -1인 경우는 시스템 색상을 사용하도록 하였다. 색상이 바뀐다고 해서 정렬 상태가 바뀌거나 캐럿이 움직이는 것은 아니므로 화면을 다시 그리는 것 외에는 전혀 할 일이 없다. 전경색과 배경색이 바뀌면 즉시 화면을 그려야 하지만 선택영역의 색상은 좀 다르다. 선택 색상이 화면에 적용되기 위해서는 일단 선택영역이 있어야 한다. 그리고 선택영역이 항상 보이는 상태이거나 아니면 이 윈도우가 포커스를 가지고 있는 상태여야 한다. 그 외의 경우는 굳이 화면을 다시 그릴 필요가 없다.

이처럼 옵션이 변경될 때는 최소한의 필요한 동작만 해야 한다. 항상 다시 그리거나 무조건 재정렬하면 정확하기야 하겠지만 느려진다. 옵션 변경에 따라 꼭 필요한 동작인지 조건 점검을 한 후 불필요한 동작은 생략하는 것이 좋다. 상식적으로 쉽게 이해가 될 것이다. 지금까지의 어떤 설정보다도 쉽게 구현이 완료 되었다.