. 탐색기 연결

일반 페이지의 bExplorerPopup 옵션은 탐색기의 팝업메뉴에 Dangeun으로 편집 항목을 표시할 것인가 아닌가를 지정한다. 이 옵션이 설정되어 있으면 탐색기에서 편집파일을 선택한 후 곧바로 Dangeun을 호출할 수 있어 문서 중심의 편집을 할 수 있다. 편집기를 실행해놓고 편집할 파일을 여는 것이 아니라 파일을 먼저 선택해놓고 편집기를 고를 수 있으며 사용자 행위를 중심으로 하는 아주 훌륭한 방법이다.

탐색기의 팝업메뉴에 대한 설정은 레지스트리에 저장되며 각각의 확장자에 대해 팝업메뉴를 붙일 수 있다. 레지스트리의 약속된 위치에 키를 생성해놓으면 탐색기는 팝업메뉴를 열 때 이 값을 참조하여 팝업메뉴에 항목을 추가한다. 다음 함수는 모든 종류의 파일에 대해 팝업메뉴를 붙이거나 제거한다. Dangeun.cpp에 이 함수를 작성한다.

 

void RegisterPopup(BOOL bReg)

{

     TCHAR Path[MAX_PATH];

 

     GetModuleFileName(g_hInst,Path,MAX_PATH);

     lstrcat(Path, " \"%1\"");

     if (bReg) {

          SHRegWriteString(SHCR,"*\\shell\\Dangeun으로 편집\\Command",NULL,Path);

     } else {

          SHDeleteKey(SHCR,"*\\shell\\Dangeun으로 편집");

     }

}

 

코드 내용을 보면 알겠지만 HKEY_CURRENT_USER *서브키에 shell\Dangeun으로 편집 서브키를 작성해놓으면 * 확장자, 즉 모든 확장자에 대해 이 팝업메뉴를 보여준다. 이 메뉴가 선택되면 Command 서브키에 기록된 실행파일을 실행하되 인수로 선택 파일의 경로를 넘겨 주도록 되어 있다. 예를 들어 ReadMe.txt 파일에서 Dangeun으로 편집을 선택하면 Dangeun.exe ReadMe.txt가 실행된다. 긴 이름을 지원하기 위해 인수는 반드시 따옴표로 묶어야 한다.

팝업메뉴의 항목을 삭제할 때는 레지스트리의 서브키를 삭제하면 된다. 이 코드에서 사용된 SHDeleteKey 함수는 하위 항목까지 한꺼번에 삭제한다. RegDeleteKey 함수는 98이하에서는 하위 항목을 지워주지만 2000에서는 그렇지 않으므로 재귀 호출을 사용해야만 하위 항목을 지울 수 있는데 비해 이 함수는 운영체제 버전에 상관없이 하위 항목을 삭제한다. 이 함수를 쓰기 위해서는 Shlwapi.h를 인클루드해야 하며 Shlwapi.lib를 연결해야 하는데 이 작업은 Dangeun1을 만들 때 이미 다 해놓았다.

ApplyNow에서는 bExplorerPopup 옵션값이 변경될 때 이 함수를 호출하여 팝업메뉴를 설치하거나 제거한다. 이 옵션은 ApiEdit와는 상관이 없으므로 while 루프 바깥에서 적용해야 한다.

 

void ApplyNow()

{

     HWND hChild;

     SInfo *pSi;

     HDC hdc;

     LOGFONT tFont;

 

    if (Option.bExplorerPopup != NewOption.bExplorerPopup) {

        RegisterPopup(NewOption.bExplorerPopup);

    }

     ....

 

설정 대화상자에서 이 옵션을 선택한 후 탐색기를 확인해보면 당장 팝업메뉴에 당근 항목이 나타날 것이다.

이 메뉴를 선택하면 당근이 실행된다. 하지만 아직까지 편집 대상 파일을 인수로 전달받는 기능을 작성하지 않았기 때문에 파일은 열리지 않는데 이 기능은 잠시 후에 작성하도록 하자. 이 옵션에 의해 레지스트리에 기록되는 값은 Dangeun.exe의 절대경로다. 이 프로그램은 설치를 필요로 하지 않는 단독 실행파일이므로 어떤 위치로나 자유롭게 옮겨서 실행할 수 있으며 또한 흔한 경우는 아니지만 사용자에 의해 실행파일의 이름이 Baechoo.exe Muoo.exe로 바뀔 수도 있다.

그래서 RegisterPopup에서 한 번 등록해놓은 절대경로가 항상 정확하다고 보장할 수 없으므로 매 실행시마다 실제 경로로 변경하도록 한다. OnCreate에 다음 코드를 작성하도록 하자.

 

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

{

     ....

     if (SHRegReadInt(SHCU,KEY"Setting","StartAction",1000) == 1000) {

     } else {

          Option.Load(KEY);

        if (Option.bExplorerPopup) {

           RegisterPopup(TRUE);

        }

     }

     ....

 

레지스트리에서 설정상태를 읽어온 직후에 bExplorerPopup 옵션이 선택되어 있으면 자신의 경로를 갱신하도록 하였다. 이렇게 하면 위치를 옮기거나 이름을 바꾸더라도 한 번만 실행하면 레지스트리의 정보가 갱신되어 탐색기가 항상 당근을(이름이 뭘로 바뀌었든지) 제대로 찾을 수 있다. 탐색기의 팝업메뉴에 응용 프로그램의 메뉴를 추가하려면 원칙적으로 탐색기와 통신할 수 있는 COM 개체를 만들어야 한다. COM 개체는 선택된 파일에 따라 다른 팝업 항목을 만들 수 있으며 메뉴의 캡션을 실시간으로 결정할 수 있는 등 여러 가지 장점이 있다.

하지만 COM 개체는 분리된 DLL이어야 한다는 것이 부담스럽고 이 예제의 경우 모든 파일에 대해 팝업메뉴를 선택할 수 있으며 메뉴의 캡션이 고정되어 있으므로 좀 더 간단한 방법을 사용하였다. 탐색기와의 연결을 완료하려면 탐색기가 전달하는 인수로부터 편집할 파일명을 추출해 내고 그 파일을 즉시 열어야 한다. 초기화 완료 시점인 OnTimer에서 명령행 인수를 조사하면 된다.

 

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

{

     int i;

     HWND hChild;

     TCHAR szKey[16];

     int nEditing;

     TCHAR Path[MAX_PATH];

 

     switch (wParam) {

     case 100:

          KillTimer(hWnd,100);

        if (__argc > 1) {

           OpenFromFile(__argv[1]);

           break;

        }

 

          switch (Option.StartAction)

          ....

 

명령행 인수가 전달되었으면 OpenFromFile 함수로 이 파일을 열어 주었다. 인수로 전달된 파일을 열 때는 이 파일을 당장 열라는 명시적인 명령을 받았으므로 StartAction을 처리하지 않는다. 이제 탐색기에서 편집 대상을 먼저 고르고 당근을 실행할 수 있게 되었다. 탐색기가 당근이 설치된 경로를 찾아 실행하고 편집할 파일을 인수로 알려주며 당근은 인수로 전달된 파일을 열 수 있다.

차후에 확장자 연결 기능을 구현하면 이 코드가 또 사용된다. 자주 사용하는 특정 확장자의 파일을 Dangeun.exe와 연결해놓으면 탐색기에서 파일을 더블클릭하기만 해도 곧바로 이 파일을 편집할 수 있다. 예를 들어 txt 확장자의 편집 프로그램을 Dangeun.exe로 설정하면 텍스트 파일을 더블클릭할 때 메모장 대신 당근이 실행될 수도 있다. 이 기능은 1.0스팩에는 포함되어 있지 않지만 언젠가는 구현할 것이며 그 준비를 여기서 미리 해놓은 셈이다.