Click here to Skip to main content
15,847,653 members
Articles / Desktop Programming

TabCtrl - Adjustable Control with Zooming and Scrolling Tabs

Rate me:
Please Sign up or sign in to vote.
4.97/5 (140 votes)
25 Mar 2021Public Domain2 min read 212.1K   22.7K   346   107
In this article, you will learn about an adjustable control that has zooming and scrolling tabs, dragging with the mouse, custom drawing and much more.

Sample Image

Introduction

Tabs can be top or bottom of child windows. The user can drag tabs using the mouse. Control has a zoom (shrink of tabs) and scrolling tabs mode. Also, if there is one tab, the area of tabs can be hidden.

Control has 28 built-in tab drawing styles, including tabs VS2003, VS2008, VS2010 and VS2019. Drawing for all styles is created programmatically and does not require resources. You can create your own style by editing an existing render class or creating a new one.

This control is based on CWnd class and can be placed as a child window anywhere, for example, in the client area of the frame or dialog.

Using the Code

Child windows are added using their HWND and they can be of any type, for example, modeless dialogs. TabCtrl consists of three areas: control area, tabs area, windows area. This knowledge can be useful to you when creating a drawing class and working with TabCtrl functions.

Sample Image

To create the control and add elements to it, you can do the next steps:

C++
#include "TabCtrl.h"

TabCtrlEx<TabCtrlStyle_VS2019_client_light> m_TabCtrl;
CListCtrl m_List1, m_List2;

...

// Creation and initialization of TabCtrl.
if( !m_TabCtrl.Create(this,WS_CHILD | WS_VISIBLE,CRect(0,0,0,0),ID_TabCtrl) )
    return -1;    // error.

// Creation of ImageList with icons for buttons (close, menu, scroll) and for tabs.
if( !m_TabCtrl.CreateSystemImage(NULL,IDB_IMAGES_SYSTEM,true,14) ||
    !m_TabCtrl.CreateImage(NULL,IDB_IMAGES_TAB_NORMAL,IDB_IMAGES_TAB_DISABLE,true,16) )
    return -1;    // error.

// Creation of child windows.
if( !m_List1.Create(WS_CLIPCHILDREN | LVS_REPORT,CRect(0,0,0,0),&m_TabCtrl,ID_List1) ||
    !m_List2.Create(WS_CLIPCHILDREN | LVS_REPORT,CRect(0,0,0,0),&m_TabCtrl,ID_List2) )
    return -1;    // error.
m_List1.InsertColumn(0,"Mail",LVCFMT_LEFT,100);
m_List2.InsertColumn(0,"Calendar",LVCFMT_LEFT,100);

// Attaching of child windows to the TabCtrl.
if( !m_TabCtrl.Add(m_List1,"Mail",0) ||
    !m_TabCtrl.Add(m_List2,"Calendar",1) )
    return -1;    // error.

// Load state from registry and update.
m_TabCtrl.LoadState(AfxGetApp(),"TabCtrl","State");
m_TabCtrl.Update();

Class TabCtrl does not perform any rendering. For its drawing, it calls the functions of TabCtrl::Draw interface. To draw TabCtrl, you need to create an object inherited from the TabCtrl::Draw class, implement its functions, and pass the TabCtrl::Draw pointer to TabCtrl using the TabCtrl::SetDrawManager function call.

Similarly, a TabCtrl::IRecalc interface is used to specify the size and spacing between TabCtrl areas. A TabCtrl::IBehavior interface will help you adjust the behavior of the TabCtrl, and a TabCtrl::ToolTip will help you create tooltips for tabs and buttons. There is also a TabCtrl::Ability class for setting the ability to click on buttons and a TabCtrl::Notify class for notifying about events in TabCtrl.

If you implement any of the above interfaces, then this implementation must exist for the entire time the control is running. If you are working with only one style, then use the template class, TabCtrlEx. The name of the style class is specified as a template parameter, for example:

C++
TabCtrlEx<TabCtrlStyle_VS2003_client> m_TabCtrl;

Some styles have already been created. For example, styles similar to the docking/floating panels in Visual Studio 2003, 2008, 2010 and 2019. See the TabCtrlComplex class in the DemoDlg.h file for a list of all existing style classes.

Classes ITabCtrlStyle::RecalcStub and ITabCtrlStyle::BehaviorStub create a default implementation for the functions of TabCtrl::IRecalc and TabCtrl::IBehavior interfaces respectively. You can use them to create your own style classes.

The control requires a call of Update() after you add or delete tabs, as well as change its properties and state.

Good luck!

History

  • 28th May, 2010: Initial version
  • 10th June, 2010: Added redirect WM_NOTIFY message from child windows to a parent of the TabCtrl control
  • 12th June, 2010: Corrected error display of tooltips
  • 16th March, 2021: Improved sources and text of the article
  • 25th March, 2021: Added a new style and scrolling of tabs with the mouse wheel

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication


Written By
Software Developer
Canada Canada

Comments and Discussions

 
QuestionHaving a closing tab on each tab Pin
codevisio28-Feb-23 23:33
codevisio28-Feb-23 23:33 
Questionmissing include Pin
merano9926-Mar-21 4:55
mvemerano9926-Mar-21 4:55 
Good solution, some problems compiling with VS2015.

warning C4996: 'MBCS_Support_Deprecated_In_MFC'

Better avoid this, instead use UniCode.

tabctrl.cpp(1065): error C2039: "max": Ist kein Element von "std"
tabctrl.cpp(1069): error C2039: "min": Ist kein Element von "std"
tabctrl.cpp(1298): error C2065: "max": nichtdeklarierter Bezeichner
tabctrl.cpp(1298): error C2062: "int"-Typ unerwartet
 
Solution a la Google:
std::max() requires the <algorithm> header.


With the added include it works. Wink | ;)
AnswerRe: missing include Pin
Aleh Baradzenka26-Mar-21 17:18
Aleh Baradzenka26-Mar-21 17:18 
QuestionHide/Show some tabs Pin
Eugene Pustovoyt24-Mar-21 23:28
Eugene Pustovoyt24-Mar-21 23:28 
AnswerRe: Hide/Show some tabs Pin
Aleh Baradzenka25-Mar-21 16:28
Aleh Baradzenka25-Mar-21 16:28 
GeneralRe: Hide/Show some tabs Pin
Eugene Pustovoyt25-Mar-21 19:08
Eugene Pustovoyt25-Mar-21 19:08 
QuestionThanks Pin
Javene Mcgowan18-Mar-21 8:26
Javene Mcgowan18-Mar-21 8:26 
QuestionMFC PropertySheet class Pin
geoyar17-Mar-21 12:10
professionalgeoyar17-Mar-21 12:10 
AnswerRe: MFC PropertySheet class Pin
Aleh Baradzenka17-Mar-21 15:59
Aleh Baradzenka17-Mar-21 15:59 
GeneralRe: MFC PropertySheet class Pin
geoyar17-Mar-21 16:10
professionalgeoyar17-Mar-21 16:10 
Question5 stars. How to transform into a DLL? Pin
thinBASIC17-Mar-21 7:42
thinBASIC17-Mar-21 7:42 
AnswerRe: 5 stars. How to transform into a DLL? Pin
Aleh Baradzenka17-Mar-21 15:33
Aleh Baradzenka17-Mar-21 15:33 
GeneralRe: 5 stars. How to transform into a DLL? Pin
thinBASIC17-Mar-21 21:24
thinBASIC17-Mar-21 21:24 
GeneralMy vote of 5 Pin
Vincent Radio16-Mar-21 22:45
professionalVincent Radio16-Mar-21 22:45 
NewsNew version! Pin
Aleh Baradzenka26-Feb-21 7:58
Aleh Baradzenka26-Feb-21 7:58 
QuestionVS2013 style Pin
jung-kreidler1-Dec-17 2:34
jung-kreidler1-Dec-17 2:34 
Question来自中国的朋友的问题 Pin
Member 1294799512-Jan-17 21:40
Member 1294799512-Jan-17 21:40 
AnswerRe: 来自中国的朋友的问题 Pin
Southmountain18-Mar-21 10:21
Southmountain18-Mar-21 10:21 
QuestionControls on Child Dialog in TabControl Flickers on resize in VS2013 Any Solution? Pin
dijesh_ka31-Mar-16 1:34
dijesh_ka31-Mar-16 1:34 
QuestionGood work Pin
wdwcode18-Dec-14 3:11
wdwcode18-Dec-14 3:11 
QuestionGood Source Pin
37640838421-Nov-14 19:29
37640838421-Nov-14 19:29 
AnswerRe: Good Source Pin
Aleh Baradzenka22-Nov-14 21:44
Aleh Baradzenka22-Nov-14 21:44 
QuestionGreat Work! But DDX_Control() problem. Pin
tuxxon2-Oct-14 3:48
tuxxon2-Oct-14 3:48 
QuestionHow to send a message when the current tab changes Pin
Bob H23-Mar-14 6:52
Bob H23-Mar-14 6:52 
AnswerRe: How to send a message when the current tab changes Pin
Aleh Baradzenka23-Mar-14 10:11
Aleh Baradzenka23-Mar-14 10:11 

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.