Full-Screen Caption Bar

Environment: VC6 SP5, NT4 SP3, Win9x, Win2k, and WinXP


After working with Remote Desktop from Microsoft, I saw the full-screen caption bar that came on top. The FullScreenHeader is a lookalike of that caption; it is made in Win32 and I've tried to make it somewhat customized.

This is my first Win32 app every released, and it may be errors in it. Please point out any errors that I may have made.

Why did I made this? Well, it is the really good opensource utility called RealVNC (http://www.realvnc.com). It is a "remote desktop" freeware with very nice clones. Check them out at UltraVNC (http://www.ultravnc.com) and TightVNC (http://www.tightvnc.com). Many features have been added and I've already implemented the caption in each of these versions. Hopefully, this will be integrated in feature releases of every VNC. If not, you can download all the versions from my Web site: http://lars.werner.no.

Using the Code

You need to add five resources to your project, plus one context menu, as shown in the following code snippet.

void CTitleBar::LoadPictures()
  hClose=LoadBitmap(hInstance,    MAKEINTRESOURCE(IDB_CLOSE));
  hMaximize=LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_MAXIMIZE));
  hMinimize=LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_MINIMIZE));
  hPinUp=LoadBitmap(hInstance,    MAKEINTRESOURCE(IDB_PINUP));
  hPinDown=LoadBitmap(hInstance,  MAKEINTRESOURCE(IDB_PINDOWN));

These pictures are included in the demo project. All pictures should be the same size, but you decide the width and height. See the "Customize" section for more info.

You also need to add a context menu to the resource; the default name is IDR_tbMENU. If you have set the tbLastIsStandard=TRUE, you have to add three "default" entries to the menu. From the bottom, they are Close, Minmize, and Restore. All IDs used on each item can be set to eg: IDC_NULL because it is not in use. The tbWMCOMMANDIDStart/End flag sets the range for the IDs used internally in a context menu.

If you want to add other entries to the context menu, you can add them above the three default entries if you're using them. The parent will get an WM_USER+tbWMUSERID+nItem sent to its message queue. (See the "Customize" section for options that are available to you.)

Implementing in MFC

CTitleBar *TitleBar;

//Eg in OnInitDialog() procedure
TitleBar=new CTitleBar(AfxGetInstanceHandle(), this->GetSafeHwnd());

//Eg on OnCancel()
delete TitleBar;

You can also declare it without pointers:

CTitleBar TitleBar;

//Eg in OnInitDialog() procedure
Title.Create(AfxGetInstanceHandle(), this->GetSafeHwnd());

Here is a simple Win32 example. It uses the desktop hwnd to create a child toolbar.

#include "stdafx.h"
#include "res\\Resource.h"
#include "FullScreenTitleBar.h"

CTitleBar *TitleBar;

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
  // TODO: Place code here.

  TitleBar=new CTitleBar(hInstance, ::GetDesktopWindow());

  MSG msg;

  //Wait until loop is finished
  while ( GetMessage(&msg, NULL, 0,0) )

  //Delete and quit program
  delete TitleBar;

  return 0;

This ends the section on how to implement the captionbar in Win32/MFC. Here are the rest of the public variables:

  • void Create(HINSTANCE hInst, HWND ParentWindow)—Create a new caption bar
  • void SetText(LPTSTR TextOut)—Set a headertext
  • void DisplayWindow(BOOL Show, BOOL SetHideFlag=FALSE)—Displaywindow is an alternative to showwindow. It adds the "slide" of the window. The option "SetTheHideflag" is a override; when it is true, the window will scroll to the top and it will call a ShowWindow(m_hWnd, SW_HIDE)
  • HWND GetSafeHwnd()—Returns the HWND for the main window


There are several options that might be changed at compile time for the captionbar. Here is a complete list:

Option Default Value Description
#define tbWidth 500 Width of caption bar
#define tbHeight 20 Height of caption bar
#define tbcxPicture 16 Default size of picture (cx)
#define tbcyPicture 14 Default size of picture (cy)
#define tbTopSpace 3 Top margin
#define tbLeftSpace 20 Left margin
#define tbRightSpace 20 Right margin
#define tbButtonSpace 1 Space between buttons
#define tbFont "Arial" Font name used in the caption
#define tbFontSize 10 Size of font
#define tbTextColor RGB(255,255,255) Color of text
#define tbStartColor RGB(0,128,192) Background color - Start of gradient
#define tbEndColor RGB(0,0,192) Background color - End of gradient
#define tbGradientWay TRUE TRUE = Vertical, FALSE = Horiz.
If you don't like the gradient, set tbStartColor=tbEndColor
#define tbBorderPenColor RGB(255,255,255) Color of the border around caption bar
#define tbBorderPenShadow RGB(100,100,100) Color of the shadow of the caption bar (bottom)
#define tbTriangularPoint 10 Triangularpoint is how many pixels it should move on the 1eft and right side to make the captionbar not so like the other captionbars
#define tbBorderWidth 2 Width of the pen used to draw the border
#define tbHideAtStartup TRUE Hide window when created
#define tbPinNotPushedIn FALSE Is the pin pushed in or out at startup (INVERTED!)
#define tbScrollWindow TRUE Animate window to scroll up/down
#define tbScrollDelay 20 Timer variable for scrolling the window (cycletime) [ms]
#define tbAutoScrollTime 10 tbAutoScrollDelay milliseconds steps. If it is 10, then = 10 (steps)

100ms (tbAutoScrollDelay) = 1000ms delay
#define tbScrollTimerID 1 Timer id - Internally used, but it can cause conflicts!
#define tbAutoScrollTimer 2 Timer id - Internally used, but it can cause conflicts!
#define tbAutoScrollDelay 100 Timer variable for how many times the cursor is not over the window. If it is tbAutoScrollTime, it will hide if autohide
#define tbIDC_CLOSE 10 Resource ID - close button
#define tbIDC_MAXIMIZE 20 Resource ID - maximize button
#define tbIDC_MINIMIZE 30 Resource ID - minimize button
#define tbIDC_PIN 40 Resource ID - pin button
#define tbDefault FALSE FALSE = Send a custom WM message, TRUE = Send Minimize, maximize, and close to parent (normal Sendmessage and Showmessage commands)
#define tbWM_CLOSE WM_USER+1000 Message to send to parent on close event
#define tbWM_MINIMIZE WM_USER+1001 Message to send to parent on minimize event
#define tbWM_MAXIMIZE WM_USER+1002 Message to send to parent on maximize event
#define tbMENUID IDR_tbMENU Resource name for the context menu
#define tbWMCOMMANDIDStart 50000 Start: This is the internal id number sent into the WM_COMMAND on each item
#define tbWMCOMMANDIDEnd 51000 End: This is the internal id number sent into the WM_COMMAND on each item
#define tbWMUSERID 2000 This is WM_USER+n setting. Eg: if first item is clicked, you will get an WM_USER+n+0 to the parent, and WM_USER+n+1 for the next item, etc. etc. (sent to parent)
#define tbLastIsStandard TRUE TRUE = Bottom of the menu is close, minimize and restore

FALSE = Every item is sent as WM_USER+n to parent

All other variables (private) should not be tweaked; it may cause failure in other procedures in the program. Modify these at your own risk.

Known Issues

Sometimes, when you delete the caption bar, a destroywindow is called. Because the window is made as a child, it will send a message to the parent asking it to be closed. This might cause the parent to close also. A solution to this problem is to create the caption bar at run time, hide it, and show it as you need it. And, when the main program closes, you can destroy the object. This bug will be sorted out in a later version.

If you encounter the situation where no messages are being sent to your parent window, please check the tbDefault variable. If the user presses the context menu, it will send a "click" to any of the buttons in the parent, and use the parameters used for the buttons.

Version History

First release (non-public): V1.0
First release: v1.1


Download demo project - 75 Kb
Download source - 8 Kb

About the Author

Lars Werner

Thnx for viewing my article...

Check out some of my projects:

http://lars.werner.no/sizeme/ - Ultimate tool for maximize your output on CD/DVDs!

http://lars.werner.no/unpacker/ - Auto extract of multiple archives (RAR/ZIP) with queue support and cleanup options!

http://lars.werner.no/vnc/ - Fullscreen captionbar modified VNC clones (RealVNC, UltraVNC and TightVNC)

Visit http://lars.werner.no/ for more info!


  • good looks, but some problems

    Posted by fredwobus on 10/18/2005 05:21pm

    Hi Lars, I tried out the title bar, and I like the look and feel, but I also found some problems. (1) No support for multiple monitors. You need to call the appropriate functions in the Windows API to find the bounding rect of the current monitor. If your app is opened on the second screen the title bars stays on the first screen. (2) The code assumes that the desktop rect always starts at (0,0), this assumption is easily broken when you drag your taskbar to the top of your screen. the animation will not stop then and the titlebar moves all over the place. I had to make a lot of modifications to make the code handle screenrects other than (0,0)[resx,resy] Maybe you can update your code (and convert it to MFC maybe???) Cheers, Fred

  • Nice, but...

    Posted by Legacy on 02/11/2004 12:00am

    Originally posted by: Anonymous

    the slide animation's kind'a skippy.

    • Timer used for animation

      Posted by Large on 03/15/2004 04:45am

      If the animation is slow, i guess you're system have problem sending the timer messages and updating the gfx at the same time. I have not encounter the same problem. On the other side, the animation could be skippy if you use vnc inside remote desktop or something simular like that. Have a nice day, regards Lars Werner http://lars.werner.no

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • With JRebel, developers get to see their code changes immediately, fine-tune their code with incremental changes, debug, explore and deploy their code with ease (both locally and remotely), and ultimately spend more time coding instead of waiting for the dreaded application redeploy to finish. Every time a developer tests a code change it takes minutes to build and deploy the application. JRebel keeps the app server running at all times, so testing is instantaneous and interactive.

  • You probably have several goals for your patient portal of choice. Is "community" one of them? With a bevy of vendors offering portal solutions, it can be challenging for a hospital to know where to start. Fortunately, YourCareCommunity helps ease the decision-making process. Read this white paper to learn more. "3 Ways Clinicians can Leverage a Patient Portal to Craft a Healthcare Community" is a published document owned by www.medhost.com

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds