Application Security Testing: An Integral Part of DevOps
Environment: VC6 SP4, W2K SP1 - Does not work on Win95 with DirectX because of Transparent Bitmap drawing.
After having this base code for about a year and a half it has finally matured to the stage where I feel that it can be used in other people's applications. The basis of the CCaptionButton class is to create a "button-like" interface toolbar in the caption area. My original idea was to create a uniform interface with the existing windows captions (Minimize,Maximize,Close), but I decided to go the more creative route and use bitmaps which would allow me to create a unique interface rather than the same old bland captions. With this CCaptionButton was born. It uses 2 bitmaps per caption plus 1 common mousedown bitmap. You can also pass in HICONs for the captions, but they are then just converted to HBITMAPs.
- Bitmap Image Captions
- Icon Image Captions
- Dynamic Replace
- Dynamic Add
- Dynamic Deletion
- Caption Press notification
- Flexible Design
As you look through the class you may notice that some functions that you would expect to see are missing. This is for a simple reason. I did not need to use them during the course of creating programs with this class. They should be quite easy to add so post an addition in the comments below.
The initialization may seem complex, but it is actually fairly simple. You will probably spend most of your time creating the bitmaps. For the first 3 captions I used a technique of combining bitmaps together to create a uniform mouseover effect. This is not necessary, but saves lots of memory in the .exe since you don't have to store different mouseover bitmaps for every caption.
// declare as class variable or global CCaptionButton cbExtra; // subclass the window cbExtra.Init(hWnd); // set the number of regular captions (Minimize/Maximize/Close) cbExtra.SetNumOfDefaultCaptions(3); // set the images transparency color COLORREF crTransparent = RGB(255,0,255); cbExtra.SetTransparentColor(crTransparent); // set the bitmap to be displayed cbExtra.SetSelectionBitmap((HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_SELECTION), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS|LR_DEFAULTCOLOR)); // create our mouseover bitmaps (you could load them directly, // but this way saves memory) HBITMAP hMouseOverBitmap = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_MOUSEOVER), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS|LR_DEFAULTCOLOR); // caption AM Productions HBITMAP hCaptionAMBitmap = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_BITMAP_AM), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS|LR_DEFAULTCOLOR); HBITMAP hCaptionAMBitmapHilite = CCaptionButton::CombineBitmaps(hCaptionAMBitmap, hMouseOverBitmap, crTransparent); // caption 2 HBITMAP hCaption2Bitmap = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_BITMAP2), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS|LR_DEFAULTCOLOR); HBITMAP hCaption2BitmapHilite = CCaptionButton::CombineBitmaps(hCaption2Bitmap, hMouseOverBitmap,crTransparent); // caption 3 HBITMAP hCaption3Bitmap = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_BITMAP3), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS|LR_DEFAULTCOLOR); HBITMAP hCaption3BitmapHilite = CCaptionButton::CombineBitmaps(hCaption3Bitmap, hMouseOverBitmap,crTransparent); // create caption with ID = 1, mouseover effect bitmap of // hCaptionAMBitmapHilite, normal bitmap of hCaptionAMBitmap, // and tooltip text of "AM Productions - Visit Now!" cbExtra.New(1,hCaptionAMBitmapHilite,hCaptionAMBitmap, "AM Productions - Visit Now!"); cbExtra.New(2,hCaption2BitmapHilite,hCaption2Bitmap,"Caption 2"); cbExtra.New(3,hCaption3BitmapHilite,hCaption3Bitmap,"Caption 3"); // just load it directly from the bitmap resources cbExtra.New(4, (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_BITMAP5), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS|LR_DEFAULTCOLOR), (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_BITMAP6), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS|LR_DEFAULTCOLOR), "Caption 4");
At this point you may be saying "That's all great, but how do I know if a caption has been pressed?" Well here is your answer. When a caption is clicked a WM_CBLBUTTONCLICKED is generated and sent to the window with the captions. The WPARAM of this message contains the ID of the caption which was pressed, and the LPARAM contains a POINT structure of the screen coordinates of the cursor when the caption was clicked (good for displaying menus).
What is with all those "Dynamic" features? Well the CCaptionButton class has the ability to add, replace, and delete captions at runtime. To add a caption simply call the New() function, but as a fifth parameter specify the zero based index of where you would like to insert the caption (from right to left). It is not much harder to replace an existing caption.
// replacing a caption cbExtra.Replace(nCurrentCaptionID, nNewCaptionID, hNewMouseoverBitmap, hNewNormalBitmap, pNewToolTipText);
Deleting a caption may seem difficult, but I'm sure that you will get used to it.
// deleting a caption cbExtra.Delete(nCurrentCaptionID);
- Adds significant overhead to a window's message processing
- Flickering during window resize
- Removed the SetCaptionType() and SetWindowType() functions and auto-detected that information in Init().
- Now works with child windows.
- Example shows the use with a child window
- Example shows the use with a modeless dialog
I know that there is a lot of room for improvement, so feel free to post or email comments.