An Advanced TabCtrl

Download Source Code and Example

The aim for this project was to control the colors of the TabCtrl. In MFC you are not able to
configure your own color combinations for the TabCtrl. With this TabCtrlAdvanced you can choose your
own colors for the background, the display area and the TabCtrl items.

Normally the OnCtlColor function is called in response to a message, so I use a SendMessage to
get the color, although it is now also implemented as a virtual function. The message call is then
mapped to the OnCtlColor in the WindowProc. I thought that this is a nice way to map a range of
messages to one (or if you want more) function(s).

Get your desired color by calling:


SendMessage(WM_CTLCOLOR_XXX, (WPARAM)CDC*, (LPARAM)LPDRAWITEMSTRUCT)


WM_CTLCOLOR_XXX can be one of:

  • WM_CTLCOLOR_BKGND     For the Background, behind the Items
  • WM_CTLCOLOR_TABITEM   For the Item
  • WM_CTLCOLOR_DISPLAY   For the client area of the selected Item

The return value is a CBrush*.Note: You only have to give the LPDRAWITEMSTRUCT if you want to have
the background color for an Item.

I changed the original second parameter of OnCtlColor, to get all the information of the item, so you
can give every item its own color! OK this can be a bit too much color, but if you want to point out one
item more than the others than it might be useful for your users.

To get the full control of the appearance of the items I had to draw them on my own. I like it when
they are bit round at the corners and so I used the createRoundedRectRgn function to create the region
for every item. I used Region because I can easily add them to the clipping region of the Drawing-Process
and I can fill them with a CBrush. Try a pattern-Bitmap for the background – under NT 4.0 it will look
great! Unfortunately Win95 can only handle 8×8 sized bitmaps, but there may be someone who is able to
make Win95 use larger sized bitmaps or implement a fast function to fill a region with larger tiled-Bitmaps.

Now after I decided to work with Regions I recognize another problem, how to draw the shadows? I
solved this problem by creating two regions, one for the outer border, and one for the inner one. The
difference between these two Regions is the Border. The light is always coming from the Left-Top and
so everything above a diagonal from the Left-Bottom to the Right-Top must be drawn with the 3D-Highlight
color and the other side has to be drawn with the 3D-Shadow color.

Now to the drawing process: first of all I draw the selected Item, it is larger than the other ones
and its border will overlap its neighbors, if it is drawn later. The remaining item will be drawn line
by line from the bottom to the top. By drawing it this way I can always clip out the region for drawn
items. This avoids flickering and in case of the selected item it assures that this item looks like
placed above the others.

To add more information to every Item you can use the lParam of the TC_ITEM Structure. It is a 32-bit
value and so it can hold a pointer to a structure, or what I prefer to a class. I prefer using classes
for this kind of parameters because I can check whether they have the correct RUNTIME_CLASS or not.

In my sample I keep the color information and the Title in my additional parameter, but you can expand
this information class for whatever you need. You can see the result in the
sample
project. You can control the colors, the appearance of every item and it IS almost flicker-free!

Last updated: 4 May 1998

More by Author

Must Read