Jump to content
Tuts 4 You

Kibloy's Blog

  • entries
    7
  • comments
    19
  • views
    51,210

Endless fun with tab controls

Sign in to follow this  
Killboy

4,867 views

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.

Sign in to follow this  


10 Comments


Recommended Comments

cyberbob

Posted

Hi Killboy,

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

Share this comment


Link to comment
Killboy

Posted

Hm, what do you mean by transparent? The tab control itself or the subwindows?

Share this comment


Link to comment
cyberbob

Posted

I mean the tab control pages, gray background while using XP themes.

Share this comment


Link to comment
Killboy

Posted

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

Share this comment


Link to comment
cyberbob

Posted

big thanks, it is what I was looking for, respect;)

Share this comment


Link to comment

would be great fi someone got time to re-type it to delphi :)

Anyway thanks for sharing!

Share this comment


Link to comment

Thanx a lot, I didn't know that Win32 API codes were still online :)

Share this comment


Link to comment

Nice post killboy!, right now i´m dealing with TabControls! :)

Share this comment


Link to comment

nice share mate :) omg how did it came that i didn't see this :blink:

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...