CSizingControlBar - a resizable control bar

Cristi Posea

DevStudio-like docking window 

Newsletter | Forums | Search | Latest Updates | Submit an Article | Win a Prize!

Level:    Advanced
Posted:   17 Nov 1999
Updated: 12 Jan 2000

Platform:
VC++ 5.0-6.0, NT 4.0, Win95/98/2k
Keywords:
GUI, MFC, docking
Home >> Toolbars & Docking Windows >> General Problems? Suggestions? Email us

Features of CSizingControlBar 2.31

Instructions

Derive a class from CSizingControlBar (you have an example in mybar.h and mybar.cpp).
Add a member variable to CMainFrame (in mainfrm.h).

CMyBar m_wndMyBar;

Create the bar in CMainFrame::OnCreate(). Then set bar styles, enable it to dock... like any control bar.

Some experience in working with control bars (like toolbars) is required.

if (!m_wndMyBar.Create(_T("My Bar"), this, CSize(200, 100),
    TRUE /*bHasGripper*/, AFX_IDW_CONTROLBAR_FIRST + 32))
{
    TRACE0("Failed to create mybar\n");
    return -1;
    // fail to create
}
m_wndMyBar.SetBarStyle(m_wndMyBar.GetBarStyle() |
    CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
m_wndMyBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);

m_pFloatingFrameClass = RUNTIME_CLASS(CSCBMiniDockFrameWnd);

DockControlBar(&m_wndMyBar, AFX_IDW_DOCKBAR_LEFT);
Note: Starting with version 2.3, the line
m_pFloatingFrameClass = RUNTIME_CLASS(CSCBMiniDockFrameWnd);
must be added to CMainFrame::OnCreate(), after the EnableDocking() call. This is required!

Plugging in the CSizingControlBarCF class

1. Add scbarcf.h and scbarcf.cpp to your project.

2. In your derived class header file change the "#include "sizecbar.h" to "#include "scbarcf.h".

3. Replace the base class for your custom bar from CSizingControlBar to CSizingControlBarCF. If you used the baseCMyBar trick, you only have to change a line. Otherwise, replace all occurences of CSizingControlBar with CSizingControlBarCF in your derived class.

4. Rebuild and run. Easy, huh?

Remarks

This class is intended to be used as a base class. Do not simply add your code to the sizecbar.* files - instead create a new class derived from CSizingControlBar and put there what you need.

Window IDs: You can see above that the control bar is created with the ID AFX_IDW_CONTROLBAR_FIRST + 32. The usage of IDs in the range of AFX_IDW_CONTROLBAR_FIRST + 32 .. AFX_IDW_CONTROLBAR_LAST is required only if the bar will not be enabled for docking (that's is - it will stay fixed right under the frame's menu). But in this situation you won't be able to fully use the features of this class, so if you will enable it to dock (a reasonable guess :) then you can use any valid window ID.
Another place where the IDs are important is the saving/loading of the bar's state. You must use different IDs for each control bar that is enabled to dock, and this includes the other bars too. For example, if you have two toolbars, you can create the first one with the default ID (which is AFX_IDW_TOOLBAR = AFX_IDW_CONTROLBAR_FIRST), but the second one must have a different ID.

OnUpdateCmdUI: This member function is pure virtual in CControlBar (the base class of CSizingControlBar). Its purpose is to allow updating of controls at idle time (from here CCmdUI::DoUpdate() is called for the toolbars' buttons, dialogbars' controls, the panes of status bar, etc.).
However, I found it very useful to update the look of the "x" flat button (no timers needed). So, if you will use this function, don't forget to call the base class' member (see mybar.cpp).

Dynamic resizing: This feature allows redrawing of the bar during resizing. Also all the bars are repositioned and redrawn if necessary.
The SPI_GETDRAGFULLWINDOWS system parameter is queried for this (it is enabled by the "Show window contents while dragging" checkbox in Display Properties).

CBRS_SIZE_DYNAMIC: This bar style is required. Make sure you add it to the bar, otherwise the application will crash when the user floats a bar. You can add it using SetBarStyle() after Create(), or by changing the default style for Create() to something like: WS_VISIBLE | WS_CHILD | CBRS_TOP | CBRS_SIZE_DYNAMIC.

State persistence: The common MFC control bars' docking state is saved using CMainFrame::SaveBarState(). In addition to the info saved by this function, the CSizingControlBar class needs to save 3 sizes. This is done in CSizingControlBar::SaveState() function, so a m_wndMyBar.SaveState() call is required. Please note that the state storing code must be placed in CMainFrame's OnClose() or DestroyWindow(), not in OnDestroy(), because at the time WM_DESTROY message is received, the floating bars are already destroyed.
In CMainFrame::OnCreate(), the m_wndMyBar.LoadState() call must be placed before LoadBarState().
Alternatively, if you have multiple CSizingControlBar derived bars, you can call once the static member SizingControlBar::GlobalSaveState() instead of calling each bar's SaveState(). The same for LoadState() - there is a CSizingControlBar::GlobalLoadState() function. See both samples here for more details.

See also www.datamekanix.com for a full changelog, FAQ, a dedicated message board and more.


Home >> Toolbars & Docking Windows
last updated 12 Jan 2000
Copyright © CodeProject, 1999-2000.
All rights reserved
webmaster@codeproject.com