BCGControlBar Pro for MFC
Library Architecture

The BCGControlBar Library Professional Edition (Pro Version) introduces non MFC-based docking architecture. It means that all control bars aren't derived from CControlBar anymore. The base class for all control bars in Pro Version is CBCGPBaseControlBar (that in its turn derived from CBCGPWnd).

The main idea behind the Pro Version architecture does not differ from MFC so much. Even more, we were trying to make the Pro Version highly compatible with MFC (and BCGControlBar Library Standard Edition).

Below you can see the picture of an application built with the Pro Version:

Library Architecture

The application main frame window is usually represented by CBCGPFrameWnd or CBCGPMDIFrameWnd. The main frame is called "dock site". All control bars may have three types of parents: "dock site", "dock bar" or "miniframe window". Control bars may be divided to two general types: non resizable control bars (such as status bars and toolbars) and resizable control bars. Under "resizable" control bars we mean bars that may be resized by splitters (or "sliders"), may form "containers" (one control bar can be docked to another control bar and create a splitter between them) and can't be attached (docked) to dock bars. All non resizable control bars should be derived from CBCGPControlBar. All resizable control bars should be derived from CBCGPDockingControlBar (this class implements the base ability to be docked at the dock site, be placed in container, to become autohide and so on).

Dock site.

The main frame window or dock site is the owner of all control bars and miniframe windows. It contains an embedded member of the CBCGPDockManager class (the docking manager later). The docking manger maintains a list of all control bars that belong to the dock site. The list is ordered in the way that the bars created at the outer edges of the dock site come first. When it's required to recalculate the layout, it loops over this list, adjusts layout of each control bar to the current bounding rectangle (of the dock site) and subtracts the control bar area. You can call mainframeclass::AdjustDockingLayout or RecalcLayout every time you need to adjust the docking layout and this call will be redirected to the docking manager.

Dock bar.

Each main frame may have "dock bars" placed along the borders (aligned to the borders). Dock bar is a control bar of a CBCGPDockBar class. Dock bar can accept CBCGPControlBar-derived objects (usually toolbars). Dock bars should be created during initialization of the main frame window by calling mainframeclass::EnableDocking (DWORD dwDockStyle). If you want to enable "auto hide" bars at some sides of the main frame window you should call mainframeclass::EnableAutoHideBars(DWORD dwDockStyle). This call will create CBCGPAutoHideDockBar objects next to each dock bar. You can still use CBRS_ styles to specify docking alignment. Each dock bar is divided (contains a list of) to "dock rows". Dock rows are represented by the CBCGPDockBarRow class. Each dock row contains a list of toolbars. When a toolbar is being docked (by mouse, for example) or moved from one row to another within the same dock bare, the framework creates a new row and resizes the dock bar accordingly or places the toolbar on the existing row.

Miniframe window.

When a control bar is floating it resides on the miniframe window. Miniframe windows are presented by two classes: CBCGPMiniFrameWnd (can contain only one control bar) and CBCGPMultiMiniFrameWnd (can contain several control bars). A miniframe window is created automatically by the framework when a control bar is being floated. To make control bar floating in code you can call CBCGPBaseControlBar::FloatControlBar (). Take a note, when a control bar becomes floating its parent is changed automatically and set to miniframe window. When a control bar is being docked its parent is changed back to a dock bar (for toolbars) or dock site (for resizable control bars).

Sliders

Sliders (or splitters) are represented by the CBCGPSlider class. Sliders are created automatically by the framework when a docking control bar is docked to the dock site or to another control bar. When the bar is docked to the dock site the new slider is called "default slider". It contains all information regarding the layout of the docking control bars it resizes. Default sliders are placed in the general list of control bars maintained by the dock manager and control all layout operation performed on the "contained" docking control bars.

Containers

All resizable control bars, when docked one to other, are maintained in "containers". Containers are represented by the CBCGPBarContainer class. Each container has pointers to the "left" bar, "right" bar, "left" sub-container, "right" sub-container and splitter between left and right parts. In this way we're able to build a tree of several control bars and splitters and thus achieve very complicated layouts of control bars that can be resized together. The CBCGPBarContainerManager class maintains the tree of containers (it contains a pointer to the root container). Also, it maintains two lists of control bars and sliders that were placed in this tree. Bar container managers are usually embedded into default sliders and miniframe windows carrying multiple control bars.

Autohide control bars

Each docking control bar automatically enabled to have "autohide" ability. When the user clicks the pin button located on the caption of the docking control bar, the bar is switched to autohide mode. The framework creates a new toolbar of CBCGPAutoHideToolbar type and a new button of CBCGPAutoHideButton type, places the toolbar on the autohide dock bar (according to the current bar alignment), attaches the autohide button to the toolbar and attaches the pointer to the docking control bar to the button. At this point the docking control bar is placed in the special list of autohide bars maintained by the dock manager.

Tabbed control bars and outlook bars

The CBCGPBaseTabWnd class implements the base functionality of tabbed window with detachable tabs. The CBCGPBaseTabbedBar is derived from CBCGPDockingControlBar and maintains a pointer to a CBCGPBaseTabWnd object. In this way we achieve the ability to dock and resize tabbed control bars. Use CBCGPDockingControlBar::AttachToTabWnd to create docking tabbed control bars on the fly.

Outlook bar control is also based on tabbed bars in the Pro Version (CBCGPOutlookBar is derived from CBCGPBaseTabbedBar).

Some tips how to customize the application behavior

  1. You can create a new control bar applying a combination of several new styles:

    • CBRS_BCGP_FLOAT: makes control bar floating
    • CBRS_BCGP_AUTOHIDE: enables auto hide mode
    • CBRS_BCGP_CLOSE: control bar can be closed (hidden)

    The CBCGPBaseControlBar implements the following virtual Boolean methods to reflect these flags: CBCGPBaseControlBar::CanBeClosed, CBCGPBaseControlBar::CanAutoHide, CBCGPBaseControlBar::CanFloat. You can override them in the derived classes to customize this behavior.

  2. You can customize the docking behavior by overriding CBCGPBaseControlBar::CanAcceptBar method. If a control bar returns FALSE pBar will not be docked to this control bar.
  3. The library now allows two docking modes: immediate (that was available in the first beta - when a control bar is dragged and docked with a context) and standard (when a control bar is dragged and docked using "drag rectangle"). The docking mode can be either BCGP_DOCK_TYPE::DT_IMMEDIATE or BCGP_DOCK_TYPE::BCGP_DT_STANDARD and it is defined globally by CBCGPDockManager::m_dockModeGlobal. You can alter this variable anytime. If you want to control docking mode for individual control bars, you can override BCGP_DOCK_TYPE CBCGPBaseControlBar::GetDockMode ().
  4. If you want to create a "static" control bar that can't float and it's not possible to dock any control bar before it (like the outlook bar in BCGPOutlookDemo example) you have to create it as non-floating and override CBCGPBaseControlBar::DoesAllowDynInsertBefore method returning FALSE. Starting version 6.01 the default implementation returns FALSE if the bar has been created without CBRS_BCGP_FLOAT style.
  5. Outlook bars behave as a regular tabbed control bar. When you dock one control bar to another, the resulted style will be defined according to the following styles specified when the second docking control bar was created:

    • CBRS_BCGP_REGULAR_TABS: creates regular tabbed control bar
    • CBRS_BCGP_OUTLOOK_TABS: creates outlook-style tabbed bar

    CBCGPDockingControlBar has SetTabbedControlBarRTC method. You can use it to customize control bars that will be created as a result of the docking to a tab window.

  6. You can insert any CWnd-derived controls to outlook and tabbed control bars. The library will automatically wrap those bars using CBCGPDockingCBWrapper objects. This will allow detaching these bars from outlook and tabbed control bars providing at the same time the required docking behavior. CBCGPBaseTabWnd (that is used as a base class for tab window and outlook window) has the SetDockingBarWrapperRTC method that enables you to customize the wrapper appearance and behavior. Set CBCGPBaseTabWnd::m_bEnableWrapping to FALSE to disable this feature. Please, note, when a control bar is wrapped, its immediate parent is set to a dummy docking control bar that in its turn is inserted into a tab window.
  7. If you want to add a tab as non-detachable you can call CBCGPBaseTabWnd::AddTab and set bDetachable to FALSE or call CBCGPBaseTabWnd::EnableTabDetach.
  8. If you want to enable/disable tab swapping call CBCGPBaseTabWnd::EnableTabSwap.
  9. It's highly recommended to create ALL control bars with IDs different than -1.
  10. If you make any changes in the initial docking layout, you have to clear the application registry entry to see the changes (if your application saves the docking state to the registry).
  11. If you enable detachable tabs, the tabbed windows may be created and destroyed dynamically, do not save pointers to dynamic tabbed windows.
  12. If you call CBCGPDockingControlBar::AttachToTabWnd for two non-tabbed docking control bars, a pointer to a tabbed window will be returned using the last parameter ppTabbedControlBar. You can use it to continue adding tabs to the newly created tabbed window (or for other operations).
  13. If you want to dock one docking control bar to another with any alignment, you can call CBCGPDockingControlBar::DockToWindow. The original control bar must be docked somewhere at this time. For toolbars you can still use CBCGPFrameWnd::DockControlBarLeftOf.
  14. The ShowControlBar method has a third non-default parameter bActivate, therefore some existing code may not compile.
  15. CBCGPDockingControlBar::m_bHideInAutoHideMode is a new static member that controls how docking control bars behave in the auto hide mode when you call CBCGPFrameWnd::ShowControlBar. If this variable is set to TRUE, control bars and their auto hide buttons will be hidden. Otherwise, control bars will slide in/out.
  16. Do not use GetStyle() & WS_VISIBLE to determine the control bar visibility. Use CBCGPBaseControlBar::IsVisible instead, because it correctly handles the visibility state in tabbed/autohide modes.
  17. If you want to create a non-floating, non-resizable control bar you should not call DockControlBar. You have to call CBCGPDockManager::AddControlBar (CBCGPControlBar* pNonFloatingBar, ...) instead. This call will register this control bar with docking manager and this bar will take a part in the docking layout.
  18. If you want to create non-floating resizable control bar, you should create it WITHOUT CBRS_BCGP_FLOAT style and call DockControlBar (CBCGPDockingControlBar* pResizableBar).
  19. If you want to exclude a control bar from docking layout, remove toolbar from its dock bar and so on you have to call CBCGPBaseControlBar::UnDockControlBar. You should NOT call this method for control bars in autohide mode or control bars resided in tabs of tabbed windows.
  20. If a control bar has been set to autohide mode, you must call SetAutoHideMode (FALSE,...) before you call CBCGPBaseControlBar::FloatControlBar or CBCGPBaseControlBar::UnDockControlBar.
  21. You can disable autohide animation using CBCGPDockingControlBar::m_bDisableAnimation.