tab控件

来源:互联网 发布:高中知识软件下载 编辑:程序博客网 时间:2024/05/09 08:59

//by dump(许彦) 

    Tab控制    (需要链接的头文件及链接库:commctrl.h comctl32.lib)

 

    tab控制类似于笔记本里的分割物或者文件柜里的标签,通过使用tab控制,应用程序可以在窗口或者对话框范围内定义多个页面,各页包括一定特征的信息或一组控制,当用户选择制表符的时候,对应的应用程序信息就显示出来。

 

    关于Tab控制

 

    你可以指定WC_TABCONTROL窗口类,然后通过调用CreateWindowEx函数来创建一个tab控制,当公有控制动态链接库(DLL)被装载的时候,这种窗口类才被注册。为了确保DLL被装载, 要使用InitCommonControls函数!

 

    你通过向tab控制发送消息来添加标签和其它影响这个控制的外观和行为,每个消息都有一个对应的宏,你可以通过发送消息来替换它们。你无法在tab控制里禁用一个标签,但是你可以使对应的页失去能力,使标签在属性表里失去控制能力。

 

    关于Tab控制的样式

 

    当你要创建某个控制时,你可以通过指定tab控制样式来使tab控制具有某些特征。例如,你可以在tab控制里指定tab控制的对齐特性和一般外观。

 

你通过指定TCS_BUTTON样式可以使标签看起来象按钮一样,这种类型的标签和按钮控制具有一样的功能,就是说,点击一个标签应该执行替换显示一个页面的命令,在一个按钮tab控制里代表这个显示区域没有用,故周围边界没有画出。

 

你可以使用TCS_FOCUSONBUTTONDOWN样式来指定tab在被鼠标点击时接受输入焦点,这种样式一般只在 TCS_BUTTONS样式下使用,通过使用TCS_FOCUSNEVER样式可以使标签被点击时不接受输入焦点。

 

在默认情况下,tab控制只把标签显示为一行,如果所有的标签不是被完整的显示出来,tab控制将显示一个up-down控制,用户通过它滚动其它的标签到视窗里,你也能指定TCS_MULTILINE样式使tab控制把标签显示为多行,这种样式使所有的标签能够完整的显示出来。这种标签的每一行都是左对齐的,除非你指定TCS_RIGHTJUSTIFY对齐样式,这样,每个标签会增加它们的宽度来使每一行的标签能够充满tab控制的整个宽度。

 

tab控制自动地调整每一个标签的大小来容纳它们的图标和可能存在的字符。通过指定TCS_FIXEDWIDTH样式,能使所有的标签具有相同的宽度,所有这些标签完全匹配控制大小,你可以用TCM_SETITEMSIZE消息来指定它的宽度和高度。在每一个标签里,控制居中图标和字符,并把图标放在符号的左边,你可以通过指定TCS_FORCEICONLEFT样式强制把图标放在左边,让字符不居中,你能通过用TCS_FORCELABELLEFT样式左对齐图标和字符,但你无法同时用TCS_FIXEDWIDTH样式和TCS_RIGHTJUSTIFY样式。

 

你可以通过指定TCS_OWNERDRAWFIXED样式让父窗口来绘制控制里的标签。获取更多的信息,见Owner-Drawn Tabs链接。

你可以用TCS_TOOLTIPS样式让tab控制创建一个ToolTip控制,相关信息,见Tab Control ToolTips链接。

 

标签和标签属性

 

控制里的每一个标签由一个图标和字符组成,还有应用程序定义的数据,由一个TCITEM结构来指定这些信息。你可以添加标签到tab控制里,找回标签的数值,获取和设置标签的内容,删除标签。标签是以基于0的索引来标识的。

 

添加标签到控制,可以使用TCM_INSERTITEM消息,在一个TCITEM结构里指定项目的位置和地址。你能通过TCM_GETITEM和TCM_SETITEM消息来获取和设置现有的标签内容。对于每个标签,你能指定一个图标和字符两者之一,或者两者都指定,你同样可以使程序定义的数据和标签联系起来。

 

你可以通过TCM_GETITEMCOUNT消息来重新得到标签的当前值,通过TCM_DELETEITEM消息来删除一个标签,和通过TCM_DELETEALLITEMS消息来删除tab控制里的所有标签。

 

你可以把应用程序数据与每一个标签关联起来,你可以存储每一个页面的信息和它们对应的标签。默认情况下,tab控制为每一个标签分配4个额外的字节给应用程序定义的数据,你能通过TCM_SETITEMEXTRA消息来改变每个标签的额外字节数,但只有当tab控制为空的时候才能这样做。

 

应用程序定义的数据是通过TCITEM结构的lParam成员来指定的,如果你用超过4字节的应用程序定义数据,你需要定义你自己的结构,然后用它来替换TCITEM,你可以使用TCM_GETITEM和TCM_SETITEM的消息来获取和设置应用程序定义数据,可以用同样的方法来得到和设置关于标签的其它信息。

 

你的结构的第一个成员必须是一个TCITEMHEADER结构,剩余的成员指定应用程序数据,TCITEMHEADER除没有lParam成员外,与TCITEM是一样的。因此在你定义的结构和TCITEMHEADER结构的大小之间的差就等于额外字节数——程序数据。

 

显示范围

 

tab控制的显示区是应用程序显示当前页的区域,比如,一个应用程序创建一个子窗口或者对话框,设置窗口大小和位置来调整显示范围,给这个窗口一个长方形的tab控制,你能通过TCM_ADJUSTRECT消息来计算矩形显示范围。

 

有时,这个显示范围必须是一个给定的大小——比如,一个非模态子对话框的大小,你可以使用TCM_ADJUSTRECT来为tab控制计算对应的长方形窗口。

 

tab选择

 

当用户选择一个标签, tab控制以WM_NOTIFY 消息的形式把消息发送给他的父窗口。在选择改变之前TCN_SELCHANGING消息就要被送出, 并且TCN_SELCHANGE消息在选择改变之后就被送出。

 

你能处理TCN_SELCHANGING来存储即将退去页面的状态,返回TRUE来防止选择改变,比如,你也许不希望从一个无效设置的子对话框中转换过来。

 

你必须处理TCN_SELCHANGE来显示不断到来的需要在显示区显示的页面,这也许简单地在子窗口中改变显示的信息。经常是,每页包括子窗口或者对话框,在这种情况下,应用程序也许通过销毁或者隐藏退去的子窗口或者对话框来处理这些消息,然后创建或者显示引入的子窗口或者对话框。

 

你通过TCM_GETCURSEL和TCM_SETCURSEL消息能获取和设置当前选择。

 

tab控制的图像列表

 

每一个标签可以有一个图标与它相关联,这可以用tab控制的一个图像列表的索引来指定,当一个tab控制被创建,没有图像列表关联它,应用程序能够通过ImageList_Create函数创建一个图像列表,然后通过 TCM_SETIMAGELIST消息分配到tab控制。

 

你可以添加图像到tab控制,图像列表正如你希望添加到其它图像列表一样,但是,应用程序应该通过TCM_REMOVEIMAGE消息来移动图像替换ImageList_Remove函数,这条消息确保标签保留以前的图像关联。

 

销毁一个tab控制但不销毁一个关联它的图像列表后,你必须格外销毁这个图像列表,如果你希望把同一个图像列表与多个tab控制关联的话,这是很有用的。

 

找回与tab控制当前关联的图像列表的句柄,你可以通过发送TCM_GETIMAGELIST消息。

 

标签大小与位置

 

tab控制里的每个标签都有大小和位置,你可以设置标签的大小,找回标签边界矩形,或者指定标签的位置。

 

对固定宽度和owner-drawn tab控制,你可以通过用TCM_SETITEMSIZE消息来设置标签的宽度和高度,在其它样式的tab控制中,每个标签的大小计算是基于图标和符号的,tab控制包括边和页面边距的空间。你可以通过用TCM_SETPADDING消息来设置页边距的大小。

 

你可以通过TCM_GETITEMRECT消息来确定标签的当前矩形边界,通过TCM_HITTEST消息来确定指定的区域。

 

在一个具有TCS_MULTILINE样式的tab控制中,你可以通过TCM_GETROWCOUNT消息来确定当前标签的行数。

 

Owner-Drawn标签

 

如果一个tab控制具有TCS_OWNERDRAWFIXED样式,那么父窗口必须通过处理WM_DRAWITEM消息来绘制标签。在标签需要被绘制的时候,tab控制随时发送这条消息。lParam参数指定DRAWITEMSTRUCT结构的地址,它包含标签的索引,它的矩形边界,哪一个设备(DC)需要被绘制。

 

通常,DRAWITEMSTRUCT的itemData成员包含TCITEM结构的lParam成员的值,但是,如果你改变每个标签应用程序定义数据的数量,itemData包含数据替换的地址,你可以通过用TCM_SETITEMEXTRA消息来改变每个标签应用程序定义数据的数量。

 

指定tab控制项目组的大小,父窗口必须处理WM_MEASUREITEM消息。之所以所有的标签在一个owner-draw tab控制中是相同的大小,是因为这条消息只发送一次,没有哪种tab控制样式可以使owner- drawn标签具有不同的大小,你同样可以通过用TCM_SETITEMSIZE消息设置标签的宽度和高度。

 

tab控制ToolTips(工具栏提示)

 

你可以用一个ToolTip控制来简要介绍tab控制里的标签,tab控制具有TCS_TOOLTIPS风格时就创建一个ToolTip控制,当它创建后被销毁时ToolTip也被销毁,你同样可以创建一个ToolTip控制并分配它到tab控制中。

 

如果你在tab控制中使用ToolTip控制,父窗口必须处理TTN_NEEDTEXT通知消息描述每一个标签请求。

 

在多个tab控制上使用同一个ToolTip控制,创建ToolTip然后通过TCM_SETTOOLTIPS消息指定它到tab控制,你可以通过TCM_SETTOOLTIPS消息获取一个tab控制当前的ToolTip控制句柄,如果你创建你自己的ToolTip控制,你不需要用TCS_TOOLTIPS样式,更多关于ToolTip控制的信息,见ToolTip控制 链接。

 

tab控制消息的默认处理

 

这个部分介绍tab控制的消息处理过程,tab控制的消息讨论细节见本文档的其它部分。

 

消息                  处理过程

WM_CAPTURECHANGED    tab控制释放鼠标捕获它本身不对它做任何事,如果另一个窗口捕获鼠标并且一个按钮保持按下,这个命令释放这个按钮。

WM_CREATE             分配和初始化一个内部数据结构,如果TCS_TOOLTIPS样式被指定,控制创建一个ToolTip控制

WM_DESTROY            释放在WM_CREATE处理期间分配的资源

WM_GETDLGCODE        返回一个DLGC_WANTARROWS和DLGC_WANTCHARS值的联合

WM_GETFONT            返回被用作字符的字体句柄

WM_KEYDOWN            处理方向键和改变选择

WM_KILLFOCUS         使标签具有焦点无效,导致它被重画来反映没有焦点的状态

WM_LBUTTONDOWN       Forwards the message to the ToolTip控制,即便要,如果用户点击一个标签就改变选择,如果用户点击一个按钮,这个控制就重画这个按钮显示凹陷外观并捕获鼠标。如果用户点击标签或者按钮中的一个,并且TCS_FOCUSONBUTTONDOWN样式被指定,控制就设 置它自身的焦点。

WM_LBUTTONUP         如果按钮被压制就释放鼠标,如果光标在按钮上面并且被按下 ,控制就改变选择从而重画按钮。

WM_MOUSEMOVE         Forwards the message to the ToolTip控制,即便要,如果 TCS_BUTTONS样式被指定并且鼠标被按下后点击,控制可能同样重画受到影响的按钮给它一个凹陷的外观

WM_NOTIFY             Forwards通过ToolTip控制发送通知消息

WM_PAINT              围绕显示范围画一条边(除非TCS_BUTTONS样式被指定)并且画一 些标签交叉无效矩形。对于各自的标签,它画标签的主要部分(或者发送一条WM_DRAWITEM消息给父 窗口)然后画一条边围绕标签,如果wParam参数是NULL,控制假定值是一个HDC和用来作画的设备。

WM_RBUTTONDOWN       发送一条NM_RCLICK通知消息到父窗口。

WM_SETFOCUS          标签具有焦点无效,所以它要重画反映得到焦点状态。

WM_SETFONT            设置作用于符号的字体。

WM_SETREDRAW         设置一个内部标志的状态,确定无论控制被重画当项目组被插 入和删除,当字体被改变,等等。

WM_SIZE              重新计算标签的位置,可能导致tab控制的无效部分将被部分标签或者全部重画。

 

使用tab控制

 

这个部分介绍两个使用tab控制的例子,第一个例子示范在一个主窗口中怎样使用tab控制在多个文字页面之间切换,第二个例子示范在一个对话框中怎样使用多个对话框页面。

 

创建一个tab控制

 

这个例子示范怎样创建一个tab控制并且把它显示在应用程序主窗口的客户区,应用程序在tab控制的显示范围中显示一个第三种窗口(一个静态控制),当父窗口在处理WM_SIZE消息时改变tab控制和static控制的位置和大小。

 

有7个标签,一个星期中的每一天中的一个,当用户选择一个标签,应用程序在静态控制中显示对应星期几的名字,下面是这个例子中使用的全局变量。

 

//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

 

下列函数创建tab控制然后为一个星期中的每一天添加一个标签,每一天的名字被定义为字符串资源,以IDS_FIRSTDAY(定义在应用程序头文件中)连续的开始,父窗口和tab控制两者必须具有WS_CLIPSIBLINGS窗口风格,应用程序初始化函数在创建主窗口后调用这个函数。

 

//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;

}

 

下面的函数创建的静态控制占据tab控制的显示区域,应用程序初始化函数在创建主窗口和tab控制后调用这个函数。

// 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;

}

 

下面是应用程序的窗口过程相关部分,应用程序处理WM_SIZE消息改变tab控制和static控制的大小和位置,这个例子发送给tab控制一个TCM_ADJUSTRECT消息(通过用TabCtrl_AdjustRect宏)来确定静态控制适当的位置和大小。

 

当一个标签被选择,tab控制发送一个WM_NOTIFY消息,指定TCN_SELCHANGE通知消息,应用程序通过设置静态控制中的文本来响应这条消息。

 

// 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,

                        GET_X_LPARAM(lParam), GET_Y_LPARAM(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,

                    GET_X_LPARAM(lParam), GET_Y_LPARAM(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;

}

 

创建一个tab对话框

 

这个部份的例子示范怎样在控制的多个页面上创建对话框,主对话框是一个模态对话框,控制的每一个页面是通过具有WS_CHILD样式风格的对话框模板来定义的,当一个标签被选择时,引入一个页面时,一个非模态对话框将被创建并且退去页面的对话框将被销毁。

 

提示:在许多案例中,你能通过用property sheets更容易地实现多页面对话框,关于property sheets的更多信息,见property sheets链接。

 

主对话框模板简单地定义两个按钮控制,当处理WM_INITDIALOG消息时,对话框过程创建一个tab控制并且载入这个对话框的资源模板中各个子对话框。

 

这条信息被存储进应用程序定义的一个DLGHDR结构中,一个指向这个结构的联合通过使用SetWindowLong函数对话框窗口,这个结构被定义在应用程序的头文件中,如下所示:

 

#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;

 

下面的函数在主对话框处理WM_INITDIALOG消息时运行,函数分配DLGHDR结构,载入对话框模板中的子对话框资源,并创建tab控制。

 

每个子对话框是通过DLGTEMPLATE结构来指定大小的,这个函数检查每个子对话框的大小,并用TCM_ADJUSTRECT宏消息来计算一个tab控制适当的大小,然后它调整对话框大小,移动两个按钮控制的位置,这个例子通过使用TabCtrl_AdjustRect宏来发送TCM_ADJUSTRECT消息。

 

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 box 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);

}

 

下面的函数为主对话框处理TCN_SELCHANGE通知消息,函数销毁退去页面的对话框,然后它用CreateDialogIndirect函数来为引入的页面创建一个非模态对话框。

 

// 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);

}

 

下面的函数处理每一个子对话框的WM_INITDIALOG消息,你无法指定通过CreateDialogIndirect函数创建的对话框的位置,这个函数使用SetWindowPos函数来放置子对话框在tab控制显示范围的里面。

 

// 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);

}

 

在Internet Explorer上更新制表符控制

Internet Explorer 支持以下新特点。

项目状态

tab控制项目现在支持项目状态用来支持TCM_DESELECTALL 消息。另外, TCITEM 结构支持项目状态值。更多信息参见tab控制项目状态。

扩展样式

tab控制现在支持扩展样式,该扩展样式允许扩展tab控制的功能。更多信息参见tab控制扩展样式。

结构重命名

当保持向后的兼容性,被tab控制使用的所有结构都可以改名以依照当前的命名惯例。例如, TC_ITEM 结构现在被命名为TCITEM 。

 

原创粉丝点击