Virtual Developer Workshop: Containerized Development with Docker
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).
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 8x8 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