C, Win32 API: l need help on Owner draw tab control

Firstly, thanks to you all who had in the time past guided me in my win32 programming.
right now, l need a help on owner drawn tab control.

l did the following code after creating the tab control with CreateWindowEx
Code. However, it worked fine when l didn't use the owner draw style but l don't like the default. l want to customize it.

NOTE: subject1 through subject6 are the indices of dropdown list combobox.

What l want to do is to first check if a user has made a selection. if yes, get the index, add a tab and set the tab title to the subject selected. but if no, do nothing - don't create tab.


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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
case WM_DRAWITEM:
		
		lpdis=(LPDRAWITEMSTRUCT) lParam;
		
		TCITEM	tie={0};
		
		if(SubjectTabs==lpdis->hwndItem){//get handle of the tab control
			if(SubjectTabs==NULL){
				MessageBox(hWnd,L"Tab can not be created.",szTitle,0);
				MessageBox(hWnd,L"Application closes",szTitle,0);
				SendMessage(hWnd,WM_CLOSE,0,0);
				break;
			}
			if(subject1){//if English is not selected, do the inner loop
				MessageBox(hWnd,L"Problem with English Subject.",szTitle,0);
				MessageBox(hWnd,L"Application closes",szTitle,0);
				SendMessage(hWnd,WM_CLOSE,0,0);
				break;
			}
			else{//
				tie.mask = TCIF_TEXT;
				tie.cchTextMax = 100;
				tie.pszText=subject1tab;//sets tab name
				SendMessage(SubjectTabs,TCM_INSERTITEM,(WPARAM)0,(LPARAM)&tie);//send message to add tab
				FillRect(lpdis->hDC,&lpdis->rcItem,(HBRUSH)GetStockObject(WHITE_BRUSH));
				SetBkColor(lpdis->hDC,RGB(255,255,255));
			}

			if(subject2<=0){//if subject 2 is not selected, do nothing
				//do nothing and tab will not be added	
			}
			else{
				tie.mask = TCIF_TEXT;
				tie.cchTextMax = 100;
				tie.pszText=subject2tab;//sets tab name
				SendMessage(SubjectTabs,TCM_INSERTITEM,(WPARAM)1,(LPARAM)&tie);//send message to add tab
				FillRect(lpdis->hDC,&lpdis->rcItem,(HBRUSH)GetStockObject(WHITE_BRUSH));
				SetBkColor(lpdis->hDC,RGB(255,255,255));
			}

			if(subject3<=0){//if subject 3 is not selected, do nothing
				//do nothing and tab will not be added
			}
			else{
				tie.mask = TCIF_TEXT;
				tie.cchTextMax = 100;
				tie.pszText=subject3tab;////
				SendMessage(SubjectTabs,TCM_INSERTITEM,(WPARAM)2,(LPARAM)&tie);//send message to add tab
				FillRect(lpdis->hDC,&lpdis->rcItem,(HBRUSH)GetStockObject(WHITE_BRUSH));
				SetBkColor(lpdis->hDC,RGB(255,255,255));
			}

			if(subject4<=0){//if subject 4 is not selected, do nothing
				//do nothing and tab will not be added
			}
			else{
				tie.mask = TCIF_TEXT;
				tie.cchTextMax = 100;
				tie.pszText=subject4tab;////
				SendMessage(SubjectTabs,TCM_INSERTITEM,(WPARAM)3,(LPARAM)&tie);//send message to add tab
				FillRect(lpdis->hDC,&lpdis->rcItem,(HBRUSH)GetStockObject(WHITE_BRUSH));
				SetBkColor(lpdis->hDC,RGB(255,255,255));
			}

			if(subject5<=0){//if subject 5 is not selected, do nothing
				//do nothing and tab will not be added
			}
			else{
				tie.mask = TCIF_TEXT;
				tie.cchTextMax = 100;
				tie.pszText=subject5tab;
				SendMessage(SubjectTabs,TCM_INSERTITEM,(WPARAM)4,(LPARAM)&tie);//send message to add tab
				FillRect(lpdis->hDC,&lpdis->rcItem,(HBRUSH)GetStockObject(WHITE_BRUSH));
				SetBkColor(lpdis->hDC,RGB(255,255,255));
			}

			if(subject6<=0){//if subject 6 is not selected, do nothing
				//do nothing and tab will not be added
			}
			else{
				tie.mask = TCIF_TEXT;
				tie.cchTextMax = 100;

				tie.pszText=subject6tab;////
				SendMessage(SubjectTabs,TCM_INSERTITEM,(WPARAM)5,(LPARAM)&tie);//send message to add tab
				FillRect(lpdis->hDC,&lpdis->rcItem,(HBRUSH)GetStockObject(WHITE_BRUSH));
				SetBkColor(lpdis->hDC,RGB(255,255,255));
			}
		}
		break;


but l got the following error;
1>c:\users\chibu\documents\visual studio 2010\projects\unical ptume\unical ptume\unical ptume.cpp(349): error C2360: initialization of 'tie' is skipped by 'case' label
1> c:\users\chibu\documents\visual studio 2010\projects\unical ptume\unical ptume\unical ptume.cpp(261) : see declaration of 'tie'
1>c:\users\chibu\documents\visual studio 2010\projects\unical ptume\unical ptume\unical ptume.cpp(355): error C2361: initialization of 'tie' is skipped by 'default' label
1> c:\users\chibu\documents\visual studio 2010\projects\unical ptume\unical ptume\unical ptume.cpp(261) : see declaration of 'tie'

So can someone help me on out/
Thanks in advance.
Last edited on
you can either move the declaration of tie so it is completely outside the switch statement, or add braces (which is what i do.

[code]
case WM_DRAWITEM:
{
//blah
}

see https://msdn.microsoft.com/en-us/library/61af7cx3.aspx
@Jaybobb6: It work - compiled. Thanks. Humm, but the tab control was not created. May be l didn't code it well. but any more light on it will be appreciated as there are no much tut on the subject on the net for me to refer to. l didn't much understand that of microsoft. https://support.microsoft.com/en-us/kb/179909
sorry, I haven't done any owner draw stuff for many years.
Hopefully someone else can contribute there.
How did you create the TabControl ?
@Thomas1965:
1
2
SubjectTabs=CreateWindow(WC_TABCONTROL,L"",WS_CHILD|WS_VISIBLE|TCS_OWNERDRAWFIXED,0,0,0,0,hwnd,(HMENU)IDC_TAB1,hInst,NULL);		
	


where SubjectTabs is a HWND type.
However, it now works cos l followed the tut on https://support.microsoft.com/en-us/kb/179909 but it doesn't look fine. The whole tab is the color l set and nothing to differentiate between tabs. l want it to be in a way, the tab(the title area where the user clicks to toggle between tabs) will have a blue colour while the display area will be white and again, the titles l set doesn't show but shows when l don't use the custom style. Please l need more help tut on it.
Thanks in advance.

PS: never mine the x,y,cy,cy coordinate, cos l used movewindow in wm_size to size them.
Last edited on
Could you post the complete code or upload the project somewhere?
@Thomas1965:
For owner draw that does not work:

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
case WM_CREATE:

INITCOMMONCONTROLSEX icce = {0};
	TCITEM tie={0};
	icce.dwICC=ICC_TAB_CLASSES;
	icce.dwSize=sizeof(INITCOMMONCONTROLSEX);
	InitCommonControlsEx(&icce);
HWND SubjectTabs=CreateWindow(WC_TABCONTROL,L"",WS_CHILD|WS_VISIBLE|TCS_OWNERDRAWFIXED,300,50,700,1000,hwnd,(HMENU)IDC_TAB1,hInst,NULL);	
....

case WM_DRAWITEM:
		
		lpdis=(LPDRAWITEMSTRUCT)lParam;
		switch(lpdis->itemID){
		case 0:
			tie.mask = TCIF_TEXT;
			tie.cchTextMax = 100;
			tie.iImage=-1;
			tie.pszText=L"Tab 1";//sets tab name
			SendMessage(SubjectTabs,TCM_INSERTITEM,(WPARAM)0,(LPARAM)&tie);
			FillRect(lpdis->hDC,&lpdis->rcItem,(HBRUSH)GetStockObject(WHITE_BRUSH));
			SetBkColor(lpdis->hDC,RGB(100,200,155));
			break;
		case 1:
		tie.mask = TCIF_TEXT;
			tie.cchTextMax = 100;
			tie.iImage=-1;
			tie.pszText=L"Tab 2";//sets tab name
			SendMessage(SubjectTabs,TCM_INSERTITEM,(WPARAM)0,(LPARAM)&tie);
			FillRect(lpdis->hDC,&lpdis->rcItem,(HBRUSH)GetStockObject(WHITE_BRUSH));
			SetBkColor(lpdis->hDC,RGB(100,200,155));
			break;
		}
		break;


but if l use style TCS_FIXEDWIDTH do the following, it works fine;

Default draw:

1
2
3
4
5
6
7
case WM_CREATE:
HWND SubjectTabs=CreateWindow(WC_TABCONTROL,L"",WS_CHILD|WS_VISIBLE|TCS_FIXEDWIDTH,300,50,700,1000,hwnd,(HMENU)IDC_TAB1,hInst,NULL);	
tie.mask = TCIF_TEXT;
		tie.cchTextMax = 100;
		tie.iImage=-1;
		tie.pszText=L"Tab 1;//sets tab name
		SendMessage(SubjectTabs,TCM_INSERTITEM,(WPARAM)0,(LPARAM)&tie); 
I have do a little experiment with TCS_OWNERDRAWFIXED.

Main.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#ifndef MAIN_H
#define MAIN_H

#include <Windows.h>
#include <tchar.h>

#define WIN_WIDTH   800
#define WIN_HEIGHT  600

TCHAR *ClsName = _T("BasicApp");
TCHAR *WndName = _T("Template");

ATOM WINAPI RegisterMyClass(HINSTANCE hInstance);
LRESULT CALLBACK WndProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int);

HWND CreateTabControl(HWND hMainWindow);
void PaintTab(LPDRAWITEMSTRUCT lpdis);

#endif


Main.cpp
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include <windows.h>
#include <commctrl.h>
#include "main.h"

HWND        g_hTabControl;
HINSTANCE   g_hInstance;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
  MSG        Msg;
	HWND       hWnd;
	
	g_hInstance = hInstance;

  if (!RegisterMyClass(hInstance))
    return FALSE;

  int left = (GetSystemMetrics(SM_CXSCREEN) - WIN_WIDTH) / 2;
  int top = (GetSystemMetrics(SM_CYSCREEN) - WIN_HEIGHT) / 2;

	hWnd = CreateWindow(ClsName, WndName, WS_BORDER | WS_SYSMENU	,
                      left, top, WIN_WIDTH, WIN_HEIGHT,
                      NULL, NULL, hInstance, NULL);

	if (!hWnd)
		return FALSE;
		
	INITCOMMONCONTROLSEX cc = {0};
	
	cc.dwSize = sizeof(INITCOMMONCONTROLSEX);
	cc.dwICC = ICC_TAB_CLASSES;
	InitCommonControlsEx(&cc);

	ShowWindow(hWnd, SW_SHOWNORMAL);
	UpdateWindow(hWnd);

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

	return Msg.wParam;
}

ATOM WINAPI RegisterMyClass(HINSTANCE hInstance)
{
  WNDCLASSEX WndClsEx;

	WndClsEx.cbSize        = sizeof(WNDCLASSEX);
	WndClsEx.style         = CS_HREDRAW | CS_VREDRAW;
	WndClsEx.lpfnWndProc   = WndProcedure;
	WndClsEx.cbClsExtra    = 0;
	WndClsEx.cbWndExtra    = 0;
	WndClsEx.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
	WndClsEx.hCursor       = LoadCursor(NULL, IDC_ARROW);
	WndClsEx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	WndClsEx.lpszMenuName  = NULL;
	WndClsEx.lpszClassName = ClsName;
	WndClsEx.hInstance     = hInstance;
	WndClsEx.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

	return RegisterClassEx(&WndClsEx);
}

LRESULT CALLBACK WndProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
  switch (Msg)
  {
    case WM_CREATE:
      g_hTabControl = CreateTabControl(hWnd);
      break;
    case WM_DRAWITEM:
      PaintTab((LPDRAWITEMSTRUCT)lParam);
			break;

		case WM_DESTROY:
      PostQuitMessage(0);
      break;
    default:
      return DefWindowProc(hWnd, Msg, wParam, lParam);
  }
  return 0;
}

void PaintTab(LPDRAWITEMSTRUCT lpdis)
{
  COLORREF TextColor;
  
  switch (lpdis->itemID)
  {
    case 0:
      TextColor = RGB(0,0, 128);
      break;
    case 1:
      TextColor = RGB(0,128, 0);
      break;
    default:
      TextColor = RGB(128, 0, 0);
  }
  TCHAR buf[128];
  
  TCITEM tci;
  tci.mask = TCIF_TEXT;
  tci.pszText = buf;
  tci.cchTextMax = sizeof(buf) * sizeof(TCHAR);
  TabCtrl_GetItem(g_hTabControl, lpdis->itemID, &tci);
  
  FillRect(lpdis->hDC,&lpdis->rcItem,(HBRUSH)GetStockObject(WHITE_BRUSH));
  SetTextColor(lpdis->hDC, TextColor);
  SetBkMode(lpdis->hDC, TRANSPARENT);
	DrawText(lpdis->hDC, tci.pszText, _tcslen(tci.pszText), &lpdis->rcItem, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
}

HWND CreateTabControl(HWND hMainWindow)
{
  DWORD dwStyle = WS_VISIBLE | WS_TABSTOP | WS_CHILD | TCS_OWNERDRAWFIXED;
  
  HWND hWnd = CreateWindow(WC_TABCONTROL, NULL, dwStyle,
                           10, 10, WIN_WIDTH - 20, WIN_HEIGHT - 20, hMainWindow,
                           NULL, g_hInstance, NULL);
                           
  TCITEM  tci;
              
  tci.mask = TCIF_TEXT;
  tci.iImage = -1;
  tci.pszText = _T("German");             
  TabCtrl_InsertItem(hWnd, 0, &tci);
  
  tci.pszText = _T("English");             
  TabCtrl_InsertItem(hWnd, 1, &tci);
  
  tci.pszText = _T("Spanish");             
  TabCtrl_InsertItem(hWnd, 2, &tci);
  
  return hWnd;
}

Hope you find it helpful
@thomas1965: Thanks alot - it worked. However, only the top part(the part where user clicks to toggle between tab) changed color. Is there a way to also change the color of the tab client area?
I don't think that there is a way, you can paint only inside the lpdis->rcItem.

However I saw one example in a book that used modeless dialogs for the content.
Ok. Can you please help me with the book name/title. Thanks
I can try, but what help do you need ?
So l can see how it is being done. Am just beginning to code in win32. or you give me a snap shot of it or PM the name.
I still don't know what you want to do.
You mentioned book name/title, but what are they?
Maybe you can upload the project and the complete task and send me a PM.
Ok. Thanks for your help and concern. l will do so.
I have done something like that maybe it can be usefull !

#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#include <Windows.h>
#include <CommCtrl.h>

LRESULT CALLBACK wndproc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK wndproc2(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK Aboutdlgproc(HWND, UINT, WPARAM, LPARAM);
HWND WINAPI Createtabcontrol(HWND hwndparent, HINSTANCE hinstance, LPTSTR sztext);
VOID painttab(LPDRAWITEMSTRUCT lpdis, HWND hwndtab);
HWND tabchildwindow(HWND hwndtab, HINSTANCE hinstance);
struct
{
TCHAR *szday;
}
dayoftheweek[] = { TEXT("Lundi"), TEXT("Mardi"), TEXT("Mercredi"), TEXT("Jeudi"), TEXT("Vendredi"), TEXT("Samedi"), TEXT("Dimanche") };

int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE previnstance, PSTR szcmdline, int cmdshow)
{
static TCHAR szappname[] = TEXT("About box demo program 3");
HWND hwnd;
MSG msg;
WNDCLASS wc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL,IDI_APPLICATION );
wc.hInstance = hinstance;
wc.lpfnWndProc = wndproc;
wc.lpszClassName = TEXT("classe 1");
wc.lpszMenuName = NULL;
wc.style = 0;

if (!RegisterClass(&wc))
{
MessageBox(NULL, TEXT("This software required windows NT "), TEXT("ERROR"), MB_ICONERROR);
return 0;
}
wc.lpszClassName = TEXT("classe 2");
wc.lpfnWndProc = wndproc2;
RegisterClass(&wc);
hwnd = CreateWindowEx(0, TEXT("classe 1"), szappname, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hinstance, NULL);

ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);

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

LRESULT CALLBACK wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
//DWORD dwstyle ;
static HINSTANCE hinstance;
static HWND hwndtab, hwndchild;
static TCHAR *sztext;
switch (msg)
{
case WM_CREATE:
hinstance = ((LPCREATESTRUCT)lparam)->hInstance;
hwndtab = Createtabcontrol(hwnd, hinstance, sztext);
hwndchild = tabchildwindow(hwnd, hinstance);

return 0;
case WM_SIZE:

HDWP hdwp;
RECT rc;
SetRect(&rc, 0, 0, LOWORD(lparam), HIWORD(lparam));
TabCtrl_AdjustRect(hwndtab, FALSE, &rc);
hdwp = BeginDeferWindowPos(2);
DeferWindowPos(hdwp, hwndtab, NULL, 0, 0, LOWORD(lparam), HIWORD(lparam), SWP_NOCOPYBITS | SWP_NOZORDER);
DeferWindowPos(hdwp, hwndchild, HWND_BOTTOM, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOCOPYBITS );
EndDeferWindowPos(hdwp);
break;
case WM_NOTIFY:
HBRUSH hbrush;
switch (((LPNMHDR)lparam)->code)
{
case TCN_SELCHANGE:
{
int ipage;
ipage = TabCtrl_GetCurSel(hwndtab);
sztext = dayoftheweek[ipage].szday;
hbrush = CreateSolidBrush(RGB(rand() % 255, rand() % 255, rand() % 255));
SetClassLong(hwndchild, GCL_HBRBACKGROUND, (LONG)hbrush);
InvalidateRect(hwndchild, NULL, TRUE);

break;
}
}
return 0;

case WM_DRAWITEM:
painttab((LPDRAWITEMSTRUCT)lparam, hwndtab);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;

}
return DefWindowProc(hwnd, msg, wparam, lparam);
}

HWND WINAPI Createtabcontrol(HWND hwndparent, HINSTANCE hinstance, LPTSTR sztext)
{
INITCOMMONCONTROLSEX icex;
RECT rcclient;
HWND hwndtab;

TCITEM tie;
int i;
GetClientRect(hwndparent, &rcclient);

icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_TAB_CLASSES;
InitCommonControlsEx(&icex);
hwndtab = CreateWindowEx(0, WC_TABCONTROL, NULL, WS_CHILD | WS_CLIPSIBLINGS| WS_VISIBLE,
0, 0, rcclient.right, rcclient.bottom,hwndparent, NULL, hinstance, NULL);
tie.mask = TCIF_TEXT | TCIF_IMAGE;

tie.iImage = -1;


for (i = 0; i < 7; i++)
{
sztext = dayoftheweek[i].szday;
tie.pszText = sztext;
if (TabCtrl_InsertItem(hwndtab, i, &tie) == -1)
{
DestroyWindow(hwndtab);
return NULL;
}
}
return hwndtab;
}



VOID painttab(LPDRAWITEMSTRUCT lpdis, HWND hwndtab)
{
COLORREF textcolor;
switch (lpdis->itemID)
{
case 0:
textcolor = RGB(255, 255, 255);
break;
default:
textcolor = RGB(255, 255, 255);
break;
}
TCHAR szbuffer[128];
TCITEM tci;
tci.mask = TCIF_TEXT;
tci.pszText = szbuffer;
tci.cchTextMax = sizeof(szbuffer) / sizeof(TCHAR);

TabCtrl_GetItem(hwndtab, lpdis->itemID, &tci);
FillRect(lpdis->hDC, &lpdis->rcItem, (HBRUSH)CreateSolidBrush(RGB(29, 107, 214)));
SetTextColor(lpdis->hDC, textcolor);
SetBkMode(lpdis->hDC, TRANSPARENT);
DrawText(lpdis->hDC, tci.pszText, lstrlen(tci.pszText), &lpdis->rcItem, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}

HWND tabchildwindow(HWND hwndtab, HINSTANCE hinstance)
{
HWND childwindow;
childwindow = CreateWindowEx(0, TEXT("classe 2"), NULL, WS_OVERLAPPED | WS_CHILDWINDOW | WS_VISIBLE, 0, 0, 0, 0, hwndtab, NULL, hinstance, NULL);
return childwindow;
}

LRESULT CALLBACK wndproc2(HWND hwnd , UINT msg, WPARAM wparam, LPARAM lparam)
{

return DefWindowProc(hwnd, msg, wparam, lparam);
}
Topic archived. No new replies allowed.