notepad2 컴파일 삽질기 부록#5 : context-menu 통합 및 수정 (#1, #2 통합)

구차니님께서 수고해주신 덕분에 context 메뉴(오른쪽 버튼 클릭 메뉴)를 통해 Notepad2를 사용할 수 있었다.
(삽질기 부록#1 : context-menu 추가삽질기 부록#2 : context-menu 추가 업그레이드 참조)

그런데, Notepad2 3.1.21 정식버전에서는 이 수정을 미묘하게 바꿔야 했으며, okto님의 수정요청도 받아들여 수정한 것도 있어 전체를 통합한 수정방법을 포스팅한다.
(File 메뉴에서 context-menu 관련 체크박스 2개가 동시에 체크되지 않도록 수정)


삽질기 1~3을 모두 적용했다고 가정하고 시작함.

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


1. resource.h

다음 두 줄을 추가한다.
#define IDM_REGISTRY_UNKNOWN            40690
#define IDM_REGISTRY_ALL                40691


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.h

새로운 함수 하나를 추가한다.
void CheckRegistry();


4. Notepad2.c

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


다음, LRESULT CALLBACK MainWndProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam)에서 아래 내용을 찾는다.
case WM_COMMAND:
  return MsgCommand(hwnd,wParam,lParam);
여기에 아래와 같이 한 줄을 추가한다.
case WM_COMMAND:
  CheckRegistry();
  return MsgCommand(hwnd,wParam,lParam);


다음, 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",&key1);
if (res == ERROR_SUCCESS)
{
WCHAR cmd[] = L"Open with &notepad2";
RegSetValue(key1, NULL, REG_SZ, cmd, wcslen(cmd));
}
RegCloseKey(key1);

  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);
}
RegCloseKey(key1);

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");
bRegistryUnknownType = FALSE;
}

}
bRegistryAllType = !bRegistryAllType;
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",&key1);
if (res == ERROR_SUCCESS)
{
WCHAR cmd[] = L"Open with &notepad2";
RegSetValue(key1, NULL, REG_SZ, cmd, wcslen(cmd));
}
RegCloseKey(key1);

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);
}
RegCloseKey(key1);
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");
bRegistryAllType = FALSE;
}

}
bRegistryUnknownType = !bRegistryUnknownType;
break;


마지막으로 함수를 하나 추가한다.
void CheckRegistry()
{
    HKEY key;
    LONG res;

    res = RegOpenKey(HKEY_CLASSES_ROOT,L"*\\shell\\Open with notepad2",&key);
    if(res == ERROR_SUCCESS)
            bRegistryAllType = TRUE;
    else    bRegistryAllType = FALSE;
    RegCloseKey(key);

    res = RegOpenKey(HKEY_CLASSES_ROOT,L"unknown\\shell\\Open with notepad2",&key);
    if(res == ERROR_SUCCESS)
            bRegistryUnknownType = TRUE;
    else    bRegistryUnknownType = FALSE;
    RegCloseKey(key);
}

이렇게 수정하면 아래처럼 File 메뉴에서 context-menu 관련 기능을 사용할 수 있다.

사용자 삽입 이미지

두 개의 context-menu중 하나만 선택되도록 수정했음. ^^;