. 프로젝트의 팝업메뉴

프로젝트는 파일창의 트리 뷰에 로컬 드라이브와 함께 나타나는데 두 개의 이질적인 노드가 같이 표시됨에도 전혀 어색하거나 동작상의 이상한 점이 거의 없다. DGFileProc 함수를 작성할 때는 프로젝트에 대해 전혀 고려하지 않았음에도 불구하고 프로젝트 지원을 위해 DGFileProc은 전혀 수정되지 않았다. 이렇게 되는 이유는 LoadProject 함수가 파일창에 프로젝트를 대신 등록하고 있고 GetNodePath 함수가 프로젝트 노드를 인식하도록 수정되었기 때문이다.

DGFileProc 함수 자체는 프로젝트 지원을 위한 여분의 코드가 거의 필요없고 더 추가해야 할 코드는 팝업메뉴 지원 코드뿐이다. 로컬 드라이브의 팝업메뉴와 프로젝트의 팝업메뉴는 조금 차이가 나는데 프로젝트에 이미 소속된 파일을 삭제한다거나 이름을 바꾸는 기능은 프로젝트 관리 대화상자에 있으므로 파일창에는 있을 필요가 없다. 대신 프로젝트를 닫거나 편집하는 명령이 필요하다.

팝업메뉴를 여는 위치에 따라 필요한 메뉴항목이 달라지며 리소스에는 두 벌의 팝업메뉴가 이미 작성되어 있다. 파일창 닫기나 살펴보기 모드 등의 명령은 두 메뉴가 공유한다. 팝업메뉴를 출력하는 WM_CONTEXTMENU가 수정되어야 하고 추가된 명령을 WM_COMMAND에서 처리해야 한다.

 

LRESULT CALLBACK DGFileProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)

{

     TVHITTESTINFO ht;

     ....

     case WM_CONTEXTMENU:

          POINT pt;

          hMenu=LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_POPUP));

 

          ht.pt.x=LOWORD(lParam);

          ht.pt.y=HIWORD(lParam);

          ScreenToClient(hWnd,&ht.pt);

          TreeView_HitTest(hFileTree,&ht);

          TreeView_SelectItem(hFileTree,ht.hItem);

 

          for (tNode=ht.hItem;tNode2=TreeView_GetParent(hFileTree,tNode);tNode=tNode2);

          TV.mask=TVIF_IMAGE;

          TV.hItem=tNode;

          TreeView_GetItem(hFileTree,&TV);

 

          if (TV.iImage == DGI_PROJECT) {

              hPopup=GetSubMenu(hMenu, 2);

          } else {

              hPopup=GetSubMenu(hMenu, 1);

               if (Option.bShowHidden) {

                   CheckMenuItem(hMenu, IDM_FILEWND_HIDDEN, MF_BYCOMMAND | MF_CHECKED);

              } else {

                   CheckMenuItem(hMenu, IDM_FILEWND_HIDDEN, MF_BYCOMMAND | MF_UNCHECKED);

              }

 

              if (TreeView_GetParent(hFileTree,ht.hItem)==NULL) {

                   EnableMenuItem(hMenu, IDM_FILEWND_DELETE, MF_BYCOMMAND | MF_GRAYED);

                   EnableMenuItem(hMenu, IDM_FILEWND_RENAME, MF_BYCOMMAND | MF_GRAYED);

              } else {

                   EnableMenuItem(hMenu, IDM_FILEWND_DELETE, MF_BYCOMMAND | MF_ENABLED);

                   EnableMenuItem(hMenu, IDM_FILEWND_RENAME, MF_BYCOMMAND | MF_ENABLED);

              }

          }

 

          if (LOWORD(lParam)==65535) {

              pt.x=20;

              pt.y=20;

              ClientToScreen(hWnd,&pt);

              lParam=MAKELPARAM(pt.x,pt.y);

          }

          if (Option.bBrowseMode) {

              CheckMenuItem(hPopup, IDM_FILEWND_BROWSE, MF_BYCOMMAND | MF_CHECKED);

          } else {

              CheckMenuItem(hPopup, IDM_FILEWND_BROWSE, MF_BYCOMMAND | MF_UNCHECKED);

          }

 

          TrackPopupMenu(hPopup, TPM_LEFTALIGN, LOWORD(lParam), HIWORD(lParam),

              0, hWnd, NULL);

          DestroyMenu(hMenu);

          return 0;

 

WM_CONTEXTMENU 메시지를 받았을 때 선택된 노드의 루트를 찾고 루트의 이미지 번호로 어떤 팝업메뉴를 보여줄 것인가를 결정한다. 루트가 프로젝트 노드이면 프로젝트 팝업메뉴를 보여주고 로컬 드라이브이면 기존의 팝업메뉴를 보여준다.

WM_COMMAND에서는 프로젝트 팝업메뉴에 추가된 메뉴항목을 처리한다.

 

LRESULT CALLBACK DGFileProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)

{

     case WM_COMMAND:

          switch (LOWORD(wParam)) {

          ....

          case IDM_PROJECT_EDIT:

              Node=TreeView_GetSelection(hFileTree);

              for (tNode=Node;tNode2=TreeView_GetParent(hFileTree,tNode);tNode=tNode2);

              TV.mask=TVIF_PARAM;

              TV.hItem=tNode;

              TreeView_GetItem(hFileTree,&TV);

              lstrcpy(Path,(TCHAR *)TV.lParam);

              DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_PROJECT),

                   g_hFrameWnd, DgProjectProc,(LPARAM)Path);

              break;

          case IDM_PROJECT_CLOSE:

              Node=TreeView_GetSelection(hFileTree);

              for (tNode=Node;tNode2=TreeView_GetParent(hFileTree,tNode);tNode=tNode2);

              TreeView_DeleteItem(hFileTree,tNode);

              break;

 

프로젝트 편집 명령이 선택되면 루트 노드의 lParam에 저장된 프로젝트 경로를 조사하여 프로젝트 관리 대화상자의 lParam으로 넘겨주면 된다. 프로젝트를 편집하고 프로젝트 파일을 갱신하는 모든 작업은 프로젝트 관리 대화상자가 알아서 하므로 이 함수는 단지 프로젝트 경로와 함께 대화상자를 띄워주기만 하면 된다.

프로젝트 닫기 명령이 선택되면 트리 뷰에서 프로젝트 노드를 제거하기만 하면 된다. 프로젝트를 닫는다는 것은 더 이상 이 프로젝트를 통해 파일을 열지 않겠다는 뜻이므로 파일창에서 사라지는 것이 곧 프로젝트를 닫는 것이다.