. 설정 대화상자 호출

설정 대화상자의 코드와 설정을 적용하는 ApplyNow 함수를 완성했다. 이제 호스트가 이 함수를 호출하도록 해보자. 도구/기본 설정 메뉴항목을 선택할 때 Config 함수만 호출하면 된다.

 

void OnCommand(HWND hWnd,WPARAM wParam,LPARAM lParam)

{

     case IDM_TOOL_CONFIG:

          Config();

          break;

     ....

 

Config 함수는 설정 대화상자를 만들고 화면에 표시하여 사용자로부터 옵션을 변경할 수 있도록 하고 옵션을 적용하는 것까지 다 하므로 이 함수만 불러주면 설정 변경에 관련된 모든 동작이 처리된다. Option구조체는 항상 사용자가 선택한 설정상태를 가지게 될 것이다. 이 구조체는 새로운 차일드를 생성할 때도 적용된다. 다음 함수는 새로 차일드를 만들 때 ApiEdit컨트롤의 설정을 Option구조체의 설정대로 변경한다.

 

void SetSetting(CApiEdit &Ae)

{

     SOption Ori;

     HDC hdc;

     LOGFONT tFont;

 

     if (Option.Hangul) {

          MySetImeMode(Ae.hWnd,TRUE);

     }

 

     if (Option.bNoFirstSpace != Ori.bNoFirstSpace) {

          Ae.SetNoFirstSpace(Option.bNoFirstSpace);

     }

 

     if (Option.RightWrap != Ori.RightWrap) {

          Ae.SetRightWrap(Option.RightWrap);

     }

 

     if (Option.ColMark != Ori.ColMark) {

          Ae.SetColMark(Option.ColMark);

     }

 

     if (Option.LineRatio != Ori.LineRatio) {

          Ae.SetLineRatio(Option.LineRatio);

     }

 

     if (Option.bWrap == TRUE) {

          if (Option.nWrap != Ae.GetWrap()) {

               Ae.SetWrap(Option.nWrap);

          }

     } else {

          Ae.SetWrap(0);

     }

 

     if (Option.HideSelType != Ori.HideSelType) {

          Ae.SetHideSelType(Option.HideSelType);

     }

 

     if (Option.nShowCurLine != Ori.nShowCurLine) {

          Ae.SetShowCurLine(Option.nShowCurLine);

     }

 

     if (Option.bShowMargin != Ori.bShowMargin) {

          Ae.SetShowState(SHOWMARGIN,Option.bShowMargin);

     }

 

     if (Option.bShowLineNum != Ori.bShowLineNum) {

          Ae.SetShowState(SHOWLINENUM,Option.bShowLineNum);

     }

 

     if (Option.bShowEnter != Ori.bShowEnter) {

          Ae.SetShowState(SHOWENTER,Option.bShowEnter);

     }

 

     if (Option.bShowTab != Ori.bShowTab) {

          Ae.SetShowState(SHOWTAB,Option.bShowTab);

     }

 

     if (Option.bShowSpace != Ori.bShowSpace) {

          Ae.SetShowState(SHOWSPACE,Option.bShowSpace);

     }

 

     if (Option.TabWidth != Ori.TabWidth) {

          Ae.SetTabWidth(Option.TabWidth);

     }

 

     if (Option.bUseLineEnd != Ori.bUseLineEnd) {

          Ae.SetUseLineEnd(Option.bUseLineEnd);

     }

 

     if (Option.bAllowDrag != Ori.bAllowDrag) {

          Ae.SetAllowDrag(Option.bAllowDrag);

     }

 

     if (Option.CaretWidth != Ori.CaretWidth) {

          Ae.SetCaretWidth(Option.CaretWidth);

     }

 

     if (Option.bHideCurLine != Ori.bHideCurLine) {

          Ae.SetHideCurLine(Option.bHideCurLine);

     }

 

     if (Option.bCalcTabWithAvg != Ori.bCalcTabWithAvg) {

          Ae.SetCalcTabWithAvg(Option.bCalcTabWithAvg);

     }

 

     if (Option.logfont.lfHeight != Ori.logfont.lfHeight) {

          tFont=Option.logfont;

          hdc=GetDC(NULL);

          tFont.lfHeight=Option.logfont.lfHeight*GetDeviceCaps(hdc,LOGPIXELSY)/72;

          tFont.lfWidth=0;

          ReleaseDC(NULL,hdc);

          Ae.SetFont(&tFont);

     }

 

     if (Option.cFore & 0xff000000) {

          Ae.SetForeColor(Option.cFore & 0xffffff);

     }

 

     if (Option.cBack & 0xff000000) {

          Ae.SetBackColor(Option.cBack & 0xffffff);

     }

 

     if (Option.cSelFore & 0xff000000) {

          Ae.SetSelForeColor(Option.cSelFore & 0xffffff);

     }

 

     if (Option.cSelBack & 0xff000000) {

          Ae.SetSelBackColor(Option.cSelBack & 0xffffff);

     }

 

     if (Option.MarColor1 & 0xff000000) {

          Ae.SetMarColor1(Option.MarColor1 & 0xffffff);

     }

 

     if (Option.MarColor2 & 0xff000000) {

          Ae.SetMarColor2(Option.MarColor2 & 0xffffff);

     }

 

     if (Option.MarkColor & 0xff000000) {

          Ae.SetMarkColor(Option.MarkColor & 0xffffff);

     }

 

     if (Option.CodeColor & 0xff000000) {

          Ae.SetCodeColor(Option.CodeColor & 0xffffff);

     }

 

     if (Option.CurColor & 0xff000000) {

          Ae.SetCurColor(Option.CurColor & 0xffffff);

     }

 

     if (Option.NumColor & 0xff000000) {

          Ae.SetNumColor(Option.NumColor & 0xffffff);

     }

}

 

기본 옵션을 가지는 Ori 구조체를 생성하면 이 구조체는 호스트의 디폴트 옵션대로 생성될 것이다. Ori 구조체 내용과 Option 구조체의 내용 중 다른 것만 찾아 내면 ApiEdit에 추가로 지정해야 할 설정값을 알 수 있으며 이 옵션들을 새로 생성된 ApiEdit에 적용한다. 그 외의 옵션은 디폴트와 같으므로 굳이 새로 옵션을 적용할 필요가 없다. 만약 컨트롤의 디폴트와 호스트의 디폴트가 다르다면 컨트롤의 디폴트와 다른 값을 찾아 적용해야 한다.

예를 들어 색상값은 Ori와 비교하지 않고 상위 바이트가 0이 아닌 경우, 즉 컨트롤의 디폴트와 다를 경우만 색상을 설정하도록 하였다. Option::Init에서 초기화하는 호스트의 디폴트가 컨트롤 디폴트와 다르기만 하면 색상을 무조건 변경한다. 이 함수는 차일드가 생성된 직후에 호출되며 따라서 옵션 변경 후 생성되는 모든 ApiEdit Option 구조체의 설정대로 생성된다.

SetSetting ApplyNow의 코드가 비슷하지만 두 함수는 적용하는 대상이 다르다. ApplyNow는 이미 생성되어 있는 ApiEdit에 대해서 적용하는 것이고 SetSetting은 새로 생성되는 ApiEdit의 옵션을 변경하는 것이다. 차일드가 생성되는 WM_CRAETE에서 ApiEdit를 생성한 직후에 이 함수를 불러 주면 된다.

 

LRESULT CALLBACK DGChildProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)

{

     switch(iMessage) {

     case WM_CREATE:

          ....

          pSi=new SInfo;

          SetWindowLong(hWnd,0,(LONG)pSi);

          pSi->Ae.Create(0,0,0,0,WS_CHILD | WS_VISIBLE,1,hWnd);

        SetSetting(pSi->Ae);

     ....

 

글꼴 선택을 위해 폰트 열거 결과를 가지는 arFont 배열은 메인 윈도우가 파괴될 때 해제하도록 한다. 설정 대화상자가 한 번도 호출되지 않았다면 arFont NULL값을 가질 것이며 이 때는 배열을 해제하지 않아도 된다.

 

void OnDestroy(HWND hWnd,WPARAM wParam,LPARAM lParam)

{

    if (arFont)

        free(arFont);

     PostQuitMessage(0);

}

 

이로써 설정 대화상자에 대한 모든 코드 작성이 끝났다. 여기까지 코드를 작성한 후 실행해보면 제대로 동작할 것이다. ApiEdit Dangeun은 여기서 적용한 옵션보다 더 많은 옵션을 제공하며 앞으로 계속 만들어 나갈 것이다. 일단 설정 변경에 대한 기본 뼈대가 완성되었으므로 추가되는 옵션을 처리하는 것은 그리 어렵지 않다. 대화상자 프로시저는 더 손볼 것이 없고 ApplyNow SetSetting 함수에 적용 코드만 추가로 작성하면 된다.