NGenericToolBar.cpp
上传用户:whjcdz88
上传日期:2007-01-02
资源大小:350k
文件大小:28k
源码类别:

工具条

开发平台:

Visual C++

  1. // NGenericToolBar.cpp: implementation of the CNGenericToolBar class.
  2. //
  3. /*
  4. Copyright (C) 1998 Tony Hoyle (tmh@netfusion.co.uk)
  5. This program is free software; you can redistribute it and/or modify it under the terms
  6. of the GNU General Public License as published by the Free Software Foundation; either
  7. version 2 of the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  9. without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License along with this program;
  12. if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  13. */
  14. //////////////////////////////////////////////////////////////////////
  15. #include "stdafx.h"
  16. #include "NGenericToolBar.h"
  17. #include "NGenericMenu.h"
  18. #include "afxpriv.h"
  19. #ifdef _DEBUG
  20. #undef THIS_FILE
  21. static char THIS_FILE[]=__FILE__;
  22. #define new DEBUG_NEW
  23. #endif
  24. IMPLEMENT_DYNAMIC(CNGenericToolBar,CToolBar)
  25. BEGIN_MESSAGE_MAP(CNGenericToolBar,CToolBar)
  26. //{{AFX_MSG_MAP(CNGenericToolBar)
  27. ON_WM_CONTEXTMENU()
  28. ON_WM_DESTROY()
  29. ON_WM_PAINT()
  30. ON_WM_NCCALCSIZE()
  31. ON_WM_NCPAINT()
  32. ON_WM_NCHITTEST()
  33. ON_WM_WINDOWPOSCHANGING() 
  34. //}}AFX_MSG_MAP
  35. ON_COMMAND(IDM_BUTTONSONLY,OnButtonsOnly)
  36. ON_COMMAND(IDM_BUTTONSANDTEXT,OnTextAndButtons)
  37. ON_COMMAND(IDM_TEXTONLY,OnTextOnly)
  38. ON_COMMAND(IDM_RECALCSIZE,OnRecalcSize)
  39.  END_MESSAGE_MAP()
  40. CArray<CNGenericToolBar*,CNGenericToolBar*> CNGenericToolBar::m_ToolbarList;
  41. BOOL CNGenericToolBar::m_bButtons=FALSE;
  42. BOOL CNGenericToolBar::m_bText=FALSE;
  43. //////////////////////////////////////////////////////////////////////
  44. // Construction/Destruction
  45. //////////////////////////////////////////////////////////////////////
  46. CNGenericToolBar::CNGenericToolBar()
  47. {
  48. m_bHasText=FALSE;
  49. m_bHasBitmaps=TRUE;
  50. m_bForceText=FALSE;
  51. m_bSysMenuIcon=FALSE;
  52. m_dwGenericToolBarStyle = 0x0000;
  53. }
  54. CNGenericToolBar::~CNGenericToolBar()
  55. {
  56. }
  57. void CNGenericToolBar::OnRecalcSize()
  58. {
  59. SettingChange();
  60. RecalcSize();
  61. GetParentFrame()->DelayRecalcLayout();
  62. }
  63. void CNGenericToolBar::SettingChange()
  64. {
  65. TBBUTTON tb;
  66. for(int n=0; n<GetCount(); n++)
  67. {
  68. SendMessage(TB_GETBUTTON,n,(LPARAM)&tb);
  69. tb.iString=m_bText?m_TextIds[n]:-1;
  70. _SetButton(n,&tb);
  71. }
  72. SendMessage(TB_SETMAXTEXTROWS,m_bText||m_bForceText?4:0);
  73. SendMessage(TB_SETBITMAPSIZE,0,m_bButtons&&m_bHasBitmaps?MAKELONG(16,15):0);
  74. SendMessage(TB_AUTOSIZE);
  75. }
  76. BOOL CNGenericToolBar::RecalcSize()
  77. {
  78. CRect rect;
  79. int cx=0,cy=0;
  80. SendMessage(TB_AUTOSIZE);
  81. for(int n=0; n<GetToolBarCtrl().GetButtonCount(); n++)
  82. {
  83. GetItemRect(n,&rect);
  84. if(rect.Width()>cx) cx=rect.Width();
  85. if(rect.Height()>cy) cy=rect.Height();
  86. }
  87. m_sizeButton.cx=cx;
  88. m_sizeButton.cy=cy-2;
  89. m_bDelayedButtonLayout=TRUE;
  90. ::InvalidateRect(*this,NULL,FALSE);
  91. return TRUE;
  92. }
  93. BOOL CNGenericToolBar::CreateEx(CWnd* pParentWnd, DWORD dwExStyle, DWORD dwStyle, UINT nID, LPCTSTR szTitle)
  94. {
  95. if(!CToolBar::Create(pParentWnd,dwStyle,nID)) return FALSE;
  96. if(szTitle) SetWindowText(szTitle);
  97. m_pParent=pParentWnd;
  98. ModifyStyle(0,dwExStyle);
  99. m_pop.CreatePopupMenu();
  100. m_pop.AppendMenu(MF_STRING,IDM_BUTTONSONLY,"&Buttons");
  101. m_pop.AppendMenu(MF_STRING,IDM_BUTTONSANDTEXT,"Buttons &and Text");
  102. m_pop.AppendMenu(MF_STRING,IDM_TEXTONLY,"&Text");
  103. m_ToolbarList.Add(this);
  104. return TRUE;
  105. }
  106. BOOL CNGenericToolBar::LoadToolBar(LPCTSTR lpszResourceName)
  107. {
  108. if(!CToolBar::LoadToolBar(lpszResourceName)) return FALSE;
  109. CString tmp;
  110. LPCTSTR p,q;
  111. SendMessage(TB_SETMAXTEXTROWS,4);
  112. m_accelList.SetSize(0);
  113. for(int n=0; n<GetCount(); n++)
  114. {
  115. if(GetItemID(n)!=-1)
  116. {
  117. tmp.LoadString(GetItemID(n));
  118. p=tmp;
  119. while(*p && *p!='n')
  120. p++;
  121. if(*p)
  122. {
  123. p++;
  124. while(*p && *p!='n')
  125. p++;
  126. }
  127. if(*p)
  128. {
  129. for(q=p; *q; q++)
  130. {
  131. if(*q=='&')
  132. {
  133. int s=m_accelList.GetSize();
  134. m_accelList.SetSize(s+1);
  135. m_accelList[s].nKey=toupper(*(q+1));
  136. m_accelList[s].nId=GetItemID(n);
  137. break;
  138. }
  139. }
  140. SetButtonText(n,p+1);
  141. m_bHasText=TRUE;
  142. m_bText=TRUE;
  143. }
  144. else
  145. {
  146. if(m_bHasText) SetButtonText(n," ");
  147. }
  148. }
  149. }
  150. TBBUTTON tb;
  151. m_TextIds.SetSize(0);
  152. for(n=0; n<GetCount(); n++)
  153. {
  154. SendMessage(TB_GETBUTTON,n,(LPARAM)&tb);
  155. m_TextIds.Add(tb.iString);
  156. tb.iString=m_bText?m_TextIds[n]:-1;
  157. }
  158. m_bButtons = TRUE;
  159. OnRecalcSize();
  160. return TRUE;
  161. }
  162. BOOL CNGenericToolBar::SetButtonText(int nIndex, LPCTSTR lpszText)
  163. {
  164. if(!CToolBar::SetButtonText(nIndex,lpszText)) return FALSE;
  165. return RecalcSize();
  166. }
  167. void CNGenericToolBar::OnContextMenu(CWnd* pWnd, CPoint point) 
  168. {
  169. m_pop.CheckMenuItem(IDM_BUTTONSONLY,m_bButtons&&!m_bText?MF_CHECKED:MF_UNCHECKED);
  170. m_pop.CheckMenuItem(IDM_BUTTONSANDTEXT,m_bButtons&&m_bText?MF_CHECKED:MF_UNCHECKED);
  171. m_pop.CheckMenuItem(IDM_TEXTONLY,!m_bButtons&&m_bText?MF_CHECKED:MF_UNCHECKED);
  172. m_pop.EnableMenuItem(IDM_BUTTONSONLY,MF_ENABLED);
  173. m_pop.EnableMenuItem(IDM_BUTTONSANDTEXT,m_bHasText?MF_ENABLED:MF_GRAYED);
  174. m_pop.EnableMenuItem(IDM_TEXTONLY,m_bHasText?MF_ENABLED:MF_GRAYED);
  175. m_pop.TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,pWnd);
  176. }
  177. void CNGenericToolBar::OnButtonsOnly()
  178. {
  179. if(!m_bText && m_bButtons) return;
  180. m_bText=FALSE;
  181. m_bButtons=TRUE;
  182. SendToAllToolbars(WM_COMMAND,IDM_RECALCSIZE);
  183. }
  184. void CNGenericToolBar::OnTextOnly()
  185. {
  186. if(m_bText && !m_bButtons) return;
  187. m_bText=TRUE;
  188. m_bButtons=FALSE;
  189. SendToAllToolbars(WM_COMMAND,IDM_RECALCSIZE);
  190. }
  191. void CNGenericToolBar::OnTextAndButtons()
  192. {
  193. if(m_bText && m_bButtons) return;
  194. m_bText=TRUE;
  195. m_bButtons=TRUE;
  196. SendToAllToolbars(WM_COMMAND,IDM_RECALCSIZE);
  197. }
  198. void CNGenericToolBar::OnDestroy() 
  199. {
  200. CToolBar::OnDestroy();
  201. for(int n=0; n<m_ToolbarList.GetSize(); n++)
  202. if(m_ToolbarList[n]==this)
  203. {
  204. m_ToolbarList.RemoveAt(n);
  205. break;
  206. }
  207. }
  208. void CNGenericToolBar::SendToAllToolbars(UINT uMsg, WPARAM wParam, LPARAM lParam)
  209. {
  210. for(int n=0; n<m_ToolbarList.GetSize(); n++)
  211. m_ToolbarList[n]->SendMessage(uMsg,wParam,lParam);
  212. }
  213. void CNGenericToolBar::SetVisualState(BOOL bButtons, BOOL bText)
  214. {
  215. if(!bText && !bButtons) bButtons=TRUE;
  216. m_bText=bText;
  217. m_bButtons=bButtons;
  218. SendToAllToolbars(WM_COMMAND,IDM_RECALCSIZE);
  219. }
  220. BOOL CNGenericToolBar::GetVisualState(BOOL bText)
  221. {
  222. if(bText) return m_bText;
  223. else return m_bButtons;
  224. }
  225. // Borrowed from MFC
  226. void CNGenericToolBar::_SetButton(int nIndex, TBBUTTON* pButton)
  227. {
  228. // get original button state
  229. TBBUTTON button;
  230. VERIFY(DefWindowProc(TB_GETBUTTON, nIndex, (LPARAM)&button));
  231. // prepare for old/new button comparsion
  232. button.bReserved[0] = 0;
  233. button.bReserved[1] = 0;
  234. // TBSTATE_ENABLED == TBBS_DISABLED so invert it
  235. pButton->fsState ^= TBSTATE_ENABLED;
  236. pButton->bReserved[0] = 0;
  237. pButton->bReserved[1] = 0;
  238. // nothing to do if they are the same
  239. if (memcmp(pButton, &button, sizeof(TBBUTTON)) != 0)
  240. {
  241. // don't redraw everything while setting the button
  242. DWORD dwStyle = GetStyle();
  243. ModifyStyle(WS_VISIBLE, 0);
  244. VERIFY(DefWindowProc(TB_DELETEBUTTON, nIndex, 0));
  245. VERIFY(DefWindowProc(TB_INSERTBUTTON, nIndex, (LPARAM)pButton));
  246. ModifyStyle(0, dwStyle & WS_VISIBLE);
  247. // invalidate appropriate parts
  248. if (((pButton->fsStyle ^ button.fsStyle) & TBSTYLE_SEP) ||
  249. ((pButton->fsStyle & TBSTYLE_SEP) && pButton->iBitmap != button.iBitmap))
  250. {
  251. // changing a separator
  252. Invalidate(FALSE);
  253. }
  254. else
  255. {
  256. // invalidate just the button
  257. CRect rect;
  258. SendMessage(TB_AUTOSIZE);
  259. if (DefWindowProc(TB_GETITEMRECT, nIndex, (LPARAM)&rect))
  260. InvalidateRect(rect, FALSE);    // don't erase background
  261. }
  262. }
  263. }
  264. // Calculate the non-client area - adjusting for grippers
  265. void CNGenericToolBar::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
  266. {
  267.      CToolBar::OnNcCalcSize(bCalcValidRects,lpncsp);
  268.      // adjust non-client area for gripper at left or top
  269.      if (m_dwStyle & CBRS_FLOATING)
  270.  {          // no grippers
  271.      }
  272.  else if (m_dwStyle & CBRS_ORIENT_HORZ)
  273.  {
  274.           // move 2 pixels right to make room
  275.           lpncsp->rgrc[0].left += 2;
  276.           lpncsp->rgrc[0].right += 2;
  277.           lpncsp->rgrc[0].top += 2;
  278.           lpncsp->rgrc[0].bottom += 2;
  279.      }
  280.  else
  281.  {          // move 4 pixels downto make room
  282.           lpncsp->rgrc[0].top += 4;
  283.           lpncsp->rgrc[0].bottom += 4;     
  284.  }
  285. }
  286. // Draw the gripper at left or top
  287. void CNGenericToolBar::DrawGripper(CWindowDC *pDC, CRect& rectWindow)
  288. {
  289.      // get the gripper rect (1 pixel smaller than toolbar)
  290.      CRect gripper = rectWindow;
  291.      gripper.DeflateRect(1,1);
  292.      if (m_dwStyle & CBRS_FLOATING)
  293.  {          // no grippers
  294.      }
  295.  else if (m_dwStyle & CBRS_ORIENT_HORZ)
  296.  {          // gripper at left
  297.           gripper.right = gripper.left+3;
  298.           pDC->Draw3dRect(gripper,::GetSysColor(COLOR_3DHIGHLIGHT),::GetSysColor(COLOR_3DSHADOW));
  299.           gripper.OffsetRect(+4,0);
  300.           pDC->Draw3dRect(gripper,::GetSysColor(COLOR_3DHIGHLIGHT),::GetSysColor(COLOR_3DSHADOW));
  301.           rectWindow.left += 8; 
  302.  } else
  303.  {          // gripper at top
  304.           gripper.bottom = gripper.top+3;
  305.           pDC->Draw3dRect(gripper,::GetSysColor(COLOR_3DHIGHLIGHT),::GetSysColor(COLOR_3DSHADOW));
  306.           gripper.OffsetRect(0,+4);
  307.           pDC->Draw3dRect(gripper,::GetSysColor(COLOR_3DHIGHLIGHT),::GetSysColor(COLOR_3DSHADOW));
  308.           rectWindow.top += 8;
  309.      }
  310. }
  311. void CNGenericToolBar::DrawSysMenuIcon(CWindowDC* pDC, CRect& rectWindow)
  312. {
  313. if(!m_bSysMenuIcon) return; // Do nothing if this isn't needed
  314. if(m_dwStyle&CBRS_ORIENT_HORZ)
  315. {
  316. DrawIconEx(*pDC,rectWindow.left+2,rectWindow.top+6,m_hSysMenuIcon,16,16,0,NULL,DI_NORMAL);
  317. m_rectSysMenu.SetRect(rectWindow.left+2,rectWindow.top+6,rectWindow.left+2+16,rectWindow.top+6+16);
  318. rectWindow.left+=16;
  319. }
  320. else
  321. {
  322. DrawIconEx(*pDC,rectWindow.left+12,rectWindow.top+2,m_hSysMenuIcon,16,16,0,NULL,DI_NORMAL);
  323. m_rectSysMenu.SetRect(rectWindow.left+12,rectWindow.top+2,rectWindow.left+12+16,rectWindow.top+2+16);
  324. rectWindow.top+=16;
  325. }
  326. }
  327. // Erase the non-client area (borders) - copied from MFC implementation
  328. void CNGenericToolBar::EraseNonClient(BOOL bRaised)
  329. {
  330.      // get window DC that is clipped to the non-client area
  331.      CWindowDC dc(this);
  332.      CRect rectClient;
  333.      GetClientRect(rectClient);
  334.      CRect rectWindow;
  335.      GetWindowRect(rectWindow);
  336.      ScreenToClient(rectWindow);
  337.      rectClient.OffsetRect(-rectWindow.left, -rectWindow.top);
  338.      dc.ExcludeClipRect(rectClient);     // draw borders in non-client area
  339.      rectWindow.OffsetRect(-rectWindow.left, -rectWindow.top);
  340. DrawBorders(&dc, rectWindow);     // erase parts not drawn
  341.      dc.IntersectClipRect(rectWindow);
  342.      SendMessage(WM_ERASEBKGND, (WPARAM)dc.m_hDC);
  343.      DrawGripper(&dc, rectWindow); // <-- my addition to draw gripper}
  344.  DrawSysMenuIcon(&dc, rectWindow); // Draw icon for system menu, if needed
  345. }
  346. BOOL CNGenericToolBar::TranslateMenuChar(UINT nChar)
  347. {
  348. for(int n=0; n<m_accelList.GetSize(); n++)
  349. {
  350. if(m_accelList[n].nKey==(UINT)toupper(nChar))
  351. {
  352. m_pParent->PostMessage(WM_COMMAND,m_accelList[n].nId);
  353. return TRUE;
  354. }
  355. }
  356. return FALSE;
  357. }
  358. BOOL CNGenericToolBar::KeyboardFilter(UINT nChar, UINT nRepCnt, UINT nFlags)
  359. {
  360. return FALSE;
  361. }
  362. void CNGenericToolBar::DrawBorders(CDC* pDC, CRect& rect)
  363. {
  364. ASSERT_VALID(this);
  365. ASSERT_VALID(pDC);
  366. DWORD dwStyle = m_dwStyle;
  367. if (!(dwStyle & CBRS_BORDER_ANY))
  368. return;
  369. // prepare for dark lines
  370. ASSERT(rect.top == 0 && rect.left == 0);
  371. COLORREF clr=GetSysColor(COLOR_3DSHADOW);
  372. if(dwStyle&CBRS_BORDER_RIGHT)
  373. pDC->FillSolidRect(rect.right-1,0,rect.right,rect.bottom,clr); //right
  374. if(dwStyle&CBRS_BORDER_BOTTOM)
  375. pDC->FillSolidRect(0,rect.bottom-1,rect.right,rect.bottom,clr); //bottom
  376. clr=GetSysColor(COLOR_3DHIGHLIGHT);
  377. if(dwStyle&CBRS_BORDER_TOP)
  378. pDC->FillSolidRect(0,0,rect.right,1,clr); //top
  379. if(dwStyle&CBRS_BORDER_LEFT)
  380. pDC->FillSolidRect(0,0,1,rect.bottom,clr); //left
  381. if(dwStyle&CBRS_BORDER_TOP)
  382. rect.top++;
  383. if(dwStyle&CBRS_BORDER_RIGHT)
  384. rect.right--;
  385. if(dwStyle&CBRS_BORDER_BOTTOM)
  386. rect.bottom--;
  387. if(dwStyle&CBRS_BORDER_LEFT)
  388. rect.left++;
  389. }
  390. // Because buttons are transparent, we need to repaint the background
  391. void CNGenericToolBar::RepaintBackground()
  392. {
  393.      // get parent window (there should be one)
  394.      CWnd* pParent = GetParent();
  395.      if (pParent)
  396.  {
  397.           // get rect for this toolbar
  398.           CRect rw; GetWindowRect(&rw);
  399.           // convert rect to parent coords
  400.           CRect rc = rw; pParent->ScreenToClient(&rc);
  401.           // invalidate this part of parent
  402.           pParent->InvalidateRect(&rc);
  403.           // now do all the other toolbars (etc) that belong to the parent
  404.           for (CWnd* pSibling = pParent->GetWindow(GW_CHILD); pSibling; pSibling = pSibling->GetNextWindow(GW_HWNDNEXT))
  405.   {
  406.                // but do not draw ourselves
  407.                if (pSibling == this) continue;
  408.                // convert rect to siblings coords
  409.                CRect rc = rw; pSibling->ScreenToClient(&rc);
  410.                // invalidate this part of sibling
  411.                pSibling->InvalidateRect(&rc);
  412.           }
  413.      }
  414. }
  415. // Revised by Zhenxin Li.
  416. // I remove these two functions, then the separators are drawn correctly.
  417. // I don't know why.
  418. // Draw the separators in the client area
  419. void CNGenericToolBar::DrawSeparators()
  420. {
  421. // get a dc for the client area
  422. // CClientDC dc(this);
  423. // draw the separators on it
  424. // DrawSeparators(&dc);
  425. }
  426. // Draw the separators
  427. void CNGenericToolBar::DrawSeparators(CClientDC* pDC)
  428. {
  429. /*     // horizontal vs vertical
  430.      bool ishorz = (m_dwStyle & CBRS_ORIENT_HORZ) != 0;
  431.      // get number of buttons
  432.      int nIndexMax = (int)DefWindowProc(TB_BUTTONCOUNT, 0, 0);
  433.      int nIndex;
  434.      // try each button
  435.      for (nIndex = 0; nIndex < nIndexMax; nIndex++)
  436.  {
  437.           UINT dwStyle = GetButtonStyle(nIndex);
  438.           UINT wStyle = LOWORD(dwStyle);
  439.           // if it is a separator
  440.           if (wStyle == TBBS_SEPARATOR)
  441.   {
  442.                // get it's rectangle and width
  443.                CRect rect;
  444.                GetItemRect(nIndex,rect);
  445.                // if small enough to be a true separator
  446.                int w = rect.Width();
  447.                if (w <= 8)
  448.    {
  449.                     if (ishorz)
  450. {
  451.                          // draw the separator bar in the middle
  452.                          CRect rectbar = rect;
  453.                          int x = (rectbar.left+rectbar.right)/2;
  454.                          rectbar.left = x-1; rectbar.right = x+1;
  455.  rectbar.top++;
  456.  rectbar.bottom++;
  457.                          pDC->Draw3dRect(rectbar,::GetSysColor(COLOR_3DSHADOW),::GetSysColor(COLOR_3DHILIGHT));
  458.                     }
  459. else
  460. {
  461.                          // draw the separator bar in the middle
  462.                          CRect rectbar = rect;
  463.                          rectbar.left = rectbar.left - m_sizeButton.cx;
  464.                          rectbar.right = rectbar.left + m_sizeButton.cx;
  465.                          rectbar.top = rectbar.bottom+1;
  466.                          rectbar.bottom = rectbar.top+3;
  467.                          int y = (rectbar.top+rectbar.bottom)/2;
  468.                          rectbar.top = y-1; rectbar.bottom = y+1;
  469.                          pDC->Draw3dRect(rectbar,::GetSysColor(COLOR_3DSHADOW),::GetSysColor(COLOR_3DHILIGHT));
  470.                     }
  471.                }
  472.           }
  473.      }*/
  474. }
  475. // Because buttons are transparent, we need to repaint background if style changes
  476. void CNGenericToolBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
  477. {
  478. static CUIntArray styles;
  479.      // get the number of buttons
  480.      int nIndexMax = (int)DefWindowProc(TB_BUTTONCOUNT, 0, 0);
  481.      int nIndex;
  482.      // save styles
  483.      for (nIndex = 0; nIndex < nIndexMax; nIndex++)
  484.  {
  485.           UINT dwStyle = GetButtonStyle(nIndex);
  486.           styles.SetAtGrow(nIndex,dwStyle);
  487.      }
  488.      // do base class processing
  489.      CToolBar::OnUpdateCmdUI(pTarget,bDisableIfNoHndler);
  490.      // make checked button appear pushed in
  491.      for (nIndex = 0; nIndex < nIndexMax; nIndex++)
  492.  {
  493.           UINT dwStyle = GetButtonStyle(nIndex);
  494.           if (dwStyle & TBBS_DISABLED)
  495.   {
  496.                // don't touch if disabled (avoids flicker)
  497.           } else if (dwStyle & TBBS_CHECKBOX)
  498.   {
  499.                UINT dwStyleWas = dwStyle;
  500.                // if checked, make it pressed, else not pressed
  501.                if (dwStyle & TBBS_CHECKED)
  502.    {
  503.                     dwStyle |= TBBS_PRESSED;
  504.                } else if (!(styles[nIndex]&TBBS_CHECKED) && (styles[nIndex]&TBBS_PRESSED))
  505.    {
  506.                     dwStyle |= TBBS_PRESSED;
  507.                } else
  508.    {
  509.                     dwStyle &= ~TBBS_PRESSED;
  510.                }
  511.                // set new style if changed
  512.                if (dwStyleWas != dwStyle) SetButtonStyle(nIndex,dwStyle);
  513.           }
  514.      }
  515.      // check for changes to style (buttons presssed/released)
  516.      for (nIndex = 0; nIndex < nIndexMax; nIndex++)
  517.  {
  518.           UINT dwStyle = GetButtonStyle(nIndex);
  519.           if (styles[nIndex] != dwStyle)
  520.   {
  521.                // repaint whole toolbar (not just this button)
  522.                Invalidate();
  523.                // no need to check any more
  524.                break;
  525.           }
  526.      }
  527. }
  528. // Because buttons are transparent, we need to repaint background on size or move
  529. void CNGenericToolBar::OnWindowPosChanging(LPWINDOWPOS lpwp)
  530. {
  531.      // default processing
  532.      CToolBar::OnWindowPosChanging(lpwp);
  533.      RepaintBackground();
  534. }
  535. // Paint the toolbar
  536. void CNGenericToolBar::OnPaint()
  537. {
  538. // standard toolbar
  539. CToolBar::OnPaint();
  540. // erase the background
  541. EraseNonClient(FALSE);
  542. // plus separators
  543. DrawSeparators();
  544. }
  545. // Paint the non-client area - copied from MFC implementatios
  546. void CNGenericToolBar::OnNcPaint()
  547. {
  548.      //   EraseNonClient(); don't do it here
  549. }
  550. UINT CNGenericToolBar::OnNcHitTest(CPoint point) 
  551. {
  552. CPoint pt(point);
  553. CRect wRect;
  554. GetWindowRect(wRect);
  555. pt.x-=wRect.left;
  556. pt.y-=wRect.top;
  557. // If SysMenu icon is visible, hittest it specially
  558. if(m_bSysMenuIcon && m_rectSysMenu.PtInRect(pt))
  559. {
  560. OnOverSysMenu();
  561. return HTSYSMENU;
  562. }
  563. return CToolBar::OnNcHitTest(point);
  564. }
  565. BOOL CNGenericToolBar::GenericToolBarModifyStyle(DWORD dwRemove, DWORD dwAdd)
  566. {
  567. DWORD dwStyle = m_dwGenericToolBarStyle;
  568. DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
  569. if (dwStyle == dwNewStyle)
  570. return FALSE;
  571. m_dwGenericToolBarStyle = dwNewStyle;
  572. return TRUE;
  573. }
  574. CSize CNGenericToolBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
  575. {
  576. DWORD dwMode = bStretch ? LM_STRETCH : 0;
  577. dwMode |= bHorz ? LM_HORZ : 0;
  578. CSize s = CalcLayout(dwMode);
  579. // Revised by Zhenxin Li.
  580. // Make room for gripper.
  581. if (m_dwStyle&CBRS_ORIENT_HORZ)
  582. s.cx += 2;
  583. else
  584. s.cy += 4;
  585. return s;
  586. }
  587. // Revised by Zhenxin Li.
  588. // Borrow from MFC source. Make a little change.
  589. void CNGenericToolBar::_GetButton(int nIndex, TBBUTTON* pButton) const
  590. {
  591. CNGenericToolBar* pBar = (CNGenericToolBar*)this;
  592. VERIFY(pBar->DefWindowProc(TB_GETBUTTON, nIndex, (LPARAM)pButton));
  593. // TBSTATE_ENABLED == TBBS_DISABLED so invert it
  594. pButton->fsState ^= TBSTATE_ENABLED;
  595. }
  596. #ifdef _MAC
  597. #define CX_OVERLAP  1
  598. #else
  599. #define CX_OVERLAP  0
  600. #endif
  601. struct _AFX_CONTROLPOS
  602. {
  603. int nIndex, nID;
  604. CRect rectOldPos;
  605. };
  606. // Revised by Zhenxin Li.
  607. // Borrow from MFC source. Recalculate each button's m_sizeButton value.
  608. int CNGenericToolBar::WrapToolBar(TBBUTTON* pData, int nCount, int nWidth)
  609. {
  610. ASSERT(pData != NULL && nCount > 0);
  611. int nResult = 0;
  612. int x = 0;
  613. CSize m_sizeButton = CToolBar::m_sizeButton;
  614. m_sizeButton.cy += 2;
  615. BOOL bMenuClass = IsKindOf(RUNTIME_CLASS(CNGenericMenu));
  616. for (int i = 0; i < nCount; i++)
  617. {
  618. pData[i].fsState &= ~TBSTATE_WRAP;
  619. if (pData[i].fsState & TBSTATE_HIDDEN)
  620. continue;
  621. if (bMenuClass)
  622. {
  623. CRect r;
  624. DefWindowProc(TB_GETITEMRECT, i, (LPARAM)&r);
  625. m_sizeButton = CSize(r.right-r.left, r.bottom-r.top);
  626. }
  627. int dx, dxNext;
  628. if (pData[i].fsStyle & TBSTYLE_SEP)
  629. {
  630. dx = pData[i].iBitmap;
  631. dxNext = dx;
  632. }
  633. else
  634. {
  635. dx = m_sizeButton.cx;
  636. dxNext = dx - CX_OVERLAP;
  637. }
  638. if (x + dx > nWidth)
  639. {
  640. BOOL bFound = FALSE;
  641. for (int j = i; j >= 0  &&  !(pData[j].fsState & TBSTATE_WRAP); j--)
  642. {
  643. // Find last separator that isn't hidden
  644. // a separator that has a command ID is not
  645. // a separator, but a custom control.
  646. if ((pData[j].fsStyle & TBSTYLE_SEP) &&
  647. (pData[j].idCommand == 0) &&
  648. !(pData[j].fsState & TBSTATE_HIDDEN))
  649. {
  650. bFound = TRUE; i = j; x = 0;
  651. pData[j].fsState |= TBSTATE_WRAP;
  652. nResult++;
  653. break;
  654. }
  655. }
  656. if (!bFound)
  657. {
  658. for (int j = i - 1; j >= 0 && !(pData[j].fsState & TBSTATE_WRAP); j--)
  659. {
  660. // Never wrap anything that is hidden,
  661. // or any custom controls
  662. if ((pData[j].fsState & TBSTATE_HIDDEN) ||
  663. ((pData[j].fsStyle & TBSTYLE_SEP) &&
  664. (pData[j].idCommand != 0)))
  665. continue;
  666. bFound = TRUE; i = j; x = 0;
  667. pData[j].fsState |= TBSTATE_WRAP;
  668. nResult++;
  669. break;
  670. }
  671. if (!bFound)
  672. x += dxNext;
  673. }
  674. }
  675. else
  676. x += dxNext;
  677. }
  678. return nResult + 1;
  679. }
  680. // Revised by Zhenxin Li.
  681. // Must borrow from MFC source, because this function is not virtual.
  682. // If not borrow, the new CalcSize function won't be called.
  683. void CNGenericToolBar::SizeToolBar(TBBUTTON* pData, int nCount, int nLength, BOOL bVert)
  684. {
  685. ASSERT(pData != NULL && nCount > 0);
  686. if (!bVert)
  687. {
  688. int nMin, nMax, nTarget, nCurrent, nMid;
  689. // Wrap ToolBar as specified
  690. nMax = nLength;
  691. nTarget = WrapToolBar(pData, nCount, nMax);
  692. // Wrap ToolBar vertically
  693. nMin = 0;
  694. nCurrent = WrapToolBar(pData, nCount, nMin);
  695. if (nCurrent != nTarget)
  696. {
  697. while (nMin < nMax)
  698. {
  699. nMid = (nMin + nMax) / 2;
  700. nCurrent = WrapToolBar(pData, nCount, nMid);
  701. if (nCurrent == nTarget)
  702. nMax = nMid;
  703. else
  704. {
  705. if (nMin == nMid)
  706. {
  707. WrapToolBar(pData, nCount, nMax);
  708. break;
  709. }
  710. nMin = nMid;
  711. }
  712. }
  713. }
  714. CSize size = CalcSize(pData, nCount);
  715. WrapToolBar(pData, nCount, size.cx);
  716. }
  717. else
  718. {
  719. CSize sizeMax, sizeMin, sizeMid;
  720. // Wrap ToolBar vertically
  721. WrapToolBar(pData, nCount, 0);
  722. sizeMin = CalcSize(pData, nCount);
  723. // Wrap ToolBar horizontally
  724. WrapToolBar(pData, nCount, 32767);
  725. sizeMax = CalcSize(pData, nCount);
  726. while (sizeMin.cx < sizeMax.cx)
  727. {
  728. sizeMid.cx = (sizeMin.cx + sizeMax.cx) / 2;
  729. WrapToolBar(pData, nCount, sizeMid.cx);
  730. sizeMid = CalcSize(pData, nCount);
  731. if (nLength < sizeMid.cy)
  732. {
  733. if (sizeMin == sizeMid)
  734. {
  735. WrapToolBar(pData, nCount, sizeMax.cx);
  736. return;
  737. }
  738. sizeMin = sizeMid;
  739. }
  740. else if (nLength > sizeMid.cy)
  741. sizeMax = sizeMid;
  742. else
  743. return;
  744. }
  745. }
  746. }
  747. CSize CNGenericToolBar::CalcSize(TBBUTTON* pData, int nCount)
  748. {
  749. ASSERT(pData != NULL && nCount > 0);
  750. CPoint cur(0,0);
  751. CSize sizeResult(0,0);
  752. CSize m_sizeButton = CToolBar::m_sizeButton;
  753. m_sizeButton.cy += 2;
  754. BOOL bMenuClass = IsKindOf(RUNTIME_CLASS(CNGenericMenu));
  755. for (int i = 0; i < nCount; i++)
  756. {
  757. if (pData[i].fsState & TBSTATE_HIDDEN)
  758. continue;
  759. if (bMenuClass)
  760. {
  761. CRect r;
  762. DefWindowProc(TB_GETITEMRECT, i, (LPARAM)&r);
  763. m_sizeButton = CSize(r.right-r.left, r.bottom-r.top);
  764. }
  765. if (pData[i].fsStyle & TBSTYLE_SEP)
  766. {
  767. // A separator represents either a height or width
  768. if (pData[i].fsState & TBSTATE_WRAP)
  769. // Revised by Zhenxin Li
  770. // Add 3 points for separator in flat toolbar.
  771. sizeResult.cy = max(cur.y + m_sizeButton.cy + pData[i].iBitmap * 2 / 3, sizeResult.cy) + 3;
  772. else
  773. sizeResult.cx = max(cur.x + pData[i].iBitmap, sizeResult.cx);
  774. }
  775. else
  776. {
  777. sizeResult.cx = max(cur.x + m_sizeButton.cx, sizeResult.cx);
  778. sizeResult.cy = max(cur.y + m_sizeButton.cy, sizeResult.cy);
  779. }
  780. if (pData[i].fsStyle & TBSTYLE_SEP)
  781. cur.x += pData[i].iBitmap;
  782. else
  783. cur.x += m_sizeButton.cx - CX_OVERLAP;
  784. if (pData[i].fsState & TBSTATE_WRAP)
  785. {
  786. cur.x = 0;
  787. cur.y += m_sizeButton.cy;
  788. if (pData[i].fsStyle & TBSTYLE_SEP)
  789. // Revised by Zhenxin Li
  790. // Like above, add 3 points for separator in flat toolbar.
  791. cur.y += pData[i].iBitmap * 2 / 3 + 3;
  792. }
  793. }
  794. return sizeResult;
  795. }
  796. CSize CNGenericToolBar::CalcLayout(DWORD dwMode, int nLength)
  797. {
  798. ASSERT_VALID(this);
  799. ASSERT(::IsWindow(m_hWnd));
  800. if (dwMode & LM_HORZDOCK)
  801. ASSERT(dwMode & LM_HORZ);
  802. int nCount;
  803. TBBUTTON* pData;
  804. CSize sizeResult(0,0);
  805. // Load Buttons
  806. {
  807. nCount = DefWindowProc(TB_BUTTONCOUNT, 0, 0);
  808. if (nCount != 0)
  809. {
  810. int i;
  811. pData = new TBBUTTON[nCount];
  812. for (i = 0; i < nCount; i++)
  813. _GetButton(i, &pData[i]);
  814. }
  815. }
  816. if (nCount > 0)
  817. {
  818. if (!(m_dwStyle & CBRS_SIZE_FIXED))
  819. {
  820. BOOL bDynamic = m_dwStyle & CBRS_SIZE_DYNAMIC;
  821. if (bDynamic && (dwMode & LM_MRUWIDTH))
  822. SizeToolBar(pData, nCount, m_nMRUWidth);
  823. else if (bDynamic && (dwMode & LM_HORZDOCK))
  824. SizeToolBar(pData, nCount, 32767);
  825. else if (bDynamic && (dwMode & LM_VERTDOCK))
  826. SizeToolBar(pData, nCount, 0);
  827. else if (bDynamic && (nLength != -1))
  828. {
  829. CRect rect; rect.SetRectEmpty();
  830. CalcInsideRect(rect, (dwMode & LM_HORZ));
  831. BOOL bVert = (dwMode & LM_LENGTHY);
  832. int nLen = nLength + (bVert ? rect.Height() : rect.Width());
  833. SizeToolBar(pData, nCount, nLen, bVert);
  834. }
  835. else if (bDynamic && (m_dwStyle & CBRS_FLOATING))
  836. SizeToolBar(pData, nCount, m_nMRUWidth);
  837. else
  838. SizeToolBar(pData, nCount, (dwMode & LM_HORZ) ? 32767 : 0);
  839. }
  840. sizeResult = CalcSize(pData, nCount);
  841. if (dwMode & LM_COMMIT)
  842. {
  843. _AFX_CONTROLPOS* pControl = NULL;
  844. int nControlCount = 0;
  845. BOOL bIsDelayed = m_bDelayedButtonLayout;
  846. m_bDelayedButtonLayout = FALSE;
  847. for(int i = 0; i < nCount; i++)
  848. if ((pData[i].fsStyle & TBSTYLE_SEP) && (pData[i].idCommand != 0))
  849. nControlCount++;
  850. if (nControlCount > 0)
  851. {
  852. pControl = new _AFX_CONTROLPOS[nControlCount];
  853. nControlCount = 0;
  854. for(int i = 0; i < nCount; i++)
  855. {
  856. if ((pData[i].fsStyle & TBSTYLE_SEP) && (pData[i].idCommand != 0))
  857. {
  858. pControl[nControlCount].nIndex = i;
  859. pControl[nControlCount].nID = pData[i].idCommand;
  860. CRect rect;
  861. GetItemRect(i, &rect);
  862. ClientToScreen(&rect);
  863. pControl[nControlCount].rectOldPos = rect;
  864. nControlCount++;
  865. }
  866. }
  867. }
  868. if ((m_dwStyle & CBRS_FLOATING) && (m_dwStyle & CBRS_SIZE_DYNAMIC))
  869. m_nMRUWidth = sizeResult.cx;
  870. for (i = 0; i < nCount; i++)
  871. _SetButton(i, &pData[i]);
  872. if (nControlCount > 0)
  873. {
  874. for (int i = 0; i < nControlCount; i++)
  875. {
  876. CWnd* pWnd = GetDlgItem(pControl[i].nID);
  877. if (pWnd != NULL)
  878. {
  879. CRect rect;
  880. pWnd->GetWindowRect(&rect);
  881. CPoint pt = rect.TopLeft() - pControl[i].rectOldPos.TopLeft();
  882. GetItemRect(pControl[i].nIndex, &rect);
  883. pt = rect.TopLeft() + pt;
  884. pWnd->SetWindowPos(NULL, pt.x, pt.y, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
  885. }
  886. }
  887. delete[] pControl;
  888. }
  889. m_bDelayedButtonLayout = bIsDelayed;
  890. }
  891. delete[] pData;
  892. }
  893. //BLOCK: Adjust Margins
  894. {
  895. CRect rect; rect.SetRectEmpty();
  896. CalcInsideRect(rect, (dwMode & LM_HORZ));
  897. sizeResult.cy -= rect.Height();
  898. sizeResult.cx -= rect.Width();
  899. CSize size = CControlBar::CalcFixedLayout((dwMode & LM_STRETCH), (dwMode & LM_HORZ));
  900. sizeResult.cx = max(sizeResult.cx, size.cx);
  901. sizeResult.cy = max(sizeResult.cy, size.cy);
  902. }
  903. return sizeResult;
  904. }
  905. CSize CNGenericToolBar::CalcDynamicLayout(int nLength, DWORD dwMode)
  906. {
  907. CSize s;
  908. if ((nLength == -1) && !(dwMode & LM_MRUWIDTH) && !(dwMode & LM_COMMIT) &&
  909. ((dwMode & LM_HORZDOCK) || (dwMode & LM_VERTDOCK)))
  910. s = CalcFixedLayout(dwMode & LM_STRETCH, dwMode & LM_HORZDOCK);
  911. else
  912. s = CalcLayout(dwMode, nLength);
  913. return s;
  914. }