. 찾기/바꾸기 대화상자

다음은 파일에서 찾기 대화상자이며 이미 리소스에 작성되어 있다. 시작 폴더와 검색 파일 유형, 검색할 문자열 그리고 검색 옵션을 입력받는다.

문서 찾기 대화상자와 모양은 비슷하지만 검색 옵션이 좀 다르다. 단어단위로, 대소문자 구분 옵션은 동일하지만 문서 전체를 검색하므로 검색 방향은 필요없고 되돌리기 옵션도 필요치 않다. 대신 하위 폴더도 검색할 것인지와 검색결과에서 파일명을 어떻게 표시할 것인가에 대한 옵션이 추가되어 있다. 시작 폴더는 검색을 시작할 폴더이며 대상 파일은 검색할 파일 이름 패턴이다. 와일드 카드 표현식으로 세미콜론으로 끊어서 여러 개의 패턴을 지정할 수 있다.

제일 밑에 있는 시작 폴더를 기준으로 한 파일명 표시는 검색된 파일의 경로를 완전 경로로 보여줄 것인가 아니면 시작 폴더에서의 상대적인 경로로 보여줄 것인가를 지정한다. 예를 들어 C:\Project\Dangeun 폴더에서 *.cpp 파일을 검색했을 때 이 폴더 아래의 Test\Alpha 서브폴더의 Dg.cpp에서 원하는 문자열을 찾았다면 검색결과창에 이 파일의 경로를 C:\Project\Dangeun\Test\Alpha\Dg.cpp로 출력할 것인가 아니면 Test\Alpha\Dg.cpp로 출력할 것인가를 지정한다.

바꾸기 대화상자도 거의 비슷하게 생겼다. 바꿀 내용 콤보박스가 추가되어 있다는 점만 빼고 나면 찾기와 동일하다.

문서의 찾기/바꾸기 대화상자와 마찬가지로 파일검색에 필요한 옵션만 입력받아줄 뿐 실제 찾기를 하는 것은 아니다. 이 대화상자가 보여주는 옵션은 FindFlag 검색 옵션과 arFind 검색 히스토리 문자열이며 사용자의 입력 내용도 이 전역변수들에 저장된다.

두 대화상자는 템플리트만 다르며 취급하는 옵션들이 거의 비슷하기 때문에 대화상자 프로시저는 공유할 수 있다. 대화상자 프로시저는 다음과 같이 작성한다.

 

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

{

     TCHAR szTemp[256];

     TCHAR Folder[MAX_PATH];

     HWND hActive;

     SInfo *pSi;

     int s,e;

 

     switch(iMessage)

     {

     case WM_INITDIALOG:

          MoveToParentCenter(hDlg);

 

          if (FindFlag & AE_FIND_WHOLEWORD) {

              CheckDlgButton(hDlg,IDC_FIND_WHOLEWORD,BST_CHECKED);

          }

 

          if (FindFlag & AE_FIND_MATCHCASE) {

              CheckDlgButton(hDlg,IDC_FIND_MATCHCASE,BST_CHECKED);

          }

 

          if (FindFlag & AE_FIND_RECURSIVE) {

              CheckDlgButton(hDlg,IDC_FIND_RECURSIVE,BST_CHECKED);

          }

 

          if (FindFlag & AE_FIND_SHORTPATH) {

              CheckDlgButton(hDlg,IDC_FIND_SHORTPATH,BST_CHECKED);

          }

 

          RefillHistory(GetDlgItem(hDlg,IDC_FIND_WHAT),arFind[0]);

          if (Option.bInitFind) {

              hActive=(HWND)SendMessage(g_hMDIClient,WM_MDIGETACTIVE,0,NULL);

              if (hActive != NULL) {

                   pSi=(SInfo *)GetWindowLong(hActive,0);

                   pSi->Ae.GetSelect(s,e);

                   if (s==e) {

                        pSi->Ae.GetNowWord(pSi->Ae.GetOffset(),s,e);

                   }

                   if (abs(s-e) <= 255 && abs(s-e) > 0) {

                        pSi->Ae.GetText(szTemp,256,s,e);

                        SetDlgItemText(hDlg,IDC_FIND_WHAT,szTemp);

                   }

              }

          }

          RefillHistory(GetDlgItem(hDlg,IDC_FIND_FOLDER),arFind[2]);

          RefillHistory(GetDlgItem(hDlg,IDC_FIND_TYPE),arFind[3]);

          RefillHistory(GetDlgItem(hDlg,IDC_FIND_TO),arFind[1]);

          SendMessage(GetDlgItem(hDlg,IDC_FIND_WHAT), CB_LIMITTEXT, (WPARAM)255, 0);

          SendMessage(GetDlgItem(hDlg,IDC_FIND_FOLDER), CB_LIMITTEXT, (WPARAM)MAX_PATH, 0);

          SendMessage(GetDlgItem(hDlg,IDC_FIND_TYPE), CB_LIMITTEXT, (WPARAM)255, 0);

          SendMessage(GetDlgItem(hDlg,IDC_FIND_TO), CB_LIMITTEXT, (WPARAM)255, 0);

          SendMessage(hDlg,WM_COMMAND,MAKEWPARAM(IDC_FIND_WHAT,CBN_EDITCHANGE),0);

          return TRUE;

     case WM_COMMAND:

          switch (LOWORD(wParam))

          {

          case IDC_FIND_WHAT:

          case IDC_FIND_FOLDER:

          case IDC_FIND_TYPE:

          case IDC_FIND_TO:

              switch (HIWORD(wParam)) {

              case CBN_EDITCHANGE:

                   if (GetWindowTextLength(GetDlgItem(hDlg,IDC_FIND_WHAT)) == 0 ||

                        GetWindowTextLength(GetDlgItem(hDlg,IDC_FIND_FOLDER)) == 0 ||

                        GetWindowTextLength(GetDlgItem(hDlg,IDC_FIND_TYPE)) == 0 ||

                        (GetDlgItem(hDlg,IDC_FIND_TO) != NULL &&

                        GetWindowTextLength(GetDlgItem(hDlg,IDC_FIND_TO)) == 0)) {

                        EnableWindow(GetDlgItem(hDlg,IDC_BTNFIND),FALSE);

                   } else {

                        EnableWindow(GetDlgItem(hDlg,IDC_BTNFIND),TRUE);

                   }

                   break;

              case CBN_SELCHANGE:

                   PostMessage(hDlg,WM_COMMAND,MAKEWPARAM(IDC_FIND_WHAT,CBN_EDITCHANGE),0);

                   break;

              }

              break;

          case IDC_BTN_BRFOLDER:

              GetDlgItemText(hDlg,IDC_FIND_FOLDER,szTemp,255);

              if (BrowseFolder(hDlg,"검색을 시작할 폴더를 선택하십시오.",szTemp,Folder)==TRUE) {

                   SetDlgItemText(hDlg,IDC_FIND_FOLDER,Folder);

                   SendMessage(hDlg,WM_COMMAND,MAKEWPARAM(IDC_FIND_WHAT,CBN_EDITCHANGE),0);

              }

              return TRUE;

          case IDC_BTNFIND:

               if (IsDlgButtonChecked(hDlg,IDC_FIND_WHOLEWORD)) {

                   FindFlag |= AE_FIND_WHOLEWORD;

              } else {

                   FindFlag &= ~AE_FIND_WHOLEWORD;

              }

 

              if (IsDlgButtonChecked(hDlg,IDC_FIND_MATCHCASE)) {

                   FindFlag |= AE_FIND_MATCHCASE;

              } else {

                   FindFlag &= ~AE_FIND_MATCHCASE;

              }

 

              if (IsDlgButtonChecked(hDlg,IDC_FIND_RECURSIVE)) {

                   FindFlag |= AE_FIND_RECURSIVE;

              } else {

                   FindFlag &= ~AE_FIND_RECURSIVE;

              }

 

              if (IsDlgButtonChecked(hDlg,IDC_FIND_SHORTPATH)) {

                   FindFlag |= AE_FIND_SHORTPATH;

              } else {

                   FindFlag &= ~AE_FIND_SHORTPATH;

              }

 

              GetDlgItemText(hDlg,IDC_FIND_WHAT,szTemp,255);

              if (lstrlen(szTemp)) {

                   arFind[0].Add(szTemp);

              }

              GetDlgItemText(hDlg,IDC_FIND_FOLDER,szTemp,255);

              if (lstrlen(szTemp)) {

                   arFind[2].Add(szTemp);

              }

              GetDlgItemText(hDlg,IDC_FIND_TYPE,szTemp,255);

              if (lstrlen(szTemp)) {

                   arFind[3].Add(szTemp);

              }

              GetDlgItemText(hDlg,IDC_FIND_TO,szTemp,255);

              if (lstrlen(szTemp)) {

                   arFind[1].Add(szTemp);

              }

              EndDialog(hDlg,IDOK);

              return TRUE;

          case IDCANCEL:

              EndDialog(hDlg,IDCANCEL);

              return TRUE;

          }

          return FALSE;

     }

     return FALSE;

}

 

앞에서 작성했던 찾기/바꾸기 대화상자의 프로시저와 거의 유사하므로 특별히 분석해볼만큼 어려운 코드는 없다. 현재 설정되어 있는 검색 옵션을 보여주고 대화상자를 닫을 때 컨트롤에서 다시 검색 옵션을 읽어들이는 것이 주 기능이다. 검색 시작 폴더를 찾아주는 기능을 위해 폴더 찾아보기 유틸리티 함수를 Util.cpp에 추가한다.

 

 

 

int CALLBACK BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lParam,LPARAM lpData)

{

     switch (uMsg)

     {

     case BFFM_INITIALIZED:

          if (lpData != NULL) {

              SendMessage(hwnd,BFFM_SETSELECTION,TRUE,(LPARAM)lpData);

          }

          break;

     }

     return 0;

}

 

BOOL BrowseFolder(HWND hParent, LPCTSTR szTitle, LPCTSTR StartPath, TCHAR *szFolder)

{

     LPMALLOC pMalloc;

     LPITEMIDLIST pidl;

     BROWSEINFO bi;

 

     bi.hwndOwner = hParent;

     bi.pidlRoot = NULL;

     bi.pszDisplayName = NULL;

     bi.lpszTitle = szTitle ;

     bi.ulFlags = 0;

     bi.lpfn = BrowseCallbackProc;;

     bi.lParam = (LPARAM)StartPath;

                           

     pidl = SHBrowseForFolder(&bi);

 

     if (pidl == NULL) {

          return FALSE;

     }

     SHGetPathFromIDList(pidl, szFolder);

 

     if (SHGetMalloc(&pMalloc) != NOERROR) {

          return FALSE;

     }

     pMalloc->Free(pidl);

     pMalloc->Release();

     return TRUE;

}

 

폴더 선택 공통 대화상자라는 것은 제공되지 않으므로 SHBrowseForFolder 쉘 함수로 폴더를 입력받아야 한다. 이 함수는 폴더간의 구분을 위해 PIDL이라는 다소 생소한 타입을 사용하고 구조체가 복잡하기 때문에 쉽게 쓸 수 있도록 BrowseFolder라는 래퍼 함수를 만들었으며 검색 시작 폴더로 대화상자를 초기화하기 위해 콜백 함수를 정의하였다. 콜백 함수는 BrowseFolder 함수만 사용하므로 Util.h에 원형을 선언하지 않아도 된다. 이 함수가 보여주는 대화상자는 다음과 같은 모양을 하고 있다.

한 번쯤은 구경해 봤음직한 대화상자일 것이다. BrowseFolder 함수는 재사용을 고려하여 작성되었으므로 일반적인 폴더 선택 목적으로 사용할 수 있다. 인수로 부모 윈도우의 핸들, 타이틀바의 캡션, 대화상자가 열릴 때 기본적으로 선택될 폴더 그리고 사용자가 선택한 폴더 경로를 돌려받기 위한 버퍼를 전달하기만 하면 된다.