Click here to Skip to main content
Click here to Skip to main content

CCustomTabCtrl - MFC Tab Control

, 17 May 2006
Rate this:
Please Sign up or sign in to vote.
An MFC tab control - a clone of the Excel tab sheet control.

Introduction

CCustomTabCtrl is an MFC control derived from the CWnd class. You can find a similar control in Microsoft Management Console Services used to switch between extended and standard views. CCustomTabCtrl can be created in one orientation only - bottom. XP Themes scroll buttons are supported if the operating system is WinXP and XP Themes are enabled. CCustomTabCtrl control also works properly if the state of XP Themes enabling is changed during the running of the application.

Using the code in dialog applications

Using the CCustomTabCtrl class is very simple. To add it to your project, please follow the steps given below:

  1. Add ThemeUtil.h, ThemeUtil.cpp, CustomTabCtrl.h, CustomTabCtrl.cpp, Tmschema.h and Schemadef.h to your project.
  2. Include CustomTabCtrl.h in the appropriate header file - usually dialog class header where the class CCustomTabCtrl is used:
    //CustomTabCtrlDemoDlg.h : header file
    #include "CustomTabCtrl.h"
  3. Declare m_ctrlTab object of type CCustomTabCtrl in your dialog header:
    //CustomTabCtrlDemoDlg.h : header file
    class CCustomTabCtrlDemoDlg : CDialog
    {
        ......
    private:
        CCustomTabCtrl m_ctrlTab;
    };
  4. Create the control:
    1. Dynamically by calling Create.

      In your dialog's OnInitDialog, add the following code:

      //CustomTabCtrlDemoDlg.cpp : definition file
      m_ctrlTab.Create(WS_VISIBLE|WS_CHILD, 
                      CRect(0,0,100,20), this, 1);
    2. Via a dialog template.

      Create a custom control in the dialog resource and then in the control's properties, specify the class name as "CCustomTabCtrl":

      To link up m_ctrlTab with the control, add the following in your dialog's DoDataExchange:

      //  CustomTabCtrlDemoDlg.cpp : definition file
      void CCustomTabCtrlDemoDlg::DoDataExchange(CDataExchange* pDX)
      {
         CDialog::DoDataExchange(pDX);
         //{{AFX_DATA_MAP(CCustomTabCtrlDemoDlg)
         DDX_Control(pDX, IDC_TAB, m_ctrlTab);
         //}}AFX_DATA_MAP
      }
  5. After creating the tab control, add as many tabs as you need.

    To add tab items, call InsertItem in your dialog's OnInitDialog:

    //CustomTabCtrlDemoDlg.cpp : definition file
    m_ctrlTab.InsertItem(0,"SS_BLACKRECT");
    m_ctrlTab.InsertItem(1,"SS_GRAY");
    m_ctrlTab.InsertItem(2,"SS_WHITERECT");
    m_ctrlTab.SetCurSel(0);
  6. Process WM_NOTIFY messages from the tab control in your dialog class.

    As the user clicks tab, the tab control (CCustomTabCtrl) sends notification messages (CTCN_SELCHANGE) to its parent window. Handle these messages if you want to do something in response. In the example shown below, I modify the style of the m_ctrlColor control (CStatic):

    //CustomTabCtrlDemoDlg.cpp : definition file
    BEGIN_MESSAGE_MAP(CCustomTabCtrlDemoDlg, CDialog)
    //{{AFX_MSG_MAP(CCustomTabCtrlDemoDlg)
    ON_NOTIFY(CTCN_SELCHANGE, IDC_TAB, OnSelchangeTab)
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    ....
    void CCustomTabCtrlDemoDlg::OnSelchangeTab(
       NMHDR* pNMHDR, LRESULT* pResult) 
    {
        switch(m_ctrlTab.GetCurSel())
        {
        case 0:  // Black rectangle
          m_ctrlColor.ModifyStyle(
           SS_BLACKRECT|SS_GRAYRECT|SS_WHITERECT,SS_BLACKRECT);
          break;
        case 1: // Gray rectangle
          m_ctrlColor.ModifyStyle(
           SS_BLACKRECT|SS_GRAYRECT|SS_WHITERECT,SS_GRAYRECT);
          break;
        default: // White rectangle
          m_ctrlColor.ModifyStyle(
           SS_BLACKRECT|SS_GRAYRECT|SS_WHITERECT,SS_WHITERECT);
          break;
        }
        m_ctrlColor.Invalidate();
        *pResult = 0;
    }
  7. Finally, move the tab control in the right place on the dialog:
    //  CustomTabCtrlDemoDlg.cpp : definition file
        
    void CCustomTabCtrlDemoDlg::OnSize(UINT nType, int cx, int cy) 
    {
       CDialog::OnSize(nType, cx, cy);
       if(m_ctrlTab.m_hWnd && cx && cy)
       {
           CRect r;
           m_ctrlTab.GetWindowRect(r);
           ScreenToClient(r);
           m_ctrlTab.MoveWindow(r.left,cy-r.Height()-
           r.left,cx-2*r.left,r.Height());
       }
    }

Using the code in SDI/MDI applications

Create a SDI/MDI project and follow the steps below:

  1. Add TabMDIFrameWnd.h and TabMDIFrameWnd.cpp to your MDI project, TabSDIFrameWnd.h and TabSDIFrameWnd.cpp to the SDI project.
  2. Replace CFrameWnd with CTabSDIFrameWnd and CMDIFrameWnd with CTabMDIFrameWnd in MainFrm.h and MainFrm.cpp files.
  3. Modify CMainFrame::OnCreate() like this:
    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {    
        ...
    
        if (!m_wndStatusBar.Create(this) || 
            !m_wndStatusBar.SetIndicators(indicators,
                               sizeof(indicators)/sizeof(UINT)))
        {
          TRACE0("Failed to create status bar\n");
          return -1;      // fail to create
        }
    
        
        if(!m_wndTab.Create(
            WS_CHILD|WS_VISIBLE|CTCS_FOURBUTTONS|CTCS_DRAGMOVE|
               CTCS_TOOLTIPS,CRect(0,0,0,m_nHeight),this,IDC_TABCTRL))
        {
          TRACE0("Failed to create tab control\n");
          return -1;
        }
    
        m_wndTab.SetDragCursors(AfxGetApp()->LoadCursor(
                                                IDC_CURSORMOVE),NULL);
        m_wndTab.SetItemTooltipText(CTCID_FIRSTBUTTON,"First");
        m_wndTab.SetItemTooltipText(CTCID_PREVBUTTON,"Prev");
        m_wndTab.SetItemTooltipText(CTCID_NEXTBUTTON,"Next");
        m_wndTab.SetItemTooltipText(CTCID_LASTBUTTON,"Last");
    
        m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
        ...
    }
  4. In the MDI project, add pMainFrame->AddView(sLabel,this,sTooltip) in CView::OnInitialUpdate(), pMainFrame->DeleteView(this) in CView::OnDestroy() and pMainFrame->OnActivateView(pActivateView) in CView::OnActivateView(). To edit a view, double click on the tab control item.
  5. In the SDI application, insert pMainFrame->AddView(sLabel,this,sTooltip) in CView::OnInitialUpdate() and pMainFrame->DeleteContents() in CDocument::DeleteContents(). To add, delete and edit a view, right click on the tab control and use a popup menu.

CCustomTabCtrl class members

Construction

CCustomTabCtrl Constructs a CCustomTabCtrl object.
Create Creates a tab control and attaches it to an instance of CCustomTabCtrl object.

Attributes

GetItemCount Retrieves the number of tabs in the tab control.
GetCurSel Determines the currently selected tab in a tab control.
SetCurSel Selects a tab in a tab control.
IsItemHighlighted Retrieves the highlight state of a tab item.
HighlightItem Sets the item's highlight state.
GetItemData Retrieves the application-specific value associated with an item.
SetItemData Sets the item's application-specific value.
GetItemText Retrieves the text of a tab item.
SetItemText Changes the text of a tab item.
GetItemRect Retrieves the rectangle of a tab item.
SetItemTooltipText Changes the tooltip text of a tab item.
SetDragCursors Sets the tab control's drag cursors.
ModifyStyle Modifies the tab control's styles.
SetControlFont Sets the tab control's current font.
GetDefaultFont Retrieves the reference to the default font's LOGFONT structure.

Operations

InsertItem Inserts a new tab in a tab control.
DeleteItem Removes an item from a tab control.
DeleteAllItems Removes all items from a tab control.
MoveItem Moves a tab item within the current tab control.
CopyItem Copies a tab item within the current tab control.
HitTest Determines which tab or button, if any, is at a specified screen position.
EditLabel Begins in-place editing of an item's text.

CCustomTabCtrl::CCustomTabCtrl

CCustomTabCtrl( );

Remarks

Call this function to construct a CCustomTabCtrlobject.

CCustomTabCtrl::Create

BOOL Create( DWORD dwStyle, const RECT& rect, 
                          CWnd* pParentWnd, UINT nID );

Return value

TRUE, if initialization of the object was successful; otherwise FALSE.

Parameters

  • dwStyle: Specifies the tab control's style. Apply any combination of tab control styles to the control.
  • rect: Specifies the tab control's size and position. It can be either a CRect object or a RECT structure.
  • pParentWnd: Specifies the tab control's parent window, usually a CDialog.
  • nID: Specifies the tab control's ID.

Remarks

In addition to the window styles like WS_CHILD, WS_VISIBLE, the following styles can be applied to a tab control:

  • CTCS_FIXEDWIDTH: Makes all tabs the same width.
  • CTCS_FOURBUTTONS: Creates a control with four buttons (First, Prev, Next, Last).
  • CTCS_AUTOHIDEBUTTONS: Auto hides the buttons. If not specified the buttons remain always on top.
  • CTCS_TOOLTIPS: The tab control has a ToolTip control associated with it.
  • CTCS_MULTIHIGHLIGHT: Multiple tabs can be selected by holding down the CTRL key when clicking.
  • CTCS_EDITLABELS: Allows the item text to be edited in place.
  • CTCS_DRAGMOVE: Item can be moved by holding the left mouse button down and dragging the cursor over the tab control.
  • CTCS_DRAGCOPY: Item can be copied by holding down the left mouse button and CTRL key, and dragging the cursor over the tab control.

CCustomTabCtrl::GetItemCount

int GetItemCount( ) const;

Return value

Number of items in the tab control.

Remarks

Call this function to retrieve the number of tabs in the tab control.

CCustomTabCtrl::GetCurSel

int GetCurSel( ) const;

Return value

Zero-based index of the selected tab if successful or – 1 if no tab is selected.

Remarks

Call this function to retrieve the currently selected tab in a tab control.

CCustomTabCtrl::SetCurSel

int SetCurSel( int nItem );

Return value

CTCERR_NOERROR if successful, otherwise CTCERR_ERRORCODE.

Parameters

nItem: The zero-based index of the item to be selected.

Remarks

Selects a tab in a tab control. A tab control does not send a CTCN_SELCHANGE notification message when a tab is selected using this function. These notifications are sent, using WM_NOTIFY, when the user clicks to change tabs.

CCustomTabCtrl::IsItemHighlighted

int IsItemHighlighted( int nItem );

Return value

1 if highlighted, 0 if not, otherwise CTCERR_ERRORCODE.

Parameters

nItem: Index of the tab item whose highlight state is to be retrieved.

Remarks

Retrieves the highlighted state of a tab item.

CCustomTabCtrl::HighlightItem

int HighlightItem( int nItem, BOOL fHighlight );

Return value

CTCERR_NOERROR if successful, otherwise CTCERR_ERRORCODE.

Parameters

nItem: Index of the tab item whose highlight state is to be set.

fHighlight: A highlight state to be set to the item.

Remarks

This function sets the highlight state to the item. A tab control does not send a CTCN_HIGHLIGHTCHANGE notification message when a tab is highlighted using this function. These notifications are sent, using WM_NOTIFY, when the user clicks to highlight tabs.

CCustomTabCtrl::GetItemData

int GetItemData( int nItem, DWORD& dwData ) const;

Return value

CTCERR_NOERROR if successful, otherwise CTCERR_ERRORCODE.

Parameters

nItem: Index of the tab item whose data is to be retrieved.

dwData: Reference to a DWORD variable that receives the 32-bit application-specific value associated with the specified item.

Remarks

This function retrieves the 32-bit application-specific value associated with the item specified by nItem.

CCustomTabCtrl::SetItemData

int SetItemData( int nItem, DWORD dwData );

Return value

CTCERR_NOERROR if successful, otherwise CTCERR_ERRORCODE.

Parameters

nItem: Index of the tab item whose data is to be set.

dwData: A 32-bit value to be associated with the item.

Remarks

This function sets the 32-bit application-specific value associated with the item specified by nItem.

CCustomTabCtrl::GetItemText

int GetItemText( int nItem, CString& sText );

Return value

CTCERR_NOERROR if successful, otherwise CTCERR_ERRORCODE.

Parameters

nItem: Index of the tab item whose text is to be retrieved.

sText: Reference to a CString object that receives the item's text.

Remarks

This function retrieves the text of a tab item.

CCustomTabCtrl::SetItemText

int SetItemText( int nItem, CString sText );

Return value

CTCERR_NOERROR if successful, otherwise CTCERR_ERRORCODE.

Parameters

nItem: Index of the tab item whose text is to be set.

sText: Pointer to a string object that contains the new item text.

Remarks

This function changes the text of a tab item.

CCustomTabCtrl::GetItemRect

int GetItemRect( int nItem, CRect& rect );

Return value

CTCERR_NOERROR if successful, otherwise CTCERR_ERRORCODE.

Parameters

nItem: Index of the tab item whose rectangle is to be retrieved.

rect: Reference to a CRect object that receives the item's rectangle.

Remarks

This function retrieves the rectangle of a tab item.

CCustomTabCtrl::SetItemTooltipText

int SetItemTooltipText( int nItem, CString sText );

Return value

CTCERR_NOERROR if successful, otherwise CTCERR_ERRORCODE.

Parameters

nItem - Zero-based index of the tab item whose tooltip text is to be set to one of these values:

  • CTCID_FIRSTBUTTON: ID of the first button.
  • CTCID_PREVBUTTON: ID of the previous button.
  • CTCID_NEXTBUTTON: ID of the next button.
  • CTCID_LASTBUTTON: ID of the last button.

sText: Pointer to a string object that contains the new item tooltip text.

Remarks

This function changes the tooltip text of a tab item.

CCustomTabCtrl::SetDragCursors

void SetDragCursors( HCURSOR hCursorMove, 
                         HCURSOR hCursorCopy );

Parameters

hCursorMove: Handle to the move cursor.

hCursorCopy: Handle to the copy cursor.

Remarks

Call this function to set the tab control's drag cursors.

CCustomTabCtrl::ModifyStyle

BOOL ModifyStyle( DWORD dwRemove, DWORD dwAdd, 
                                   UINT nFlags );

Return value

TRUE if successful, otherwise FALSE.

Remarks

For help, see CWnd::ModifyStyle(). Call this function to set the tab control's styles. (Don't use SetWindowLong() to modify CCustomTabCtrl styles.)

CCustomTabCtrl::SetControlFont

void SetControlFont( LOGFONTt& lf, BOOL fRedraw = FALSE );

Parameters

lf: Specifies the new font.

fRedraw: If TRUE, redraw the CCustomTabCtrl object.

Remarks

Sets the tab control's current font to the specified font.

CCustomTabCtrl::GetDefaultFont

static const LOGFONT& GetDafaultFont();

Return value

Reference to the default font's LOGFONT structure.

Remarks

Retrieves the reference to the default font's LOGFONT structure..

CCustomTabCtrl::InsertItem

int InsertItem( int nItem, CString sText, 
                          LPARAM lParam = 0 );

Return value

Zero-based index of the new tab if successful; otherwise CTCERR_ERRORCODE.

Parameters

nItem: Zero-based index of the new tab.

sText: Pointer to a string object that contains the new item text.

lParam: Application-defined data associated with the tab.

Remarks

Call this function to insert a new tab in an existing tab control.

CCustomTabCtrl::DeleteItem

int DeleteItem( int nItem );

Return value

CTCERR_NOERROR if successful, otherwise CTCERR_ERRORCODE.

Parameters

nItem - Zero-based value of the item to be deleted.

Remarks

Call this function to remove the specified item from a tab control.

CCustomTabCtrl::DeleteAllItems

void DeleteAllItems( );

Remarks

Call this function to remove all items from a tab control.

CCustomTabCtrl::MoveItem

int MoveItem(int nItemSrc, int nItemDst);

Return value

CTCERR_NOERROR if successful, otherwise CTCERR_ERRORCODE.

Parameters

nItemSrc: Zero-based index of the source item.

nItemDst: Zero-based index of the destination item.

Remarks

Moves a tab item within the current tab control. A tab control does not send a CTCN_ITEMMOVE notification message when a tab is moved using this function. These notifications are sent, using WM_NOTIFY, when the user uses a mouse to move items.

CCustomTabCtrl::CopyItem

int CopyItem(int nItemSrc, int nItemDst);

Return value

CTCERR_NOERROR if successful, otherwise CTCERR_ERRORCODE.

Parameters

nItemSrc: Zero-based index of the source item.

nItemDst: Zero-based index of the destination item.

Remarks

Copies a tab item within the current tab control. A tab control does not send a CTCN_ITEMCOPY notification message when a tab is copied using this function. These notifications are sent, using WM_NOTIFY, when the user uses a mouse to copy items.

CCustomTabCtrl::HitTest

int HitTest( CPoint pt);

Return value

The zero based index of the matching item or one of these values:

  • CTCHT_ONFIRSTBUTTON: The position is over the first button.
  • CTCHT_ONPREVBUTTON: The position is over the previous button.
  • CTCHT_ONNEXTBUTTON: The position is over the next button.
  • CTCHT_ONLASTBUTTON: The position is over the last button.
  • CTCHT_NOWHERE: The position is inside the tab control's client window, but it is not over either a tab item or a button.

Parameters

pt: Point to be tested in client coordinates.

Remarks

Determines which tab or button, if any, is at a specified screen position.

CCustomTabCtrl::EditLabel

int EditLabel( int nItem);

Return value

CTCERR_NOERROR if successful, otherwise CTCERR_ERRORCODE.

Parameters

nItem: Index of the tab item that is to be edited.

Remarks

Begins in-place editing of an item's text.

Notification Messages

The following notification codes are supported by the tab control:

  • CTCN_CLICK: User clicked the left mouse button in the control.
  • CTCN_RCLICK: User clicked the right mouse button in the control.
  • CTCN_SELCHANGE: User changed the current selection.
  • CTCN_HIGHLIGHTCHANGE: User changed the highlight state of the item.
  • CTCN_ITEMMOVE: User moved the item.
  • CTCN_ITEMCOPY: User copied the item.
  • CTCN_LABELUPDATE: User changed the item text.
  • CTCN_OUTOFMEMORY: Control could not complete an operation because there was not enough memory available.

The notifications shown above pass a pointer to the CTC_NMHDR structure that contains an NMHDR structure as its first member which is defined as shown below:

typedef struct _CTC_NMHDR 
{
   NMHDR hdr;
   int    nItem;
   TCHAR pszText[MAX_LABEL_TEXT];
   LPARAM lParam;
   RECT rItem;
   POINT ptHitTest;
   BOOL fSelected;
   BOOL fHighlighted;
}  CTC_NMHDR;

Error codes

The following errors can be returned by the tab control functions:

  • CTCERR_NOERROR: Operation successful.
  • CTCERR_OUTOFMEMORY: Function call failed because there was not enough memory available.
  • CTCERR_INDEXOUTOFRANGE: Function call failed because a tab item index was out of range.
  • CTCERR_NOEDITLABELSTYLE: Function call failed because CTCS_EDITLABELS style was not specified.
  • CTCERR_NOMULTIHIGHLIGHTSTYLE: Function call failed because CTCS_MULTIHIGHLIGHT style was not specified.
  • CTCERR_ITEMNOTSELECTED: Function call failed because an item was not selected.
  • CTCERR_ALREADYINEDITMODE: Function failed because the tab control was already in edit mode.
  • CTCERR_TEXTTOOLONG: Function failed because an item text was too long.
  • CTCERR_NOTOOLTIPSSTYLE: Function call failed because CTCS_TOOLTIPS style was not specified.
  • CTCERR_CREATETOOLTIPFAILED: Function call failed because the creation of tooltip control failed.

What's new

16th May, 2006

  • Vertical styles (left and right) added:

  • Remarks:
    • Label editing is not supported for vertical styles.
    • I use PlgBlt() for rotating bitmaps. This function is specific to NT and higher, and will not work on Windows95.

16th April, 2006

  • Buttons for specifying style added:

  • Bug fixes:
    • Fix for RTL.
    • Fix for incorrect handling of 'OnSize' in the dialog demo application.

25th March, 2006

  • A close button and a top style added:

  • Bug fixes:
    • Fix for incorrect recalculation of the tooltip rectangles when the tab item is deleted.
    • Fix for 'Alt-F4 click' when in edit mode.
    • Fix for incorrect handling of 'OnMouseMove' in the drag and drop mode.

10th Oct, 2005

  • SDI and MDI demo projects:

30th Jul, 2004

  • "First" and "Last" buttons:

  • Built-in tooltips for items and buttons:

  • Multi-highlighted items:

  • In-place editing:

  • Drag and drop for moving and coping items.
  • Auto-repeat buttons when held down.
  • Auto hide or always on top buttons.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Andrzej Markowski
Software Developer (Senior)
United States United States
No Biography provided

Comments and Discussions

 
Question"Add Button"? Pinmemberbosfan26-Sep-14 6:08 
QuestionTab Control Development Video PinmemberJack123sweet5-Apr-14 9:12 
Questioncannot compile with vs2010 Pinmemberlanmanck15-Aug-13 17:24 
AnswerRe: cannot compile with vs2010 Pinmemberbosfan20-Sep-13 4:51 
GeneralRe: cannot compile with vs2010 Pinmemberlanmanck7-Feb-14 22:10 
QuestionThe Thought Process PinmemberScott20080818-Feb-12 21:24 
GeneralMy vote of 5 PinmemberDanielm10315-Apr-11 15:19 
GeneralMy vote of 5 Pinmembermarslxj13-Sep-10 7:27 
QuestionCan we set child dialog into the tab pages? Pinmemberpresidentkevin14-May-10 20:43 
QuestionIs it Possible to select 2 tab at a Time ? PinmemberChetan Sheladiya5-Mar-10 1:59 
AnswerRe: Is it Possible to select 2 tab at a Time ? PinmemberAndrzej Markowski6-Mar-10 11:20 
Questionremove the "First, Prev, Next, Last" buttons PinmemberMember 114470222-Feb-10 4:40 
AnswerRe: remove the "First, Prev, Next, Last" buttons PinmemberAndrzej Markowski24-Feb-10 15:43 
GeneralUsing it in a Views that are in seperate DLLs PinmemberMember 305406010-Dec-09 7:22 
GeneralVC 6.0 MDI sample PinmemberVaclav_Sal4-Aug-09 22:44 
QuestionHow to navigate tab intems using a keyboard Pinmembermazhar_cse6-May-09 21:21 
AnswerRe: How to navigate tab intems using a keyboard Pinmembervarandas7924-Jan-11 7:40 
GeneralExample projects PinmemberGabor Bernat6-Aug-08 22:57 
GeneralRe: Example projects PinmemberJoao Araujo3-Dec-08 18:30 
GeneralExcellent work, Thank you!! PinmemberDanielm10321-Apr-08 18:57 
QuestionGDI Leak Pinmemberstpetrus20-Jan-08 15:27 
QuestionLicense? PinmemberQuynh Nguyen13-Dec-07 21:11 
AnswerRe: License? Pinmemberforeverlove9-Apr-08 20:59 
AnswerRe: License? Pinmemberforeverlove10-Apr-08 23:55 
GeneralCreating a View from a plugin Pinmemberthomas_tom9913-Nov-07 3:10 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141216.1 | Last Updated 17 May 2006
Article Copyright 2004 by Andrzej Markowski
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid