Tab control managed using CTabCtrl MFC class is a good
replacement candidate for Property Sheets. But these Tab Controls are less used and
discussed still less. This article explains how to use the CTabCtrl class
for manipulating a Tab Control and hold 2 different dialog boxes. The sample
given here can be extended to
add more dialog boxes.
The article had been revised to support the child controls
inside the dialog boxes placed on the CTabCtrl. There had been a lot of
queries from our visitors on this issue. We had not been able to reply to
each one of them. Sorry about that. We've revised the article.
Creating the Tab Holder Dialog for CTabCtrl:
As a first step for using this tab control, a placeholder
dialog needs to be created. This place holder could be a Form View or a Dialog box. This
example illustrates CTabCtrl usage with a Dialog box.
- Create an MFC Dialog based application. Modify the Title
of the dialog to "Tab control Holder Dialog". This is to
differentiate the parent dialog from the rest of the child
dialog boxes.
- Place a Tab Control on the dialog box. The article
uses the ID of the tab control as IDC_TABCTRL1.
- A derived class of CTabCtrl has to be created now. This
class will handle initializing the tab sheet dialogs,
activating each of them at every selection etc.,
Creating the Derived class for CTabCtrl:
- Open the class wizard by pressing the key combination
Ctrl + W. Click on the Add Class --> New button.
We'll use this interface to add a derived class for
CTabCtrl.
- Enter the name of the derived class (of CTabCtrl ) in
the empty text box. This article uses MyTabCtrl as
the class name for the derived class. Select the CTabCtrl
as the Base Class. Two Files will be created as
MyTabCtrl.h and MyTabCtrl.cpp.
- Add the following data and function members to the
MyTabCtrl class, in the MyTabCtrl.h file.
|
//Array to hold the list of dialog boxes/tab pages
for CTabCtrl
int m_DialogID[2];
//CDialog Array Variable to hold the dialogs
CDialog *m_Dialog[2];
//Function to Create the dialog boxes during startup
void InitDialogs();
//Function to activate the tab dialog boxes
void ActivateTabDialogs();
|
- Open the class wizard for MyTabCtrl and add a
handler for TCN_SELCHANGE event (of
CTabCtrl). This can be done through the Class Wizard
--> Message Maps tab.
- Open the MyTabCtrl.cpp file and paste the following
functions. All these functions except ActivateTabDialogs()
and InitDialogs() are
simple modifications to the original functions, which
were generated by the wizard.
- We will have to include the Child dialog header
files in this MyTabCtrl.cpp.
//Constructor for the class derived from CTabCtrl
MyTabCtrl::MyTabCtrl()
{
m_DialogID[0] =IDD_DIALOG1;
m_DialogID[1] =IDD_DIALOG2;
m_Dialog[0] = new MyDlg1();
m_Dialog[1] = new MyDlg2();
m_nPageCount = 2;
}
//This function creates the Dialog boxes once
void MyTabCtrl::InitDialogs()
{
m_Dialog[0]->Create(m_DialogID[0],GetParent());
m_Dialog[1]->Create(m_DialogID[1],GetParent());
}
//Selection change event for the class derived from
CTabCtrl
void MyTabCtrl::OnSelchange(NMHDR* pNMHDR, LRESULT*
pResult)
{
// TODO: Add your control notification handler code here
ActivateTabDialogs();
*pResult = 0;
}
void MyTabCtrl::ActivateTabDialogs()
{
int nSel = GetCurSel();
if(m_Dialog[nSel]->m_hWnd)
m_Dialog[nSel]->ShowWindow(SW_HIDE);
CRect l_rectClient;
CRect l_rectWnd;
GetClientRect(l_rectClient);
AdjustRect(FALSE,l_rectClient);
GetWindowRect(l_rectWnd);
GetParent()->ScreenToClient(l_rectWnd);
l_rectClient.OffsetRect(l_rectWnd.left,l_rectWnd.top);
for(int nCount=0; nCount < m_nPageCount; nCount++){
m_Dialog[nCount]->SetWindowPos(&wndTop,
l_rectClient.left, l_rectClient.top,
l_rectClient.Width(), l_rectClient.Height(),
SWP_HIDEWINDOW);
}
m_Dialog[nSel]->SetWindowPos(&wndTop,
l_rectClient.left, l_rectClient.top,
l_rectClient.Width(), l_rectClient.Height(),
SWP_SHOWWINDOW);
m_Dialog[nSel]->ShowWindow(SW_SHOW);
}
|
- Now the above can be enough for a basic tab
control with CTabCtrl, which can be made to hold 2 dialog boxes or
tab sheets.
The next step will be to create two
dialog boxes which will be used as the Tab sheets.
Creating the Tab Sheets for CTabCtrl:
- Create two Dialog boxes by using the Visual
Studio --> Menu --> Insert Resource --> Dialog.
- Ensure that their ids are
IDD_DIALOG1,
IDD_DIALOG2. The
sample in this article uses these IDs marked in
Blue.
- Put some controls or some sample text on the
dialog boxes for
differentiating both of them from each other.
- For both the dialogs, set the Properties
Dialog --> Styles --> Style equal to Child.
- Also Un-check the Properties Dialog -->
Styles --> Title bar and System Menu.
They should be set to false. Because the tab sheets
cannot have a title bar.
- Set the Properties Dialog --> More Styles -->
Visible style to True.
- For both the dialogs create two dialog classes
by using the class wizard.
Initializing and Activating the Tab Sheets in CTabCtrl:
- Open the Parent dialog which holds the Tab
Control.
- Open the class wizard.
- In the Class wizard --> Member Variables
tab, add a variable for the Tab control. Use the
MyTabCtrl as the class representing the Tab
Control, instead of CTabCtrl. This
sample uses the variable name as
m_tbCtrl. The
green colored items
relate the tab control ID
and the member variable
for the tab control.
After this, in the OnInitDialog of the same
class, add the following lines of code.
m_tbCtrl.InitDialogs();
m_tbCtrl.InsertItem(0,"Sample Tab 1"); m_tbCtrl.InsertItem(1,"Sample Tab 2");
m_tbCtrl.ActivateTabDialogs();
|
Now the application is ready to be
launched. Build the application and execute it.
The application will have 2 tab sheets and upon
clicking the tab buttons, the dialogs get
activated correspondingly.
Do not forget to include the Child
dialog header files in the MytabCtrl.cpp.
There will be a small problem if
you press ESC key or Enter keys. The tab sheets
will disappear. To avoid this refer to,
How to avoid closing of the dialog boxes when
ESCAPE key or ENTER key is pressed.
The sample program for the above article is
available at
CTabCtrl Sample.
Note:
There was a problem in the sample code