Tuts 4 You: Endless fun with tab controls - Tuts 4 You

Jump to content

Subscribe to Kibloy's Blog        RSS Feed
-----

Endless fun with tab controls

7 Comments
Anyone who ever tried to implement tab controls using plain Windows API will probably agree with me that it's a ****ing PITA to get it working properly.

Some of the problems you'll most likely be facing, mostly because of poor documentation:
  • Handling and adjusting the windows for each tab
  • Getting Windows to draw the themed background on the windows
  • Adding transparent (32-bit) icons to tabs

After a lot of googling and guessing around, I got most of this stuff working.
I came up with a bunch of functions to help with getting tab controls work without having to deal with all the hassle.

The functions should be used exclusively, that is without modifying tab items yourself as the functions assume certain conditions and might cause undefined behaviour if things aren't as expected.

Some of the things you shouldn't do:

- Add a tab without using the appropiate function
- Remove a tab without using the appropiate function
- Change the tab items' lParam value (they hold the window handles)
- Change the tab's ImageList
- Call SetProp on the tab window with "TabCtrlCurWnd" ;D

You can still modify the tab control's GWLP_USERDATA.

A quick overview over the functions:

int AddTab(HWND TabWindow, HWND Window, char * Caption, int Index)

Adds a tab item to the tab control and associates the window to it.
The window is moved and resized to fit the tab control dimensions.

bool RemoveTab(HWND TabWindow, int Index)

Removes the tab item from the tab control.

bool TabCleanup(HWND TabWindow)

Removes all tab items from the tab control.
Cleans up internal resources and hides all windows associated with it.

It's recommended to call this function before the tab control is destroyed,
e.g. if you get a WM_CLOSE message in your dialogbox proc.

bool SetTabIcon(HWND TabWindow, int Index, HICON Icon)

Sets the tab item's icon.
Supports 32bit icons (24bit + 8bit alpha) if comctl32.dll v6 is used (ie. visual styles enabled).
The icon should be 16x16 in size and at least contain an 8bit (256 colors) channel.

int TabToFront(HWND TabWindow, int Index)

Selects the specified tab and shows the appropiate window.


For a more detailed overview over the functions take a look at tabs.h

In order for the tab selection to work, you will have to add this piece of
code to the tab control's parent window handler (usually the dialog procedure):

case WM_NOTIFY:
	switch(((NMHDR *)lParam)->code)
	{
	case TCN_SELCHANGE: // Get currently selected tab window to front
		TabToFront(TabWindow, -1);
		break;
	default:
		return false;
	}
	break;


Alright, that should be it :)

Attached are the .h and .cpp and an example project.

Attached File(s)

7 Comments On This Entry

Page 1 of 1

cyberbob 

05 February 2009 - 09:50 AM
cool! thanks a lot!
0

cyberbob 

30 May 2009 - 10:24 AM
Hi Killboy,

Do you know by any chance, how to make tab control background transparent using XP themes?
0

Killboy 

30 May 2009 - 05:28 PM
Hm, what do you mean by transparent? The tab control itself or the subwindows?
0

cyberbob 

31 May 2009 - 10:12 AM
I mean the tab control pages, gray background while using XP themes.
0

Killboy 

31 May 2009 - 05:36 PM
If I got you right, the code I provided does that for all windows added through AddTab.
Take a look at EnableThemeDialogTexture:

#define ETDT_DISABLE	   0x00000001
#define ETDT_ENABLE		0x00000002
#define ETDT_USETABTEXTURE 0x00000004
#define ETDT_ENABLETAB	 (ETDT_ENABLE | ETDT_USETABTEXTURE)

void EnableThemeDialogTexture(HWND Window, DWORD dwFlags)
{
typedef HRESULT (WINAPI * ENABLETHEMEDIALOGTEXTURE)(HWND, DWORD);
ENABLETHEMEDIALOGTEXTURE pEnableThemeDialogTexture;

	if(VisualStylesEnabled()){
		pEnableThemeDialogTexture = (ENABLETHEMEDIALOGTEXTURE)GetProcAddress(LoadLibrary("uxtheme.dll"), "EnableThemeDialogTexture");
		if(pEnableThemeDialogTexture){
			pEnableThemeDialogTexture(Window, dwFlags);
		}
	}
}

bool VisualStylesEnabled()
{
HMODULE hMod;
DLLGETVERSIONPROC pDllGetVersion;
DLLVERSIONINFO DllVersion;

	hMod = GetModuleHandle("comctl32.dll");
	if(hMod){
		pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hMod, "DllGetVersion");
		if(pDllGetVersion){
			DllVersion.cbSize = sizeof(DLLVERSIONINFO);
			if(pDllGetVersion(&DllVersion) == S_OK){
				return (DllVersion.dwMajorVersion >= 6);
			}
		}
	}
	return false;
}


EnableThemeDialogTexture is an uxtheme API, rename it if it's already defined.
It only exists on XP and above obviously, that's why it needs GetProcAddress.

Call it for any window you place on top of the tab control like this:
EnableThemeDialogTexture(Window, ETDT_ENABLETAB);

Hope this is what you're looking for...
0

cyberbob 

31 May 2009 - 10:42 PM
big thanks, it is what I was looking for, respect;)
0

ChupaChu 

24 July 2009 - 02:06 PM
would be great fi someone got time to re-type it to delphi :)

Anyway thanks for sharing!
0
Page 1 of 1

September 2010

S M T W T F S
   1234
5 6 7891011
12131415161718
19202122232425
2627282930  

Search My Blog

Recent Entries

Recent Comments