. 편집

보기, 색상 페이지가 주로 프로그램의 외형에 관련된 옵션을 다루는 것에 비해 편집 페이지는 프로그램의 동작에 대한 옵션을 다룬다. 대화상자의 모양은 다음과 같다.

탭 크기와 그 외 편집 동작에 대한 선택 여부를 입력받는 많은 체크박스들이 배치되어 있다. 이중 일부 옵션은 아직 구현되지 않은 것들이다. 대화상자 프로시저의 코드는 다음과 같이 작성한다.

 

BOOL CALLBACK EditDlgProc(HWND hDlg,UINT iMessage,WPARAM wParam,LPARAM lParam)

{

     HWND hCon;

     int tint;

 

     switch(iMessage)

     {

     case WM_INITDIALOG:

          hCon=GetDlgItem(hDlg,IDC_TABWIDTH);

          SendMessage(hCon,CB_ADDSTRING,0,(LPARAM)"1");

          SendMessage(hCon,CB_ADDSTRING,0,(LPARAM)"2");

          SendMessage(hCon,CB_ADDSTRING,0,(LPARAM)"4");

          SendMessage(hCon,CB_ADDSTRING,0,(LPARAM)"8");

          SendMessage(hCon,CB_ADDSTRING,0,(LPARAM)"16");

 

          hCon=GetDlgItem(hDlg,IDC_UNDOLIMIT);

          SendMessage(hCon,CB_ADDSTRING,0,(LPARAM)"최저(10K)");

          SendMessage(hCon,CB_ADDSTRING,0,(LPARAM)"작음(100K)");

          SendMessage(hCon,CB_ADDSTRING,0,(LPARAM)"보통(1M)");

          SendMessage(hCon,CB_ADDSTRING,0,(LPARAM)"(5M)");

          SendMessage(hCon,CB_ADDSTRING,0,(LPARAM)"최대(10MB)");

 

          hCon=GetDlgItem(hDlg,IDC_FINDDLGPOS);

          SendMessage(hCon,CB_ADDSTRING,0,(LPARAM)"메인 윈도우의 왼쪽 위");

          SendMessage(hCon,CB_ADDSTRING,0,(LPARAM)"메인 윈도우의 오른쪽 위");

          SendMessage(hCon,CB_ADDSTRING,0,(LPARAM)"메인 윈도우의 오른쪽 아래");

          SendMessage(hCon,CB_ADDSTRING,0,(LPARAM)"메인 윈도우 중앙");

          return TRUE;

     case WM_COMMAND:

          switch (LOWORD(wParam))   {

          case IDC_TABWIDTH:

          case IDC_UNDOLIMIT:

          case IDC_FINDDLGPOS:

              switch (HIWORD(wParam)) {

              case CBN_SELCHANGE:

              case CBN_EDITCHANGE:

                   PropSheet_Changed(GetParent(hDlg),hDlg);

                   break;

              }

              return TRUE;

          case IDC_ALLOWDRAG:

          case IDC_USELINEEND:

          case IDC_INITFIND:

          case IDC_INITNEXTFIND:

          case IDC_SOUNDFINDFAIL:

          case IDC_SPACEFORTAB:

          case IDC_AUTOINDENT:

          case IDC_BLOCKINDENTWITHTAB:

          case IDC_HOMETOFIRSTCHAR:

          case IDC_CALCTABWITHAVG:

              PropSheet_Changed(GetParent(hDlg),hDlg);

              return TRUE;

          }

          break;

     case WM_NOTIFY:

          switch (((LPNMHDR)lParam)->code) {

          case PSN_SETACTIVE:

              g_StartPage=3;

              SetDlgItemInt(hDlg,IDC_TABWIDTH,NewOption.TabWidth,FALSE);

              CheckDlgButton(hDlg,IDC_ALLOWDRAG,NewOption.bAllowDrag ? BST_CHECKED:BST_UNCHECKED);

              CheckDlgButton(hDlg,IDC_USELINEEND,NewOption.bUseLineEnd ? BST_CHECKED:BST_UNCHECKED);

              SendDlgItemMessage(hDlg,IDC_UNDOLIMIT,CB_SETCURSEL,NewOption.UndoLimit,0);

              SendDlgItemMessage(hDlg,IDC_FINDDLGPOS,CB_SETCURSEL,NewOption.FindDlgPos,0);

              CheckDlgButton(hDlg,IDC_INITFIND,NewOption.bInitFind ? BST_CHECKED:BST_UNCHECKED);

              CheckDlgButton(hDlg,IDC_INITNEXTFIND,NewOption.bInitNextFind ? BST_CHECKED:BST_UNCHECKED);

              CheckDlgButton(hDlg,IDC_SOUNDFINDFAIL,NewOption.bSoundFindFail ? BST_CHECKED:BST_UNCHECKED);

                   CheckDlgButton(hDlg,IDC_SPACEFORTAB,NewOption.bSpaceForTab ? BST_CHECKED:BST_UNCHECKED);

                   CheckDlgButton(hDlg,IDC_AUTOINDENT,NewOption.bAutoIndent ? BST_CHECKED:BST_UNCHECKED);

                   CheckDlgButton(hDlg,IDC_BLOCKINDENTWITHTAB,NewOption.bBlockIndentWithTab ? BST_CHECKED:BST_UNCHECKED);

                   CheckDlgButton(hDlg,IDC_HOMETOFIRSTCHAR,NewOption.bHomeToFirstChar ? BST_CHECKED:BST_UNCHECKED);

                   CheckDlgButton(hDlg,IDC_CALCTABWITHAVG,NewOption.bCalcTabWithAvg ? BST_CHECKED:BST_UNCHECKED);

              return TRUE;

          case PSN_APPLY:

              ApplyNow();

              return TRUE;

          case PSN_KILLACTIVE:

              tint=GetDlgItemInt(hDlg,IDC_TABWIDTH,NULL,FALSE);

              if (tint < 1 || tint > 32) {

                   MessageBox(hDlg,"탭은 1~32사이의 값을 지정해야 합니다","알림",MB_OK);

                   SetWindowLong(hDlg,DWL_MSGRESULT,TRUE);

                   return TRUE;

              }

 

              NewOption.TabWidth=GetDlgItemInt(hDlg,IDC_TABWIDTH,NULL,FALSE);

              NewOption.bAllowDrag=IsDlgButtonChecked(hDlg,IDC_ALLOWDRAG) ? TRUE:FALSE;

              NewOption.bUseLineEnd=IsDlgButtonChecked(hDlg,IDC_USELINEEND) ? TRUE:FALSE;

              NewOption.UndoLimit=SendDlgItemMessage(hDlg,IDC_UNDOLIMIT,CB_GETCURSEL,0,0);

              NewOption.FindDlgPos=SendDlgItemMessage(hDlg,IDC_FINDDLGPOS,CB_GETCURSEL,0,0);

              NewOption.bInitFind=IsDlgButtonChecked(hDlg,IDC_INITFIND) ? TRUE:FALSE;

              NewOption.bInitNextFind=IsDlgButtonChecked(hDlg,IDC_INITNEXTFIND) ? TRUE:FALSE;

              NewOption.bSoundFindFail=IsDlgButtonChecked(hDlg,IDC_SOUNDFINDFAIL) ? TRUE:FALSE;

              NewOption.bSpaceForTab=IsDlgButtonChecked(hDlg,IDC_SPACEFORTAB) ? TRUE:FALSE;

              NewOption.bAutoIndent=IsDlgButtonChecked(hDlg,IDC_AUTOINDENT) ? TRUE:FALSE;

              NewOption.bBlockIndentWithTab=IsDlgButtonChecked(hDlg,IDC_BLOCKINDENTWITHTAB) ? TRUE:FALSE;

              NewOption.bHomeToFirstChar=IsDlgButtonChecked(hDlg,IDC_HOMETOFIRSTCHAR) ? TRUE:FALSE;

              NewOption.bCalcTabWithAvg=IsDlgButtonChecked(hDlg,IDC_CALCTABWITHAVG) ? TRUE:FALSE;

              return TRUE;

          }

          break;

     }

     return FALSE;

}

 

대화상자에 배치된 컨트롤들이 대부분 체크박스들이므로 특별히 눈여겨 볼만한 코드가 없다. 옵션을 컨트롤에 표시하고 변경된 값을 다시 읽어들이는 코드들이며 앞에서 만들었던 페이지들에 비해 훨씬 더 간단한 구조를 가진다. 한 번 죽 훑어 보기만 해도 무슨 코드인지 금방 알 수 있을 것이다.

이 외에 문법, 인쇄 페이지도 있는데 이 페이지는 리소스만 만들어져 있고 아직 기능 구현이 되지 않았으므로 옵션에 관련된 코드도 작성되어 있지 않다. 어떤 모양을 가지는 페이지인지 구경이나 일단 해보도록 하자.

 

컨트롤만 있고 코드가 없기 때문에 과연 썰렁하다. 대화상자 프로시저도 형식만 갖추고 있으며 실질적인 코드는 아직 작성되어 있지 않다.

 

BOOL CALLBACK SyntaxDlgProc(HWND hDlg,UINT iMessage,WPARAM wParam,LPARAM lParam)

{

     switch(iMessage)

     {

     case WM_INITDIALOG:

          return TRUE;

     case WM_NOTIFY:

          LPNMHDR hdr;

          hdr=(LPNMHDR)lParam;

          switch (hdr->code) {

          case PSN_SETACTIVE:

              g_StartPage=4;

              return TRUE;

          case PSN_APPLY:

              return TRUE;

          case PSN_KILLACTIVE:

              return TRUE;

          }

          break;

     }

     return FALSE;

}

 

BOOL CALLBACK PrintDlgProc(HWND hDlg,UINT iMessage,WPARAM wParam,LPARAM lParam)

{

     switch(iMessage)

     {

     case WM_INITDIALOG:

          return TRUE;

     case WM_NOTIFY:

          LPNMHDR hdr;

          hdr=(LPNMHDR)lParam;

          switch (hdr->code) {

          case PSN_SETACTIVE:

              g_StartPage=5;

              return TRUE;

          case PSN_APPLY:

              return TRUE;

          case PSN_KILLACTIVE:

              return TRUE;

          }

          break;

     }

     return FALSE;

}

 

이 두 함수의 코드는 한참 후에 천천히 채워질 것이다. 그래도 빈 대화상자나마 있어야 프로퍼티 시트가 초기화를 할 수 있으므로 코드에는 일단 포함시켜 두도록 하자.

 

여기까지 설정 대화상자를 작성했다. 많은 양의 코드가 추가되었는데 이 대화상자가 하는 일은 설정을 직접 바꾸는 것도 아니고 변경된 옵션을 적용하는 것도 아니다. 오로지 Option의 사본인 NewOption의 값을 보여주고 사용자가 이 구조체의 값을 편리하게 변경하도록 하는 것이 하는 일의 전부이다. 구조체가 크다 보니 필요한 컨트롤이 많고 따라서 컨트롤 입출력 코드가 많을 뿐이지 하는 일은 아주 단순하다.