notepad2 컴파일 삽질기 부록#1 : context-menu 추가


나름 열심히 뜯어고친 Notepad2를 잘 쓰고 있었는데, 구차니님께서 소스 일부를 수정하셨습니다.
context-menu(마우스 오른쪽 버튼 클릭시 뜨는 메뉴)에 Notepad2를 손쉽게 등록할 수 있도록 수정해주셨는데, 수정 방법을 간략하게만 포스팅하셨더군요.

이왕 연재한 것이라 이 내용까지 포스팅하겠습니다.
삽질기 1~4를 모두 적용했다고 가정하고 시작합니다.

수정 대상파일은 resource.h, Notepad2.rc, Notepad2.c의 3개이며, 모두 src 폴더에 저장되어 있습니다.


1. resource.h

다음 두 줄을 추가합니다.
#define IDM_REGISTRY_UNKNOWN            40226
#define IDM_REGISTRY_ALL                40227


그리고, 아래 내용을 찾습니다.
#define _APS_NEXT_COMMAND_VALUE         40226
이 코드를 아래와 같이 수정합니다.
#define _APS_NEXT_COMMAND_VALUE         40228
resource.h 파일은 두 부분으로 나뉘는 모습인데, 앞의 두 줄은 앞부분에 삽입하면 됩니다.


2. Notepad2.rc

IDR_MAINWND MENU DISCARDABLE에서 아래 내용을 찾습니다.
MENUITEM "Propert&ies...",              IDM_FILE_PROPERTIES
MENUITEM "Create &Desktop Link",        IDM_FILE_CREATELINK
MENUITEM SEPARATOR
POPUP "&Favorites"
BEGIN
    MENUITEM "&Open Favorites...\tAlt+I",   IDM_FILE_OPENFAV
    MENUITEM "&Add Current File...\tAlt+K", IDM_FILE_ADDTOFAV
    MENUITEM "&Manage...\tF9",              IDM_FILE_MANAGEFAV
END
이 부분을 아래와 같이 수정합니다.
MENUITEM "Propert&ies...",              IDM_FILE_PROPERTIES
MENUITEM SEPARATOR
MENUITEM "Create &Desktop Link",        IDM_FILE_CREATELINK
MENUITEM "Add context-menu to all file type", IDM_REGISTRY_ALL
, CHECKED
MENUITEM "Add context-menu to unknown file type",
                                        IDM_REGISTRY_UNKNOWN
, CHECKED
MENUITEM SEPARATOR
POPUP "&Favorites"
BEGIN
    MENUITEM "&Open Favorites...\tAlt+I",   IDM_FILE_OPENFAV
    MENUITEM "&Add Current File...\tAlt+K", IDM_FILE_ADDTOFAV
    MENUITEM "&Manage...\tF9",              IDM_FILE_MANAGEFAV
END

구분자 하나와 context-menu에 관련된 두 줄을 추가하는 내용입니다.


3. Notepad2.c

파일 앞부분의 변수 선언부에 다음 내용을 추가합니다.
BOOL      bRegistryUnknownType;
BOOL      bRegistryAllType;


다음, void MsgInitMenu(HWND hwnd,WPARAM wParam,LPARAM lParam)에서 아래 내용을 찾습니다.
EnableCmd(hmenu,IDM_EDIT_SELTONEXT,i);
EnableCmd(hmenu,IDM_EDIT_SELTOPREV,i && lstrlenA(efrData.szFind));
EnableCmd(hmenu,IDM_EDIT_REPLACE,i /*&& !bReadOnly*/);

CheckCmd(hmenu,IDM_VIEW_USE2NDDEFAULT,Style_GetUse2ndDefault(hwndEdit));
이 부분을 아래와 같이 수정합니다. 2줄을 추가하는 것입니다.
EnableCmd(hmenu,IDM_EDIT_SELTONEXT,i);
EnableCmd(hmenu,IDM_EDIT_SELTOPREV,i && lstrlenA(efrData.szFind));
EnableCmd(hmenu,IDM_EDIT_REPLACE,i /*&& !bReadOnly*/);

CheckCmd(hmenu,IDM_REGISTRY_UNKNOWN,bRegistryUnknownType);
CheckCmd(hmenu,IDM_REGISTRY_ALL,bRegistryAllType);

CheckCmd(hmenu,IDM_VIEW_USE2NDDEFAULT,Style_GetUse2ndDefault(hwndEdit));


다음은 LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam)의 수정입니다.
이 함수는 전체가 하나의 switch-case 문으로 되어있는데, 이 case 중에 IDM_REGISTRY_ALL, IDM_REGISTRY_UNKNOWN 둘을 추가합니다.
case IDM_REGISTRY_ALL:
    // Register registry - type unknown
      if (bRegistryAllType)
      {
         //WinNT requires the key to have no subkeys
          RegDeleteKey(HKEY_CLASSES_ROOT, L"*\\shell\\Open with notepad2\\command");
          RegDeleteKey(HKEY_CLASSES_ROOT, L"*\\shell\\Open with notepad2");
      }
      else
      {
          HKEY key1;
          LONG res = RegCreateKey(HKEY_CLASSES_ROOT,
              L"*\\shell\\Open with notepad2\\command",
              &key1);
          if (res == ERROR_SUCCESS)
          {
              WCHAR cmd[MAX_PATH + 4];
            WCHAR path[MAX_PATH];
            int len;
            GetModuleFileName(GetModuleHandle(NULL), path, MAX_PATH);
              len = wsprintf(cmd, L"%s %%1", path);
              RegSetValue(key1, NULL, REG_SZ, cmd, len);
          }
      }       
    bRegistryAllType = (bRegistryAllType) ? FALSE : TRUE;
    break;

case IDM_REGISTRY_UNKNOWN:
    // Register registry - type all
    if (bRegistryUnknownType)
      {
         //WinNT requires the key to have no subkeys
          RegDeleteKey(HKEY_CLASSES_ROOT, L"Unknown\\shell\\Open with notepad2\\command");
          RegDeleteKey(HKEY_CLASSES_ROOT, L"Unknown\\shell\\Open with notepad2");
      }
      else
      {
          HKEY key1;
          LONG res = RegCreateKey(HKEY_CLASSES_ROOT,
              L"Unknown\\shell\\Open with notepad2\\command",
              &key1);
          if (res == ERROR_SUCCESS)
          {
              WCHAR cmd[MAX_PATH + 4];
            WCHAR path[MAX_PATH];
            int len;
            GetModuleFileName(GetModuleHandle(NULL), path, MAX_PATH);
              len = wsprintf(cmd, L"%s %%1", path);
              RegSetValue(key1, NULL, REG_SZ, cmd, len);
          }
      }
    bRegistryUnknownType = (bRegistryUnknownType) ? FALSE : TRUE;
    break;


다음은 LRESULT MsgNotify(HWND hwnd,WPARAM wParam,LPARAM lParam)의 수정입니다.
이 함수는 하나의 switch-case 문으로 되어있고, 각 case 내에 switch-case 문이 또 들어있는 구조입니다.
외부의 switch문인 switch(pnmh->idFrom)의 case 중에 IDM_REGISTRY_UNKNOWN, IDM_REGISTRY_ALL를 추가합니다.
case IDM_REGISTRY_UNKNOWN:
    // Register registry - type unknown
    break;

case IDM_REGISTRY_ALL:
    // Register registry - type all
    break;


다음은 void LoadSettings()의 수정입니다.
아래 내용을 찾습니다.
iPathNameFormat = IniSectionGetInt(pIniSection,L"PathNameFormat",0);
찾은 줄의 앞에 다음의 내용을 추가합니다. (앞의 내용을 삭제하면 안됩니다)
bRegistryUnknownType = IniSectionGetInt(pIniSection,L"RegistryUnknownType",0);
if (bRegistryUnknownType) bRegistryUnknownType = 1;

bRegistryAllType = IniSectionGetInt(pIniSection,L"RegistryAllType",0);
if (bRegistryAllType) bRegistryAllType = 1;


마지막으로 void SaveSettings(BOOL bSaveSettingsNow)를 수정합니다.
아래 내용을 찾습니다.
IniSectionSetInt(pIniSection,L"PathNameFormat",iPathNameFormat);
찾은 줄의 앞에 다음 2줄을 추가합니다. (이번에도 추가입니다)
IniSectionSetInt(pIniSection,L"RegistryUnknownType",bRegistryUnknownType);
IniSectionSetInt(pIniSection,L"RegistryAllType",bRegistryAllType);

수정을 완료하면 아래와 같은 모양을 볼 수 있습니다.

사용자 삽입 이미지

짜잔~~~~~~~~~



Trackback 3 Comment 7
  1. Favicon of http://oktoya.net BlogIcon okto 2008.12.29 11:16 address edit & delete reply

    오오... 드뎌 컨텍스트메뉴까지 아우르시는 건가요?
    역시 대단하십니다요 두분...
    한글화는 번개같이 해놓도록 하지요8D

  2. Favicon of http://www.soondesign.co.kr BlogIcon 이정일 2008.12.29 11:35 address edit & delete reply

    여러분들의 노고에 박수를 보냅니다.
    :P:P:P

    • Favicon of http://zockr.tistory.com BlogIcon BLUEnLIVE 2008.12.29 20:59 address edit & delete

      전 그저 밥숟갈을... (응?)

  3. Favicon of http://oktoya.net BlogIcon okto 2008.12.30 22:22 address edit & delete reply

    결혼 기념일 축하드립니다~~~~

    • Favicon of http://zockr.tistory.com BlogIcon BLUEnLIVE 2008.12.30 23:17 address edit & delete

      고마울 뿐이라능~

  4. Favicon of http://minimonk.tistory.com BlogIcon 구차니 2008.12.31 00:44 address edit & delete reply

    우와 초스피드 포스팅이시네요 ^^;
    MsgNotify() 부분에 대해서는 굳이 안 넣어도 되는지 몰라서 그냥 그 부분만 만들어 놓고 확인을 안해 봤습니다. 아무래도 MsgNotify() 쪽에서는 아무런 코드가 없기 때문에 굳이 넣지 않아도 될꺼라고 생각이 됩니다.

    그리고 ini파일이 저장되는 시점이 종료시에 저장이 되기 때문에, 메모장2를 하나 실행하고 레지스트리 관련 설정을 바꾸고 나서 다른 메모장2를 실행하면 설정사항이 저장이 되지 않는 문제점이 발견되었습니다. 이 부분에 대해서는 조금 고려를 해봐야 할 것 같더라구요.

    제가 컴파일 하면 용량이 매우 크고 한글화가 안되어 있어서 BLUEnLIVE님께 떠밀은건데 실패인가요 ㅋㅋ(okto님을 소환해서 더블 어택을 해야겠습니다 ㅋㅋ)

    덧 : 테스트 해보니 MsgNotify()에는 전혀 루틴을 타지 않습니다. 그 부분은 삭제 하셔도 무방합니다.

    • Favicon of http://zockr.tistory.com BlogIcon BLUEnLIVE 2008.12.29 00:29 address edit & delete

      1. 이 부분은 ini에서 읽기 보다는 레지스트리에서 직접 읽는 것이 어떨까 합니다.

      2. 한글화는 원래 저도 okto님께 떠밀었습니다. ^^;;;
      컴파일 완료된 버전을 okto님께 보내드리겠습니다.
      답을 주시겠죠. ^^;;;