. 찾기, 바꾸기 전환

찾기/바꾸기 대화상자는 둘 다 모델리스형으로 열리므로 이 대화상자를 열어 놓고 다른 작업을 할 수 있다. 그러나 두 대화상자는 g_FindDlg 핸들 하나로 관리되기 때문에 한꺼번에 열 수는 없도록 되어 있다. 대화상자 프로시저를 공유하고 있기는 하지만 대화상자 핸들만 분리한다면 두 대화상자를 동시에 열 수도 있으며 전혀 문제될 것은 없다. 그러나 찾기와 바꾸기 작업을 동시에 하지는 않으므로 굳이 비슷한 대화상자 두 개를 모델리스로 같이 열 필요는 없을 것이다.

현재 코드는 찾기 대화상자가 열린 상태에서 다시 찾기 명령을 실행하면 대화상자는 만들지 않고 이미 떠 있는 찾기 대화상자로 포커스만 넘긴다. 바꾸기 대화상자도 마찬가지로 동작하며 이 방식은 별 문제가 없어 보이지만 사실 문제가 있다. 찾기 대화상자가 떠 있는 상태에서 바꾸기 대화상자를 열면 g_FindDlg가 유효한 상태이기 때문에 찾기 대화상자로 포커스만 넘어갈 뿐 바꾸기 대화상자는 나타나지 않는다. 찾기 대화상자를 닫고 바꾸기를 다시 선택해야만 하며 반대의 경우도 마찬가지이다.

이렇게 되는 이유는 두 대화상자를 관리하는 핸들이 g_FindDlg 하나밖에 없기 때문인데 그렇다고 핸들을 각각 따로 주면 두 대화상자가 동시에 열리게 되어 오히려 어색해진다. 이 문제를 깔끔하게 해결하려면 하나의 핸들로 두 대화상자를 관리하되 대화상자가 떠 있는 상태에서 다른 대화상자를 또 띄울 경우 대화상자를 바꾸는 것이 좋을 것 같다. 즉 찾기 대화상자가 떠 있는 상태에서 바꾸기 명령을 내리면 찾기 대화상자를 닫고 바꾸기 대화상자를 다시 열어주는 것이다.

이런 경우는 현실적으로 발생 빈도가 극히 낮으며 잘 목격되지도 않지만 보기에 좋지 않으므로 별도의 처리를 하도록 하자. 검색 명령 처리코드에 있는 SetFocus를 삭제하고 다음 코드를 써 넣는다.

 

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

{

     ....

     case IDM_SEARCH_FIND:

          if (!IsWindow(g_FindDlg)) {

              g_FindDlg=CreateDialog(g_hInst,MAKEINTRESOURCE(IDD_FIND),hWnd,FindDlgProc);

              ShowWindow(g_FindDlg,SW_SHOW);

          } else {

           if (GetDlgItem(g_FindDlg,IDC_FIND_TO)) {

               SendMessage(g_FindDlg,WM_COMMAND,MAKEWPARAM(IDCANCEL,0),0);

               SendMessage(hWnd,WM_COMMAND,MAKEWPARAM(IDM_SEARCH_FIND,0),0);

           } else {

               SetFocus(g_FindDlg);

           }

          }

          break;

     case IDM_SEARCH_REPLACE:

          if (!IsWindow(g_FindDlg)) {

              g_FindDlg=CreateDialog (g_hInst,MAKEINTRESOURCE(IDD_REPLACE),hWnd,FindDlgProc);

              ShowWindow(g_FindDlg,SW_SHOW);

          } else {

           if (GetDlgItem(g_FindDlg,IDC_FIND_TO)==NULL) {

               SendMessage(g_FindDlg,WM_COMMAND,MAKEWPARAM(IDCANCEL,0),0);

               SendMessage(hWnd,WM_COMMAND,MAKEWPARAM(IDM_SEARCH_REPLACE,0),0);

           } else {

               SetFocus(g_FindDlg);

           }

          }

          break;

 

찾기 명령을 선택하면 먼저 g_FindDlg 핸들이 유효한지 검사하여 모델리스 대화상자가 떠 있는지 조사한다. 만약 이미 떠 있으면 이 대화상자가 찾기 상태인지, 바꾸기 상태인지를 점검해보는데 점검하는 방법은 IDC_FIND_TO 콤보박스(찾을 내용)가 있는지 보면 된다. 이 콤보박스는 바꾸기 대화상자에만 있으므로 GetDlgItem이 콤보박스의 핸들을 리턴한다면 지금 바꾸기 대화상자가 떠 있는 상태이다.

이때는 이미 떠 있는 바꾸기 대화상자를 일단 닫고 찾기 대화상자를 다시 띄운다. 실행중에 대화상자의 템플리트를 바꿀 수 있는 방법이 있다면 좋겠으나 그런 방법은 없으므로 아예 종료하고 새로 대화상자를 만들어야 한다. 이때 DestroyWindow 함수로 직접 대화상자를 파괴하지 말고 반드시 IDCANCEL 메시지를 보내 스스로 뒷정리를 하도록 해야 한다. 그렇지 않으면 선택해놓은 옵션들을 저장할 기회를 갖지 못한다. 만약 같은 종류의 대화상자가 이미 떠 있다면 포커스만 넘긴다.

반대의 경우 즉, 찾기 대화상자가 떠 있는 상태에서 바꾸기 명령을 선택하면 동일한 방법으로 처리하면 된다. 이때는 IDC_FIND_TO 콤보박스가 없는지를 봐야할 것이다. 순간적으로 대화상자를 닫았다가 다시 열기 때문에 번쩍거릴 것 같지만 직접 실행해보면 거의 느낄 수 없다.