void CMainFrame::FloatAutoHideToolBar(CToolBar* pBar, CPoint point, DWORD dwStyle) { ASSERT(pBar != NULL); // if the bar is already floating and the dock bar only contains this // bar and same orientation then move the window rather than recreating // the frame CRect rect; GetClientRect(rect); if (pBar->m_pDockSite != NULL && pBar->m_pDockBar != NULL) { CDockBar* pDockBar = (CDockBar* )pBar->m_pDockBar; if (pDockBar->m_bFloating && pDockBar->GetDockedCount() == 1 && (dwStyle & pDockBar->m_dwStyle & CBRS_ALIGN_ANY) != 0) { CMiniDockFrameWnd* pDockFrame = (CMiniDockFrameWnd*)pDockBar->GetParent(); pDockFrame->ModifyStyle(WS_CAPTION | WS_BORDER | WS_SYSMENU, 0); pDockBar->ModifyStyle(WS_CAPTION | WS_BORDER | WS_SYSMENU, 0); ASSERT(pDockFrame != NULL);
pDockFrame->SetWindowPos(NULL, point.x, point.y, rect.Width(), rect.Height(), SWP_NOZORDER|SWP_NOACTIVATE); pDockFrame->ShowWindow(SW_SHOWNA); pDockFrame->RecalcLayout(TRUE); pDockFrame->UpdateWindow(); return; } } if (pBar->m_dwStyle & CBRS_SIZE_DYNAMIC) { dwStyle |= CBRS_SIZE_DYNAMIC; if (dwStyle & CBRS_ORIENT_VERT) { dwStyle &= ~CBRS_ALIGN_ANY; dwStyle |= CBRS_ALIGN_TOP; } } CMiniDockFrameWnd* pDockFrame = (CMiniDockFrameWnd* )CreateFloatingFrame(dwStyle); ASSERT(pDockFrame != NULL); if (pDockFrame->m_hWndOwner == NULL) pDockFrame->m_hWndOwner = pBar->m_hWnd; pDockFrame->ModifyStyle(WS_CAPTION | WS_BORDER | WS_SYSMENU, 0); CDockBar* pDockBar = (CDockBar*)pDockFrame->GetDlgItem(AFX_IDW_DOCKBAR_FLOAT); ASSERT(pDockBar != NULL); ASSERT(pBar->m_pDockSite == this); // if this assertion occurred it is because the parent of pBar was not // initially this CFrameWnd when pBar's OnCreate was called // (this control bar should have been created with a different // parent initially)
// make sure the dock bar is of correct type if(pDockBar!=NULL && !pDockBar->IsKindOf(RUNTIME_CLASS(CResizableDockBar))) { BOOL bNeedDelete = !pDockBar->m_bAutoDelete; pDockBar->m_pDockSite->RemoveControlBar(pDockBar); pDockBar->m_pDockSite = 0; // avoid problems in destroying the dockbar pDockBar->DestroyWindow(); if(bNeedDelete) { delete pDockBar; } pDockBar = NULL; }
if(pDockBar == NULL) { pDockBar = new CResizableDockBar; if(!pDockBar->Create(this,WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_CHILD|WS_VISIBLE|dwDockBarMap[i][1], dwDockBarMap[i][0])) { AfxThrowResourceException(); } } } } }同时我还修改了CMiniDockFrameWnd派生类的Create函数,让它可以resize大小: BOOL CResizableMiniDockFrameWnd::Create(CWnd* pParent, DWORD dwBarStyle) { // set m_bInRecalcLayout to avoid flashing during creation // RecalcLayout will be called once something is docked m_bInRecalcLayout = TRUE;
http://blog.csdn.net/goodboyws/archive/2005/09/28/491507.aspx
{
ASSERT(pBar != NULL); // if the bar is already floating and the dock bar only contains this
// bar and same orientation then move the window rather than recreating
// the frame
CRect rect;
GetClientRect(rect);
if (pBar->m_pDockSite != NULL && pBar->m_pDockBar != NULL)
{
CDockBar* pDockBar = (CDockBar* )pBar->m_pDockBar;
if (pDockBar->m_bFloating && pDockBar->GetDockedCount() == 1 &&
(dwStyle & pDockBar->m_dwStyle & CBRS_ALIGN_ANY) != 0)
{
CMiniDockFrameWnd* pDockFrame = (CMiniDockFrameWnd*)pDockBar->GetParent(); pDockFrame->ModifyStyle(WS_CAPTION | WS_BORDER | WS_SYSMENU, 0);
pDockBar->ModifyStyle(WS_CAPTION | WS_BORDER | WS_SYSMENU, 0);
ASSERT(pDockFrame != NULL);
pDockFrame->SetWindowPos(NULL, point.x, point.y, rect.Width(), rect.Height(),
SWP_NOZORDER|SWP_NOACTIVATE);
pDockFrame->ShowWindow(SW_SHOWNA);
pDockFrame->RecalcLayout(TRUE);
pDockFrame->UpdateWindow();
return;
}
} if (pBar->m_dwStyle & CBRS_SIZE_DYNAMIC)
{
dwStyle |= CBRS_SIZE_DYNAMIC;
if (dwStyle & CBRS_ORIENT_VERT)
{
dwStyle &= ~CBRS_ALIGN_ANY;
dwStyle |= CBRS_ALIGN_TOP;
}
} CMiniDockFrameWnd* pDockFrame = (CMiniDockFrameWnd* )CreateFloatingFrame(dwStyle); ASSERT(pDockFrame != NULL); if (pDockFrame->m_hWndOwner == NULL)
pDockFrame->m_hWndOwner = pBar->m_hWnd;
pDockFrame->ModifyStyle(WS_CAPTION | WS_BORDER | WS_SYSMENU, 0);
CDockBar* pDockBar = (CDockBar*)pDockFrame->GetDlgItem(AFX_IDW_DOCKBAR_FLOAT);
ASSERT(pDockBar != NULL); ASSERT(pBar->m_pDockSite == this);
// if this assertion occurred it is because the parent of pBar was not
// initially this CFrameWnd when pBar's OnCreate was called
// (this control bar should have been created with a different
// parent initially)
pDockBar->DockControlBar(pBar, rect);
pDockFrame->SetWindowPos(NULL, point.x, point.y, rect.Width(), rect.Height(),
SWP_NOZORDER|SWP_NOACTIVATE);
pDockFrame->RecalcLayout(TRUE);
if (GetWindowLong(pBar->m_hWnd, GWL_STYLE) & WS_VISIBLE)
{
pDockFrame->ShowWindow(SW_SHOWNA);
pDockFrame->UpdateWindow();
}
}
void CMDIFrameWndEx::EnableDocking(DWORD dwDockStyle)
{
ASSERT((dwDockStyle & ~(CBRS_ALIGN_ANY|CBRS_FLOAT_MULTI)) == 0);
//MainFrame内部使用MFC的CDockBar.因为仅在Floating状态下,我们派生的
//CResizableDockBar的Resizable特性才有必要使用.
CMDIFrameWnd::EnableDocking(dwDockStyle); //替换Mini-Frame和Dock Bar
m_pFloatingFrameClass = RUNTIME_CLASS(CResizableMiniDockFrameWnd); for(int i=0; i<4; i++)
{
if(dwDockBarMap[i][1] & dwDockStyle & CBRS_ALIGN_ANY)
{
CDockBar* pDockBar = (CDockBar*)GetControlBar(dwDockBarMap[i][0]);
// make sure the dock bar is of correct type
if(pDockBar!=NULL && !pDockBar->IsKindOf(RUNTIME_CLASS(CResizableDockBar)))
{
BOOL bNeedDelete = !pDockBar->m_bAutoDelete;
pDockBar->m_pDockSite->RemoveControlBar(pDockBar);
pDockBar->m_pDockSite = 0; // avoid problems in destroying the dockbar
pDockBar->DestroyWindow();
if(bNeedDelete)
{
delete pDockBar;
}
pDockBar = NULL;
}
if(pDockBar == NULL)
{
pDockBar = new CResizableDockBar;
if(!pDockBar->Create(this,WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_CHILD|WS_VISIBLE|dwDockBarMap[i][1], dwDockBarMap[i][0]))
{
AfxThrowResourceException();
}
}
}
}
}同时我还修改了CMiniDockFrameWnd派生类的Create函数,让它可以resize大小:
BOOL CResizableMiniDockFrameWnd::Create(CWnd* pParent, DWORD dwBarStyle)
{
// set m_bInRecalcLayout to avoid flashing during creation
// RecalcLayout will be called once something is docked
m_bInRecalcLayout = TRUE;
DWORD dwStyle = WS_POPUP|WS_CAPTION|MFS_MOVEFRAME|MFS_THICKFRAME|
MFS_SYNCACTIVE|MFS_BLOCKSYSMENU|FWS_SNAPTOBARS;
if(dwBarStyle & CBRS_SIZE_DYNAMIC)
{
dwStyle &= ~MFS_MOVEFRAME;
}
DWORD dwExStyle = 0;
if(!CMiniFrameWnd::CreateEx(dwExStyle, NULL, &afxChNil, dwStyle, rectDefault, pParent))
{
m_bInRecalcLayout = FALSE;
return FALSE;
}
dwStyle = dwBarStyle&(CBRS_ALIGN_LEFT|CBRS_ALIGN_RIGHT) ? CBRS_ALIGN_LEFT:CBRS_ALIGN_TOP;
dwStyle |= dwBarStyle & CBRS_FLOAT_MULTI; if(!m_wndDockBar.Create(pParent, WS_CHILD|WS_VISIBLE|dwStyle, AFX_IDW_DOCKBAR_FLOAT))
{
m_bInRecalcLayout = FALSE;
return FALSE;
}
// set parent to CMiniDockFrameWnd
m_wndDockBar.SetParent(this);
m_bInRecalcLayout = FALSE;
m_Tooltip.Create(this); return TRUE;
}
CSize CSubToolBar::CalcDynamicLayout(int nLength, DWORD dwMode)
{
CFrameWnd* pFrame = GetParentFrame();
pFrame->ModifyStyle(WS_CAPTION, 0); //remove title bar
return CToolBar::CalcDynamicLayout(nLength, dwMode);
}这个方法可行,我在项目中就这么用的