The topics that follow demonstrate how to utilize docking views in your applications.
Incorporate docking windows into your application. See Section 21.5, "Using the Advanced Docking Windows Architecture," for more information.
In the InitInstance() method of your application object, modify your document template class to utilize SECMultiDocTemplate in place of CMultiDocTemplate.
SECMultiDocTemplate* pTemplate=new SECMultiDocTemplate( IDR_RICHEDITTYPE, RUNTIME_CLASS(CREditDoc), pDefaultMdiChildFrameClass, RUNTIME_CLASS(CRichEditView)); AddDocTemplate(pTemplate); |
Docking views are not supported by SDI applications.
See Section 8.11.7, "To set the style of a docking window." In this chapter, see Section 22.4, "Docking Views Options."
Create an SECMultiDocTemplate-derived class. Add the static data member, m_bDockingViewCaptionButton, to this class. Because it is static, this flag affects every docking view. For example:
// static docking view flags for easy access static BOOL m_bDockingViewCaptionButton; |
In the new class, override the OnEnableSysCommandEx() method to set the SCXOPT_NO_CAPTION_BUTTON style based conditionally on the state of m_bDockingviewCaptionButton, and then call the base class implementation. This override ensures that each new frame has the appropriate docking style.
// This virtual callback is called when a new // frame is being created. Override to customize // the docking view support. Note that changes // set here do not take effect until the next // frame is created (either a new document // is opened, or an existing document is // docked/undocked). Calling the EnableSysCommandEx //frame window function is necessary for immediate //update (must be used in conjunction with // this override to maintain config through all // docking states). void CMyMultiDocTemplate::OnEnableSysCommandEx (CFrameWnd* pFrame, DWORD dwScxFlags) { // use the nsSysCommandEx namespace for // easy typing using namespace nsSysCommandEx; // Flag that we are actively using the // syscommandEx options: dwScxFlags|=SCXOPT_ENABLED; // do we want a caption button? if(m_bDockingViewCaptionButton) dwScxFlags&=~SCXOPT_NO_CAPTION_BUTTON; else dwScxFlags|=SCXOPT_NO_CAPTION_BUTTON; // Pass this info along to the base class SECMultiDocTemplate::OnEnableSysCommandEx( pFrame, dwScxFlags); } |
In the InitInstance() method of your application object, modify your document template class to utilize the SECMultiDocTemplate-derived class.
CMyMultiDocTemplate* pTemplate = new CMyMultiDocTemplate( IDR_MYRESTYPE, RUNTIME_CLASS(CMyDoc), RUNTIME_CLASS(SECWorksheetWnd), RUNTIME_CLASS(CMyView))); AddDocTemplate(pTemplate); |
In the view class, add a new method, UpdateParentFrame(). This method updates the frame so they reflects the current state of the caption button.
void CMyView::UpdateParentFrame() { DWORD dwScxFlags=SCXOPT_ENABLED; if(!CMyMultiDocTemplate::m_bDockingViewCaptionButton) dwScxFlags|=SCXOPT_NO_CAPTION_BUTTON; // If parent is a dockable frame, send flags // as approp. CFrameWnd* pFrame=GetParentFrame(); ASSERT(pFrame); if( pFrame->IsKindOf( RUNTIME_CLASS(SECMDIChildWnd))) ((SECMDIChildWnd*)pFrame) ->EnableSysCommandEx(dwScxFlags); else if( pFrame->IsKindOf( RUNTIME_CLASS(SECDockableFrame))) ((SECDockableFrame *)pFrame) ->EnableSysCommandEx(dwScxFlags); // Signal a frame change to refresh // caption button (if necessary) pFrame->SetWindowPos(NULL,0,0,0,0, SWP_NOZORDER|SWP_NOMOVE| SWP_NOSIZE|SWP_FRAMECHANGED); } |
Add a toolbar button or a menu item handler that toggles the state of the caption button for the current view.
void CMyView::OnToggleDockingCaption() { CMyMultiDocTemplate::m_bDockingViewCaptionButton= !CMyMultiDocTemplate::m_bDockingViewCaptionButton; // The SECMultiDocTemplate::OnEnableSysCommandEx // override will insure each new frame created // will have the latest docking style. We // still must explicitly update this // current frame, though, for the changes to // have an immediate effect. UpdateParentFrame(); } |
See the mdi sample in the <stingray-installdir>Samples\Toolkit\MFC\DockingViews\Bounce subdirectory for a demonstration of this technique.
See Section 22.10.3, "To toggle the presence of the docking button on a dockable view frame," and replace SCXOPT_NO_CAPTION_BUTTON with SCXOPT_NO_HANDLE_RDBLCLK.
When you call OpenDocumentFile(), which is typically in the InitInstance() method of your application object, specify the bInitiallyDocked parameter (the third parameter) to be TRUE. It defaults to FALSE if not specified. For example:
// Doc the cloud view initially GetTemplate(CLOUD_DOCNAME) ->OpenDocumentFile(NULL, TRUE, TRUE); |
Insert the following line immediately before the call to ProcessShellCommand() in the application object's InitInstance() method.
cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing; |
Add a CSplitter object as a member variable in your view. You need to make the splitter a member of the view instead of the frame because the frame does not survive the docking process. For more information, see Section 22.7, "Docking Views Containment Model." For example:
CSplitterWnd m_wndSplitter; |
In the OnCreate() method of the view, create the splitter window:
// Create a 1 x 2 splitter BOOL bRC = m_wndSplitter.CreateStatic( this, 1, 2); |
Then, add additional windows or views.
// Embed view 1 in pane 0 m_wndSplitter.CreateView ( 0, 0, RUNTIME_CLASS(CMyView), size, pContext ); // Embed view 2 in pane 1 m_wndSplitter.CreateView ( 0, 1, RUNTIME_CLASS(CMyView2), size, pContext ); |
Add an OnSize() method to resize the splitter as needed.
// // VERY IMPORTANT!!! // You must size the contained window to the current size of // the view otherwise you will see nothing!!! void CMySplitterView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); m_wndSplitter.SetWindowPos(&wndTop,0,0,cx,cy, SWP_SHOWWINDOW); } |
The OnCreate() method of the view has the LPCREATESTRUCT lpCreateStruct parameter. One of the members of this structure contains the pointer to the CCreateContext:
CCreateContext* pContext = (CCreateContext*)lpCreateStruct->lpCreateParams; |
The source code for this section was taken from our SplitView sample application in <stingray-installdir>\Samples\Toolkit\MFC\DockingViews\DockTabs\SpltView.cpp.
Have your CView send a WM_SYSCOMMANDEX message to its current parent frame window. For example, the following code notifies the frame that the view is to be docked to the right.
using namespace nsSysCommandEx; ScxInfo si(GetParentFrame()->m_hWnd); si.m_dw[0]=SCXID_DOCKRIGHT; GetParentFrame()->SendMessage(WM_SYSCOMMANDEX, SCX_NEWFRAME,(LPARAM)si); |
For a list of SCXID parameters, see Section 22.8, "WM_SYSCOMMANDEX."
From your CView, send a WM_SYSCOMMANDEX message to its current parent frame window. For example:
using namespace nsSysCommandEx; ScxInfo si(GetParentFrame()->m_hWnd); si.m_dw[0]=SCXID_MDICHILD; GetParentFrame()->SendMessage(WM_SYSCOMMANDEX, SCX_NEWFRAME,(LPARAM)si); |
For a list of SCXID parameters, see Section 22.8, "WM_SYSCOMMANDEX."
Within the context of your application's main frame object (SECMDIFrameWnd-derived), call the SECMDIFrameWnd::GetActiveFrame() and CFrameWnd::GetActiveView() methods. For example:
// Retrieve a pointer to the currently active view, // regardless of whether it is inside an MDI child, // docked frame, or floating frame. CFrameWnd* pActiveFrame=GetActiveFrame(); if(pActiveFrame) CView* pActiveView= pActiveFrame->GetActiveView(); |
CMDIFrameWnd::MDIGetActive() does not return the appropriate value for a docked view.
Derive a class from SECMultiDockTemplate.
Override SECMultiDocTemplate::ToggleDocking(CFrameWnd* pFrame).
In the override, issue a call to the SECMultiDockTemplate::Dock() method instead of invoking the base class. Because this method is overloaded, you need to call the overload that accepts the SECDockPos() and SECDockSize() parameters. For example:
void CMyMultiDocTemplate::ToggleDocking(CFrameWnd* pFrame) { BOOL bDocked = IsDocked(pFrame); if (bDocked) // No change here Undock(pFrame); else { // IsToCustomDock is some function you // write to determine if special // handling needed... if(IsToCustomDock(pFrame)) { // Establish your custom docking config // dockbar row 3, col 2 SECDockPos pos(3,2); // 50% width, 100 height SECDockSize size(0.50f,100); // or whatever… UINT nDockbarID=AFX_IDW_DOCKBAR_RIGHT; // Call the overload Dock(pFrame,nDockbarID,&pos,&size); } else // old way Dock(pFrame); } } |
Copyright © Rogue Wave Software, Inc. All Rights Reserved.
The Rogue Wave name and logo, and Stingray, are registered trademarks of Rogue Wave Software. All other trademarks are the property of their respective owners.
Provide feedback to Rogue Wave about its documentation.