|
|
How to dock bars side by sideby Cristi Posea IntroductionLet's say you have 2 toolbars and you dock them at the top of the mainframe, as in this example: // ... DockControlBar(&m_wndMyBar1, AFX_IDW_DOCKBAR_TOP); DockControlBar(&m_wndMyBar2, AFX_IDW_DOCKBAR_TOP); // ... This code will dock them each on one row (they will be stacked). What if you want them docked side-by-side? Well, the There was an entry in the F.A.Q. page on this topic, and I moved it here: The easy wayKirk Stowell wrote a simple function about this, here are a couple of links to it:
That code was written for toolbars, but any control bar will work the same way. Also, the code does not work when the toolbars are docked vertically (on the left or right sides). Let's refine it a little... First, you can do it even simpler in CMainFrame::OnCreate(): CRect rc; DockControlBar(&m_wndMyBar1, AFX_IDW_DOCKBAR_LEFT); RecalcLayout(TRUE); m_wndMyBar1.GetWindowRect(rc); rc.OffsetRect(0, 1); DockControlBar(&m_wndMyBar2, AFX_IDW_DOCKBAR_LEFT, rc); If you want to dock 3 bars on the left, you should add also: RecalcLayout(TRUE); m_wndMyBar2.GetWindowRect(rc); rc.OffsetRect(0, 1); DockControlBar(&m_wndMyBar3, AFX_IDW_DOCKBAR_LEFT, rc); and so on. Now, a short explanation:
The line So, the code below has the same effect, but we will dock the second bar first, then the first one above it: CRect rc; DockControlBar(&m_wndMyBar2, AFX_IDW_DOCKBAR_LEFT); RecalcLayout(TRUE); m_wndMyBar2.GetWindowRect(rc); DockControlBar(&m_wndMyBar1, AFX_IDW_DOCKBAR_LEFT, &rc); All examples until now assumed one thing, althought you didn't noticed it: the bars must be visible. If they are not, the DockControlBarNextTo()The following function works in more cases, and it is easier to use. However, it makes use of undocumented MFC code, so be warned that there is no guarantee it will work with future versions of MFC or Visual C++.
void CMainFrame::DockControlBarNextTo(CControlBar* pBar, CControlBar* pTargetBar) { ASSERT(pBar != NULL); ASSERT(pTargetBar != NULL); ASSERT(pBar != pTargetBar); // the neighbour must be already docked CDockBar* pDockBar = pTargetBar->m_pDockBar; ASSERT(pDockBar != NULL); UINT nDockBarID = pTargetBar->m_pDockBar->GetDlgCtrlID(); ASSERT(nDockBarID != AFX_IDW_DOCKBAR_FLOAT); bool bHorz = (nDockBarID == AFX_IDW_DOCKBAR_TOP || nDockBarID == AFX_IDW_DOCKBAR_BOTTOM); // dock normally (inserts a new row) DockControlBar(pBar, nDockBarID); // delete the new row (the bar pointer and the row end mark) pDockBar->m_arrBars.RemoveAt(pDockBar->m_arrBars.GetSize() - 1); pDockBar->m_arrBars.RemoveAt(pDockBar->m_arrBars.GetSize() - 1); // find the target bar for (int i = 0; i < pDockBar->m_arrBars.GetSize(); i++) { void* p = pDockBar->m_arrBars[i]; if (p == pTargetBar) // and insert the new bar after it pDockBar->m_arrBars.InsertAt(i + 1, pBar); } // move the new bar into position CRect rBar; pTargetBar->GetWindowRect(rBar); rBar.OffsetRect(bHorz ? 1 : 0, bHorz ? 0 : 1); pBar->MoveWindow(rBar); } The function works for bars docked on any side of the frame, and any of these bars can be created invisible. This is especially useful when you have to many bars. Here is an example: DockControlBar(&m_wndMyBar1, AFX_IDW_DOCKBAR_TOP); DockControlBarNextTo(&m_wndMyBar1, &m_wndMyBar2); DockControlBarNextTo(&m_wndMyBar2, &m_wndMyBar3); DockControlBar(&m_wndMyBar4, AFX_IDW_DOCKBAR_TOP); // new row DockControlBarNextTo(&m_wndMyBar4, &m_wndMyBar5); Enjoy ! Copyright © 1998-2019 DataMekanix. All rights reserved.
|