Tab ControlsTab Controls*
*Contents  *Index  *Topic Contents
*Previous Topic: SBN_SIMPLEMODECHANGE
*Next Topic: Tab Control Reference

Tab Controls


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 certain type of information or a group of controls that the application displays when the user selects the corresponding tab.

arrowy.gifAbout Tab Controls

arrowy.gifUsing Tab Controls

arrowy.gifTab Control Updates in Internet Explorer

arrowy.gifTab Control Reference

About Tab Controls

You can create a tab control by calling the CreateWindowEx function, specifying the WC_TABCONTROL window class. This window class is registered when the common controls dynamic-link library (DLL) is loaded. To ensure that the DLL is loaded, use the InitCommonControls function.

You send messages to a tab control to add tabs and otherwise affect the control's appearance and behavior. Each message has a corresponding macro that you can use instead of sending the message explicitly. You cannot disable an individual tab in a tab control. However, you can disable a tab control in a property sheet by disabling the corresponding page.

About Tab Control Styles

You can apply certain characteristics to tab controls by specifying tab control styles when the control is created. For example, you can specify the alignment and general appearance of the tabs in a tab control.

You can cause the tabs to look like buttons by specifying the TCS_BUTTONS style. Tabs in this type of tab control should serve the same function as button controls; that is, clicking a tab should carry out a command instead of displaying a page. Because the display area in a button tab control is typically not used, no border is drawn around it.

You can cause a tab to receive the input focus when clicked by specifying the TCS_FOCUSONBUTTONDOWN style. This style is typically used only with the TCS_BUTTONS style. You can specify that a tab never receives the input focus by using the TCS_FOCUSNEVER style.

By default, a tab control displays only one row of tabs. If not all tabs can be shown at once, the tab control displays an up-down control so that the user can scroll additional tabs into view. You can cause a tab control to display multiple rows of tabs, if necessary, by specifying the TCS_MULTILINE style. With this style, all tabs can be displayed at once. The tabs are left-aligned within each row unless you specify the TCS_RIGHTJUSTIFY style. In this case, the width of each tab is increased so that each row of tabs fills the entire width of the tab control.

A tab control automatically sizes each tab to fit its icon, if any, and its label. To give all tabs the same width, you can specify the TCS_FIXEDWIDTH style. The control sizes all the tabs to fit the widest label, or you can assign a specific width and height by using the TCM_SETITEMSIZE message. Within each tab, the control centers the icon and label, placing the icon to the left of the label. You can force the icon to the left, leaving the label centered, by specifying the TCS_FORCEICONLEFT style. You can left-align both the icon and label by using the TCS_FORCELABELLEFT style. You cannot use the TCS_FIXEDWIDTH style with the TCS_RIGHTJUSTIFY style.

You can specify that the parent window draws the tabs in the control by using the TCS_OWNERDRAWFIXED style. For more information, see Owner-Drawn Tabs.

You can specify that a tab control will create a tooltip control by using the TCS_TOOLTIPS style. For more information about this, see Tab Control Tooltips.

Tabs and Tab Attributes

Each tab in a tab control consists of an icon, a label, and application-defined data. This information is specified by a TCITEM structure. You can add tabs to a tab control, get the number of tabs, retrieve and set the contents of a tab, and delete tabs. Tabs are identified by their zero-based index.

To add tabs to a tab control, use the TCM_INSERTITEM message, specifying the position of the item and the address of a TCITEM structure. You can retrieve and set the contents of an existing tab by using the TCM_GETITEM and TCM_SETITEM messages. For each tab, you can specify an icon, a label, or both. You can also specify application-defined data to associate with the tab.

You can retrieve the current number of tabs by using the TCM_GETITEMCOUNT message, delete a tab by using the TCM_DELETEITEM message, and delete all tabs in a tab control by using the TCM_DELETEALLITEMS message.

You can associate application-defined data with each tab. For example, you might save information about each page with its corresponding tab. By default, a tab control allocates four extra bytes per tab for application-defined data. You can change the number of extra bytes per tab by using the TCM_SETITEMEXTRA message. You can only use this message when the tab control is empty.

The application-defined data is specified by the lParam member of the TCITEM structure. If you use more than 4 bytes of application-defined data, you need to define your own structure and use it instead of TCITEM. You can retrieve and set application-defined data the same way you retrieve and set other information about a tab—by using the TCM_GETITEM and TCM_SETITEM messages.

The first member of your structure must be a TCITEMHEADER structure, and the remaining members must specify application-defined data. TCITEMHEADER is identical to TCITEM, except it does not have the lParam member. The difference between the size of your structure and the size of TCITEMHEADER should equal the number of extra bytes per tab.

Display Area

The display area of a tab control is the area in which an application displays the current page. Typically, an application creates a child window or dialog box, setting the window size and position to fit the display area. Given the window rectangle for a tab control, you can calculate the bounding rectangle of the display area by using the TCM_ADJUSTRECT message.

Sometimes the display area must be a particular size—for example, the size of a modeless child dialog box. Given the bounding rectangle for the display area, you can use TCM_ADJUSTRECT to calculate the corresponding window rectangle for the tab control.

Tab Selection

When the user selects a tab, a tab control sends its parent window notification messages in the form of WM_NOTIFY messages. The TCN_SELCHANGING notification message is sent before the selection changes, and the TCN_SELCHANGE notification message is sent after the selection changes.

You can process TCN_SELCHANGING to save the state of the outgoing page. You can return TRUE to prevent the selection from changing. For example, you might not want to switch away from a child dialog box in which a control has an invalid setting.

You must process TCN_SELCHANGE to display the incoming page in the display area. This might simply entail changing the information displayed in a child window. More often, each page consists of a child window or dialog box. In this case, an application might process this notification by destroying or hiding the outgoing child window or dialog box and by creating or showing the incoming child window or dialog box.

You can retrieve and set the current selection by using the TCM_GETCURSEL and TCM_SETCURSEL messages.

Tab Control Image Lists

Each tab can have an icon associated with it, which is specified by an index in the image list for the tab control. When a tab control is created, it has no image list associated with it. An application can create an image list by using the ImageList_Create function and then assign it to a tab control by using the TCM_SETIMAGELIST message.

You can add images to a tab control's image list just as you would to any other image list. However, an application should remove images by using the TCM_REMOVEIMAGE message instead of the ImageList_Remove function. This message ensures that each tab remains associated with the same image as before.

Destroying a tab control does not destroy an image list that is associated with it. You must destroy the image list separately. This is useful if you want to assign the same image list to multiple tab controls.

To retrieve the handle to the image list currently associated with a tab control, you can use the TCM_GETIMAGELIST message.

Tab Size and Position

Each tab in a tab control has a size and position. You can set the size of tabs, retrieve the bounding rectangle of a tab, or determine which tab is at a specified position.

For fixed-width and owner-drawn tab controls, you can set the exact width and height of tabs by using the TCM_SETITEMSIZE message. In other tab controls, each tab's size is calculated based on the icon and label for the tab. The tab control includes space for a border and an additional margin. You can set the thickness of the margin by using the TCM_SETPADDING message.

You can determine the current bounding rectangle for a tab by using the TCM_GETITEMRECT message. You can determine which tab, if any, is at a specified location by using the TCM_HITTEST message.

In a tab control with the TCS_MULTILINE style, you can determine the current number of rows of tabs by using the TCM_GETROWCOUNT message.

Owner-Drawn Tabs

If a tab control has the TCS_OWNERDRAWFIXED style, the parent window must paint tabs by processing the WM_DRAWITEM message. The tab control sends this message whenever a tab needs to be painted. The lParam parameter specifies the address of a DRAWITEMSTRUCT structure, which contains the index of the tab, its bounding rectangle, and the device context (DC) in which to draw.

By default, the itemData member of DRAWITEMSTRUCT contains the value of the lParam member of the TCITEM structure. However, if you change the amount of application-defined data per tab, itemData contains the address of the data instead. You can change the amount of application-defined data per tab by using the TCM_SETITEMEXTRA message.

To specify the size of items in a tab control, the parent window must process the WM_MEASUREITEM message. Because all tabs in an owner-drawn tab control are the same size, this message is sent only once. There is no tab control style for owner-drawn tabs of varying size. You can also set the width and height of tabs by using the TCM_SETITEMSIZE message.

Tab Control Tooltips

You can use a tooltip control to provide a brief description of each tab in a tab control. A tab control that has the TCS_TOOLTIPS style creates a tooltip control when it is created and destroys the tooltip control when it is destroyed. You can also create a tooltip control and assign it to a tab control.

If you use a tooltip control with a tab control, the parent window must process the TTN_NEEDTEXT notification message to provide a description of each tab on request.

To use the same tooltip control with more than one tab control, create the tooltip control yourself and assign it to the tab control by using the TCM_SETTOOLTIPS message. You can get the handle to a tab control's current tooltip control by using the TCM_GETTOOLTIPS message. If you create your own tooltip control, you should not use the TCS_TOOLTIPS style. For more information about tooltip controls, see Tooltip Controls.

Default Tab Control Message Processing

This section describes the message processing performed by a tab control. Messages specific to tab controls are discussed in other sections of this documentation.
Message Processing performed
WM_CAPTURECHANGED Does nothing if the tab control released the mouse capture itself. If another window captured the mouse and a button is held down, the command releases the button.
WM_CREATE Allocates and initializes an internal data structure. The control creates a tooltip control if the TCS_TOOLTIPS style is specified.
WM_DESTROY Frees resources allocated during WM_CREATE processing.
WM_GETDLGCODE Returns a combination of the DLGC_WANTARROWS and DLGC_WANTCHARS values.
WM_GETFONT Returns the handle to the font used for labels.
WM_KEYDOWN Processes direction keys and changes the selection, if appropriate.
WM_KILLFOCUS Invalidates the tab that has the focus so it will be repainted to reflect an unfocused state.
WM_LBUTTONDOWN Forwards the message to the tooltip control, if any, and changes the selection if the user is clicking a tab. If the user is clicking a button, the control redraws the button to give a sunken appearance and captures the mouse.

If the user is clicking either a tab or button and the TCS_FOCUSONBUTTONDOWN style is specified, the control sets the focus to itself.

WM_LBUTTONUP Releases the mouse if a button was pressed. If the cursor is over the button and is being held down, the control changes the selection accordingly and redraws the button.
WM_MOUSEMOVE Forwards the message to the tooltip control, if any. If the TCS_BUTTONS style is specified and the mouse button is being held down after clicking, the control may also redraw the affected button to give it a raised or sunken appearance.
WM_NOTIFY Forwards notification messages sent by the tooltip control.
WM_PAINT Draws a border around the display area (unless the TCS_BUTTONS style is specified) and paints any tabs that intersect the invalid rectangle.

For each tab, it draws the body of the tab (or sends a WM_DRAWITEM message to the parent window) and then draws a border around the tab. If the wParam parameter is non-NULL, the control assumes that the value is an HDC and paints using that device context.

WM_RBUTTONDOWN Sends an NM_RCLICK notification message to the parent window.
WM_SETFOCUS Invalidates the tab that has the focus so that it will be repainted to reflect a focused state.
WM_SETFONT Sets the font used for labels.
WM_SETREDRAW Sets the state of an internal flag that determines whether the control is repainted when items are inserted and deleted, when the font is changed, and so on.
WM_SIZE Recalculates the positions of tabs and may invalidate part of the tab control to force repainting of some or all tabs.

Using Tab Controls

This section provides two examples that use tab controls. The first example demonstrates how to use a tab control to switch between multiple pages of text in an application's main window. The second example demonstrates how to use a tab control to switch between multiple pages of controls in a dialog box.

Creating a Tab Control

The example in this section demonstrates how to create a tab control and display it in the client area of the application's main window. The application displays a third window (a static control) in the display area of the tab control. The parent window positions and sizes the tab control and static control when it processes the WM_SIZE message.

There are seven tabs, one for each day of the week. When the user selects a tab, the application displays the name of the corresponding day in the static control. The following global variables are used in this example.

// Global variables 
 
	HINSTANCE g_hinst;    // handle to application instance 
	char g_achTemp[256];  // temporary buffer for strings 
	HWND g_hwndMain;      // main application window 
	HWND g_hwndTab;       // tab control 
	HWND g_hwndDisplay;   // handle to static control in 
                      //   tab control's display area 
 

The following function creates the tab control and adds a tab for each day of the week. The names of the days are defined as string resources, consecutively numbered starting with IDS_FIRSTDAY (defined in the application's header file). Both the parent window and the tab control must have the WS_CLIPSIBLINGS window style. The application's initialization function calls this function after creating the main window.

// DoCreateTabControl - creates a tab control, sized to fit the 
	//     specified parent window's client area, and adds some tabs. 
	// Returns the handle to the tab control. 
	// hwndParent - parent window (the application's main window). 
 
	HWND WINAPI DoCreateTabControl(HWND hwndParent) 
	{ 
    RECT rcClient; 
    HWND hwndTab; 
    TCITEM tie; 
    int i; 
 
    // Get the dimensions of the parent window's client area, and 
    // create a tab control child window of that size. 
    GetClientRect(hwndParent, &rcClient); 
    InitCommonControls(); 
    hwndTab = CreateWindow( 
        WC_TABCONTROL, "", 
        WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE, 
        0, 0, rcClient.right, rcClient.bottom, 
        hwndParent, NULL, g_hinst, NULL 
        ); 
    if (hwndTab == NULL) 
        return NULL; 
 
    // Add tabs for each day of the week. 
    tie.mask = TCIF_TEXT | TCIF_IMAGE; 
    tie.iImage = -1; 
    tie.pszText = g_achTemp; 
 
    for (i = 0; i < 7; i++) { 
        LoadString(g_hinst, IDS_FIRSTDAY + i, 
                g_achTemp, sizeof(g_achTemp)); 
        if (TabCtrl_InsertItem(hwndTab, i, &tie) == -1) { 
            DestroyWindow(hwndTab); 
            return NULL; 
        } 
    } 
    return hwndTab; 
	} 
 

The following function creates the static control that occupies the tab control's display area. The application's initialization function calls this function after creating the main window and the tab control.

	// DoCreateDisplayWindow - creates a child window (a static 
	//     control) to occupy the tab control's display area. 
	// Returns the handle to the static control. 
	// hwndParent - parent window (the application's main window). 
 
	HWND WINAPI DoCreateDisplayWindow(HWND hwndParent) 
	{ 
    HWND hwndStatic = CreateWindow("STATIC", "", 
        WS_CHILD | WS_VISIBLE | WS_BORDER, 
        0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 
        hwndParent, NULL, g_hinst, NULL); 
 
    return hwndStatic; 
	} 
 

Following are the relevant portions of the application's window procedure. The application processes the WM_SIZE message to position and size the tab control and the static control. To determine the appropriate position and size for the static control, this example sends the tab control a TCM_ADJUSTRECT message (by using the TabCtrl_AdjustRect macro).

When a tab is selected, the tab control sends a WM_NOTIFY message, specifying the TCN_SELCHANGE notification message. The application processes this notification message by setting the text of the static control.

	// MainWindowProc - processes the message for the main window class. 
	// The return value depends on the message. 
	// hwnd - handle to the window. 
	// uMsg - identifier for the message. 
	// wParam - message-specific parameter. 
	// lParam - message-specific parameter. 
 
	LRESULT CALLBACK MainWindowProc( 
        HWND hwnd, 
        UINT uMsg, 
        WPARAM wParam, 
        LPARAM lParam 
        ) 
	{ 
    switch (uMsg) { 
        case WM_SIZE: { 
                HDWP hdwp; 
                RECT rc; 
 
                // Calculate the display rectangle, assuming the 
                // tab control is the size of the client area. 
                SetRect(&rc, 0, 0, 
                        LOWORD(lParam), HIWORD(lParam)); 
                TabCtrl_AdjustRect(g_hwndTab, FALSE, &rc); 
 
                // Size the tab control to fit the client area. 
                hdwp = BeginDeferWindowPos(2); 
                DeferWindowPos(hdwp, g_hwndTab, NULL, 0, 0, 
                    LOWORD(lParam), HIWORD(lParam), 
                    SWP_NOMOVE | SWP_NOZORDER 
                    ); 
 
                // Position and size the static control to fit the 
                // tab control's display area, and make sure the 
                // static control is in front of the tab control. 
                DeferWindowPos(hdwp, 
                    g_hwndDisplay, HWND_TOP, rc.left, rc.top, 
                    rc.right - rc.left, rc.bottom - rc.top, 0 
                    ); 
                EndDeferWindowPos(hdwp); 
            } 
            break; 
 
        case WM_NOTIFY: 
            switch (HIWORD(wParam)) { 
                case 0: 
                    . 
                    .    // menu command processing 
                    . 
 
                case TCN_SELCHANGE: { 
                        int iPage = TabCtrl_GetCurSel(g_hwndTab); 
                        LoadString(g_hinst, IDS_FIRSTDAY + iPage, 
                            g_achTemp, sizeof(g_achTemp)); 
                        SendMessage(g_hwndDisplay, WM_SETTEXT, 0 
                            (LPARAM) g_achTemp); 
                    } 
                    break; 
            } 
            break; 
 
            . 
            .       // additional message processing 
            . 
 
        default: 
            return DefWindowProc(hwnd, uMsg, wParam, lParam); 
    } 
    return 0; 
	} 
 

Creating a Tabbed Dialog Box

The example in this section demonstrates how to create a dialog box that uses tabs to provide multiple pages of controls. The main dialog box is a modal dialog box. Each page of controls is defined by a dialog box template that has the WS_CHILD style. When a tab is selected, a modeless dialog box is created for the incoming page and the dialog box for the outgoing page is destroyed.

Note In many cases, you can implement multiple-page dialog boxes more easily by using property sheets. For more information about property sheets, see Property Sheets

The template for the main dialog box simply defines two button controls. When processing the WM_INITDIALOG message, the dialog box procedure creates a tab control and loads the dialog template resources for each of the child dialog boxes.

The information is saved in an application-defined structure called DLGHDR. A pointer to this structure is associated with the dialog box window by using the SetWindowLong function. The structure is defined in the application's header file, as follows:

	#define C_PAGES 3 
 
	typedef struct tag_dlghdr { 
    HWND hwndTab;       // tab control 
    HWND hwndDisplay;   // current child dialog box 
    RECT rcDisplay;     // display rectangle for the tab control 
    DLGTEMPLATE *apRes[C_PAGES]; 
	} DLGHDR; 
 

The following function processes the WM_INITDIALOG message for the main dialog box. The function allocates the DLGHDR structure, loads the dialog template resources for the child dialog boxes, and creates the tab control.

The size of each child dialog box is specified by the DLGTEMPLATE structure. The function examines the size of each dialog box and uses the macro for the TCM_ADJUSTRECT message to calculate an appropriate size for the tab control. Then it sizes the dialog box and positions the two buttons accordingly. This example sends TCM_ADJUSTRECT by using the TabCtrl_AdjustRect macro.

	VOID WINAPI OnTabbedDialogInit(HWND hwndDlg) 
	{ 
    DLGHDR *pHdr = (DLGHDR *) LocalAlloc(LPTR, sizeof(DLGHDR)); 
    DWORD dwDlgBase = GetDialogBaseUnits(); 
    int cxMargin = LOWORD(dwDlgBase) / 4; 
    int cyMargin = HIWORD(dwDlgBase) / 8; 
    TCITEM tie; 
    RECT rcTab; 
    HWND hwndButton; 
    RECT rcButton; 
    int i; 
 
    // Save a pointer to the DLGHDR structure. 
    SetWindowLong(hwndDlg, GWL_USERDATA, (LONG) pHdr); 
 
    // Create the tab control. 
    InitCommonControls(); 
    pHdr->hwndTab = CreateWindow( 
        WC_TABCONTROL, "", 
        WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE, 
        0, 0, 100, 100, 
        hwndDlg, NULL, g_hinst, NULL 
        ); 
    if (pHdr->hwndTab == NULL) {
        // handle error
    }
 
    // Add a tab for each of the three child dialog boxes. 
    tie.mask = TCIF_TEXT | TCIF_IMAGE; 
    tie.iImage = -1; 
    tie.pszText = "First"; 
    TabCtrl_InsertItem(pHdr->hwndTab, 0, &tie); 
    tie.pszText = "Second"; 
    TabCtrl_InsertItem(pHdr->hwndTab, 1, &tie); 
    tie.pszText = "Third"; 
    TabCtrl_InsertItem(pHdr->hwndTab, 2, &tie); 
 
    // Lock the resources for the three child dialog boxes. 
    pHdr->apRes[0] = DoLockDlgRes(MAKEINTRESOURCE(DLG_FIRST)); 
    pHdr->apRes[1] = DoLockDlgRes(MAKEINTRESOURCE(DLG_SECOND)); 
    pHdr->apRes[2] = DoLockDlgRes(MAKEINTRESOURCE(DLG_THIRD)); 
 
    // Determine the bounding rectangle for all child dialog boxes. 
    SetRectEmpty(&rcTab); 
    for (i = 0; i < C_PAGES; i++) { 
        if (pHdr->apRes[i]->cx > rcTab.right) 
            rcTab.right = pHdr->apRes[i]->cx; 
        if (pHdr->apRes[i]->cy > rcTab.bottom) 
            rcTab.bottom = pHdr->apRes[i]->cy; 
    } 
    rcTab.right = rcTab.right * LOWORD(dwDlgBase) / 4; 
    rcTab.bottom = rcTab.bottom * HIWORD(dwDlgBase) / 8; 
 
    // Calculate how large to make the tab control, so 
    // the display area can accommodate all the child dialog boxes. 
    TabCtrl_AdjustRect(pHdr->hwndTab, TRUE, &rcTab); 
    OffsetRect(&rcTab, cxMargin - rcTab.left, 
            cyMargin - rcTab.top); 
 
    // Calculate the display rectangle. 
    CopyRect(&pHdr->rcDisplay, &rcTab); 
    TabCtrl_AdjustRect(pHdr->hwndTab, FALSE, &pHdr->rcDisplay); 
 
    // Set the size and position of the tab control, buttons, 
    // and dialog box. 
    SetWindowPos(pHdr->hwndTab, NULL, rcTab.left, rcTab.top, 
            rcTab.right - rcTab.left, rcTab.bottom - rcTab.top, 
            SWP_NOZORDER); 
 
    // Move the first button below the tab control. 
    hwndButton = GetDlgItem(hwndDlg, BTN_CLOSE); 
    SetWindowPos(hwndButton, NULL, 
            rcTab.left, rcTab.bottom + cyMargin, 0, 0, 
            SWP_NOSIZE | SWP_NOZORDER); 
 
    // Determine the size of the button. 
    GetWindowRect(hwndButton, &rcButton); 
    rcButton.right -= rcButton.left; 
    rcButton.bottom -= rcButton.top; 
 
    // Move the second button to the right of the first. 
    hwndButton = GetDlgItem(hwndDlg, BTN_TEST); 
    SetWindowPos(hwndButton, NULL, 
        rcTab.left + rcButton.right + cxMargin, 
        rcTab.bottom + cyMargin, 0, 0, 
        SWP_NOSIZE | SWP_NOZORDER); 
 
    // Size the dialog box. 
    SetWindowPos(hwndDlg, NULL, 0, 0, 
        rcTab.right + cyMargin + 
        2 * GetSystemMetrics(SM_CXDLGFRAME), 
        rcTab.bottom + rcButton.bottom + 2 * cyMargin + 
        2 * GetSystemMetrics(SM_CYDLGFRAME) + 
        GetSystemMetrics(SM_CYCAPTION), 
        SWP_NOMOVE | SWP_NOZORDER); 
 
    // Simulate selection of the first item. 
    OnSelChanged(hwndDlg); 
	} 
 
	// DoLockDlgRes - loads and locks a dialog template resource. 
	// Returns the address of the locked resource. 
	// lpszResName - name of the resource 
 
	DLGTEMPLATE * WINAPI DoLockDlgRes(LPCSTR lpszResName) 
	{ 
    HRSRC hrsrc = FindResource(NULL, lpszResName, RT_DIALOG); 
    HGLOBAL hglb = LoadResource(g_hinst, hrsrc); 
    return (DLGTEMPLATE *) LockResource(hglb); 
	} 
 

The following function processes the TCN_SELCHANGE notification message for the main dialog box. The function destroys the dialog box for the outgoing page, if any. Then it uses the CreateDialogIndirect function to create a modeless dialog box for the incoming page.

	// OnSelChanged - processes the TCN_SELCHANGE notification. 
	// hwndDlg - handle to the parent dialog box. 
 
	VOID WINAPI OnSelChanged(HWND hwndDlg) 
	{ 
	    DLGHDR *pHdr = (DLGHDR *) GetWindowLong( 
        hwndDlg, GWL_USERDATA); 
    int iSel = TabCtrl_GetCurSel(pHdr->hwndTab); 
 
    // Destroy the current child dialog box, if any. 
    if (pHdr->hwndDisplay != NULL) 
        DestroyWindow(pHdr->hwndDisplay); 
 
    // Create the new child dialog box. 
    pHdr->hwndDisplay = CreateDialogIndirect(g_hinst, 
        pHdr->apRes[iSel], hwndDlg, ChildDialogProc); 
	} 
	 

The following function processes the WM_INITDIALOG message for each of the child dialog boxes. You cannot specify the position of a dialog box created using the CreateDialogIndirect function. This function uses the SetWindowPos function to position the child dialog within the tab control's display area.

	// OnChildDialogInit - Positions the child dialog box to fall 
	//     within the display area of the tab control. 
 
	VOID WINAPI OnChildDialogInit(HWND hwndDlg) 
	{ 
    HWND hwndParent = GetParent(hwndDlg); 
    DLGHDR *pHdr = (DLGHDR *) GetWindowLong( 
        hwndParent, GWL_USERDATA); 
    SetWindowPos(hwndDlg, HWND_TOP, 
        pHdr->rcDisplay.left, pHdr->rcDisplay.top, 
        0, 0, SWP_NOSIZE); 
	} 
 

Tab Control Updates in Internet Explorer

Tab controls in Microsoft® Internet Explorer support the following new features.

Item States
Tab control items now support an item state to support the TCM_DESELECTALL message. Additionally, the TCITEM structure supports item state values. See Tab Control Item States for more information.
Extended Styles
Tab controls now support extended styles that allow the controls to have enhanced capabilities. See Tab Control Extended Styles for more information.
Structures Renamed
All structures used with tab controls have been renamed to conform to current naming conventions, while maintaining backward compatibility. For example, the TC_ITEM structure is now named TCITEM.

Up Top of Page
© 1997 Microsoft Corporation. All rights reserved. Terms of Use.