Hide

SftTabs/DLL 6.5 - Tab Control

Display
Print

Using C++/MFC

This section describes how to use SftTabs/DLL in an application written using C++ and the Microsoft Foundation Class library (MFC).

Adding SftTabs/DLL to an Application

Please see "Building Applications" to prepare a project for development with SftTabs/DLL.

A)Every source program making use of a SftTabs/DLL control must include the required header file SftTabs.h by using the #include directive.
#include "SftTabs.h" /* SftTabs/DLL required header file */

This include statement should appear after the #include <stdafx.h> statement or can be included at the end of stdafx.h. The file is located in the directory \Program Files (x86)\Softelvdm\SftTabs DLL 6.5\Include (unless changed during the installation).The project settings may need to be updated so the #include file can be located (see "Building Applications" for more information).

B)The source program SftTbM.CPP must be added to your project. It is added to the project, without making any modifications to the file, using Visual Studio's Project, Add To Project, Files... menu command. The file is located in the directory \Program Files (x86)\Softelvdm\SftTabs DLL 6.5\Include (unless changed during the installation).Instead of simply adding it to the project, you can include the file using the #include directive. However, it must be included in a source file (*.CPP) as it is not a header file and only one source file can #include the file SftTbM.CPP.
#include "SftTbM.cpp"

This include statement should appear after the #include "SftTabs.h" statement.The project settings may need to be updated so the source file or #include file can be located (see "Building Applications" for more information).

C)In order to use SftTabs/DLL controls, an application must call the CSftTabs::RegisterApp function. The call to this function is required so that SftTabs/DLL window classes can be registered. This call has to be made before any SftTabs/DLL controls are created. Add the following statement to your source code. The preferred location is the InitInstance member function of your CWinApp or CSftTabs_App based application object:
CSftTabs::RegisterApp(); /* Use SftTabs/DLL with this application */
D)Once SftTabs/DLL controls are no longer needed, an application must call the CSftTabs::UnregisterApp function. The call to this function is required so that SftTabs/DLL window classes can be unregistered and cleanup processing can take place. This call has to be made after all SftTabs/DLL controls have been destroyed. The preferred location is the ExitInstance member function of your CWinApp based application object:
CSftTabs::UnregisterApp(); /* No longer use SftTabs/DLL */
E)The application's executable (Exe or Dll) must be linked with the correct Lib file, depending on the target environment. Please see "Building Applications" for more information.The project settings may need to be updated so the Lib files can be located (see "Building Applications" for more information).

Adding a Tab Control

ClassWizard does not support new classes such as CSftTabs, so any tab control instance variables, notification handlers, message map entries, etc., have to be added manually.

There are two methods to add a tab control to an application:

  • using dialog resources<li>using CSftTabs::Create
  • Adding a tab control using dialog resources is accomplished by using a resource editor to design a dialog. For more information, see Creating a Dialog Resource. Once a tab control is created, its CSftTabs based object can be obtained by using the Windows GetDlgItem function or attached to a CSftTabs object using SubclassDlgItem.
CSftTabs * pTab;
pTab = (CSftTabs *) GetDlgItem(IDC_TAB);

or

CSftTabs m_Tab;
m_Tab.SubclassDlgItem(IDC_TAB, this);

Another method to create a tab control is by using the CSftTabs::Create member function.

CSftTabs m_Tab;
m_Tab.Create(WS_CHILD | WS_VISIBLE, CRect(250,200,400,700), pParentWnd, IDC_TABS);

For more information on the various parameters used, see the CSftTabs::Create member function documentation.

Handling Notifications

As with standard Windows controls, applications must respond to events and messages to cause controls to respond to user requests. For additional information, see Notifications.

ClassWizard does not support new classes such as CSftTabs, so any tab control instance variables, notification handlers, message map entries, etc., have to be added manually. To simplify this process, you can copy these items that are generated by ClassWizard for other "standard" Windows controls.

Switching Between Tabs

Switching between tabs is fully automatic, however, an application may wish to prevent a user from switching to another tab. By responding to the WM_COMMAND, SFTTABSN_SWITCHING notification, an application can prevent completion of the tab switch by sending a WM_CANCELMODE message to the tab control.

// Event handler prototype added to dialog/window class
afx_msg void OnTabSwitching();

// Event handler(s) added to message map
BEGIN_MESSAGE_MAP(CSampleView, CView)
  ON_SFTTABSN_SWITCHING(IDC_TAB, OnTabSwitching)
END_MESSAGE_MAP()

// Event handler implementation
void CSampleView::OnTabSwitching()
{
    if (YouDontLikeThisUser())
        m_Tab.SendMessage(WM_CANCELMODE);// cancel switching
}

An application has to make attached controls or dialogs visible when switching between tabs. The SftTabs/DLL API offers functions to manage dialogs and Windows controls that are attached to tabs. See Implementing Tabbed Dialogs and Implementing Tabbed Windows for more information.

Implementing Tabbed Dialogs

A tabbed dialog is created just like any other dialog. A tabbed dialog has a tab control with an available client area. In this client area, pages are displayed. Each tab has an attached page (although during development of a tabbed dialog, a tab doesn't require an attached page). As the user switches between tabs, the appropriate page is created, displayed and destroyed.

A tabbed dialog and each page are based on the class CSftTabsDialog and CSftTabsPage, which are both derived from the MFC class CDialog. This makes conversion of existing dialogs and development of new pages very easy. Tabbed dialogs and pages are first designed using a resource editor. The section Creating a Dialog Resource describes how the necessary tabbed dialog and page (dialog) resources are created.

ClassWizard can be used to create the dialogs and pages. However, ClassWizard can only create new classes based on CDialog (not CSftTabsDialog or CSftTabsPage). After ClassWizard generates a new class derived from CDialog, you have to manually change references to CDialog to the classes CSftTabsDialog and CSftTabsPage. When adding new member functions, make sure to call the CSftTabsDialog and CSftTabsPage base classes instead of CDialog.

Once the necessary dialogs have been designed, the tab control layout can be defined using the SftTabs/DLL Wizard. The SftTabs/DLL Wizard also creates much of the code required to initialize the tab control. This code should be copied to the application (with possibly minor modifications).

Creating a Tabbed Dialog

The following sample code (from \Program Files (x86)\Softelvdm\SftTabs DLL 6.5\Samples\MFC\Dialog\MainDlg.cpp) shows a typical implementation of a tabbed dialog. Most of the code has been created using the SftTabs/DLL Wizard and then copied into the application.

/*- Tab Control Initialization Data --------------------------------------------*/

static const SFTTABS_CONTROL CtlInit = {
    SFTTABSSTYLE_MODERN_I,               /* tab style */
    2,                                   /* number of rows */
    0,                                   /* number of tabs per row (if fFixed) */
    0,                                   /* width of left margin */
    0,                                   /* width of right margin */
    FALSE,                               /* same width for all tabs */
    TRUE,                                /* Client area wanted */
    FALSE,                               /* allow multiline label text */
    TRUE,                                /* use with dialog */
    FALSE,                               /* use specified background color only for text */
    FALSE,                               /* scrollable tabs */
    FALSE,                               /* hide scroll buttons */
    TRUE,                                /* bold font for active tab wanted */
    TRUE,                                /* fill rows completely */
    NULL,                                /* scroll button bitmap */
    NULL,                                /* Dialog data associated with active tab */
    NULL,                                /* Dialog window handle associated with active tab */
    NULL,                                /* Frame, used as client area */
    TRUE,                                /* Tooltips wanted */
    FALSE,                               /* drop text if it doesn't fit */
    FALSE,                               /* conditional scroll buttons */
    BMBUTTONSTYLE_STD,                   /* scroll button style */
    FALSE,                               /* display ... if truncated */
    TRUE,                                /* Flyby highlighting */
    FALSE,                               /* use client area colors in partially obscured frames */
    FALSE,                               /* scroll buttons on left side */
    -1,                                  /* row indentation */
    FALSE,                               /* don't show truncated pattern for clipped tab */
    FALSE,                               /* full size scroll buttons */
    TRUE,                                /* use themes on Windows XP */
    TRUE,                                /* use exact window region */
    FALSE,                               /* always show prefix _ */
    0,0,0,0,                             /* animation values */
    NULL,                                /* disabled button bitmap */
    TRUE,                                /* focus rectangle if the control has i/p focus */
    FALSE,                               /* TRUE if Close button wanted */
    FALSE,                               /* TRUE if Close button disabled */
    FALSE,                               /* TRUE if WM_CLOSE message wanted */
    FALSE,                               /* TRUE if Minimize, Restore, Close buttons are full size */
    SFTTABS_BUTTON_NEAR,                 /* scroll button alignment */
    SFTTABS_BUTTON_NEAR,                 /* Minimize, Restore, Close button alignment */
    FALSE,                               /* TRUE if Minimize button wanted */
    FALSE,                               /* TRUE if Minimize button disabled */
    FALSE,                               /* TRUE if Restore button wanted */
    FALSE,                               /* TRUE if Restore button disabled */
    NULL,                                /* Close, Minimize, Restore button bitmap */
    NULL,                                /* Close, Minimize, Restore disabled button bitmap */
    TEXT(""),                            /* scroll left button tooltip */
    TEXT(""),                            /* scroll button tooltip */
    TEXT(""),                            /* Close button tooltip */
    TEXT(""),                            /* Minimize button tooltip */
    TEXT(""),                            /* Restore button tooltip */
    0,                                   /* custom modifications */
    0,                                   /* forced height/width depending on tab style - 0 to ignore */
    FALSE,                               /* switch tabs on button release (or down if FALSE) */
    FALSE,                               /* Rendering compatible with pre-6.0 */
    FALSE,                               /* don't display clientarea border - select styles only */
};

static const SFTTABS_TAB Tab0 = {   /*The First One */
    SFTTABS_NOCOLOR, RGB(0,0,255),       /* background, foreground color */
    SFTTABS_NOCOLOR, RGB(0,0,255),       /* background, foreground color (when selected) */
    { SFTTABS_GRAPH_LEFT, 0 },           /* location */
    TRUE,                                /* enabled/disabled */
    0,                                   /* userdata */
    0,                                   /* reserved */
    NULL,                                /* reserved */
    SFTTABS_NOCOLOR,                     /* Flyby foreground color */
    SFTTABS_NOCOLOR,                     /* Client area background color */
    0,0,0,0,                             /* animation values */
    NULL,                                /* tab-specific ImageList handle*/
    FALSE,                               /* hidden tab */
    SFTTABS_NOCOLOR,                     /* gradient fill background color */
    SFTTABS_NOCOLOR,
    SFTTABS_NOCOLOR,                     /* gradient fill background color, active tab */
    SFTTABS_NOCOLOR,
    SFTTABS_NOCOLOR,                     /* gradient fill client area color */
    SFTTABS_NOCOLOR,
};
static const SFTTABS_TAB Tab1 = {   /*&Second */
    SFTTABS_NOCOLOR, RGB(255,0,0),       /* background, foreground color */
    SFTTABS_NOCOLOR, RGB(255,0,0),       /* background, foreground color (when selected) */
    { SFTTABS_GRAPH_RIGHT, 0 },          /* location */
    TRUE,                                /* enabled/disabled */
    0,                                   /* userdata */
    0,                                   /* reserved */
    NULL,                                /* reserved */
    SFTTABS_NOCOLOR,                     /* Flyby foreground color */
    SFTTABS_NOCOLOR,                     /* Client area background color */
    0,0,0,0,                             /* animation values */
    NULL,                                /* tab-specific ImageList handle*/
    FALSE,                               /* hidden tab */
    SFTTABS_NOCOLOR,                     /* gradient fill background color */
    SFTTABS_NOCOLOR,
    SFTTABS_NOCOLOR,                     /* gradient fill background color, active tab */
    SFTTABS_NOCOLOR,
    SFTTABS_NOCOLOR,                     /* gradient fill client area color */
    SFTTABS_NOCOLOR,
};
static const SFTTABS_TAB Tab2 = {   /*&Third */
    SFTTABS_NOCOLOR, RGB(128,128,0),     /* background, foreground color */
    SFTTABS_NOCOLOR, RGB(128,128,0),     /* background, foreground color (when selected) */
    { SFTTABS_GRAPH_NONE, 0 },           /* location */
    TRUE,                                /* enabled/disabled */
    0,                                   /* userdata */
    0,                                   /* reserved */
    NULL,                                /* reserved */
    SFTTABS_NOCOLOR,                     /* Flyby foreground color */
    SFTTABS_NOCOLOR,                     /* Client area background color */
    0,0,0,0,                             /* animation values */
    NULL,                                /* tab-specific ImageList handle*/
    FALSE,                               /* hidden tab */
    SFTTABS_NOCOLOR,                     /* gradient fill background color */
    SFTTABS_NOCOLOR,
    SFTTABS_NOCOLOR,                     /* gradient fill background color, active tab */
    SFTTABS_NOCOLOR,
    SFTTABS_NOCOLOR,                     /* gradient fill client area color */
    SFTTABS_NOCOLOR,
};
static const SFTTABS_TAB Tab3 = {   /*F&ourth */
    SFTTABS_NOCOLOR, RGB(0,255,255),     /* background, foreground color */
    SFTTABS_NOCOLOR, RGB(0,255,255),     /* background, foreground color (when selected) */
    { SFTTABS_GRAPH_NONE, 0 },           /* location */
    TRUE,                                /* enabled/disabled */
    0,                                   /* userdata */
    0,                                   /* reserved */
    NULL,                                /* reserved */
    SFTTABS_NOCOLOR,                     /* Flyby foreground color */
    SFTTABS_NOCOLOR,                     /* Client area background color */
    0,0,0,0,                             /* animation values */
    NULL,                                /* tab-specific ImageList handle*/
    FALSE,                               /* hidden tab */
    SFTTABS_NOCOLOR,                     /* gradient fill background color */
    SFTTABS_NOCOLOR,
    SFTTABS_NOCOLOR,                     /* gradient fill background color, active tab */
    SFTTABS_NOCOLOR,
    SFTTABS_NOCOLOR,                     /* gradient fill client area color */
    SFTTABS_NOCOLOR,
};
static const SFTTABS_TAB Tab4 = {   /*F&ifth */
    SFTTABS_NOCOLOR, RGB(0,0,128),       /* background, foreground color */
    SFTTABS_NOCOLOR, RGB(0,0,128),       /* background, foreground color (when selected) */
    { SFTTABS_GRAPH_NONE, 0 },           /* location */
    TRUE,                                /* enabled/disabled */
    0,                                   /* userdata */
    0,                                   /* reserved */
    NULL,                                /* reserved */
    SFTTABS_NOCOLOR,                     /* Flyby foreground color */
    SFTTABS_NOCOLOR,                     /* Client area background color */
    0,0,0,0,                             /* animation values */
    NULL,                                /* tab-specific ImageList handle*/
    FALSE,                               /* hidden tab */
    SFTTABS_NOCOLOR,                     /* gradient fill background color */
    SFTTABS_NOCOLOR,
    SFTTABS_NOCOLOR,                     /* gradient fill background color, active tab */
    SFTTABS_NOCOLOR,
    SFTTABS_NOCOLOR,                     /* gradient fill client area color */
    SFTTABS_NOCOLOR,
};
static const SFTTABS_TAB Tab5 = {   /*Si&xth */
    SFTTABS_NOCOLOR, RGB(128,0,0),       /* background, foreground color */
    SFTTABS_NOCOLOR, RGB(128,0,0),       /* background, foreground color (when selected) */
    { SFTTABS_GRAPH_NONE, 0 },           /* location */
    TRUE,                                /* enabled/disabled */
    0,                                   /* userdata */
    0,                                   /* reserved */
    NULL,                                /* reserved */
    SFTTABS_NOCOLOR,                     /* Flyby foreground color */
    SFTTABS_NOCOLOR,                     /* Client area background color */
    0,0,0,0,                             /* animation values */
    NULL,                                /* tab-specific ImageList handle*/
    FALSE,                               /* hidden tab */
    SFTTABS_NOCOLOR,                     /* gradient fill background color */
    SFTTABS_NOCOLOR,
    SFTTABS_NOCOLOR,                     /* gradient fill background color, active tab */
    SFTTABS_NOCOLOR,
    SFTTABS_NOCOLOR,                     /* gradient fill client area color */
    SFTTABS_NOCOLOR,
};

The OnInitDialog message handler of the tabbed dialog initializes the tab control and associates CSftTabsPage based objects to each tab.

BOOL CMainDlg::OnInitDialog()
{
    CSftTabsDialog::OnInitDialog();

    SetIcon(m_hIcon, TRUE);   // Set big icon
    SetIcon(m_hIcon, FALSE);  // Set small icon

    int index;
    SFTTABS_TAB Tab;
    /* Associate the tab control created from the dialog       */
    /* resource with the C++ object.                           */
    m_Tab.SubclassDlgItem(IDC_TAB, this /* parent window */);
    /* You could use DDX/DDV instead and add the following     */
    /* line to the DoDataExchange function of the tab          */
    /* control's parent window (remove the //).                */
    // DDX_Control(pDX, IDC_TAB, m_Tab);

    /* Initialization is faster if we set redraw off */
    m_Tab.SetRedraw(FALSE);

    /* We are using new features */
    m_Tab.SetVersion(SFTTABS_6_5);

    index = m_Tab.AddTab(_T("The First One"));
    m_Tab.SetToolTip(index, _T("Demonstrates tabbing into and out of the tab page"));
    Tab = Tab0;
    Tab.graph.item.hBitmap = (HBITMAP) m_SampleBitmap.m_hObject;
    m_Tab.SetTabInfo(index, &Tab);
    m_Tab.SetTabDialog(index, new CPage1(this)); /* tab page */

    index = m_Tab.AddTab(_T("&Second"));
    m_Tab.SetToolTip(index, _T("Demonstrates how an application can prevent tab switching"));
    Tab = Tab1;
    Tab.graph.item.hIcon = m_hSampleIcon;
    m_Tab.SetTabInfo(index, &Tab);
    m_Tab.SetTabDialog(index, new CPage2(this)); /* tab page */

    index = m_Tab.AddTab(_T("&Third"));
    m_Tab.SetToolTip(index, _T("This page is reset everytime you switch to it"));
    m_Tab.SetTabInfo(index, &Tab2);
    m_Tab.SetTabDialog(index, new CPage3(this)); /* tab page */

    index = m_Tab.AddTab(_T("F&ourth"));
    m_Tab.SetToolTip(index, _T("A page with private OK, Cancel, Next and Previous page buttons"));
    m_Tab.SetTabInfo(index, &Tab3);
    m_Tab.SetTabDialog(index, new CPage4(this)); /* tab page */

    index = m_Tab.AddTab(_T("F&ifth"));
    m_Tab.SetToolTip(index, _T("A page that has not yet been implemented"));
    m_Tab.SetTabInfo(index, &Tab4);
    // If you don't want to attach a page to the tab, the following is optional
//  m_Tab.SetTabDialog(index, new an_object_based_on_CSftTabsPage(this)); /* tab page */

    index = m_Tab.AddTab(_T("Si&xth"));
    m_Tab.SetToolTip(index, _T("A page with nested tab controls and pages"));
    m_Tab.SetTabInfo(index, &Tab5);
    m_Tab.SetTabDialog(index, new CPage6(this)); /* tab page */

    m_Tab.SetControlInfo(&CtlInit);

    // Make sure to turn redraw back on
    m_Tab.SetRedraw(TRUE);
    m_Tab.InvalidateRect(NULL, TRUE);

    // If you are not using the sheet/page classes, remove the call to InitializeTabControl.
    // Initialize tab control
    InitializeTabControl(0, &m_Tab, NULL);

    // Update Tab2 to use transition effects
    {
        SFTTABS_TAB Tab;
        m_Tab.GetTabInfo(2, &Tab);
        Tab.animationStyleShow = SFTTABS_SLIDE_FROM_LEFT;
        Tab.animationTimeShow = 400;
        m_Tab.SetTabInfo(2, &Tab);
    }

    // Update Tab5 to use transition effects
    {
        SFTTABS_TAB Tab;
        m_Tab.GetTabInfo(5, &Tab);
        Tab.animationStyleShow = SFTTABS_EXPAND_CENTER;
        Tab.animationTimeShow = 400;
        m_Tab.SetTabInfo(5, &Tab);
    }

    {
        // Animate Window
        // Animation works on windows 98, 2000 or better only

        HMODULE hUser32 = GetModuleHandle(TEXT("USER32.DLL"));
        if (hUser32) {
            typedef BOOL (WINAPI* LPFNANIMATEWINDOW)(HWND, DWORD, DWORD);
            LPFNANIMATEWINDOW lpfnAnimateWindow;
            lpfnAnimateWindow = (LPFNANIMATEWINDOW)GetProcAddress(hUser32, "AnimateWindow");
            if (lpfnAnimateWindow) {
                CenterWindow();
                lpfnAnimateWindow(m_hWnd, 300, AW_HOR_POSITIVE);
            }
        }
    }

    return FALSE; // if this is a dialog's OnInitDialog member function
}

Each call to CSftTabs::SetTabDialog associates a CSftTabsPage based dialog to a tab. Cleanup of all resources, including the dynamically allocated pages, is done automatically when the tabbed dialog is destroyed.

The call to InitializeTabControl starts the tabbed dialog handling and creates the current page.

A tabbed dialog should always return FALSE from the OnInitDialog member function. The input focus has already been set by SftTabs/DLL, so returning FALSE will prevent Windows from setting the focus (to the wrong control).

Creating a Page

The implementation of a page is identical to a regular dialog, except that the base class is CSftTabsPage instead of CDialog.

The tab page dialog resource must be defined as a child window with the WS_CHILD window style. It cannot be defined as a popup or overlapped window (WS_POPUP or WS_OVERLAPPED)

Implementing Tabbed Windows

A tabbed window is created just like a regular window. A tabbed window has at least one tab control as its child window (with or without a client area). Each tab has an attached page (although during development of a tabbed window, a tab doesn't require an attached page). As the user switches between tabs, the appropriate page is created, displayed and destroyed.

A tabbed window and each page are based on the class CWnd or any of its derived classes, such as CView, CFormView, etc. Using multiple inheritance, a window can inherit the required support to make it into a tabbed window or a page. This makes conversion of existing windows and development of new pages very easy.

ClassWizard can be used to create the tabbed window and the pages initially. By using multiple inheritance, the classes CSftTabsWindowSheet and CSftTabsWindowPage are used to add tabbed window and page support to the new classes.

Creating a Tabbed Window

Most CWnd based classes are suitable to be used as a tabbed window. By using multiple inheritance, a class can be used as a tabbed window by inheriting the required support from the class CSftTabsWindowSheet.

class CSampleView : public CFormView, public CSftTabsWindowSheet
{
    ... class definitions
}

The following sample code (from \Program Files (x86)\Softelvdm\SftTabs DLL 6.5\Samples\MFC\SDI\SmplView.cpp) shows a typical implementation of a tabbed window. Most of the code has been created using the SftTabs/DLL Wizard and then copied into the application.

/*- Tab Control Initialization Data --------------------------------------------*/

static const SFTTABS_CONTROL CtlInit = {
    SFTTABSSTYLE_MODERN_I,               /* tab style */
    1,                                   /* number of rows */
    0,                                   /* number of tabs per row (if fFixed) */
    2,                                   /* width of left margin */
    0,                                   /* width of right margin */
    FALSE,                               /* same width for all tabs */
    TRUE,                                /* Client area wanted */
    FALSE,                               /* allow multiline label text */
    TRUE,                                /* use with dialog */
    FALSE,                               /* use specified background color only for text */
    TRUE,                                /* scrollable tabs */
    FALSE,                               /* hide scroll buttons */
    FALSE,                               /* bold font for active tab wanted */
    FALSE,                               /* fill rows completely */
    NULL,                                /* scroll button bitmap */
    NULL,                                /* Dialog data associated with active tab */
    NULL,                                /* Dialog window handle associated with active tab */
    NULL,                                /* Frame, used as client area */
    TRUE,                                /* Tooltips wanted */
    FALSE,                               /* drop text if it doesn't fit */
    FALSE,                               /* conditional scroll buttons */
    BMBUTTONSTYLE_THEME_SCROLL,          /* scroll button style */
    TRUE,                                /* display ... if truncated */
    TRUE,                                /* Flyby highlighting */
    TRUE,                                /* use client area colors in partially obscured frames */
    TRUE,                                /* scroll buttons on left side */
    -1,                                  /* row indentation */
    FALSE,                               /* don't show truncated pattern for clipped tab */
    TRUE,                                /* full size scroll buttons */
    TRUE,                                /* use themes on Windows XP */
    TRUE,                                /* use exact window region */
    FALSE,                               /* always show prefix _ */
    0,0,0,0,                             /* animation values */
    NULL,                                /* disabled button bitmap */
    TRUE,                                /* focus rectangle if the control has i/p focus */
    FALSE,                               /* TRUE if Close button wanted */
    FALSE,                               /* TRUE if Close button disabled */
    FALSE,                               /* TRUE if WM_CLOSE message wanted */
    FALSE,                               /* TRUE if Minimize, Restore, Close buttons are full size */
    SFTTABS_BUTTON_NEAR,                 /* scroll button alignment */
    SFTTABS_BUTTON_NEAR,                 /* Minimize, Restore, Close button alignment */
    FALSE,                               /* TRUE if Minimize button wanted */
    FALSE,                               /* TRUE if Minimize button disabled */
    FALSE,                               /* TRUE if Restore button wanted */
    FALSE,                               /* TRUE if Restore button disabled */
    NULL,                                /* Close, Minimize, Restore button bitmap */
    NULL,                                /* Close, Minimize, Restore disabled button bitmap */
    TEXT(""),                            /* scroll left button tooltip */
    TEXT(""),                            /* scroll button tooltip */
    TEXT(""),                            /* Close button tooltip */
    TEXT(""),                            /* Minimize button tooltip */
    TEXT(""),                            /* Restore button tooltip */
    0,                                   /* custom modifications */
    0,                                   /* forced height/width depending on tab style - 0 to ignore */
    FALSE,                               /* switch tabs on button release (or down if FALSE) */
    FALSE,                               /* Rendering compatible with pre-6.0 */
    FALSE,                               /* don't display clientarea border - select styles only */
};

static const SFTTABS_TAB Tab0 = {   /*&1 Text */
    SFTTABS_NOCOLOR, SFTTABS_NOCOLOR,    /* background, foreground color */
    SFTTABS_NOCOLOR, SFTTABS_NOCOLOR,    /* background, foreground color (when selected) */
    { SFTTABS_GRAPH_NONE, 0 },           /* location */
    TRUE,                                /* enabled/disabled */
    0,                                   /* userdata */
    0,                                   /* reserved */
    NULL,                                /* reserved */
    SFTTABS_NOCOLOR,                     /* Flyby foreground color */
    SFTTABS_NOCOLOR,                     /* Client area background color */
    0,0,0,0,                             /* animation values */
    NULL,                                /* tab-specific ImageList handle*/
    FALSE,                               /* hidden tab */
    SFTTABS_NOCOLOR,                     /* gradient fill background color */
    SFTTABS_NOCOLOR,
    SFTTABS_NOCOLOR,                     /* gradient fill background color, active tab */
    SFTTABS_NOCOLOR,
    SFTTABS_NOCOLOR,                     /* gradient fill client area color */
    SFTTABS_NOCOLOR,
};
static const SFTTABS_TAB Tab1 = {   /*&2 Statistics */
    SFTTABS_NOCOLOR, SFTTABS_NOCOLOR,    /* background, foreground color */
    SFTTABS_NOCOLOR, SFTTABS_NOCOLOR,    /* background, foreground color (when selected) */
    { SFTTABS_GRAPH_NONE, 0 },           /* location */
    TRUE,                                /* enabled/disabled */
    0,                                   /* userdata */
    0,                                   /* reserved */
    NULL,                                /* reserved */
    SFTTABS_NOCOLOR,                     /* Flyby foreground color */
    SFTTABS_NOCOLOR,                     /* Client area background color */
    0,0,0,0,                             /* animation values */
    NULL,                                /* tab-specific ImageList handle*/
    FALSE,                               /* hidden tab */
    SFTTABS_NOCOLOR,                     /* gradient fill background color */
    SFTTABS_NOCOLOR,
    SFTTABS_NOCOLOR,                     /* gradient fill background color, active tab */
    SFTTABS_NOCOLOR,
    SFTTABS_NOCOLOR,                     /* gradient fill client area color */
    SFTTABS_NOCOLOR,
};
static const SFTTABS_TAB Tab2 = {   /*&3 Attributes */
    SFTTABS_NOCOLOR, SFTTABS_NOCOLOR,    /* background, foreground color */
    SFTTABS_NOCOLOR, SFTTABS_NOCOLOR,    /* background, foreground color (when selected) */
    { SFTTABS_GRAPH_NONE, 0 },           /* location */
    TRUE,                                /* enabled/disabled */
    0,                                   /* userdata */
    0,                                   /* reserved */
    NULL,                                /* reserved */
    SFTTABS_NOCOLOR,                     /* Flyby foreground color */
    SFTTABS_NOCOLOR,                     /* Client area background color */
    0,0,0,0,                             /* animation values */
    NULL,                                /* tab-specific ImageList handle*/
    FALSE,                               /* hidden tab */
    SFTTABS_NOCOLOR,                     /* gradient fill background color */
    SFTTABS_NOCOLOR,
    SFTTABS_NOCOLOR,                     /* gradient fill background color, active tab */
    SFTTABS_NOCOLOR,
    SFTTABS_NOCOLOR,                     /* gradient fill client area color */
    SFTTABS_NOCOLOR,
};
static const SFTTABS_TAB Tab3 = {   /*S&oftel vdm, Inc. */
    SFTTABS_NOCOLOR, SFTTABS_NOCOLOR,    /* background, foreground color */
    SFTTABS_NOCOLOR, SFTTABS_NOCOLOR,    /* background, foreground color (when selected) */
    { SFTTABS_GRAPH_NONE, 0 },           /* location */
    TRUE,                                /* enabled/disabled */
    0,                                   /* userdata */
    0,                                   /* reserved */
    NULL,                                /* reserved */
    SFTTABS_NOCOLOR,                     /* Flyby foreground color */
    SFTTABS_NOCOLOR,                     /* Client area background color */
    0,0,0,0,                             /* animation values */
    NULL,                                /* tab-specific ImageList handle*/
    FALSE,                               /* hidden tab */
    SFTTABS_NOCOLOR,                     /* gradient fill background color */
    SFTTABS_NOCOLOR,
    SFTTABS_NOCOLOR,                     /* gradient fill background color, active tab */
    SFTTABS_NOCOLOR,
    SFTTABS_NOCOLOR,                     /* gradient fill client area color */
    SFTTABS_NOCOLOR,
};

The Create member function of the tabbed window initializes the tab control and associates CSftTabsWindowPage based objects to each tab.

BOOL CSampleView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
    if (!CFormView::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext))
        return FALSE;

    m_SavedContext = *pContext;  // save so we can use it later

    int index;

    /* Associate the tab control created from the dialog       */
    /* resource with the C++ object.                           */
    m_MainTab.SubclassDlgItem(IDC_MAINTAB, this /* parent window */);

    /* You could use DDX/DDV instead and add the following     */
    /* line to the DoDataExchange function of the tab          */
    /* control's parent window (remove the //).                */
    // DDX_Control(pDX, IDC_MAINTAB, m_MainTab);

    /* Initialization is faster if we set redraw off */
    m_MainTab.SetRedraw(FALSE);

    m_pTabEdit = new CTabEdit();         // Edit FormView
    m_pTabStats = new CStatsPage();      // Statistics page
    m_pTabAttr = new CAttrPage();        // Attributes page
    m_pTabLogo = new CLogo();            // Logo page

    /* We are using new features */
    m_MainTab.SetVersion(SFTTABS_6_5);

    index = m_MainTab.AddTab(_T("&1 Text"));
    m_MainTab.SetToolTip(index, _T("Displays the currently opened file"));
    m_MainTab.SetTabInfo(index, &Tab0);
    m_MainTab.SetTabWindowPage(index, m_pTabEdit);
    m_pTabEdit->SaveContext(&m_SavedContext); // save doc/view context

    index = m_MainTab.AddTab(_T("&2 Statistics"));
    m_MainTab.SetToolTip(index, _T("Shows file information"));
    m_MainTab.SetTabInfo(index, &Tab1);
    m_MainTab.SetTabWindowPage(index, m_pTabStats);
    m_pTabStats->SaveContext(&m_SavedContext); // save doc/view context

    index = m_MainTab.AddTab(_T("&3 Attributes"));
    m_MainTab.SetToolTip(index, _T("Changes font and printer margin information"));
    m_MainTab.SetTabInfo(index, &Tab2);
    m_MainTab.SetTabWindowPage(index, m_pTabAttr);
    m_pTabAttr->SaveContext(&m_SavedContext); // save doc/view context

    index = m_MainTab.AddTab(_T("S&oftel vdm, Inc."));
    m_MainTab.SetToolTip(index, _T("Company logo"));
    m_MainTab.SetTabInfo(index, &Tab3);
    m_MainTab.SetTabWindowPage(index, m_pTabLogo);

    m_MainTab.SetControlInfo(&CtlInit);

    // Make sure to turn redraw back on
    m_MainTab.SetRedraw(TRUE);
    m_MainTab.InvalidateRect(NULL, TRUE);

    // If you are not using the sheet/page classes, remove the call to InitializeTabControl.
    // Initialize tab control
    InitializeTabControl(this, 0, &m_MainTab, NULL);
    // Mark the view as a main, tabbed window (so accel. keys work) by registering it.
    SftTabs_RegisterWindow(m_hWnd);

    // resize this formview based on size of dialog in resource
    ResizeParentToFit();

    return TRUE;
}

Each call to CSftTabs::SetTabWindowPage associates a CSftTabsWindowPage based window with a tab.

The call to CSftTabsWindowSheet::InitializeTabControl starts the tabbed window handling and creates the current page.

Cleanup of all resources is accomplished by the call to CSftTabsWindowSheet::TerminateTabControl.

void CSampleView::OnDestroy()
{
    // Remove all pages from the tab control
    TerminateTabControl(this, &m_MainTab);
    // Unregister, or the window properties used won't be removed
    SftTabs_UnregisterWindow(m_hWnd);

    // the logo page must be explicitly delete'd
    delete m_pTabLogo;

    CFormView::OnDestroy();
}

The following WM_SIZE message handler OnSize resizes the tabbed window's child windows:

void CSampleView::OnSize(UINT nType, int cx, int cy)
{
    CFormView::OnSize(nType, cx, cy);

    if (m_MainTab.m_hWnd) {
        CRect rect;
        m_MainTab.GetClientRect(&rect);
        m_MainTab.MapWindowPoints(this, (LPPOINT)&rect, 2);
        m_MainTab.MoveWindow(rect.left, rect.top, cx-2*rect.left, cy-rect.top - rect.left, TRUE);
    }
}

As the main tabbed window receives notifications from the tab control that the user is switching to another page, it has to handle these notifications using the CSftTabsWindowSheet::TabSwitching and CSftTabsWindowSheet::TabSwitched member functions.

By calling the CSftTabsWindowSheet::TabSwitching member function, the class implementation then calls CSftTabsWindowPage::AllowSwitch to determine if the current page can be left, giving the application the opportunity to cancel tab switching.

void CSampleView::OnTabSwitching()
{
    // Switching away from the current tab
    TabSwitching(this, &m_MainTab);
}

void CSampleView::OnTabSwitched()
{
    // In case no one else wants to be an active view (such as the CLogo page),
    // we'll make the main view current
    GetParentFrame()->SetActiveView(this);

    // Switch to the new tab
    TabSwitched(this, &m_MainTab);

    // When switching tabs, views "grab" the input focus. You can explicitly set the
    // focus back to the tab control
    m_MainTab.SetFocus();
}

Creating a Page

Most CWnd based classes are suitable to become a page in a tabbed window. By using multiple inheritance, a class can be used as a page by inheriting the required support from the class CSftTabsWindowPage.

class CAttrPage : public CFormView, public CSftTabsWindowPage
{
    ... class definitions
}

The following sample code (from \Program Files (x86)\Softelvdm\SftTabs DLL 6.5\Samples\MFC\SDI\AttrPage.cpp) shows a typical implementation of a page. Most of the code has been created using SftTabs/DLL Wizard.

BOOL CAttrPage::ActivatePage(CWnd* pParent, CSftTabs* pTabCtl)
{
    // This is called when the user switches to a page
    if (!m_hWnd) {
        // The window doesn't exist, create it now. Make sure it's NOT VISIBLE
        // You can modify this to create another type of window instead.
        // The exact syntax of the Create function used depends on the base
        // class used.
        if (!Create(NULL, NULL,
                WS_TABSTOP |             // Tabstop style is important
                WS_CHILD,
                CRect(0,0,0,0),          // location
                pParent,                 // Parent Window
                IDC_ATTR,                // control ID
                &m_SavedContext))
                // make sure the above control ID does not collide with
                // IDs used by other pages or by the tab control itself
            return FALSE;
        // Additional initialization if desired
        // Because the document already exists, we need to explicitly call
        // OnInitialUpdate();
        OnInitialUpdate();
    } else {
        // The user switched back to this page
    }

    // This page is now active
    SftTabs_SetPageActive(m_hWnd, pTabCtl->m_hWnd, NULL);
    // Enable + show it, its size is 0,0,0,0, it will be resized by the tab control
    EnableWindow(TRUE);
    ShowWindow(SW_SHOW);

    // Make sure this view is made active
    GetParentFrame()->SetActiveView(this, TRUE);

    return TRUE;
}

void CAttrPage::DeactivatePage(CWnd* pParent, CSftTabs* pTabCtl, BOOL fFinal)
{
    if (fFinal) {
        // You must destroy the window, the tabbed window (parent) is going away
        if (m_hWnd)
            DestroyWindow();
        else
            PostNcDestroy();
        // Views delete themselves in their PostNcDestroy member function
        // But that means a view has to have been "Create"ed for that to work.
        // For that reason we call PostNcDestroy explicitly in the DeactivatePage
        // routine of this object. That way the view can be "delete"ed without
        // having been "Create"ed first.
    } else {
        // Hide the page. If you want, you could use DestroyWindow here too.
        // In that case you save resources and the window will be recreated
        // when the user switches back to this page
        ShowWindow(SW_HIDE);
        EnableWindow(FALSE);
    }
    // clear associated page in tab's control structure
    SftTabs_SetPageInactive(pTabCtl->m_hWnd);
}

The CSftTabsWindowPage::ActivatePage and CSftTabsWindowPage::DeactivatePage member functions must be implemented by a page. SftTabs/DLL Wizard generates the required sample code.

These functions allow the application to do initialization and termination processing for each page.


Last Updated 08/13/2020 - (email)
© 2024 Softel vdm, Inc.