Reputation: 55
At first I called the Create method of the CFrameWnd within another class.
Then I continued with the Create method of CDockablePane with the FrameWnd as the pParentWnd parameter.
The second Create was not successful, an assertion occured in the following code:
void CMFCDragFrameImpl::Init(CWnd* pDraggedWnd)
{
ASSERT_VALID(pDraggedWnd);
m_pDraggedWnd = pDraggedWnd;
CWnd* pDockSite = NULL;
if (m_pDraggedWnd->IsKindOf(RUNTIME_CLASS(CPaneFrameWnd)))
{
CPaneFrameWnd* pMiniFrame = DYNAMIC_DOWNCAST(CPaneFrameWnd, m_pDraggedWnd);
pDockSite = pMiniFrame->GetParent();
}
else if (m_pDraggedWnd->IsKindOf(RUNTIME_CLASS(CPane)))
{
CPane* pBar = DYNAMIC_DOWNCAST(CPane, m_pDraggedWnd);
ASSERT_VALID(pBar);
CPaneFrameWnd* pParentMiniFrame = pBar->GetParentMiniFrame();
if (pParentMiniFrame != NULL)
{
pDockSite = pParentMiniFrame->GetParent();
}
else
{
pDockSite = pBar->GetDockSiteFrameWnd();
}
}
m_pDockManager = afxGlobalUtils.GetDockingManager(pDockSite);
if (afxGlobalUtils.m_bDialogApp)
{
return;
}
ENSURE(m_pDockManager != NULL); <-----------------------
}
Somehow a docking manager seems to be missing. Is it possible that CFrameWnd is not suitable for CDockablePane? Or the docking manager needs to be initialized?
Thanks for your help (code snippets are welcome)!
Upvotes: 0
Views: 712
Reputation: 954
To add a dockable pane to your project, the first step is to derive a new class from CDockablePane and you must add two message handlers for OnCreate and OnSize, and add a member child window as the main content. Your simple CTreePane class should look like this:
class CTreePane : public CDockablePane
{
DECLARE_MESSAGE_MAP()
DECLARE_DYNAMIC(CTreePane)
protected:
afx_msg int OnCreate(LPCREATESTRUCT lp);
afx_msg void OnSize(UINT nType,int cx,int cy);
private:
CTreeCtrl m_wndTree ;
};
int CTreePane::OnCreate(LPCREATESTRUCT lp)
{
if(CDockablePane::OnCreate(lp)==-1)
return -1;
DWORD style = TVS_HASLINES|TVS_HASBUTTONS|TVS_LINESATROOT|
WS_CHILD|WS_VISIBLE|TVS_SHOWSELALWAYS | TVS_FULLROWSELECT;
CRect dump(0,0,0,0) ;
if(!m_wndTree.Create(style,dump,this,IDC_TREECTRL))
return -1;
return 0;
}
In the OnSize handler, you should size your control to fill the entire dockable pane client area.
void CTreePane::OnSize(UINT nType,int cx,int cy)
{
CDockablePane::OnSize(nType,cx,cy);
m_wndTree.SetWindowPos(NULL,0,0,cx,cy, SWP_NOACTIVATE|SWP_NOZORDER);
}
To support a dockable pane in your frame, you must first derive from the Ex family of frames (CFrameWndEx, CMDIFrameWndEx, ..) and in the OnCreate handler, you should initialize the docking manager by setting the allowable docking area, general properties, smart docking mode, …etc.
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
...
CDockingManager::SetDockingMode(DT_SMART);
EnableAutoHidePanes(CBRS_ALIGN_ANY);
...
}void CMainFrame::OnTreePane()
{
if(m_treePane && m_treePane->GetSafeHwnd())
{
m_treePane->ShowPane(TRUE,FALSE,TRUE);
return ;
}
m_treePane = new CTreePane;
UINT style = WS_CHILD | CBRS_RIGHT |CBRS_FLOAT_MULTI;
CString strTitle = _T("Tree Pane");
if (!m_treePane->Create(strTitle, this,
CRect(0, 0, 200, 400),TRUE,IDC_TREE_PANE, style))
{
delete m_treePane;
m_treePane = NULL ;
return ;
}
m_treePane->EnableDocking(CBRS_ALIGN_ANY);
DockPane((CBasePane*)m_treePane,AFX_IDW_DOCKBAR_LEFT);
m_treePane->ShowPane(TRUE,FALSE,TRUE);
RecalcLayout();
}
Upvotes: 2