ReBar.cpp
上传用户:xywutai
上传日期:2007-01-02
资源大小:72k
文件大小:9k
源码类别:

工具条

开发平台:

Visual C++

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