_Converting MFC Toolbars into Windows 95 Taskbars_ by Mark Janczura Listing One CFloatingFrame* CMainFrame::CreateFloatingFrame(DWORD dwStyle) { CFloatingFrame* pFrame = NULL; ASSERT(m_pFloatingFrameClass != NULL); pFrame = (CFloatingFrame*)m_pFloatingFrameClass->CreateObject(); if (pFrame == NULL) AfxThrowMemoryException(); ASSERT_KINDOF(CFloatingFrame, pFrame); if (!pFrame->Create(this, dwStyle)) AfxThrowResourceException(); return pFrame; } Listing Two void CMyDockContext::EndDrag() { CancelLoop(); if (m_dwOverDockStyle != 0) { CDockBar* pDockBar = GetDockBar(m_dwOverDockStyle); ASSERT(pDockBar != NULL); CRect rect = (m_dwOverDockStyle & CBRS_ORIENT_VERT) ? m_rectDragVert : m_rectDragHorz; UINT uID = _AfxGetDlgCtrlID(pDockBar->m_hWnd); if (uID >= AFX_IDW_DOCKBAR_TOP && uID <= AFX_IDW_DOCKBAR_BOTTOM) { m_uMRUDockID = uID; m_rectMRUDockPos = rect; pDockBar->ScreenToClient(&m_rectMRUDockPos); } // dock it at the specified position, RecalcLayout will snap ((CMainFrame*)m_pDockSite)->DockControlBar(m_pBar, pDockBar, &rect); ((CMainFrame*)m_pDockSite)->RecalcLayout(); } else if ((m_dwStyle & CBRS_SIZE_DYNAMIC)||(HORZF(m_dwStyle) && !m_bFlip) || (VERTF(m_dwStyle) && m_bFlip)) { m_dwMRUFloatStyle = CBRS_ALIGN_TOP | (m_dwDockStyle & CBRS_FLOAT_MULTI); m_ptMRUFloatPos = m_rectFrameDragHorz.TopLeft(); ((CMainFrame*)m_pDockSite)->FloatControlBar(m_pBar, m_ptMRUFloatPos, m_dwMRUFloatStyle); } else // vertical float { m_dwMRUFloatStyle = CBRS_ALIGN_LEFT|(m_dwDockStyle & CBRS_FLOAT_MULTI); m_ptMRUFloatPos = m_rectFrameDragVert.TopLeft(); ((CMainFrame*)m_pDockSite)->FloatControlBar(m_pBar, m_ptMRUFloatPos, m_dwMRUFloatStyle); } } Listing Three void CMyDockContext::GetDimsFromPoint (CRect& rect, CPoint pt) { UINT uState = ABE_FLOAT; // Assume that the AppBar is floating // Let's get floating out of the way first // Get the rectangle that bounds the size of the screen // minus any docked (but not-autohidden) AppBars. CRect rc, rcSav; ::SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0); rcSav = rc; // Leave a + width/height-of-a-scrollbar gutter around the workarea rc.InflateRect(-GetSystemMetrics(SM_CXVSCROLL), -GetSystemMetrics(SM_CYHSCROLL)); if (rc.PtInRect(pt)) { // If the point is in the adjusted workarea return; } // If we get here, the AppBar should be docked; determine the proper edge // Get the dimensions of the screen int cxScreen = GetSystemMetrics(SM_CXSCREEN); int cyScreen = GetSystemMetrics(SM_CYSCREEN); // Find the center of the screen CPoint ptCenter(cxScreen / 2, cyScreen / 2); // Find the distance from the point to the center CPoint ptOffset = pt - ptCenter; // Determine if the point is farther from the left/right or top/bottom BOOL fIsLeftOrRight = (AbsoluteValue(ptOffset.y) * cxScreen) <= (AbsoluteValue(ptOffset.x) * cyScreen); // If (it should be left/right) if (fIsLeftOrRight){ rect.top = rcSav.top; rect.bottom = rcSav.bottom; int width = rect.Width(); if (0 <= ptOffset.x) { int width = rect.Width(); rect.right = rcSav.right; rect.left = rect.right - width; } else { rect.left = rcSav.left; rect.right = rect.left + width; } } else if( !fIsLeftOrRight ) { rect.left = rcSav.left; rect.right = rcSav.right; int height = rect.Height(); if (0 <= ptOffset.y) { rect.bottom = rcSav.bottom; rect.top = rect.bottom - height; } else { rect.top = rcSav.top; rect.bottom = rect.top + height; } } } Listing Four void CMyToolBar::EnableDocking(DWORD dwDockStyle) { // must be CBRS_ALIGN_XXX or CBRS_FLOAT_MULTI only ASSERT((dwDockStyle & ~(CBRS_ALIGN_ANY|CBRS_FLOAT_MULTI)) == 0); // CBRS_SIZE_DYNAMIC toolbar cannot have the CBRS_FLOAT_MULTI style ASSERT(((dwDockStyle & CBRS_FLOAT_MULTI) == 0) || ((m_dwStyle & CBRS_SIZE_DYNAMIC) == 0)); m_dwDockStyle = dwDockStyle; if (m_pDockContext == NULL) // instantiate my own dock context m_pDockContext = (CDockContext*) new CMyDockContext(this); // permanently wire the bar's owner to its current parent m_hWndOwner = ::GetParent(m_hWnd); } 3