_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



