. 개별 윈도우의 옵션

설정 대화상자에서 지정한 옵션은 이미 만들어진 차일드는 물론이고 앞으로 만들어질 창에 대해서도 적용된다. 즉 이 대화상자에서 변경한 옵션은 모든 차일드가 공통적으로 사용하는 옵션이다. 여기서 줄간을 150으로 바꾸면 모든 창의 줄간이 같이 150으로 바뀌며 글꼴을 바꾸면 모두 한꺼번에 바뀐다. 텍스트 편집창은 모두 텍스트 편집이라는 같은 목적으로 만들어지므로 모든 옵션이 같이 적용되는 것이 마땅하다.

하지만 설정 대화상자는 매번 열었다 닫기가 번거로우므로 일부 자주 사용하는 몇 개의 옵션은 개별 창에 대해서만 신속하게 변경할 수 있는 장치가 있다면 편리할 것이다. 예를 들어 자동개행 옵션은 문서의 성격에 따라 다르게 적용할 수 있으므로 각 창의 개행 옵션은 따로 변경할 수 있어야 하며 그것도 수시로 빠른 속도로 바꿀 수 있어야 한다. 이런 목적으로 현재 활성화된 차일드 하나에 대해서만 옵션을 변경할 수 있도록 해보자.

보기 메뉴에는 이미 관련 메뉴항목이 만들어져 있으며 변경 대상은 자동개행, 제어코드 보기, 줄간, 글꼴 등이며 아직 기능은 없지만 문법도 문서에 따라 다르게 적용할 수 있도록 할 것이다. 글꼴은 원칙적으로 폰트 선택 대화상자에서 선택해야 하지만 신속하게 글꼴을 바꾸기에는 부적합하므로 미리 정의된 글꼴 세트 10개를 다음과 같이 선언한다.

 

LOGFONT arCustomFont[10]={

     {0,0,0,0,0,0,0,0,0,0,0,0,0,""},

     {10,0,0,0,0,0,0,0,HANGEUL_CHARSET,3,2,1,VARIABLE_PITCH | FF_MODERN,"굴림"},

     {12,0,0,0,0,0,0,0,HANGEUL_CHARSET,3,2,1,VARIABLE_PITCH | FF_MODERN,"굴림"},

     {10,0,0,0,0,0,0,0,HANGEUL_CHARSET,3,2,1,VARIABLE_PITCH | FF_MODERN,"굴림체"},

     {12,0,0,0,0,0,0,0,HANGEUL_CHARSET,3,2,1,VARIABLE_PITCH | FF_MODERN,"굴림체"},

     {12,0,0,0,0,0,0,0,HANGEUL_CHARSET,3,2,1,VARIABLE_PITCH | FF_MODERN,"궁서"},

     {15,0,0,0,0,0,0,0,HANGEUL_CHARSET,3,2,1,VARIABLE_PITCH | FF_MODERN,"궁서"},

     {20,0,0,0,0,0,0,0,HANGEUL_CHARSET,3,2,1,VARIABLE_PITCH | FF_MODERN,"궁서"},

     {12,0,0,0,0,0,0,0,HANGEUL_CHARSET,3,2,1,VARIABLE_PITCH | FF_MODERN,"바탕"},

     {15,0,0,0,0,0,0,0,HANGEUL_CHARSET,3,2,1,VARIABLE_PITCH | FF_MODERN,"바탕"}

};

 

보기/활성창의 글꼴 아래에 있는 메뉴항목을 선택하면 활성창의 글꼴을 이 구조체의 글꼴로 변경할 것이다. 이 구조체 배열의 lfHeight는 포인트 단위인데 실제로 폰트를 생성할 때 이 값은 픽셀로 처리되므로 포인트 단위를 픽셀값으로 변경해야 한다. OnCreate에서 이 값을 해상도에 맞게 변경한다.

 

int OnCreate(HWND hWnd,WPARAM wParam,LPARAM lParam)

{

    int i;

    HDC hdc;

     ....

    hdc=GetDC(NULL);

    for (i=1;i<10;i++) {

        arCustomFont[i].lfHeight=arCustomFont[i].lfHeight*GetDeviceCaps(hdc,LOGPIXELSY)/72;

    }

    ReleaseDC(NULL,hdc);

     DragAcceptFiles(hWnd,TRUE);

     return 0;

}

 

활성창의 옵션 변경은 OnCommand에서 처리한다. 각 메뉴항목에 대응되는 함수를 호출하는 아주 단순한 명령의 나열들이다.

 

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

{

     CHOOSEFONT CFT;

     LOGFONT lf;

     ....

     case IDM_VIEW_WORDWRAP:

          pSi->Ae.SetWrap(pSi->Ae.GetWrap()==0 ? Option.nWrap:0);

          break;

     case IDM_VIEW_CODE:

          if (pSi->Ae.GetShowState(SHOWENTER)) {

               pSi->Ae.SetShowState(SHOWENTER,FALSE);

               pSi->Ae.SetShowState(SHOWTAB,FALSE);

               pSi->Ae.SetShowState(SHOWSPACE,FALSE);

          } else {

               pSi->Ae.SetShowState(SHOWENTER,TRUE);

               pSi->Ae.SetShowState(SHOWTAB,TRUE);

               pSi->Ae.SetShowState(SHOWSPACE,TRUE);

          }

          break;

     case IDM_FONT_1:

          pSi->Ae.SetFont(&arCustomFont[0]);

          break;

     case IDM_FONT_2:

          pSi->Ae.SetFont(&arCustomFont[1]);

          break;

     case IDM_FONT_3:

          pSi->Ae.SetFont(&arCustomFont[2]);

          break;

     case IDM_FONT_4:

          pSi->Ae.SetFont(&arCustomFont[3]);

          break;

     case IDM_FONT_5:

          pSi->Ae.SetFont(&arCustomFont[4]);

          break;

     case IDM_FONT_6:

          pSi->Ae.SetFont(&arCustomFont[5]);

          break;

     case IDM_FONT_7:

          pSi->Ae.SetFont(&arCustomFont[6]);

          break;

     case IDM_FONT_8:

          pSi->Ae.SetFont(&arCustomFont[7]);

          break;

     case IDM_FONT_9:

          pSi->Ae.SetFont(&arCustomFont[8]);

          break;

     case IDM_FONT_10:

          pSi->Ae.SetFont(&arCustomFont[9]);

          break;

     case IDM_FONT_11:

          memset(&CFT, 0, sizeof(CHOOSEFONT));

          CFT.lStructSize = sizeof(CHOOSEFONT);

          CFT.hwndOwner=hWnd;

          pSi->Ae.GetFont(&lf);

          CFT.lpLogFont=&lf;

          CFT.Flags=CF_EFFECTS | CF_SCREENFONTS;

          if (ChooseFont(&CFT)) {

               pSi->Ae.SetFont(&lf);

          }

          break;

     case IDM_LINE_1:

          pSi->Ae.SetLineRatio(100);

          break;

     case IDM_LINE_2:

          pSi->Ae.SetLineRatio(120);

          break;

     case IDM_LINE_3:

          pSi->Ae.SetLineRatio(150);

          break;

     case IDM_LINE_4:

          pSi->Ae.SetLineRatio(200);

          break;

     case IDM_LINE_5:

          pSi->Ae.SetLineRatio(300);

          break;

     ....

 

자동개행은 0 Option.nWrap 사이를 토글한다. 제어코드는 세 가지 종류가 있지만 각 코드를 개별적으로 토글하려면 메뉴항목이나 단축키가 많아져 오히려 번거로우므로 세 가지 코드를 한꺼번에 토글하도록 했다. 글꼴은 글꼴 선택 항목만 제외하고 arCustomFont 구조체 배열에 미리 정의된 글꼴로 SetFont 함수를 호출하였고 줄간은 미리 정의된 값으로 SetLineRatio를 호출하였다. 이제 보기 메뉴를 사용하면 활성창에 대한 옵션은 간단하게 변경할 수 있으며 단축키가 지원되는 자동개행, 제어코드 보기는 <Ctrl+W>, <Ctrl+E>로 간단하게 토글할 수 있다.

메뉴로 설정상태를 신속하게 변경할 수 있도록 했으므로 메뉴에 현재 설정상태를 보여주어야 한다. OnInitMenu 함수에 다음 코드를 작성한다.

 

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

{

     ....

     if (hActive) {

          ....

          if (pSi->Ae.GetWrap() != 0) {

               CheckMenuItem(hMenu, IDM_VIEW_WORDWRAP, MF_BYCOMMAND | MF_CHECKED);

          } else {

               CheckMenuItem(hMenu, IDM_VIEW_WORDWRAP, MF_BYCOMMAND | MF_UNCHECKED);

          }

 

          if (pSi->Ae.GetShowState(SHOWENTER)) {

               CheckMenuItem(hMenu, IDM_VIEW_CODE, MF_BYCOMMAND | MF_CHECKED);

          } else {

               CheckMenuItem(hMenu, IDM_VIEW_CODE, MF_BYCOMMAND | MF_UNCHECKED);

          }

 

          for (s=IDM_LINE_1;s<=IDM_LINE_5;s++) {

               CheckMenuItem(hMenu,s,MF_BYCOMMAND | MF_UNCHECKED);

          }

          switch (pSi->Ae.GetLineRatio())

          {

          case 100:CheckMenuItem(hMenu,IDM_LINE_1,MF_BYCOMMAND | MF_CHECKED);break;

          case 120:CheckMenuItem(hMenu,IDM_LINE_2,MF_BYCOMMAND | MF_CHECKED);break;

          case 150:CheckMenuItem(hMenu,IDM_LINE_3,MF_BYCOMMAND | MF_CHECKED);break;

          case 200:CheckMenuItem(hMenu,IDM_LINE_4,MF_BYCOMMAND | MF_CHECKED);break;

          case 300:CheckMenuItem(hMenu,IDM_LINE_5,MF_BYCOMMAND | MF_CHECKED);break;

          }

     }

}

 

현재 선택된 옵션에 대해 메뉴 옆에 체크 표시를 붙여주었다. , 글꼴은 정확하게 비교하기가 어려우므로 체크 표시를 붙이지 않았다.