UIFlatBar.cpp
上传用户:yatsl7111
上传日期:2007-01-08
资源大小:1433k
文件大小:9k
源码类别:

图形图象

开发平台:

Visual C++

  1. ////////////////////////////////////////////////////////////////
  2. // Copyright 1998 Paul DiLascia
  3. // If this code works, it was written by Paul DiLascia.
  4. // If not, I don't know who wrote it.
  5. //
  6. // CFlatToolBar implements dockable flat-style toolbars with "grippers"
  7. //
  8. #include "StdAfx.h"
  9. #include "UIFlatBar.h"
  10. #include "UIModulVer.h"
  11. // if you want to see extra TRACE diagnostics, set below to TRUE
  12. BOOL CFlatToolBar::bTRACE   = FALSE;
  13. #ifdef _DEBUG
  14. #define FBTRACEFN
  15. CTraceFn __fooble;
  16. if (bTRACE)
  17. TRACE
  18. #define FBTRACE
  19. if (bTRACE)       
  20. TRACE
  21. #else
  22. #define FBTRACEFN TRACE
  23. #define FBTRACE   TRACE
  24. #endif
  25. /////////////////
  26. // One of these for each drop-down button
  27. //
  28. struct DROPDOWNBUTTON {
  29. DROPDOWNBUTTON* next;
  30. UINT idButton;  // command ID of button
  31. UINT idMenu;  // popup menu to display
  32. };
  33. // these define size of grippers
  34. const GRIP_WIDTH   = 3;
  35. const GRIP_MARGIN  = 5;
  36. // flags stored in item data
  37. #define ITEMF_INITIALIZED 0x01 // item data initialized
  38. #define ITEMF_CHECKED 0x02 // item is checked
  39. #ifdef _DEBUG
  40. #define new DEBUG_NEW
  41. #undef THIS_FILE
  42. static char THIS_FILE[] = __FILE__;
  43. #endif
  44. ////////////////////////////////////////////////////////////////
  45. // CFlatToolBar--does flat tool bar in MFC.
  46. //
  47. IMPLEMENT_DYNAMIC(CFlatToolBar, CFlatToolBarBase)
  48. BEGIN_MESSAGE_MAP(CFlatToolBar, CFlatToolBarBase)
  49. ON_NOTIFY_REFLECT(TBN_DROPDOWN,  OnTbnDropDown)
  50. ON_WM_WINDOWPOSCHANGING()
  51. ON_WM_WINDOWPOSCHANGED()
  52. ON_WM_NCCALCSIZE()
  53. ON_WM_ERASEBKGND()
  54. ON_WM_NCCREATE()
  55. ON_WM_PAINT()
  56. ON_WM_CREATE()
  57. END_MESSAGE_MAP()
  58. CFlatToolBar::CFlatToolBar()
  59. {
  60. FBTRACE(_T("CFlatToolBar::CFlatToolBar, comctl32 version = %dn"),
  61. iVerComCtl32);
  62. m_bDrawDisabledButtonsInColor = FALSE; // don't use color
  63. m_bInCoolBar = FALSE; // assume not inside coolbar
  64. m_pDropDownButtons = NULL; // list of drop-down buttons
  65. m_bShowDropdownArrowWhenVertical = TRUE;
  66. m_bNoEntry = FALSE;
  67. }
  68. CFlatToolBar::~CFlatToolBar()
  69. {
  70. while (m_pDropDownButtons) {
  71. DROPDOWNBUTTON* pnext = m_pDropDownButtons->next;
  72. delete m_pDropDownButtons;
  73. m_pDropDownButtons = pnext;
  74. }
  75. }
  76. /////////////////
  77. // Create handler: set flat style by default
  78. //
  79. int CFlatToolBar::OnCreate(LPCREATESTRUCT lpcs)
  80. {
  81. if (CFlatToolBarBase::OnCreate(lpcs) == -1)
  82. return -1;
  83. ModifyStyle(0, TBSTYLE_FLAT);
  84. return 0;  // OK
  85. }
  86. ////////////////
  87. // Load function sets flat style after loading buttons.
  88. //
  89. BOOL CFlatToolBar::LoadToolBar(LPCTSTR lpszResourceName)
  90. {
  91. // Set transparent/flat style before loading buttons to allow zero-height
  92. // border. This required because of bug in comctl32.dll that always adds
  93. // a border, unless flat/transparent.
  94. //
  95. DWORD dwStyle = GetStyle();
  96. ModifyStyle(0, TBSTYLE_FLAT|TBSTYLE_TRANSPARENT);
  97. BOOL bRet = CFlatToolBarBase::LoadToolBar(lpszResourceName);
  98. SetWindowLong(m_hWnd, GWL_STYLE, dwStyle);
  99. return bRet;
  100. }
  101. //////////////////
  102. // Calcluate size of client area. Adds room for grippers
  103. //
  104. void CFlatToolBar::OnNcCalcSize(BOOL bCalc, NCCALCSIZE_PARAMS* pncp)
  105. {
  106. if (m_bInCoolBar) { // if I am in a coolbar (rebar):
  107. Default();   // ..bypass CToolBar/CControlBar
  108. } else {
  109. CRect& rc = (CRect&)pncp->rgrc[0]; // rect to return
  110. // copied from MFC below:
  111. CRect rcMargin(0,0,0,0);
  112. CControlBar::CalcInsideRect(rcMargin, m_dwStyle & CBRS_ORIENT_HORZ);
  113. // adjust non-client area for border space
  114. rc.left  += rcMargin.left;
  115. rc.top   += rcMargin.top; // MFC has -2 here, bug for newer comctl32
  116. rc.right += rcMargin.right;
  117. rc.bottom+= rcMargin.bottom;
  118. }
  119. }
  120. //////////////////
  121. // MFC doesn't handle moving a TBSTYLE_FLAT toolbar correctly. The simplest
  122. // way to fix it is to repaint whatever was underneath whenever the toolbar
  123. // moves. This is done in this and the following function. All this stuff is
  124. // only required because flat toolbars paint transparently (don't paint their
  125. // backgrounds).
  126. // 
  127. void CFlatToolBar::OnWindowPosChanging(LPWINDOWPOS lpwp)
  128. {
  129. if (m_bInCoolBar)
  130. // inside coolbars, don't do MFC thing
  131. Default();
  132. else {
  133. CFlatToolBarBase::OnWindowPosChanging(lpwp);
  134. if (!(lpwp->flags & SWP_NOMOVE))
  135. GetWindowRect(&m_rcOldPos);  // remember old position
  136. }
  137. }
  138. //////////////////
  139. // Now toolbar has really moved: repaint area beneath old position
  140. //
  141. void CFlatToolBar::OnWindowPosChanged(LPWINDOWPOS lpwp)
  142. {
  143. if (m_bInCoolBar) {
  144. Default();
  145. } else {
  146. CFlatToolBarBase::OnWindowPosChanged(lpwp);
  147. if (!(lpwp->flags & SWP_NOMOVE)) {  // if moved:
  148. InvalidateOldPos(m_rcOldPos);  // invalidate area of old position
  149. // Now paint my non-client area at the new location.
  150. // Without this, you will still have a partial display bug (try it!)
  151. SendMessage(WM_NCPAINT);
  152. }
  153. }
  154. }
  155. //////////////////
  156. // Invalidate toolbar rectangle. Because flat toolbars are transparent,
  157. // this requires invalidating parent and all siblings that intersect the
  158. // rectangle.
  159. //
  160. void CFlatToolBar::InvalidateOldPos(const CRect& rcInvalid)
  161. {
  162. // make parent paint the area beneath rectangle
  163. CWnd* pParent = GetParent(); // parent (dock bar/frame) window
  164. ASSERT_VALID(pParent); // check
  165. CRect rc = rcInvalid; // copy rectangle
  166. pParent->ScreenToClient(&rc); // convert to parent client coords
  167. pParent->InvalidateRect(&rc); // invalidate
  168. // now do same for each sibling too
  169. for (CWnd* pSib = pParent->GetWindow(GW_CHILD);
  170.   pSib;
  171.   pSib=pSib->GetNextWindow(GW_HWNDNEXT)) {
  172. CRect rc; // window rect of sibling
  173. pSib->GetWindowRect(&rc); // ...
  174. if (rc.IntersectRect(rc, rcInvalid)) { // if intersects invalid rect
  175. pSib->ScreenToClient(&rc); // convert to sibling coords
  176. pSib->InvalidateRect(&rc); // invalidate
  177. pSib->SendMessage(WM_NCPAINT); // nonclient area too!
  178. }
  179. }
  180. }
  181. ////////////////
  182. // Override to avoid MFC in case I'm inside a coolbar
  183. //
  184. BOOL CFlatToolBar::OnEraseBkgnd(CDC* pDC)
  185. {
  186. return m_bInCoolBar ? Default() : CFlatToolBarBase::OnEraseBkgnd(pDC);
  187. }
  188. //////////////////
  189. // If toolbar is inside a coolbar, need to make the parent frame
  190. // my owner so it will get notifications.
  191. //
  192. BOOL CFlatToolBar::OnNcCreate(LPCREATESTRUCT lpcs)
  193. {
  194. CWnd* pParent = GetParent();
  195. ASSERT(pParent);
  196. TCHAR classname[64];
  197. GetClassName(pParent->m_hWnd, classname, countof(classname));
  198. if (_tcscmp(classname, REBARCLASSNAME)==0) {
  199. CFrameWnd* pFrame = GetParentFrame();
  200. ASSERT_VALID(pFrame);
  201. SetOwner(pFrame);
  202. m_bInCoolBar = TRUE;
  203. }
  204. return CFlatToolBarBase::OnNcCreate(lpcs);
  205. }
  206. //////////////////
  207. // Avoid MFC if I'm inside a coolbar
  208. //
  209. void CFlatToolBar::OnPaint()
  210. {
  211. if (m_bInCoolBar)
  212. Default(); // bypass CToolBar/CControlBar
  213. else
  214. CFlatToolBarBase::OnPaint();
  215. }
  216. ////////////////////////////////////////////////////////////////
  217. // Stuff for handling drop-down buttons in toobars
  218. //
  219. //////////////////
  220. // Add dropdown buttons.
  221. // The manager takes care of setting appropriate styles, etc.
  222. //
  223. // Args:
  224. // - array of LONGs: MAKELONG(commandID, menuID)
  225. // - number of buttons
  226. //
  227. BOOL CFlatToolBar::AddDropDownButton(UINT nIDButton, UINT nIDMenu, BOOL bArrow)
  228. {
  229. ASSERT_VALID(this);
  230. DROPDOWNBUTTON* pb = FindDropDownButton(nIDButton);
  231. if (!pb) {
  232. pb = new DROPDOWNBUTTON;
  233. ASSERT(pb);
  234. pb->next = m_pDropDownButtons;
  235. m_pDropDownButtons = pb;
  236. }
  237. pb->idButton = nIDButton;
  238. pb->idMenu   = nIDMenu;
  239. int iButton = CommandToIndex(nIDButton);
  240. DWORD dwStyle = GetButtonStyle(iButton);
  241. dwStyle |= TBSTYLE_DROPDOWN;
  242. SetButtonStyle(iButton, dwStyle);
  243. if (bArrow)
  244. SetExtendedStyle(TBSTYLE_EX_DRAWDDARROWS);
  245. return TRUE;
  246. }
  247. //////////////////
  248. // Find buttons structure for given ID
  249. //
  250. DROPDOWNBUTTON* CFlatToolBar::FindDropDownButton(UINT nID)
  251. {
  252. for (DROPDOWNBUTTON* pb = m_pDropDownButtons; pb; pb = pb->next) {
  253. if (pb->idButton == nID)
  254. return pb;
  255. }
  256. return NULL;
  257. }
  258. //////////////////
  259. // Handle TBN_DROPDOWN
  260. // Default is to display the specified menu at the right place.
  261. // You can override to generate dynamic menus
  262. //
  263. // Args:
  264. // - NMTOOLBAR struct from TBN_DROPDOWN
  265. // - command id of button
  266. // - point to display menu at
  267. //
  268. void CFlatToolBar::OnTbnDropDown(NMHDR* pNMHDR, LRESULT* pRes)
  269. {
  270. const NMTOOLBAR& nmtb = *(NMTOOLBAR*)pNMHDR;
  271. // get location of button
  272. CRect rc;
  273. GetRect(nmtb.iItem, rc);
  274. ClientToScreen(&rc);
  275. // call virtual function to display dropdown menu
  276. OnDropDownButton(nmtb, nmtb.iItem, rc);
  277. }
  278. /////////////////
  279. // Virtual fn you can override to hand drop-down button
  280. // events with more friendly args
  281. //
  282. void CFlatToolBar::OnDropDownButton(const NMTOOLBAR& nmtb, UINT nID, CRect rc)
  283. {
  284. DROPDOWNBUTTON* pb = FindDropDownButton(nmtb.iItem);
  285. if (pb && pb->idMenu) {
  286. // load and display popup menu
  287. CMenu menu;
  288. VERIFY(menu.LoadMenu(pb->idMenu));
  289. CMenu* pPopup = menu.GetSubMenu(0);
  290. ASSERT(pPopup);
  291. pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_VERTICAL,
  292. rc.left, rc.bottom, GetOwner(), &rc);
  293. }
  294. }