. 탭의 메시지 처리

파일탭은 편집중인 파일의 목록을 보여주는 장치이기도 하지만 편집할 문서를 선택하는 장치이기도 하다. 사용자가 탭을 누를 때 이 탭과 대응되는 문서를 찾아 활성창을 바꿔야 한다. 탭 프레임 프로시저에 다음 코드를 작성한다.

 

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

{

     ....

     LPNMHDR hdr;

     int idx;

     TCITEM tie;

     HWND hChild;

 

     switch(iMessage) {

     ....

     case WM_NOTIFY:

          hdr=(LPNMHDR)lParam;

          switch (hdr->code) {

          case TCN_SELCHANGE:

              idx=TabCtrl_GetCurSel(hFileTab);

              tie.mask=TCIF_PARAM;

              TabCtrl_GetItem(hFileTab,idx,&tie);

              hChild=FindChildWithFile((TCHAR *)tie.lParam);

              SendMessage(g_hMDIClient,WM_MDIACTIVATE,(WPARAM)hChild,0);

              break;

          }

          return 0;

 

탭의 선택 상태가 바뀌면 TCN_SELCHANGE 통지 메시지가 전달된다. 이때 선택된 탭의 사용자 데이터(lParam)에 저장된 완전 경로를 꺼내 FindChildWithFile 함수로 이 파일을 편집하고 있는 창을 찾아 활성화시켰다. 탭과 대응되는 문서가 정확하게 활성화될 것이다.

탭을 선택하면 활성창이 바뀌는데 반대의 경우도 똑같이 처리해야 한다. 즉 활성창이 바뀌면 대응되는 탭을 선택해야 한다. 문서창이 포커스를 받았을 때 대응되는 탭의 인덱스를 찾아 선택하면 된다.

 

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

{

    int idx;

     ....

     case WM_SETFOCUS:

          pSi=(SInfo *)GetWindowLong(hWnd,0);

          SetFocus(pSi->Ae.hWnd);

          SetStatusText(0xffff);

        idx=FindFileTab(pSi->NowFile);

        TabCtrl_SetCurSel(hFileTab,idx);

          return 0;

 

탭에는 파일 이름과 함께 변경 여부를 표시하는 이미지가 표시되는데 이 이미지도 관리 대상이다. 파일의 변경 여부가 바뀌면 탭의 이미지도 바꿔야 한다. 사용자가 파일을 편집하면 이미지도 파란색에서 빨간색으로 바뀌어야 하며 실행취소에 의해 변경이 취소되면 빨간색이 다시 파란색으로 바뀌어야 한다. 이 이미지를 관리해야 할 시점은 상태란의 파트 3이 변경될 때와 완전히 동일하다. 그래서 상태란의 텍스트를 변경할 때 이미지도 같이 변경하면 된다.

 

void SetStatusText(int mask)

{

    TCITEM tie;

    int idx;

     ....

     if (mask & 8) {

        tie.mask=TCIF_IMAGE;

          if (pSi->Ae.GetModified()) {

              lstrcpy(Text,"편집되었음");

           tie.iImage=1;

          } else {

              lstrcpy(Text,"미편집");

           tie.iImage=0;

          }

          SendMessage(hStatus, SB_SETTEXT, 3, (LPARAM)Text);

        idx=FindFileTab(pSi->NowFile);

        if (idx!=-1) {

           TabCtrl_SetItem(hFileTab,idx,&tie);

        }

     }

 

텍스트는 그대로 두고 문서의 변경 여부에 따라 이미지만 바꿔 주었다. 위의 코드에서 idx -1인 경우는 절대로 없을 것 같지만 새 이름으로 저장할 때는 파일명이 먼저 바뀌고 변경플래그가 변경되기 때문에 일시적으로 탭의 정보와 파일명이 다를 수가 있다. 굳이 -1인 경우를 구분하지 않아도 되지만 조금이라도 불필요한 처리는 생략하는 것이 좋다.

SetStatusText 함수는 변경플래그에 변화가 있을 때마다 호출되므로 파일탭의 이미지를 바꿔 주기에는 최적의 장소임이 분명하다. 하지만 이 함수는 활성 창에 대해서만 통지 메시지를 받기 때문에 비활성창까지 한꺼번에 저장하는 모두 저장(SaveAll) 명령에 대해서는 파일탭의 이미지를 제대로 바꿔 주지 못한다. 모두 저장할 때는 각 파일이 저장될 때마다 파일탭의 이미지를 변경해야 한다. SaveToFile에 다음 코드를 작성한다.

 

BOOL SaveToFile(HWND hChild,TCHAR *Path)

{

     ....

    TCITEM tie;

    int idx;

 

     ....

    tie.mask=TCIF_IMAGE;

    idx=FindFileTab(Path);

    tie.iImage=0;

    TabCtrl_SetItem(hFileTab,idx,&tie);

 

     return TRUE;

}

 

이 함수는 파일을 저장하는 최종 함수이므로 여기서 파일탭의 이미지를 0번으로 바꾸면 모두 저장시 저장된 모든 파일의 이미지가 변경된다. 이후 자동저장 기능이 추가되더라도 더 이상 저장에 의한 이미지 관리는 할 필요가 없을 것이다.