Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

CTabCtrlSSL - An easy to use, flexible extended tab control

0.00/5 (No votes)
2 Oct 2003 33  
An extended tab control that allows tab pages to be added from dialog resources

Sample Image - CTabCtrlSSL.gif

Introduction

This article has been updated and the details are available in the Updates section.

It's amazing what a bit of illness can do for your productivity at home! I've been ill for the last couple of days and here it is, yet another extended control. This time my target is the tab control. It seems to me that the tab control is a bit out of fashion these days with people preferring property sheets and pages instead. Well, I tried to use them and couldn't get the result I wanted. I needed some controls above the tabbed area (a bit like the demo, but a few more controls) and I just couldn't get that with property sheets and pages.

The problem with the standard tab control is that involves loads of effort to get pages in to the tab control. A quick in the MSDN located an example by Jeff Prosise that implemented a tabbed view, CTabView, allowing the tabs to be specified as dialog resources. Well, when it comes to code I'm a bit like I was as a ten year old with watches: I've got to fiddle about with it and see how it works and wonder how it could be better.

The first problem was that Jeff's solution was for a view class and I needed a control. The transition here is fairly easy as the view just wraps up the control. The second issue I had was that it didn't give much flexibility over what you could do with the tab pages. "How do I handle events within the page?" I asked myself. The answer was to allow the client to inherit from the tab page class and allow tab page objects to be added to the control and not just dialog resources.

Why is that solutions always present a new problem? By allowing this approach I then introduced a tricky situation with releasing the tab pages. Internally the tab control was creating the tab pages on the heap and maintaining a list of the pages that had been added. When the control was destroyed delete was called on each page in turn. This obviously causes problems if the pages are created outside of the tab control and passed in to it. In this case the tab control would destroy the pages created externally and then the parent dialog would try and do the same!!

After a lengthy discussion in the Visual C++ forum with Tomasz Sowinski we came up with the answer. The tab control has a protected function for adding pages to the control and the public functions call this one. What is actually passed in to the protected function is a structure containing a pointer to a tab page and a flag indicating if the tab control should destroy it. This way if the tab page is passed in then the flag is set to false, but if the tab control creates the tab page the flag is set to true. At destruction time only the pages with the flag set are destroyed by the tab control. All others are someone else's problem.

How to use it

  1. Create a dialog resource and class for the dialog that you want a tab control on.
  2. Add a tab control from the toolbox to the dialog resource.
  3. Create a member variable for the tab control and change it's type to CTabCtrlSSL.
  4. In the OnInitDialog handler for your dialog class create and add any pages you want on the tab control.
BOOL CCTabCtrlSSL_demoDlg::OnInitDialog () {
	CDialog::OnInitDialog ();
   
   // Setup the tab control

   int nPageID = 0;
   m_tabDemo.AddSSLPage (_T("Basic Tab"), nPageID++, IDD_TAB_BASIC);
   m_advancedTab.Create (IDD_TAB_ADVANCED, this);
   m_tabDemo.AddSSLPage (_T("Advanced Page"), nPageID++, &m_advancedTab);
   m_aboutTab.Create (IDD_TAB_ABOUT, this);
   m_tabDemo.AddSSLPage (_T("About"), nPageID++, &m_aboutTab);
   
   return TRUE; // return TRUE unless you set the focus to a control

}

As you can see from the above code sample (taken from the demo), to add a basic tab call AddSSLPage and just pass it the resource ID of the dialog resource. For an advanced tab, create the dialog resource setting the window style to Child and the border style to none, then call AddSSLPage and pass in a pointer to your CTabPageSSL-derived object.

To continue the style I started with CButtonSSL, here is the documentation for the classes:

Overview | Class members | Known problems

CTabCtrlSSL

A "tab control" is analogous to the dividers in a notebook or the labels in a file cabinet. By using a tab control, an application can define multiple pages for the same area of a window or dialog box. Each page consists of a set of information or a group of controls that the application displays when the user selects the corresponding tab. CTabCtrlSSL extends the standard tab control by providing an interface for adding tabs to the control that are defined as dialog resources. These tabs are defined internally as CTabPageSSL objects. There is also an interface for adding objects of this type to the tab control allowing custom objects to be defined by inheriting from CTabPageSSL.

Any tab pages that are created by CTabCtrlSSL (those where the tab is added by passing in a dialog resource id) are destroyed by CTabCtrlSSL. It is the clients responsibility to destroy any CTabPageSSL-derived objects that are passed in to CTabCtrlSSL.

#include "TabCtrlSSL.h"

Overview | Class members | Known problems

Class members

Construction

CTabCtrlSSL Constructs a CTabCtrlSSL object.

Page functions

AddSSLPage Adds a tab to the control.
RemoveSSLPage Removes a tab from the control.
GetSSLPageCount Returns the number of tabs that have been added to the control.
GetSSLPageTitle Returns the label for a particular tab page.
SetSSLPageTitle Sets the label for a particular tab page.
GetSSLPageID Returns the page ID for the specified tab page.
SetSSLPageID Sets the page ID for the specified tab page.
ActivateSSLPage Makes the specified tab page the active one.
GetSSLActivePage Gets the currently active tab page.
GetSSLPageIndex Returns the page index of the specified tab page.

Overridables

OnInitPage Override in derived class to initialize pages.
OnActivatePage Override in derived class to respond to page activations.
OnDeactivatePage Override in derived class to respond to page deactivations.
OnDestroyPage Override in derived class to free resources.

Overview | Class members | Known problems

CTabCtrlSSL::CTabCtrlSSL

CTabCtrlSSL ();

Remarks

Constructs a CTabCtrlSSL object.

Overview | Class members | Known problems

CTabCtrlSSL::AddSSLPage

int AddSSLPage (LPCTSTR pszTitle, int nPageID, int nTemplateID);

int AddSSLPage (LPCTSTR pszTitle, int nPageID, LPCTSTR pszTemplateName);

int AddSSLPage (LPCTSTR pszTitle, int nPageID, CTabPageSSL* pTabPage);

Return Value

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

Parameters

pszTitle

Address of a null-terminated string that contains the tab text.

nPageID

The zero-based numeric ID for referring to the page to be added.

nTemplateID

Specifies the tab page�s resource ID.

pszTemplateName

Points to a null-terminated string that contains the name of the dialog resource to load.

pTabPage

Points to the CTabPageSSL object to be added.

Remarks

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

Overview | Class members | Known problems

See Also CTabCtrlSSL::RemoveSSLPage, CTabCtrlSSL::GetSSLPage

CTabCtrlSSL::RemoveSSLPage

BOOL RemoveSSLPage (int nIndex);

Return Value

Nonzero if successful; otherwise 0.

Parameters

nIndex

Zero-based value of the item to delete.

Remarks

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

Overview | Class members | Known problems

See Also CTabCtrlSSL::AddSSLPage, CTabCtrlSSL::GetSSLPage

CTabCtrlSSL::GetSSLPageCount

int GetSSLPageCount ();

Return Value

Number of items in the tab control.

Remarks

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

Overview | Class members | Known problems

CTabCtrlSSL::GetSSLPageTitle

BOOL GetSSLPageTitle (int nIndex, CString& strTitle);

Return Value

Nonzero if successful; otherwise 0.

Parameters

nIndex

Zero-based value of the relevant tab page.

strTitle

A CString reference to receive the title of the tab page.

Remarks

Call this function to retrieve the title of the specified item in a tab control.

Overview | Class members | Known problems

See Also CTabCtrlSSL::SetSSLPageTitle

CTabCtrlSSL::SetSSLPageTitle

BOOL SetSSLPageTitle (int nIndex, LPCTSTR pszTitle);

Return Value

Nonzero if successful; otherwise 0.

Parameters

nIndex
Zero-based value of the relevant tab page.

pszTitle

Points to a null-terminated string that contains the title to set for the specified tab page.

Remarks

Call this function to set the title of the specified item in a tab control.

Overview | Class members | Known problems

See Also CTabCtrlSSL::GetSSLPageTitle

CTabCtrlSSL::GetSSLPageID

int GetSSLPageID (int nIndex);

Return Value

Zero-based page identifier if successful; otherwise -1.

Parameters

nIndex

Zero-based index of the relevant tab page.

Remarks

Call this function to retrieve the page identifier as specified when the tab was added of the specified item in a tab control. The page identifier may also be altered with the SetSSLPageID function.

Overview | Class members | Known problems

See Also CTabCtrlSSL::SetSSLPageID

CTabCtrlSSL::SetSSLPageID

int SetSSLPageID (int nIndex, int nPageID);

Return Value

The previous zero-based page identifier if successful; otherwise -1.

Parameters

nIndex

Zero-based index of the relevant tab page.

nPageID

The new zero-based page identifier to be set.

Remarks

Call this function to alter the page identifier for a specified tab page.

Overview | Class members | Known problems

See Also CTabCtrlSSL::GetSSLPageID

CTabCtrlSSL::ActivateSSLPage

BOOL ActivateSSLPage (int nIndex);

Return Value

Nonzero if successful; otherwise 0.

Parameters

nIndex

Zero-based index of the tab page to activate.

Remarks

Call this function to change the active tab.

Overview | Class members | Known problems

See Also CTabCtrlSSL::GetSSLActivePage

CTabCtrlSSL::GetSSLActivePage

int GetSSLACtivePage ();

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.

See Also CTabCtrlSSL::ActivateSSLPage

Overview | Class members | Known problems

CTabCtrlSSL::GetSSLPage

CWnd* GetSSLPage (int nIndex);

Return Value

A pointer to the requested tab page if successful; otherwise NULL.

Parameters

nIndex

Zero-based index of the tab page to get.

Remarks

Call this function to get a specific tab in the tab control.

Overview | Class members | Known problems

CTabCtrlSSL::GetSSLPageIndex

int GetSSLPageIndex (int nPageID);

Return Value

Zero-based index of the specified tab if successful; otherwise -1.

Parameters

nPageID

Zero-based page identifier of the relevant tab page.

Remarks

Call this function to retrieve the zero-based index of a tab page in the tab control.

Overview | Class members | Known problems

CTabCtrlSSL::OnInitPage

BOOL OnInitPage (int nIndex, int nPageID);

Return Value

Nonzero if successful; otherwise 0.

Parameters

nIndex

Zero-based index of the tab page being initialized.

nPageID

Zero-based page identifier of the page being initialized.

Remarks

Override in derived class to initialize pages.

Overview | Class members | Known problems

CTabCtrlSSL::OnActivatePage

void OnActivatePage (int nIndex, int nPageID);

Parameters

nIndex

Zero-based index of the tab page being activated.

nPageID

Zero-based page identifier of the page being activated.

Remarks

Override in derived class to respond to page activations.

Overview | Class members | Known problems

CTabCtrlSSL::OnDeactivatePage

void OnDeactivatePage (int nIndex, int nPageID);

Parameters

nIndex

Zero-based index of the tab page being activated.

nPageID

Zero-based page identifier of the page being activated.

Remarks

Override in derived class to respond to page deactivations.

Overview | Class members | Known problems

CTabCtrlSSL::OnDestroyPage

void OnDestroyPage (int nIndex, int nPageID);

Parameters

nIndex

Zero-based index of the tab page being activated.

nPageID

Zero-based page identifier of the page being activated.

Remarks

Override in derived class to free resources.

Overview | Class members | Known problems

Known problems

As far as I know there aren't any, but then the advanced tab part hasn't been tested much. If you find any let me know.

Updates

  • 01 Oct 2003

    The most common question I have had about CTabCtrlSSL is about x, y, or z control that someone can't receive messages for.

    I have explained the problem and the solution many times to many people and now, with thanks to John A Johnson, I have a solution that really works and can be applied to the source code for all.

    The problem was that WM_COMMAND, WM_NOTIFY and WM_CMDMSG were passed on to the parent of the tab page, the tab control, which then passed them on to its parent (usually a dialog) so that the parent dialog could handle notifications, etc. of the tab pages. Unfortunately, this meant that any derived tab page would never get a chance to handle its own control notifications, unless you removed the OnCommand, OnNotify and OnCmdMsg handlers in CTabPageSSL.

    The real solution is to turn off this command routing by default as most people want to handle control notifications in the class that owns them directly, but allow people to turn command routing back on, if they want the parent dialog to handle them instead. This resulted in a few extra methods in CTabPageSSL. But if you only want to handle commands/notifications in your derived tab page, you won't need to change your code at all, just drop in the new TabPageSSL.h and TabPageSSL.cpp.

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