
Introduction
Have you ever wanted to create a "tabbed window" effect, but found the amount of
information on the web lacking? Or, did you find out how to use "property sheets", but thought that method was too complicated?
Background
I was in both of those situations for years, and it seemed like I would never be able to use tabs how I wanted.
That I couldn't "get" property sheets may be a testament of my programming ability. Yet, it may have
been a more mature programmer who was able to create a different, simpler method. I submit this method in
the hope that it's usefulness outweighs any criticisms.
How It Works
Uses normal dialogs, along with some positioning and hiding.
Child windows are placed on top of a tab control in the main window.
Getting Started
There are 3 major steps to getting this to work:
- Prepare the dialogs
- Set up main dialog's header file
- Code main dialog's methods
Prepare the Dialogs
Make a tab control on the main window. This is the style I used, but it shouldn't be important:

Create four standard blank dialogs, one for each tab, with these settings (style is important):

Check "Control parent" in "Extended Styles" if you want to be able to tab in and out from the tab control and the child windows.
Create the classes for each child dialog as you normally would in ClassWizard, and that's all you need to set up for them!
I put a simple, appropriately labeled Static Text control on each one just so I knew that it worked. You can resize the
dialogs to the planned run-time size for easier arrangement of their controls, but that will be handled programmatically
when the child window is shown.
Set Up Main Dialog's Header File
Include child window header files:
#include "GeneralDlg.h"
#include "DisplayDlg.h"
#include "SoundsDlg.h"
#include "AdvancedDlg.h"
Create instances of the child window classes and the method for switching the child windows:
public:
CSettingsDlg(CWnd* pParent = NULL);
CGeneralDlg m_dGeneralDlg;
CDisplayDlg m_dDisplayDlg;
CSoundsDlg m_dSoundsDlg;
CAdvancedDlg m_dAdvancedDlg;
void ShowWindowNumber(int number);
Create a CRect
structure to hold the position of the child windows:
DECLARE_MESSAGE_MAP()
private:
CRect m_rSettingsRect;
};
Using ClassWizard, add a WM_SHOWWINDOW
message to the main dialog, and a
TCN_SELCHANGE
message to the tab control.
Code Main Dialog's Methods
Method for showing and hiding child windows:
void CSettingsDlg::ShowWindowNumber(int number)
{
int windowCount = 4;
if ((number >= 0) && (number < windowCount))
{
CDialog *m_dPointer[4];
m_dPointer[0] = &m_dGeneralDlg;
m_dPointer[1] = &m_dDisplayDlg;
m_dPointer[2] = &m_dSoundsDlg;
m_dPointer[3] = &m_dAdvancedDlg;
for (int count = 0; count < windowCount; count++)
{
if (count != number)
{
m_dPointer[count]->ShowWindow(SW_HIDE);
}
else if (count == number)
{
m_dPointer[count]->SetWindowPos(&wndTop, m_rSettingsRect.left,
m_rSettingsRect.top, m_rSettingsRect.right,
m_rSettingsRect.bottom, SWP_SHOWWINDOW);
m_cTab.SetCurSel(count);
}
}
}
}
Whenever the main window is shown, show the first child window:
void CSettingsDlg::OnShowWindow(BOOL bShow, UINT nStatus)
{
CDialog::OnShowWindow(bShow, nStatus);
if (bShow)
{
ShowWindowNumber(0);
}
}
When a tab is selected, show the right child window:
void CSettingsDlg::OnSelchangeTab(NMHDR* pNMHDR, LRESULT* pResult)
{
ShowWindowNumber(m_cTab.GetCurFocus());
pNMHDR = NULL;
pResult = NULL;
}
Fill out OnInitDialog
:
BOOL CSettingsDlg::OnInitDialog()
{
CDialog::OnInitDialog();
SetIcon(m_hIcon, TRUE);
SetIcon(m_hIcon, FALSE);
CRect tabRect;
m_cTab.GetWindowRect(tabRect);
m_rSettingsRect.left = 13;
m_rSettingsRect.top = 44;
m_rSettingsRect.right = tabRect.Width() - 7;
m_rSettingsRect.bottom = tabRect.Height() - 38;
m_dGeneralDlg.Create(IDD_GENERAL, this);
m_dDisplayDlg.Create(IDD_DISPLAY, this);
m_dSoundsDlg.Create(IDD_SOUNDS, this);
m_dAdvancedDlg.Create(IDD_ADVANCED, this);
ShowWindowNumber(0);
TCITEM tabItem;
tabItem.mask = TCIF_TEXT;
tabItem.pszText = _T(" &General ");
m_cTab.InsertItem(0, &tabItem);
tabItem.pszText = _T(" Display ");
m_cTab.InsertItem(1, &tabItem);
tabItem.pszText = _T(" Sounds ");
m_cTab.InsertItem(2, &tabItem);
tabItem.pszText = _T(" Advanced ");
m_cTab.InsertItem(3, &tabItem);
return TRUE;
}
Now you can build it and see if it works!
Points of Interest
I didn't realize the current code in ShowWindowNumber
right away. It had a lot of
if
/else
if
/../else
conditions with essentially the same code in each.
I would not have shared this code if I had not found a better way to switch the windows. Thus,
ShowWindowNumber
is the most important and interesting part of this article.
Where Can You Go From Here?
You can use this idea to make a settings dialog in your application.
The members of each tab window can be accessed like this:
CString string = m_dSettingsDlg.m_dGeneralDlg.m_sString;
There is a lot of room for improvement if used in an actual application, but this shows the basic implementation.