Click here to Skip to main content
13,300,002 members (49,776 online)
Click here to Skip to main content
Add your own
alternative version


84 bookmarked
Posted 31 Jan 2007

CMyTabCtrl - Very Simple Dynamic Tab Control for MFC

, 31 Jan 2007
Rate this:
Please Sign up or sign in to vote.
A Very Simple to use and expandable CTabCtrl Class
Sample image


One of the most aggravating things about using a tab control is having to use property sheets or embedding child dialogs into the tab control. Both approaches work, but cause the program to have more code than I think is necessary. So I decided to create a very simple to use tab control class, which dynamically creates the child controls for you, and also cleans up the memory for you. This class is very easy to use, and requires very little coding, and should save you a lot of time! It supports as many tabs as you need right out of the box, and can create as many controls as you need as well! It allows you to insert a child control into a tab with a single line of code! It allows for easy access to control values and the ability to modify the controls very easily. It also supports keyboard navigation though the child controls.


The class was designed for one of my projects "Options" dialog. The tab class takes care of all object memory cleanup, and dynamically creates and destroys all child window objects for you. I've tested the class with Win2K and XP, I don't use Win98 anymore, but I'm sure it probably works fine with 98. It is compatible with XP visual styles, many thanks for the idea I used from another codeproject article for the XP styles compatibility; ( ) (I create a solid background brush from a pixel of the color we need, rather than using a repositioned patternbrush of the bitmap)

Using the code

Using the class is simple, just add...

#include "CMyTabClass.h"

to your dialog's header file like so...

#pragma once
#include "afxcmn.h"

#include "MyTabCtrl.h" //<-- Add here

// COptionsDlg dialog

class COptionsDlg : public CDialog

Next create a public member variable for your CTabCtrl in your dialog, and add the WS_TABSTOP style to your CTabCtrl as well, once you have done that, change your declared variable from "CTabCtrl" to "CMyTabCtrl" as shown below...

     //CTabCtrl m_cTab; //<-- comment this out
     CMyTabCtrl m_cTab; //<-- add this

Your now ready to use the tab class! Currently the class has support for: GroupBoxes, RadioBoxes, Checkboxes, Buttons, and Statictext You could very easily add support for more controls, just take a look at the code and modify it a little bit.

The following functions are what you use for inserting controls, here is a explanation of how they work...

  • uID is the ID of the control you are making, this must be unique of course.
  • sCaption would be the text in the control.
  • iX and iY are your X and Y offsets, so you can move your control around within the tab control.
  • iTab is the tab which you want to insert the control in.
  • iLen would be the length of the control.
  • bCheck is the check state of the item once it is created (Checked or Unchecked)

uLocation is a Positioning Helper, it can be one or more of following: P_TOP, P_LEFT, P_RIGHT, P_BELOW Every time you insert a control, the class remembers the location of the last control inserted, so you can use uLocation to position the next control Below (P_BELOW), and align it with the previous controls left side (P_LEFT) You can use a Bitwise OR to include multiple...

uLocation = P_BELOW|P_LEFT;
  • P_BELOW = aligns the top of control you are inserting, with the bottom of the previous inserted control
  • P_TOP = aligns the top of control you are inserting, with the top of the previous inserted control
  • P_LEFT = aligns the left of control you are inserting, with the left of the previous inserted control
  • P_RIGHT = aligns the left of control you are inserting, with the right of the previous inserted control

The BottomOf, RightOf, LeftOf, and TopOf functions are helper functions for positioning as well. You can use them to obtain the location of a previously inserted control, then drop that value into your iX or iY to help position a new control.

//control creation functions
void CreateCheckBox(BOOL bCheck, LPCTSTR sCaption, int nID,
     int iTab, UINT uLocation = 0, int iX = 0, int iY = 0);
void CreateGroupBox(LPCTSTR sCaption, int nID, int iTab, 
     int width, int height, UINT uLocation = 0, int iX = 0,
     int iY = 0);
void CreateRadioBox(BOOL bCheck, LPCTSTR sCaption, int nID,
     int iTab, UINT uLocation = 0, int iX = 0, int iY = 0,
     DWORD dwStyle = 0);
void CreateButton(LPCTSTR sCaption, int nID, int iTab, 
     UINT uLocation = 0, int iX = 0, int iY = 0, 
     int iLen = 50);
void CreateEdit(LPCTSTR sCaption, int nID, int iTab, 
     UINT uLocation = 0, int iX = 0, int iY = 0, 
     int iLen = 100);
void CreateStatic(LPCTSTR sCaption, int nID, int iTab, 
     UINT uLocation = 0, int iX = 0, int iY = 0);

//placment helpers
int BottomOf(int nID);
int RightOf(int nID);
int LeftOf(int nID);
int TopOf(int nID);

//get value helpers
CString GetItemText(int nID);
int GetItemTextLength(int nID);
int GetItemTextAsInt(int nID);
BOOL GetItemCheckState(int nID);

Below is an example of the code in use, 9 controls are created in 2 Tabs with only 12 lines of code.

BOOL COptionsDlg::OnInitDialog()

    //Must call this first to initialize the tab class


    m_cTab.CreateCheckBox(FALSE,"Start Program with 
         Windows", 2, 0, 0, 10, 15);
    m_cTab.CreateCheckBox(FALSE,"Connect to All Contacts 
         on Startup", 3, 0, P_BELOW | P_LEFT);

    m_cTab.CreateGroupBox("New Contact Acceptance", 4, 0,
         310, 52, P_BELOW, 0, 10);
    m_cTab.CreateRadioBox(FALSE,"Auto Accept All New 
        Contacts", 5, 0, P_LEFT | P_TOP, 10, 15, WS_GROUP);
    m_cTab.CreateRadioBox(TRUE,"New Contacts Must Match 
         Connection Password", 6, 0, P_BELOW | P_LEFT, 0, 
          0, 0);
    m_cTab.CreateCheckBox(FALSE,"Play Sound When Contact 
         Comes Online", 9, 1, 0, 10, 15);
    m_cTab.CreateCheckBox(FALSE,"Play Sound On New 
         Messages", 10, 1, P_BELOW | P_LEFT);    
    //Just a simple test to demonstrate how easy it is to 
    //access the controls
    CString s;
    //get the text from control number 8
    TRACE("TEST: %s\n",s);    
    return TRUE;

As you can see, inserting controls into your tab control looks very nice and neat, and is easy. But how do we make pushbuttons call functions you ask? The class sends a message to your dialog with the WPARAM containing the uID of the button which was pressed, so you can handle any button event with a single function, and a simple switch, or if/then statement.


LRESULT COptionsDlg::ButtonPressed(WPARAM w, LPARAM l)
    CString s;
    TRACE("BUTTON %d was pressed [%s]\n",w,s);
    return 0;

Points of Interest

Buttons and Keyboard Navigation were the tricky parts of the class, examining the code will shed some light on how I addressed the issues, Using PreTranslateMessage I trapped some specific messages for keyboard and button events, then I reposted them back to the class as a new type of message for processing, I did this so that a minimal amount of code would appear in the PreTranslateMessage message function, to prevent slowing down the message pump.

In order to maneuver through child controls without a mouse, you can use the tab button to move between controls in your dialog (make sure your tab control has WS_TABSTOP style) Then once you tab to your TabControl, use the up and down arrow keys on your keyboard to select the child controls, and space bar to activate or deactivate them.


Jan 2007, Public Release.


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


About the Author

Brooks Y.
Web Developer
United States United States
No Biography provided

You may also be interested in...


Comments and Discussions

QuestionAdding custom control Pin
Member 853403527-Oct-16 9:20
memberMember 853403527-Oct-16 9:20 
QuestionMFC Tab Control Development Video Pin
Jack123sweet5-Apr-14 9:09
memberJack123sweet5-Apr-14 9:09 
GeneralMy vote of 3 Pin
Member 101906786-Nov-13 21:31
memberMember 101906786-Nov-13 21:31 
QuestionWant to add CSliderCtrl on Tab Pin
nothingmag18-Jul-12 20:31
membernothingmag18-Jul-12 20:31 
GeneralMy vote of 5 Pin
Member 87736342-Apr-12 7:22
memberMember 87736342-Apr-12 7:22 
GeneralMy vote of 4 Pin
ghinton19-Feb-12 11:51
memberghinton19-Feb-12 11:51 
QuestionItem colors Pin
ghinton19-Feb-12 11:50
memberghinton19-Feb-12 11:50 
General[My vote of 2] function '__thiscall CMyTabCtrl::CMyTabCtrl(void)' already has a body Pin
xiang_yan8-Sep-10 1:02
memberxiang_yan8-Sep-10 1:02 
QuestionCan it use in a SDI formview based app? Pin
maplewang26-May-09 5:07
membermaplewang26-May-09 5:07 
QuestionHow to change the font name, size, caption for edit control Pin
santhosh33kumar15-Sep-08 4:44
membersanthosh33kumar15-Sep-08 4:44 
Generalerror in VS2005 Pin
PoweRoy12-Aug-08 3:48
memberPoweRoy12-Aug-08 3:48 
GeneralRe: error in VS2005 Pin
PoweRoy12-Aug-08 4:07
memberPoweRoy12-Aug-08 4:07 
GeneralRe: error in VS2005 Pin
Axter26-Apr-09 2:52
memberAxter26-Apr-09 2:52 
QuestionAccelerators (&) Pin
Ray Bolger14-May-08 6:17
memberRay Bolger14-May-08 6:17 
QuestionCan made scrollable property page? Pin
Shock20-Jan-08 10:05
memberShock20-Jan-08 10:05 
GeneralDoesn't work on Visual Studio 6.0 Pin
victoria195019-Jan-08 4:27
membervictoria195019-Jan-08 4:27 
QuestionHow to add Dialogs derived from CDialog to CPropertySheet Pin
hari prasad sathpadi5-Sep-07 2:04
memberhari prasad sathpadi5-Sep-07 2:04 
GeneralCMyTabCtl and Visual Studio 6.0 Pin
morgan.hallgren23-Aug-07 0:30
membermorgan.hallgren23-Aug-07 0:30 
GeneralLicence Pin
df4944-Mar-07 4:38
memberdf4944-Mar-07 4:38 
QuestionCreateGroupBox(...) Pin
Daeha6-Feb-07 22:32
memberDaeha6-Feb-07 22:32 
GeneralCMyTabCtl and Visual Studio 2005 Pin
neuhaj0e5-Feb-07 12:58
memberneuhaj0e5-Feb-07 12:58 
AnswerRe: CMyTabCtl and Visual Studio 2005 Pin
neuhaj0e6-Feb-07 13:53
memberneuhaj0e6-Feb-07 13:53 
AnswerRe: CMyTabCtl and Visual Studio 2005 Pin
indrekm10-Feb-07 2:40
memberindrekm10-Feb-07 2:40 
GeneralRe: CMyTabCtl and Visual Studio 2005 Pin
PoweRoy12-Aug-08 4:25
memberPoweRoy12-Aug-08 4:25 
GeneralRe: CMyTabCtl and Visual Studio 2005 Pin
RHBrooks15-Jun-09 10:59
memberRHBrooks15-Jun-09 10:59 
GeneralRe: CMyTabCtl and Visual Studio 2005 Pin
Anil K P3-Aug-09 20:24
memberAnil K P3-Aug-09 20:24 
GeneralRe: CMyTabCtl and Visual Studio 2005 Pin
bsepp6-Aug-09 6:04
memberbsepp6-Aug-09 6:04 

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

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

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.171207.1 | Last Updated 1 Feb 2007
Article Copyright 2007 by Brooks Y.
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid