How to display a tab control?

Hi!

I'm trying to make a simple tab control with two tabs display in the window, but no matter how I do it, it won't show up. I've consulted the MSND documentation and came up with this file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <windows.h>
#include <commctrl.h>

char className[]="TabControl";

LRESULT CALLBACK WindowProcedure(HWND,UINT,WPARAM,LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszArgument,int nFunsterStil){
    MSG messages;
    WNDCLASSEX wincl;

    wincl.hInstance=hInstance;
    wincl.lpszClassName=className;
    wincl.lpfnWndProc=WindowProcedure;
    wincl.style=0;
    wincl.cbSize=sizeof(WNDCLASSEX);
    wincl.hIcon=LoadIcon(NULL,IDI_APPLICATION);
    wincl.hIconSm=LoadIcon(NULL,IDI_APPLICATION);
    wincl.hCursor=LoadCursor(NULL,IDC_ARROW);
    wincl.lpszMenuName=NULL;
    wincl.cbClsExtra=0;
    wincl.cbWndExtra=0;
    wincl.hbrBackground=HBRUSH(COLOR_3DFACE+1);

    if(!RegisterClassEx(&wincl))return 0;

    HWND windowHandle=CreateWindow(className,"TabControl",WS_OVERLAPPEDWINDOW,200,325,480,320,NULL,NULL,hInstance,NULL);
    ShowWindow(windowHandle,SW_SHOW);
    
    HWND tabHandle=CreateWindow(WC_TABCONTROL,"",WS_CHILD,6,0,474,320,windowHandle,NULL,hInstance,NULL);
    TCITEM tab1Data;
    tab1Data.mask=TCIF_TEXT;
    tab1Data.pszText="Tab1";
    TabCtrl_InsertItem(tabHandle,0,&tab1Data);
    TCITEM tab2Data;
    tab2Data.mask=TCIF_TEXT;
    tab2Data.pszText="Tab2";
    TabCtrl_InsertItem(tabHandle,0,&tab2Data);
    HWND tab1Handle=CreateWindow(WC_STATIC,"",WS_CHILD,6,40,474,320,tabHandle,NULL,hInstance,NULL);
    HWND tab2Handle=CreateWindow(WC_STATIC,"",WS_CHILD,6,40,474,320,tabHandle,NULL,hInstance,NULL);
    ShowWindow(tab1Handle,SW_SHOW);

    while(GetMessage(&messages,NULL,0,0)){
        TranslateMessage(&messages);
        DispatchMessage(&messages);
    };
    return messages.wParam;
}

LRESULT CALLBACK WindowProcedure (HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam){
    switch(message){
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd,message,wParam,lParam);
    };
    return 0;
}


I assume it has something to do with linking the tab1 and tab2Handles with the tab items, but how exactely do I do that?

Thank you!
You haven't made the tab control visible for a start.
Just change this:

HWND windowHandle=CreateWindow(className,"TabControl",WS_OVERLAPPEDWINDOW,200,325,480,320,NULL,NULL,hInstance,NULL);
to this:
HWND windowHandle=CreateWindow(className,"TabControl",WS_OVERLAPPEDWINDOW | WS_VISIBLE,200,325,480,320,NULL,NULL,hInstance,NULL);
and this
HWND tabHandle=CreateWindow(WC_TABCONTROL,"",WS_CHILD,6,0,474,320,windowHandle,NULL,hInstance,NULL);
with this:
HWND tabHandle=CreateWindow(WC_TABCONTROL | WS_VISIBLE,"",WS_CHILD,6,0,474,320,windowHandle,NULL,hInstance,NULL);
Last edited on
He uses the ShowWindow(windowHandle,SW_SHOW); to show the main window


On another issue - there are going to be problems directly making controls that are
children of the tab control window - tab controls do not quite work that way.
Last edited on
Thanks for the WS_VISIBLE tip; it's much easier than calling ShowWindow() explicitely. However, the tab control still does not show up with this:
1
2
3
4
5
6
7
8
9
    HWND tabHandle=CreateWindow(WC_TABCONTROL,"",WS_CHILD|WS_VISIBLE,6,0,474,30,windowHandle,NULL,hInstance,NULL);
    TCITEM tab1Data;
    tab1Data.mask=TCIF_TEXT;
    tab1Data.pszText="Tab1";
    TabCtrl_InsertItem(tabHandle,0,&tab1Data);
    TCITEM tab2Data;
    tab2Data.mask=TCIF_TEXT;
    tab2Data.pszText="Tab2";
    TabCtrl_InsertItem(tabHandle,0,&tab2Data);


I have eventually found out that in order to manipulate the tab content, I need to call TabCtrl_GetCurSel() or similar functions and hide/show windows based on the returned value. But that's really not a problem. The only trouble is that the tabs are not drawn.
Are you seeing nothing at all??

I see the tabs - but the problem is that 30 is not a good enough height for the tab control window - it is barely enough to show the tabs themselves.
I think I've found the problem: CreateWindow returns NULL. The error code is 1407 = ERROR_CANNOT_FIND_WND_CLASS.
But it doesn't make any sense at all; I've included commctrl.h which has the WC_TABCONTROL defined.
I've tried changing the value directly into "SysTabControl32", but it still throws the same error. Am I missing something?

1
2
HWND tabHandle=CreateWindow(WC_TABCONTROLA,"",WS_CHILD|WS_CLIPSIBLINGS|WS_VISIBLE,0,0,200,100,windowHandle,NULL,hInstance,NULL);
    if(tabHandle==NULL)return GetLastError();


Oh and WC_TABCONTROLW throws
cannot convert `const wchar_t*' to `const CHAR*' for argument `2' to `HWND__* CreateWindowExA(DWORD, const CHAR*, const CHAR*, DWORD, int, int, int, int, HWND__*, HMENU__*, HINSTANCE__*, void*)'
Last edited on
Have you linked commctrl32?
Sure. Otherwise it would have caused undeclaration errors from start.

By the way, I'm using Code::Blocks 10.05.
Last edited on
What happens if you just put WC_TABCONTROL.

personally I tend to include #include <tchar.h>
then use the _TEXT macro to sort out the char/wchar requirements for string literals

HWNDtabHandle=CreateWindow(WC_TABCONTROL,_TEXT(""),WS_CHILD|WS_CLIPSIBLINGS|WS_VISIBLE,0,0,200,100,windowHandle,NULL,hInstance,NULL);
Just adding WS_VISIBLE to your original code shows the tabs just fine when compiling with VS2010.
Thanks a lot guestgulkan, modoran and hanst99.
The problem was solved.

I had to add this code before generating the windows:
1
2
3
4
INITCOMMONCONTROLSEX icce{0};
icce.dwSize=sizeof(INITCOMMONCONTROLSEX);
icce.dwICC=ICC_WIN95_CLASSES;
InitCommonControlsEx(&icce);

and also link the comctl32 library (I guess that's what hanst meant).
Last edited on
Topic archived. No new replies allowed.