. 대화상자 호출

검색 옵션을 입력받는 대화상자와 폴더 검색 함수까지 작성했으므로 이제 파일에서 찾기 함수를 구현해보자. 검색 메뉴에 있는 파일에서 찾기, 파일에서 바꾸기 메뉴항목을 선택하면 각 대화상자를 호출한다.

 

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

{

     ....

     case IDM_SEARCH_FILES:

          if (DialogBox(g_hInst,MAKEINTRESOURCE(IDD_FILEFIND),hWnd,FileFindDlgProc)==IDOK) {

              FindOrReplaceInFiles(FALSE);

          }

          break;

     case IDM_SEARCH_RFILES:

          if (DialogBox(g_hInst,MAKEINTRESOURCE(IDD_FILEREPLACE),hWnd,FileFindDlgProc)==IDOK) {

              FindOrReplaceInFiles(TRUE);

          }

          break;

 

파일검색 대화상자를 열어 놓은 채로 편집을 하지는 않기 때문에 이 대화상자들은 모델리스일 필요가 없다. CreateDialog 함수로 대화상자를 만드는 대신 DialogBox 함수로 모달형으로 대화상자를 실행했다. 대화상자 프로시저에서 사용자가 찾기 버튼을 클릭하면 IDOK를 리턴할 것이며 이때 파일검색을 시작하면 된다. 파일 찾기와 바꾸기는 절차가 비슷하기 때문에 한 함수가 두 기능을 모두 제공하되 인수만 다르게 하였다.

 

void FindOrReplaceInFiles(BOOL bReplace)

{

     BOOL bDeep;

 

     if ((lstrlen(arFind[0].Get(0))==0) ||

          (bReplace && lstrlen(arFind[1].Get(0))==0) ||

          (lstrlen(arFind[2].Get(0))==0 || _access(arFind[2].Get(0),0)!=0) ||

          (lstrlen(arFind[3].Get(0))==0)) {

          return;

     }

 

     if (FindFlag & AE_FIND_RECURSIVE) {

          bDeep=TRUE;

     } else {

          bDeep=FALSE;

     }

 

     TotalFind=0;

     if (Option.bShowOutput==FALSE) {

          Option.bShowOutput=TRUE;

          Relayout();

     }

     SendMessage(hList,LVM_DELETEALLITEMS,0,0);

 

     if (bReplace) {

          lstrcpy(LastFIF,arFind[1].Get(0));

          FindInFiles(arFind[2].Get(0),arFind[3].Get(0),FIF_DEEP | FIF_INCHID,

              OnReplaceFile,(LPVOID)NULL);

     } else {

          lstrcpy(LastFIF,arFind[0].Get(0));

          FindInFiles(arFind[2].Get(0),arFind[3].Get(0),FIF_DEEP | FIF_INCHID,

              OnFindFile,(LPVOID)NULL);

     }

}

 

bReplace 인수가 TRUE이면 바꾸기를 하고 FALSE이면 찾기를 한다. 먼저 전역변수에 설정된 옵션이 유효한지 검사해보는데 찾을 내용이 입력되지 않았다거나 시작 폴더가 유효하지 않으면 검색을 시작할 수 없으므로 리턴해 버린다. TotalFind는 총 검색된 개수를 가지는 전역변수인데 검색을 시작하기 전에 0으로 초기화된다. 검색결과창이 숨겨진 상태이면 강제로 보이도록 하며 결과창의 리스트 뷰에 이전 검색결과가 있으면 모두 비우도록 하여 새로운 검색 준비를 한다.

검색을 시작하기 전에 검색 대상 단어 또는 바꾼 후의 단어를 LastFIF 전역변수에 미리 조사해놓는다. 이 문자열은 검색결과창에서 검색결과를 찾아갈 때 사용된다. 찾을 내용 문자열은 arFind[0]의 처음에 저장되는데 이 히스토리는 파일 찾기뿐만 아니라 문서 찾기에서도 공유하고 있다. 따라서 파일검색 후 문서 찾기 명령을 실행하면 결과창의 검색결과가 어떤 문자열에 대한 검색결과인지를 알 수 없게 되므로 따로 저장해두어야 한다.

이 모든 점검과 준비를 마친 후 FindInFiles 함수를 호출함으로써 비로소 파일검색을 시작한다. 찾기 명령이나 바꾸기 명령이나 폴더를 검색하는 절차는 동일하므로 둘 다 동일한 인수로 FindInFiles 함수를 호출하면 된다. , 조건에 맞는 파일을 찾았을 때 이 파일을 어떻게 처리할 것인지를 지정하는 콜백 함수만 다를 뿐이다. OnFindFile 함수는 파일에서 문자열을 찾아줄 것이고 OnReplaceFile 함수는 파일에서 문자열을 바꿀 것임을 쉽게 유추할 수 있다. 이 두 함수는 잠시 후에 작성하게 될 것이다.

여기까지 파일에서 찾기와 바꾸기를 구현하는 여러 단계의 함수들을 작성해 왔는데 이 함수들의 실행 과정을 그림으로 정리해보자면 다음과 같이 그릴 수 있다.

이렇게 호출 구조가 복잡한 이유는 파일에서 찾기 및 바꾸기가 옵션의 입력, 검색 준비, 폴더 검색 과정이 동일하므로 대부분의 루틴을 공유할 수 있기 때문이다. 파일을 찾았을 때 구체적으로 어떤 동작을 할 것인가만 달라지므로 이 동작만 콜백 함수로 처리하도록 하였다.