home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / barcool.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  9KB  |  331 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFX_CORE3_SEG
  14. #pragma code_seg(AFX_CORE3_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #define new DEBUG_NEW
  23.  
  24. /////////////////////////////////////////////////////////////////////////////
  25. // CReBar
  26.  
  27. BEGIN_MESSAGE_MAP(CReBar, CControlBar)
  28.     //{{AFX_MSG_MAP(CReBar)
  29.     ON_WM_NCCREATE()
  30.     ON_WM_PAINT()
  31.     ON_WM_NCCALCSIZE()
  32.     ON_WM_ERASEBKGND()
  33.     ON_WM_NCPAINT()
  34.     ON_NOTIFY_REFLECT(RBN_HEIGHTCHANGE, OnHeightChange)
  35.     ON_NOTIFY_REFLECT(RBN_ENDDRAG, OnHeightChange)
  36.     ON_MESSAGE(RB_SHOWBAND, OnShowBand)
  37.     ON_MESSAGE_VOID(WM_RECALCPARENT, OnRecalcParent)
  38.     //}}AFX_MSG_MAP
  39. END_MESSAGE_MAP()
  40.  
  41. CReBar::CReBar()
  42. {
  43.     SetBorders();
  44. }
  45.  
  46. void CReBar::OnRecalcParent()
  47. {
  48.     CFrameWnd* pFrameWnd = GetParentFrame();
  49.     ASSERT(pFrameWnd != NULL);
  50.     pFrameWnd->RecalcLayout();
  51. }
  52.  
  53. void CReBar::OnHeightChange(NMHDR* /*pNMHDR*/, LRESULT* pResult)
  54. {
  55.     // does the CReBar have a frame?
  56.     CFrameWnd* pFrameWnd = GetParentFrame();
  57.     if (pFrameWnd != NULL)
  58.     {
  59.         // it does -- tell it to recalc its layout
  60.         if (!pFrameWnd->m_bInRecalcLayout)
  61.             pFrameWnd->RecalcLayout();
  62.         else
  63.             PostMessage(WM_RECALCPARENT);
  64.     }
  65.     *pResult = 0;
  66. }
  67.  
  68. LRESULT CReBar::OnShowBand(WPARAM wParam, LPARAM)
  69. {
  70.     LRESULT lResult = Default();
  71.     if (lResult)
  72.     {
  73.         // keep window visible state in sync with band visible state
  74.         REBARBANDINFO rbBand;
  75.         rbBand.cbSize = sizeof(rbBand);
  76.         rbBand.fMask = RBBIM_CHILD|RBBIM_STYLE;
  77.         VERIFY(DefWindowProc(RB_GETBANDINFO, wParam, (LPARAM)&rbBand));
  78.         CControlBar* pBar = DYNAMIC_DOWNCAST(CControlBar, CWnd::FromHandlePermanent(rbBand.hwndChild));
  79.         BOOL bWindowVisible;
  80.         if (pBar != NULL)
  81.             bWindowVisible = pBar->IsVisible();
  82.         else
  83.             bWindowVisible =  (::GetWindowLong(rbBand.hwndChild, GWL_STYLE) & WS_VISIBLE) != 0;
  84.         BOOL bBandVisible = (rbBand.fStyle & RBBS_HIDDEN) == 0;
  85.         if (bWindowVisible != bBandVisible)
  86.             VERIFY(::ShowWindow(rbBand.hwndChild, bBandVisible ? SW_SHOW : SW_HIDE));
  87.     }
  88.     return lResult;
  89. }
  90.  
  91. BOOL CReBar::_AddBar(CWnd* pBar, REBARBANDINFO* pRBBI)
  92. {
  93.     ASSERT_VALID(this);
  94.     ASSERT(::IsWindow(m_hWnd));
  95.     ASSERT(pBar != NULL);
  96.     ASSERT(::IsWindow(pBar->m_hWnd));
  97.  
  98.     pRBBI->cbSize = sizeof(REBARBANDINFO);
  99.     pRBBI->fMask |= RBBIM_CHILD | RBBIM_CHILDSIZE;
  100.     pRBBI->hwndChild = pBar->m_hWnd;
  101.  
  102.     CSize size;
  103.     CControlBar* pTemp = DYNAMIC_DOWNCAST(CControlBar, pBar);
  104.     if (pTemp != NULL)
  105.     {
  106.         size = pTemp->CalcFixedLayout(FALSE, m_dwStyle & CBRS_ORIENT_HORZ);
  107.     }
  108.     else
  109.     {
  110.         CRect rect;
  111.         pBar->GetWindowRect(&rect);
  112.         size = rect.Size();
  113.     }
  114.     //WINBUG: COMCTL32.DLL is off by 4 pixels in its sizing logic.  Whatever
  115.     //  is specified as the minimum size, the system rebar will allow that band
  116.     //  to be 4 actual pixels smaller!  That's why we add 4 to the size here.
  117.     ASSERT(_afxComCtlVersion != -1);
  118.     pRBBI->cxMinChild = size.cx + (_afxComCtlVersion < VERSION_IE401 ? 4 : 0);
  119.     pRBBI->cyMinChild = size.cy;
  120.     BOOL bResult = (BOOL)DefWindowProc(RB_INSERTBAND, (WPARAM)-1, (LPARAM)pRBBI);
  121.  
  122.     CFrameWnd* pFrameWnd = GetParentFrame();
  123.     if (pFrameWnd != NULL)
  124.         pFrameWnd->RecalcLayout();
  125.  
  126.     return bResult;
  127. }
  128.  
  129. BOOL CReBar::AddBar(CWnd* pBar, LPCTSTR pszText, CBitmap* pbmp, DWORD dwStyle)
  130. {
  131.     REBARBANDINFO rbBand;
  132.     rbBand.fMask = RBBIM_STYLE;
  133.     rbBand.fStyle = dwStyle;
  134.     if (pszText != NULL)
  135.     {
  136.         rbBand.fMask |= RBBIM_TEXT;
  137.         rbBand.lpText = const_cast<LPTSTR>(pszText);
  138.     }
  139.     if (pbmp != NULL)
  140.     {
  141.         rbBand.fMask |= RBBIM_BACKGROUND;
  142.         rbBand.hbmBack = (HBITMAP)*pbmp;
  143.     }
  144.     return _AddBar(pBar, &rbBand);
  145. }
  146.  
  147. BOOL CReBar::AddBar(CWnd* pBar, COLORREF clrFore, COLORREF clrBack, LPCTSTR pszText, DWORD dwStyle)
  148. {
  149.     REBARBANDINFO rbBand;
  150.     rbBand.fMask = RBBIM_STYLE | RBBIM_COLORS;
  151.     rbBand.fStyle = dwStyle;
  152.     rbBand.clrFore = clrFore;
  153.     rbBand.clrBack = clrBack;
  154.     if (pszText != NULL)
  155.     {
  156.         rbBand.fMask |= RBBIM_TEXT;
  157.         rbBand.lpText = const_cast<LPTSTR>(pszText);
  158.     }
  159.     return _AddBar(pBar, &rbBand);
  160. }
  161.  
  162. CSize CReBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
  163. {
  164.     ASSERT_VALID(this);
  165.     ASSERT(::IsWindow(m_hWnd));
  166.  
  167.     // the union of the band rectangles is the total bounding rect
  168.     int nCount = DefWindowProc(RB_GETBANDCOUNT, 0, 0);
  169.     REBARBANDINFO rbBand;
  170.     rbBand.cbSize = sizeof(rbBand);
  171.     int nTemp;
  172.  
  173.     // sync up hidden state of the bands
  174.     for (nTemp = nCount; nTemp--; )
  175.     {
  176.         rbBand.fMask = RBBIM_CHILD|RBBIM_STYLE;
  177.         VERIFY(DefWindowProc(RB_GETBANDINFO, nTemp, (LPARAM)&rbBand));
  178.         CControlBar* pBar = DYNAMIC_DOWNCAST(CControlBar, CWnd::FromHandlePermanent(rbBand.hwndChild));
  179.         BOOL bWindowVisible;
  180.         if (pBar != NULL)
  181.             bWindowVisible = pBar->IsVisible();
  182.         else
  183.             bWindowVisible =  (::GetWindowLong(rbBand.hwndChild, GWL_STYLE) & WS_VISIBLE) != 0;
  184.         BOOL bBandVisible = (rbBand.fStyle & RBBS_HIDDEN) == 0;
  185.         if (bWindowVisible != bBandVisible)
  186.             VERIFY(DefWindowProc(RB_SHOWBAND, nTemp, bWindowVisible));
  187.     }
  188.  
  189.     // determine bounding rect of all visible bands
  190.     CRect rectBound; rectBound.SetRectEmpty();
  191.     for (nTemp = nCount; nTemp--; )
  192.     {
  193.         rbBand.fMask = RBBIM_STYLE;
  194.         VERIFY(DefWindowProc(RB_GETBANDINFO, nTemp, (LPARAM)&rbBand));
  195.         if ((rbBand.fStyle & RBBS_HIDDEN) == 0)
  196.         {
  197.             CRect rect;
  198.             VERIFY(DefWindowProc(RB_GETRECT, nTemp, (LPARAM)&rect));
  199.             rectBound |= rect;
  200.         }
  201.     }
  202.  
  203.     // add borders as part of bounding rect
  204.     if (!rectBound.IsRectEmpty())
  205.     {
  206.         CRect rect; rect.SetRectEmpty();
  207.         CalcInsideRect(rect, bHorz);
  208.         rectBound.right -= rect.Width();
  209.         rectBound.bottom -= rect.Height();
  210.     }
  211.  
  212.     return CSize((bHorz && bStretch) ? 32767 : rectBound.Width(),
  213.                  (!bHorz && bStretch) ? 32767 : rectBound.Height());
  214. }
  215.  
  216. CSize CReBar::CalcDynamicLayout(int /*nLength*/, DWORD dwMode)
  217. {
  218.     if (dwMode & LM_HORZDOCK)
  219.         ASSERT(dwMode & LM_HORZ);
  220.     return CalcFixedLayout(dwMode & LM_STRETCH, dwMode & LM_HORZ);
  221. }
  222.  
  223. BOOL CReBar::Create(CWnd* pParentWnd, DWORD dwCtrlStyle, DWORD dwStyle, UINT nID)
  224. {
  225.     ASSERT_VALID(pParentWnd);   // must have a parent
  226.     ASSERT (!((dwStyle & CBRS_SIZE_FIXED) && (dwStyle & CBRS_SIZE_DYNAMIC)));
  227.  
  228.     // save the style
  229.     m_dwStyle = (dwStyle & CBRS_ALL);
  230.     if (nID == AFX_IDW_REBAR)
  231.         m_dwStyle |= CBRS_HIDE_INPLACE;
  232.  
  233.     dwStyle &= ~CBRS_ALL;
  234.     dwStyle |= CCS_NOPARENTALIGN|CCS_NOMOVEY|CCS_NODIVIDER|CCS_NORESIZE|RBS_VARHEIGHT;
  235.     dwStyle |= dwCtrlStyle;
  236.  
  237.     // initialize common controls
  238.     VERIFY(AfxDeferRegisterClass(AFX_WNDCOMMCTL_COOL_REG));
  239.     _AfxGetComCtlVersion();
  240.     ASSERT(_afxComCtlVersion != -1);
  241.  
  242.     // create the HWND
  243.     CRect rect; rect.SetRectEmpty();
  244.     if (!CWnd::Create(REBARCLASSNAME, NULL, dwStyle, rect, pParentWnd, nID))
  245.         return FALSE;
  246.  
  247.     // Note: Parent must resize itself for control bar to be resized
  248.  
  249.     return TRUE;
  250. }
  251.  
  252. void CReBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHandler)
  253. {
  254.     UpdateDialogControls(pTarget, bDisableIfNoHandler);
  255. }
  256.  
  257. BOOL CReBar::OnNcCreate(LPCREATESTRUCT lpCreateStruct)
  258. {
  259.     if (!CControlBar::OnNcCreate(lpCreateStruct))
  260.         return FALSE;
  261.  
  262.     // if the owner was set before the rebar was created, set it now
  263.     if (m_hWndOwner != NULL)
  264.         DefWindowProc(RB_SETPARENT, (WPARAM)m_hWndOwner, 0);
  265.  
  266.     return TRUE;
  267. }
  268.  
  269. BOOL CReBar::OnEraseBkgnd(CDC*)
  270. {
  271.     return (BOOL)Default();
  272. }
  273.  
  274. void CReBar::OnNcCalcSize(BOOL /*bCalcValidRects*/, NCCALCSIZE_PARAMS* lpncsp)
  275. {
  276.     // calculate border space (will add to top/bottom, subtract from right/bottom)
  277.     CRect rect; rect.SetRectEmpty();
  278.     BOOL bHorz = (m_dwStyle & CBRS_ORIENT_HORZ) != 0;
  279.     CControlBar::CalcInsideRect(rect, bHorz);
  280.  
  281.     // adjust non-client area for border space
  282.     lpncsp->rgrc[0].left += rect.left;
  283.     lpncsp->rgrc[0].top += rect.top;
  284.     lpncsp->rgrc[0].right += rect.right;
  285.     lpncsp->rgrc[0].bottom += rect.bottom;
  286. }
  287.  
  288. void CReBar::OnNcPaint()
  289. {
  290.     EraseNonClient();
  291. }
  292.  
  293. void CReBar::OnPaint()
  294. {
  295.     Default();
  296. }
  297.  
  298. int CReBar::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
  299. {
  300.     ASSERT_VALID(this);
  301.     ASSERT(::IsWindow(m_hWnd));
  302.  
  303.     HWND hWndChild = _AfxChildWindowFromPoint(m_hWnd, point);
  304.     CWnd* pWnd = CWnd::FromHandlePermanent(hWndChild);
  305.     if (pWnd == NULL)
  306.         return CControlBar::OnToolHitTest(point, pTI);
  307.  
  308.     ASSERT(pWnd->m_hWnd == hWndChild);
  309.     return pWnd->OnToolHitTest(point, pTI);
  310. }
  311.  
  312. LRESULT CReBar::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
  313. {
  314.     // special handling for certain messages (forwarding to owner/parent)
  315.     switch (message)
  316.     {
  317.     case WM_POPMESSAGESTRING:
  318.     case WM_SETMESSAGESTRING:
  319.         return GetOwner()->SendMessage(message, wParam, lParam);
  320.     }
  321.     return CControlBar::WindowProc(message, wParam, lParam);
  322. }
  323.  
  324. #ifdef AFX_INIT_SEG
  325. #pragma code_seg(AFX_INIT_SEG)
  326. #endif
  327.  
  328. IMPLEMENT_DYNAMIC(CReBar, CControlBar)
  329.  
  330. /////////////////////////////////////////////////////////////////////////////
  331.