基于选项卡隐藏和显示容器 windows

Hiding and showing container windows based on tab

我创建了一个包含两个选项卡的选项卡控件。在每个选项卡内将有一个容器 window 来容纳其他控件(在代码示例中,例如静态控件)。 The idea is that when a new tab is selected, it will hide/show the correct container window that holds a bunch of controls.但是,我正在努力让容器 windows 持有要显示的静态控件。这是到目前为止的代码:

#include <windows.h>
#include <commctrl.h>
#pragma comment(lib, "comctl32.lib")

#define ID_TABCTRL 1
#define ID_STATIC0 2
#define ID_STATIC1 3
#define ID_TAB0 4
#define ID_TAB1 5

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HWND hTab, hTab0, hTab1;

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
    MSG  msg;
    WNDCLASS wc = { 0 };
    wc.lpszClassName = TEXT("Tab control");
    wc.hInstance = hInstance;
    wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
    wc.lpfnWndProc = WndProc;
    wc.hCursor = LoadCursor(0, IDC_ARROW);

    RegisterClass(&wc);
    CreateWindow(wc.lpszClassName, TEXT("Tab control"), WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 250, 200, 0, 0, hInstance, 0);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}


LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    TCITEM tie;
    INITCOMMONCONTROLSEX icex;

    switch (msg)
    {
        case WM_CREATE:
            icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
            icex.dwICC = ICC_TAB_CLASSES;
            InitCommonControlsEx(&icex);

            tie.mask = TCIF_TEXT;

            ///// Create Tab Control /////
            hTab = CreateWindow(WC_TABCONTROL, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 200, 150, hwnd, (HMENU)ID_TABCTRL, NULL, NULL);

            ///// Create Individual Tabs /////
            tie.pszText = TEXT("First");
            SendMessage(hTab, TCM_INSERTITEM, 0, (LPARAM)(LPTCITEM)&tie);

            tie.pszText = TEXT("Second");
            SendMessage(hTab, TCM_INSERTITEM, 1, (LPARAM)(LPTCITEM)&tie);

            ///// Create Container windows for each tab /////
            hTab0 = CreateWindow(0, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 200, 150, hTab, (HMENU)ID_TAB0, NULL, NULL);
            hTab1 = CreateWindow(0, NULL, WS_CHILD, 0, 0, 200, 150, hTab, (HMENU)ID_TAB1, NULL, NULL);

            ///// Add example control to one of the tab container windows /////
            CreateWindow(TEXT("Static"), TEXT("Yay!"), WS_CHILD | WS_VISIBLE | SS_LEFT, 20, 30, 50, 25, hTab0, (HMENU)ID_STATIC0, NULL, NULL);
            CreateWindow(TEXT("Static"), TEXT("It appears to be working"), WS_CHILD | WS_VISIBLE | SS_LEFT, 20, 30, 100, 50, hTab1, (HMENU)ID_STATIC1, NULL, NULL);

            break;

        case WM_NOTIFY:
            switch (((LPNMHDR)lParam)->code)
            {
                case TCN_SELCHANGE:
                    switch (TabCtrl_GetCurSel(hTab))
                    {
                        ///// Show or Hide the appropriate tabs /////
                        case 0:
                            ShowWindow(hTab1, SW_HIDE);
                            ShowWindow(hTab0, SW_SHOW);
                        case 1:
                            ShowWindow(hTab0, SW_HIDE);
                            ShowWindow(hTab1, SW_SHOW);
                    }
            }
            break;

        case WM_DESTROY:
            PostQuitMessage(0);
            break;
    }
    return(DefWindowProc(hwnd, msg, wParam, lParam));
}

是否只是容器 windows hTab0hTab1 卡在选项卡后面的情况 window (hTab)?

首先需要改变tab和静态表单的位置,否则会挡住生成的内容

那么可以直接通过CreateWindow, by using WC_STATIC定义生成的静态文本。

#include <Windows.h>
#include <commctrl.h>
LRESULT CALLBACK WndProc(HWND, UINT,WPARAM,LPARAM);


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT("windows");
    HWND hwnd;
    MSG msg;
    WNDCLASS wndclass;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc; 
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;
    if (!RegisterClass(&wndclass))
    { 
        MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
    }
    hwnd = CreateWindow(szAppName,
        TEXT("the hello program"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL);

    ShowWindow(hwnd,iCmdShow);
    UpdateWindow(hwnd);

    while (GetMessageW(&msg,NULL,0,0))
    {
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
    }
    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message,WPARAM wParam,LPARAM lParam)
{
    static HINSTANCE hInstance;
    static HWND hwndTab = 0 , hwndStatic1,hwndStatic2;
    TCITEM tie;
    RECT rcClient;
    INITCOMMONCONTROLSEX icex;
    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
    icex.dwICC = ICC_TAB_CLASSES;
    TCHAR tabLBL1[256];
    GetClientRect(hwnd, &rcClient);
    switch (message)
    {
    case WM_CREATE:
    {
        hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
        hwndTab = CreateWindow(WC_TABCONTROL, L"",
            WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
            0, 0, rcClient.right, rcClient.bottom,
            hwnd, NULL, hInstance, NULL);

         //Add tabs for each day of the week. 
        tie.mask = TCIF_TEXT | TCIF_IMAGE;
        tie.iImage = -1;
        wsprintf(tabLBL1, L"tab1");
        tie.pszText = tabLBL1;
        TabCtrl_InsertItem(hwndTab, 0, &tie);
        wsprintf(tabLBL1, L"tab2");
        TabCtrl_InsertItem(hwndTab, 1, &tie);


        hwndStatic1 = CreateWindow(WC_STATIC, L"123",
            WS_CHILD | WS_VISIBLE | WS_BORDER,
            200, 200, 100, 100,        // Position and dimensions; example only.
            hwndTab, NULL, hInstance,    // g_hInst is the global instance handle
            NULL);
        hwndStatic2 = CreateWindow(WC_STATIC, L"456",
            WS_CHILD | WS_VISIBLE | WS_BORDER,
            400, 200, 100, 100,        // Position and dimensions; example only.
            hwndTab, NULL, hInstance,    // g_hInst is the global instance handle
            NULL);
        ShowWindow(hwndStatic1, TRUE);
        ShowWindow(hwndStatic2, FALSE);
        return 0;
    }

    case WM_DESTROY:        
        PostQuitMessage(0);
        return 0;
    case WM_NOTIFY:
        if (((LPNMHDR)lParam)->code == TCN_SELCHANGE)
        {
            int tabID = TabCtrl_GetCurSel(hwndTab);
            switch (tabID)
            {
            case 0:
                ShowWindow(hwndStatic1, TRUE);
                ShowWindow(hwndStatic2, FALSE);
                break;
            case 1:
                ShowWindow(hwndStatic1, FALSE);
                ShowWindow(hwndStatic2, TRUE);
                break;
            default:
                break;
            }
        }
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

朱松的回答帮助解决了问题(容器windows需要是一个静态控件,并且需要定位在选项卡控件的space内,在可点击的选项卡下方)。

这是结果,交换了两个容器 window 创建行:

hTab0 = CreateWindow(TEXT("Static"), NULL, WS_CHILD | WS_VISIBLE, 1, 25, 197, 123, hTab, (HMENU)ID_TAB0, NULL, NULL);
hTab1 = CreateWindow(TEXT("Static"), NULL, WS_CHILD, 1, 25, 197, 123, hTab, (HMENU)ID_TAB1, NULL, NULL);

请注意容器 window 大小和位置如何足够小以刚好适合主选项卡控件 window(您可以将 WS_BORDER 添加到样式以查看它的确切位置适合)。