본문 바로가기
C & C++/MFC 컨트롤

[Tab] 탭 컨트롤러 만들기

by izen8 2011. 3. 29.
반응형

 

1. 대화상자를 이용한 탭컨틀롤 사용을 알아보자.

 

2. 3개의 탭을 만들고 각각 대화상자를 붙여본다.

 

3. 3개의 대화상자를 모델리스형으로 만든다.

   각각 CDlgTab1, CDlgTab2, CDlgTab3라고 하자.

 

4. 각각의 대화상자의 "Styles" 옵션중 "Style"은 "Child"로 "Border"는 "None"으로 "Tile Bar"는 언체크 한다.

 

5. 3개의 모델리스를 CMainFrame에 다음과 같이 선언하고

   CDlgTab1  *m_pDlgTab1;
   CDlgTab2  *m_pDlgTab2;
   CDlgTab3  *m_pDlgTab3;

   * 생성자NULL값으로 초기화 해주는 거와 소멸자에세 NULL이 아니면 delete해주는 거 있지 말자.

 

6. 탭컨트롤에 탭만들기. 이때 탭컨트롤 변수를 m_ctrTab라고 하자.

 

   TCITEM   item;
   item.mask  = TCIF_TEXT;
   item.pszText = "탭1";
   m_ctrTab.InsertItem(0, &item);   // 첫번째 탭 생성
   item.pszText = "탭2";
   m_ctrTab.InsertItem(1, &item);     // 두번째 탭 생성
   item.pszText = "탭3";
   m_ctrTab.InsertItem(2, &item);    // 세번째 탭 생성

 

7. 각 탭에 붙여질 모델리스 만들기

 

   // 일단 CMainFrame을 찾는다.

   CMainFrame *pFrame = (CMainFrame*) AfxGetMainWnd();

   CRect  rect;

   // 첫번째 모델리스 생성

   pFrame->m_pDlgTab1 = new CDlgTab1;
   pFrame->m_pDlgTab1->Create(&m_ctrTab);
   pFrame->m_pDlgTab1->GetWindowRect(&rect);
   pFrame->m_pDlgTab1->MoveWindow(5,25, rect.Width(), rect.Height());

                                                     // 탭의 모양에 따라 모델리스를 위치 시킨다.
   pFrame->m_pDlgTab1->ShowWindow(SW_HIDE);

   // 두번째 모델리스 생성
   pFrame->m_pDlgTab2 = new CDlgTab2;
   pFrame->m_pDlgTab2->Create(&m_ctrTab);
   pFrame->m_pDlgTab2->GetWindowRect(&rect);
   pFrame->m_pDlgTab2->MoveWindow(5,25, rect.Width(), rect.Height());
   pFrame->m_pDlgTab2->ShowWindow(SW_HIDE);
   // 세번째 모델리스 생성

   pFrame->m_pDlgTab3 = new CDlgTab3;
   pFrame->m_pDlgTab3->Create(&m_ctrTab);
   pFrame->m_pDlgTab3->GetWindowRect(&rect);
   pFrame->m_pDlgTab3->MoveWindow(5,25, rect.Width(), rect.Height());
   pFrame->m_pDlgTab3->ShowWindow(SW_HIDE);

8. 기본적으로 선택될 탭 설정과 탭에 보여줘야 할 모델리스 표시

 

   // 기본적으로 선택될 탭 설정
   m_ctrTab.SetCurSel(0);


   // 선택된 탭에서 보여줄 대화상자 표시

   pFrame->m_pDlgTab1->ShowWindow(SW_SHOW);

 

9. 탭 클릭에 따른 모델리스 표시 전환

 

   // 탭이 변경 되는 중에 발생되는 메세지. TCN_SELCHANGING

   int   nTab = m_ctrTab.GetCurSel(); // 변경되기 전에 선택된 탭 번호

 

   CMainFrame *pFrame = (CMainFrame*) AfxGetMainWnd();
   switch(nTab)
   {
   case 0:
      pFrame->m_pDlgTab1->ShowWindow(SW_HIDE);
      break;
   case 1:
      pFrame->m_pDlgTab2->ShowWindow(SW_HIDE);
      break;
   case 2:
      pFrame->m_pDlgTab3->ShowWindow(SW_HIDE);
      break;
   }

 

   // 탭이 변경 되고 난 후에 발생되는 메세지. TCN_SELCHANGE

   int   nTab = m_ctrTab.GetCurSel(); // 변경되고 난후에 선택된 탭 번호
 
   CMainFrame *pFrame = (CMainFrame*) AfxGetMainWnd();
   switch(nTab)
   {
   case 0:
      pFrame->m_pDlgTab1->ShowWindow(SW_SHOW);
      break;
   case 1:
      pFrame->m_pDlgTab2->ShowWindow(SW_SHOW);
      break;
   case 2:
      pFrame->m_pDlgTab3->ShowWindow(SW_SHOW);
      break;
   }

 

   * 탭변경전에 기존 모델리스를 감추고 탭변경후 변경된 위치의 모델리스를 표시하면 된다.

////////////////////////////////////////////////////////////////////////////////
탭에 색상입히기

void MyTabCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    int select_index = lpDrawItemStruct->itemID;
    if(select_index < 0) return;
 
    CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
    CRect rect = lpDrawItemStruct->rcItem;
    
    // Tab이 그려진 테두리의 두께만큼 위치를 보정한다.
    rect.top += ::GetSystemMetrics(SM_CYEDGE);
 
    pDC->SetBkMode(TRANSPARENT);
 
    char tab_text[40];
 
    TC_ITEM data;
    data.mask = TCIF_TEXT|TCIF_IMAGE;
    data.pszText = tab_text;
    data.cchTextMax = 39;
 
    // 탭이 선택된 정보에 따라 배경색을 칠해준다.
    if(select_index == GetCurSel()) pDC->FillSolidRect(rect, m_select_border_color);
    else pDC->FillSolidRect(rect, m_unselect_border_color);
 
    // 선택된 탭의 정보를 얻는다.
    if(!GetItem(select_index, &data)) return;
 
    // 이미지를 출력한다.
    CImageList *p_image_list = GetImageList();
    if(p_image_list != NULL && data.iImage >= 0) {
        rect.left += pDC->GetTextExtent(" ").cx;
 
        IMAGEINFO image_info;
        p_image_list->GetImageInfo(data.iImage, &image_info);
        CRect image_rect(image_info.rcImage);
 
        p_image_list->Draw(pDC, data.iImage, CPoint(rect.left, rect.top), ILD_TRANSPARENT);
        rect.left += image_rect.Width();
    }
 
    CFont *p_old_font = NULL;
    if(m_user_flag == 1) p_old_font = pDC->SelectObject(mp_user_font);
    else p_old_font = pDC->SelectObject(GetFont());
 
    if(select_index == GetCurSel()){
        // 선택된 탭이라면...
        pDC->SetTextColor(m_select_text_color);
        // 텍스트의 위치를 보정하여 선택된 느낌이 강조되도록 만든다.
        rect.top -= ::GetSystemMetrics(SM_CYEDGE);
        pDC->DrawText(tab_text, rect, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
    } else {
        // 선택되지 않은 탭이라면...
        pDC->SetTextColor(m_unselect_text_color);
        pDC->DrawText(tab_text, rect, DT_SINGLELINE | DT_BOTTOM | DT_CENTER);
    }
 
    pDC->SelectObject(p_old_font);
}
 
================================================================================

BOOL MyTabCtrl::OnEraseBkgnd(CDC* pDC)
{
    BOOL ret = CTabCtrl::OnEraseBkgnd(pDC);
 
    CRect bk_rect;
    GetClientRect(bk_rect);
 
    // 탭의 높이를 제외한 영역만큼 색상을 칠한다.
    bk_rect.top += 20;
 
    pDC->FillSolidRect(bk_rect, m_select_border_color);
 
    return ret;
}


반응형

댓글