Objective Toolkit : Chapter 8 Docking Windows : Using the Docking Window Architecture
Using the Docking Window Architecture
The following topics describe how to use docking windows classes and handle special situations.
To create an application with Objective Toolkit docking windows
Use the Objective Toolkit AppWizard to create a project.
To incorporate Objective Toolkit docking windows into an existing MDI application
1. Integrate the library into your application. For more information, see “To incorporate Objective Toolkit into your application.”
2. From the View menu in Visual Studio, click Resource Includes… Ensure that the _AFX_NO_SPLITTER_RESOURCES is either absent or commented out.
 
// #define _AFX_NO_SPLITTER_RESOURCES
3. Replace the base class of your CMainFrame class. Replace CMDIFrameWnd with SECMDIFrameWnd. The MDI parent frame acquires the functionality it needs to host its resizable SECControlBar children.
4. Replace the base class of all existing MDI child frames (CMDIChildWnd) with SECMDIChildWnd.
5. Replace the base class of all windows derived from CControlBar with SECControlBar.
6. Replace the base class of all windows derived from CDialogBar with SECDialogBar.
7. Replace the base class of all toolbars derived from CToolBar or SECToolBar with SECCustomToolBar.
8. Replace the base class of the status bar derived from CStatusBar with SECStatusBar.
You need to re-derive any status bar derived from CStatusBar from SECStatusBar. You cannot use CStatusBars with our docking window enhancements because they do not have the member variables the class expects.
9. Replace the base class of all windows derived from CDockContext with SECDockContext.
10. Modify the OnCreate() member of your CMainFrame class so that all calls to CControlBar::Create(), CDialogBar::Create(), or CToolBar::Create() reflect the change in prototypes introduced by the re-derivations in the previous steps. In particular, the CControlBar::Create() member adds an additional parameter (dwExStyle) for passing extended style bits. For example, CBRS_EX_STRETCH_ON_SIZE is an extended style bit that you can set in your call to SECDialogBar::Create().
To incorporate Objective Toolkit docking windows into an existing SDI application
1. Integrate the library into your application. For more information, see “To incorporate Objective Toolkit into your application.”
2. From the View menu in Visual Studio, click Resource Includes… Ensure that the AFX_NO_SPLITTER_RESOURCES is either absent or commented out.
 
// #define _AFX_NO_SPLITTER_RESOURCES
3. Replace the base class of your CMainFrame class. Replace CFrameWnd with SECFrameWnd.
4. Replace the base class of all windows derived from CControlBar with SECControlBar.
5. Replace the base class of all windows derived from CDialogBar with SECDialogBar.
6. Replace the base class of all toolbars derived from CToolBar with SECToolBar.
7. Replace the base class of the status bar from CStatusBar with SECStatusBar.
8. Modify the OnCreate() member of your CMainFrame class so that all calls to CControlBar::Create(), CDialogBar::Create(), or CToolBar::Create() reflect the change in prototypes introduced by the re-derivations in the previous steps. In particular, the CControlBar::Create() member adds an additional parameter (dwExStyle) for passing extended style bits. For example, CBRS_EX_STRETCH_ON_SIZE is an extended style bit that you can set in your call to SECDialogBar::Create().
To use Objective Toolkit docking windows inside an OLE IP server
1. Use AppWizard to generate a full server or check ActiveX document server support.
2. Integrate the library into your application. For more information, see “To incorporate Objective Toolkit into your application.”
3. Replace the base class of the server document class (COleServerDoc) with SECOleServerDoc. Replace each base class invocation in the source file when it is appropriate.
4. Replace the base class of your OLE Server Item (COleServerItem) with SECOleServerItem.
If you selected ActiveX document server support when you were generating the application using AppWizard, replace CDocObjectServerItem with SECDocObjectServerItem instead. This provides you with CDocIPFrameWnd support.
5. Use the OnCreateControlBars() method of your COleIPFrameWnd derived class to create your controlbars.
You must cast the pWndFrame pointer from CFrameWnd to SECFrameWnd. This ensures that the proper SEC non-virtual method overrides are called— most notably, EnableDocking().
Each controlbar must set the inplace frame object as its owner, but it should be created with the pWndFrame pointer as the parent.
Refer to the following sample code for more information. In addition, please try secoleip in the samples\toolkit\MFC\docking\secoleip subdirectory. You need to run this sample once to register your server. Open an OLE container like Excel, select Insert Object and then select SecOle document. Embedded Objective Toolkit docking windows and toolbars appear as well as the toolbar customization dialog. Again, Objective Toolkit MenuBars and Docking Views are not supported inside an IP Server.
 
BOOL CInPlaceFrame::OnCreateControlBars(CFrameWnd* pWndFrame, CFrameWnd* pWndDoc)
{
// Remove this if you use pWndDoc
UNREFERENCED_PARAMETER(pWndDoc);
 
// Must cast the pWndFrame to an SECFrameWnd to insure the
// proper "SEC" nonvirtual overrides are called. This
// operation should be type safe if all the docking windows
// enablement steps were properly followed (please refer to
// the user's guide).
ASSERT_KINDOF(SECFrameWnd,pWndFrame);
SECFrameWnd* pSecWndFrame=(SECFrameWnd *)pWndFrame;
m_pDockingFrameWnd=pSecWndFrame; // save ptr for OnClose
//handler
 
// A toolbar manager is needed to provide toolbar
// customization support. In normal Objective Toolkit docking windows,
// we can simply instantiate the m_pControlBarMgr member of
// SECFrameWnd/SECMDIFrameWnd. Since this is an
// COleIPFrameWnd object, though, we must manually track
// this ptr and clean up as needed.
// Note 2: all controlbars must have pWndFrame as a parent,
// but this COleIPFrameWnd as the owner for proper command
// routing.
// Use the second toolbar mgr constructor overload to provide
// this necessary linkage.
SECToolBarManager* pToolBarMgr=
new SECToolBarManager(pSecWndFrame,this);
m_pToolBarMgr=pToolBarMgr; // save for memory cleanup
pSecWndFrame->SetControlBarManager(pToolBarMgr);
 
// Configure the customizable toolbars
VERIFY(pToolBarMgr->LoadToolBarResource(
MAKEINTRESOURCE(IDR_SECOLETYPE_SRVR_IP),
MAKEINTRESOURCE(IDR_SECOLETYPE_SRVR_IP_LG)));
pToolBarMgr->SetButtonMap(btnMap);
pToolBarMgr->DefineDefaultToolBar(AFX_IDW_TOOLBAR,_T("File"),
NUMELEMENTS(fileButtons),fileButtons,
CBRS_ALIGN_ANY,AFX_IDW_DOCKBAR_TOP);
pToolBarMgr->DefineDefaultToolBar(AFX_IDW_TOOLBAR + 5,
_T("Edit"),NUMELEMENTS(editButtons),
editButtons,CBRS_ALIGN_ANY,
AFX_IDW_DOCKBAR_TOP,AFX_IDW_TOOLBAR);
pToolBarMgr->DefineDefaultToolBar(
AFX_IDW_TOOLBAR + 6, _T("Debug"),
NUMELEMENTS(debugButtons),
debugButtons,
CBRS_ALIGN_ANY,
AFX_IDW_DOCKBAR_TOP,
AFX_IDW_TOOLBAR);
 
pToolBarMgr->EnableCoolLook(TRUE);
 
pSecWndFrame->EnableDocking(CBRS_ALIGN_ANY);
 
// Output Window
m_wndOutput.SetOwner(this); // mandatory!
if (!m_wndOutput.Create(pSecWndFrame,
_T("Output Window"),
CBRS_BOTTOM|WS_VISIBLE |
CBRS_SIZE_DYNAMIC|CBRS_TOOLTIPS,
CBRS_EX_STDCONTEXTMENU|CBRS_EX_ALLOW_MDI_FLOAT |
CBRS_EX_COOL|CBRS_EX_BORDERSPACE,
ID_OUTPUTWINDOW)) {
TRACE(_T("Failed to create dialog bar\n"));
return -1;
}
m_wndOutput.EnableDocking(CBRS_ALIGN_ANY);
pSecWndFrame->DockControlBarEx(&m_wndOutput,
AFX_IDW_DOCKBAR_BOTTOM,
0, 0, (float)0.75, 130);
// Project Workspace Window
// mandatory!
m_wndProjectWorkspace.SetOwner(this);
if (!m_wndProjectWorkspace.Create(pSecWndFrame,
_T("Project Workspace"),
CBRS_RIGHT | WS_VISIBLE |
CBRS_SIZE_DYNAMIC |
CBRS_TOOLTIPS,
CBRS_EX_STDCONTEXTMENU |
CBRS_EX_ALLOW_MDI_FLOAT |
CBRS_EX_COOL |
CBRS_EX_BORDERSPACE,
ID_PROJECTWORKSPACE))
{
TRACE(_T("Failed to create dialog bar\n"));
return -1;
}
m_wndProjectWorkspace.EnableDocking(CBRS_ALIGN_ANY);
pSecWndFrame->
DockControlBarEx(&m_wndProjectWorkspace,
AFX_IDW_DOCKBAR_RIGHT, 0, 0,
(float)1.00, 180);
// Load default toolbar state
pSecWndFrame->LoadBarState(_T("SecOleIPBarState"));
pToolBarMgr->LoadState(_T("SecOleIPBarState"));
return TRUE;
}
To create a docking window based on a dialog resource
1. Create a dialog resource for the docking window using the resource editor in Visual Studio.
2. Create an SECDialogBar-derived class to manage the client area of the docking window.
3. Instantiate an object of the SECDialogBar-derived class as a member of the frame in which the docking window is included (either SECFrameWnd or SECMDIFrameWnd).
4. In the frame window’s OnCreate() method, call the Create() method of the instantiated control bar to initialize it and then pass the resource ID of the dialog resource.
To create a docking window not based on a dialog resource
1. Ensure your frame class is either SECFrameWnd or SECMDIFrameWnd-derived.
2. Create an SECControlBar-derived class to manage the client area of the docking window.
3. As a data member of your frame class, instantiate the SECControlBar-derived object.
4. In the frame window’s OnCreate() method, call the Create() method of the instantiated control bar to initialize it.
To set the style of a docking window
1. Specify the CBRS_ styles either in the Create() call for the SECControlBar-derived class or call the CControlBar::SetBarStyle() method.
See the Objective Toolkit Class Reference for more information on the CControlBar::SetBarStyle() method and descriptions of these styles.
2. Specify the CBRS_EX_ style extensions in the Create() call for the SECControlBar-derived class.
See “Extended ControlBar Styles”for a list and a description of the extended docking windows styles.
NOTE >> The SECControlBar::SetExBarStyle() method will set the extended bar style.
To make a docking window dockable
Call SECControlBar::EnableDocking(), SECMDIFrameWnd::EnableDocking(), and SECMDIFrameWnd::DockControlBarEx().
This also applies to SECFrameWnd.
For example:
 
CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
 
...
EnableDocking(CBRS_ALIGN_ANY);
 
// Create the control bar
if (!m_wndControlBar.Create(this, _T("Control Bar 1"),
CBRS_BOTTOM | WS_VISIBLE | CBRS_SIZE_DYNAMIC, CBRS_EX_COOL,
ID_OUTPUTWINDOW))
{
 
TRACE(_T("Failed to create control bar\n"));
return -1;
}
 
m_wndControlBar.EnableDocking(CBRS_ALIGN_ANY);
DockControlBarEx(&m_wndControlBar, AFX_IDW_DOCKBAR_BOTTOM, 0, 0, (float)0.75, 130);
...
}
To create a non-dockable control bar
1. Notice the following lines in the OnCreate() method of your frame class. The following VC++ AppWizard generated comment is incorrect:
 
// TODO: Delete these three lines if you do not
// want the toolbar to be dockable
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
If you follow the directions and delete these three lines, a pseudo-docked toolbar that draws incorrectly appears. This occurs whether or not you are using Objective Toolkit. This comment is incorrect. You still need to call EnableDocking(), but you also need to pass a value of zero to create the CDockContext().
2. Instead of deleting the lines, call SECControlBar::EnableDocking() with a parameter of zero. For example:
 
m_wndToolBar.EnableDocking(0);
3. Call either ToggleDocking() or FloatControlBar() on the control bar. ToggleDocking() automatically computes an initial point for you.
 
//m_wndToolBar.m_pDockContext->ToggleDocking();
FloatControlBar(&m_wndToolBar, CPoint(50,50));
To dock a docking window that is floating
Call the DockControlBar() or DockControlBarEx() methods from your frame window class. These methods dock a control bar that is either floating or docked to another dock bar. The DockControlBarEx() method gives you more control over how and where the control bar is docked.
To float a docking window that is docked
Call the FloatControlBar() method, which is a member of SECFrameWnd/SECMDIFrameWnd. This method removes a bar from its dockbar and floats it. It can also move a floating bar to a new location.
To make an SECDialogBar size diagonally when floated
Conditionally typecast pFrameWnd to SECMDIFrameWnd or SECFrameWnd so that the FloatControlBar() method in SECMDIFrameWnd is called instead of CFrameWnd. For example:
 
if (pFrameWnd-> IsKindOf(RUNTIME_CLASS(SECMDIFrameWnd)))
((SECMDIFrameWnd*)pFrameWnd->FloatControlBar(. . .);
else if (pFrameWnd->
IsKindOf(RUNTIME_CLASS(SECFrameWnd)))
((SECFrameWnd*)pFrameWnd->
FloatControlBar(. . .);
else
pFrameWnd->FloatControlBar(. . .);
To receive notifications when the docked state of a docking window changes
1. Create an SECControlBar-derived class.
2. Override the following callback methods.
Callback method
Description
OnBarBeginDock()
Called before a bar is docked. The default implementation calls OnBarDock().
OnBarDock()
Called before a bar is docked. The default implementation does nothing.
OnBarEndDock()
Called after a bar is docked. The default implementation does nothing.
OnBarBeginFloat()
Called before a bar is floated. The default implementation calls OnBarFloat().
OnBarFloat()
Called before a bar is floated. The default implementation does nothing.
OnBarEndFloat()
Called after a bar is floated. The default implementation does nothing.
OnBarBeginMDIFloat()
Called before a bar is docked as an MDI child. The default implementation calls OnBarMDIFloat().
OnBarMDIFloat()
Called before a bar is floated as an MDI child. The default implementation does nothing.
OnBarEndMDIFloat()
Called after a bar is floated as an MDI child. The default implementation does nothing.
To hide a docking window
Use ShowControlBar(), which is a member of SECFrameWnd/SECMDIFrameWnd. Calling ShowWindow() has no effect on the control bar.
To control the docking location of a docking window
Call the SECControlBar::EnableDocking() method. This method controls the ability to dock the window as well as where the window can be docked on its parent window. Refer to the Objective Toolkit Class Reference for more information on this method and its parameters.
To determine where a docking window is docked
1. Use either CFrameWnd::GetControlBar() or CDockBar::FindBar() to get a pointer to a control bar.
2. Refer to the dock bar ID map, which is defined in both SECFrameWnd and SECMDIFrameWnd.
 
const DWORD SECFrameWnd::dwSECDockBarMap[4][2] =
{
{ AFX_IDW_DOCKBAR_TOP, CBRS_TOP },
{ AFX_IDW_DOCKBAR_BOTTOM, CBRS_BOTTOM },
{ AFX_IDW_DOCKBAR_LEFT, CBRS_LEFT },
{ AFX_IDW_DOCKBAR_RIGHT, CBRS_RIGHT },
};
 
const DWORD SECMDIFrameWnd::dwSECDockBarMap[4][2] =
{
{ AFX_IDW_DOCKBAR_TOP, CBRS_TOP },
{ AFX_IDW_DOCKBAR_BOTTOM, CBRS_BOTTOM },
{ AFX_IDW_DOCKBAR_LEFT, CBRS_LEFT },
{ AFX_IDW_DOCKBAR_RIGHT, CBRS_RIGHT },
};
3. By using the information above, you can add a member to your mainframe that determines to which dockbar a particular control bar is docked.
 
UINT CMyMainFrame::GetControlBarDockSite(...)
{
 
// In case we don't find a place holder,
// find a bar with the correct alignment
// and keep it in pPossibleBar.
 
CDockBar* pDockBar= NULL;
for (int i = 0; i < 4; i++) {
pDockBar = (CDockBar*)
GetControlBar(dwSECDockBarMap[i][0]);
if ((pDockBar->FindBar(pBarFind, -1) != -1)
{
bFound = TRUE;
break;
}
}
 
if (bFound) {
switch (dwSECDockBarMap[i]) {
case AFX_IDW_DOCKBAR_TOP:
return CBRS_TOP;
}
}
}
To determine the row and column of a docked window
Call the SECControlBar::GetBarSizePos() method. This method returns information about the control bar position. In addition, it can also return information about the dockbar position and size.
To modify a control bar’s context menu
A context (shortcut) menu is a pop-up menu that appears when the user presses the right mouse button. The SECControlBar bar defines a standard context menu and a convention for extending or modifying it. By default, the control bar is given two context menu items (Hide and Allow Docking). There are two techniques for extending the standard context menu.
If the menu item applies to all control bars of a given class, override the SECControlBar::OnExtendContextMenu() method in a derived class and extend the menu through the pMenu parameter.
To learn how to use this method of context menu extension, see the source file samples\toolkit\MFC\docking\viz\outbar.cpp and the OutputControlBar::OnExtendContextMenu() method.
If the menu item represents a capability that the main frame window enables, handle theWM_EXTENDCONTEXTMENU message in your CMainFrame class and extend the menu through the menu handle passed via LPARAM.
NOTE >> SECControlBar always sends this message to its parent frame window after constructing the default context menu.
For an example of this form of context menu extension, see the source file src\toolkit\mdi\swinmdi.cpp and the SECMDIFrameWnd::OnExtendContextMenu() method.
To add a toolbar to a control bar
1. Override SECDialogBar::OnCreate() and create the toolbar as a child of the dialog bar.
2. Override SECDialogBar::OnSize() and layout the toolbar and dialog template so they do not overlap.
To access controls in the docking window inside a message handler
Use the following code in your message handler:
 
const MSG* pMsg = CWnd::GetCurrentMessage();
 
HWND hWnd = HWND(pMsg->lParam);
ASSERT(::IsWindow(hWnd));
 
CComboBox* pCombo = STATIC_DOWNCAST( CComboBox,
CWnd::FromHandle(hWnd) );
To route messages to the client area of SECControlBar
Override OnCmdMsg() and check the focus window. If it is your control bar window, route the message to it. If not, let default handling occur.
NOTE >> We have solved this problem in our Docking Views.