ToolBarEx.cpp
上传用户:lds876
上传日期:2013-05-25
资源大小:567k
文件大小:31k
源码类别:

P2P编程

开发平台:

Visual C++

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Copyright (C) 1997 by Joerg Koenig
  3. // All rights reserved
  4. //
  5. // Distribute freely, except: don't remove my name from the source or
  6. // documentation (don't take credit for my work), mark your changes (don't
  7. // get me blamed for your possible bugs), don't alter or remove this
  8. // notice.
  9. // No warrantee of any kind, express or implied, is included with this
  10. // software; use at your own risk, responsibility for damages (if any) to
  11. // anyone resulting from the use of this software rests entirely with the
  12. // user.
  13. //
  14. // Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  15. // I'll try to keep a version up to date.  I can be reached as follows:
  16. //    J.Koenig@adg.de                 (company site)
  17. //    Joerg.Koenig@rhein-neckar.de    (private site)
  18. /////////////////////////////////////////////////////////////////////////////
  19. // ToolBarEx.cpp : implementation file
  20. //
  21. // Description:
  22. // CToolBarEx provides additional features to the standard toolbar
  23. // "CToolBar". The main addition is the flat mode (last seen in
  24. // Developer Studio 5.0).
  25. // There are no special requirements for having the flat mode in your
  26. // application (no special comctl32.dll or what ever)!
  27. // If you need custom draw abilities, then you have to use VC++ >= 4.2
  28. // However, the flat mode should work with older versions of VC++ too (let
  29. // me know of your experiences!)
  30. //
  31. // Usage:
  32. // The only task you have to perform, is to
  33. // #include "ToolBarEx.h"
  34. // in either StdAfx.h or MainFrm.h and to change the type of
  35. // CMainFrame::m_wndToolBar from CToolBar to CToolBarEx.
  36. // Don't forget to recompile :-)
  37. //
  38. // Acknowledgements:
  39. // o The main idea of how to draw a separator and the gripper is stolen
  40. // from Roger Onslow's MSIE flat toolbar.
  41. // Thanks for saving my time, Roger ;-)
  42. // o The embossed drawing of a disabled image came from
  43. // Victor M. Vogelpoel (victorv@telic.nl)
  44. // o Some hints for buttons with text came from
  45. // David Bates (bates@econ.ubc.ca)
  46. // (I'm still thinking, text on toolbar-buttons is broken.
  47. // That has to be tooltip's work. However, texts on buttons
  48. // now work)
  49. // o Thanks to Patrick Liechty (patrickl@code3.code3.com) for
  50. // the reports of his experiences with VC++ 4.0/4.1
  51. // o Thanks to Jeng-Yuan Sheu (m8501511@chu.edu.tw) for the
  52. // enhanced checked button.
  53. // o Thanks to Todd C. Wilson (todd@mediatec.com) for his
  54. // bug report and code-enhancement for users of VC++ 4.2b
  55. //
  56. //
  57. // (known) bugs and limitations:
  58. // o the CDRF_NEWFONT notification is still untested ...
  59. // o Assigning texts to buttons may cause the buttons to
  60. // resize horizontally without notified by CToolBar. This
  61. // leads to a wrong calculation inside CalcDynamicLayout()
  62. // and CalcFixedLayout(). One could override both these
  63. // functions in derived classes to avoid that problem,
  64. // but that would be a greater pain ...
  65. // o some features of the toolbars seen in Office97/DevStudio
  66. // are not implemented (for instance text-only buttons or
  67. // the way how image+text buttons are displayed. The Alt-drag
  68. // feature too is unimplemented)
  69. //
  70. // if you find others (and have a solution for them ?!), please let me know:
  71. // Joerg.Koenig@rhein-neckar.de (private site) or
  72. // J.Koenig@adg.de (company site)
  73. //
  74. // Changes:
  75. // 11/25/97
  76. // o Some minor modifications to compile with VC++ 4.0/4.1 and 4.2b
  77. // o checked buttons now look hilighted (as in Office97/DevStudio)
  78. //
  79. // 11/07/97
  80. // (2 minor bugs have been occured as a result of the last update :)
  81. // o The WRAP state of a separator will be ignored now, if
  82. // the bar is docked vertically
  83. // o Draw an image transparently. This is needed only if one
  84. // uses 256 color images.
  85. //
  86. // 10/30/97
  87. // o texts on buttons now work
  88. // o gripper improved for a closer look like Office97
  89. // o disabled images now look embossed
  90. // o a separator is drawn only if it has no WRAP state set
  91. #include "stdafx.h"
  92. #include "ToolBarEx.h"
  93. #include "testBT.h"
  94. #ifdef _DEBUG
  95. #define new DEBUG_NEW
  96. #undef THIS_FILE
  97. static char THIS_FILE[] = __FILE__;
  98. #endif
  99. /////////////////////////////////////////////////////////////////////////////
  100. // local helper class CCustomDrawInfo
  101. //
  102. // The helper class CCustomDrawInfo handles the messaging to the docking
  103. // frame of the toolbar in flat mode only. If flat-mode is disabled, then
  104. // MFC's own messanger will be used.
  105. //
  106. // A few words about custom draw on toolbars:
  107. // o custom draw is possible for MFC >= 4.2 only (older versions don't know
  108. //   anything about certain structures ...)
  109. // o MFC does not set the "rc" member of NMCUSTOMDRAW to the rectangle of the
  110. //  button that will be drawn. However, we do, so watch out, wether the
  111. //  toolbar is flat or not (or ignore the "rc" member in both cases).
  112. //  If the current mode is not "flat", then MFC's art of message arrives ...
  113. // o MFC does not send a message for separators, so we too don't do it.
  114. // o It seems that MFC toolbars never send *ERASE notifications; instead they
  115. //   send TBN_QUERYDELETE for instance.
  116. // o The CDRF_NEWFONT notification result is ignored (in flat mode. Never
  117. //   tried with original MFC, because it is broken on toolbars).
  118. /////////////////////////////////////////////////////////////////////////////
  119. class CCustomDrawInfo {
  120. #if _MFC_VER >= 0x0420
  121. NMCUSTOMDRAW m_CDRW; // custom draw information holder
  122. LRESULT m_PrePaint; // result from prepaint notification
  123. LRESULT m_ItemPrePaint; // dito for specific item
  124. CToolBarEx * m_pToolBar; // the real sender of the notification
  125. CWnd * m_pReceiver; // the receiver of the notification
  126. LRESULT NotifyParent();
  127. #endif // _MFC_VER
  128. public: // construction
  129. CCustomDrawInfo( CDC & dc, CToolBarEx * pToolBar );
  130. public:
  131. // NotifyItemPrePaint() returns TRUE,
  132. // if the user wants to do the default
  133. // (CDRF_DODEFAULT) or FALSE, if the
  134. // user wants to skip (CDRF_SKIPDEFAULT)
  135. // Note that CDRF_SKIPDEFAULT is not
  136. // allowed for CDDS_PREPAINT, CDDS_POSTPAINT !
  137. // and CDDS_ITEMPOSTPAINT
  138. void NotifyPrePaint();
  139. BOOL NotifyItemPrePaint(int item);
  140. void NotifyItemPostPaint(int item);
  141. void NotifyPostPaint();
  142. };
  143. #if _MFC_VER >= 0x420
  144. LRESULT CCustomDrawInfo :: NotifyParent() {
  145. LRESULT lRes = CDRF_DODEFAULT;
  146. if( m_pReceiver )
  147. lRes = m_pReceiver->SendMessage(WM_NOTIFY,
  148. WPARAM(m_CDRW.hdr.idFrom),
  149. LPARAM(&m_CDRW));
  150. return lRes;
  151. }
  152. CCustomDrawInfo :: CCustomDrawInfo( CDC & dc, CToolBarEx * pBar )
  153. : m_PrePaint(0)
  154. , m_ItemPrePaint(0)
  155. {
  156. VERIFY((m_pToolBar = pBar) != 0);
  157. VERIFY((m_CDRW.hdc = dc.GetSafeHdc()) != 0);
  158. HWND hwnd = pBar->GetSafeHwnd();
  159. VERIFY(::IsWindow(hwnd));
  160. // initialise the NMHDR member of the customdraw structure
  161. m_CDRW.hdr.hwndFrom = hwnd;
  162. m_CDRW.hdr.idFrom = UINT(::GetWindowLong(hwnd, GWL_ID));
  163. m_CDRW.hdr.code = NM_CUSTOMDRAW;
  164. // Do not use CControlBar::GetDockingFrame() to receive
  165. // the parent. CWnd::GetParent() is inacceptable too.
  166. // Both these functions don't work, if the toolbar is
  167. // floating in the air!
  168. m_pReceiver = pBar->GetParentFrame();
  169. if( m_pReceiver )
  170. VERIFY(::IsWindow(m_pReceiver->GetSafeHwnd()));
  171. }
  172. void CCustomDrawInfo :: NotifyPrePaint() {
  173. // fill the customdraw structure with values for CDDS_PREPAINT
  174. m_CDRW.dwDrawStage = CDDS_PREPAINT;
  175. // the rest of the structure stays undefined in this stage
  176. // of drawing.
  177. m_PrePaint = NotifyParent();
  178. }
  179. BOOL CCustomDrawInfo :: NotifyItemPrePaint( int nItem ) {
  180. BOOL bRet = TRUE; // we assume to do the default
  181. if( m_PrePaint & CDRF_NOTIFYITEMDRAW ) {
  182. m_CDRW.dwDrawStage = CDDS_ITEMPREPAINT;
  183. m_pToolBar->GetItemRect(nItem, &m_CDRW.rc);
  184. m_CDRW.dwItemSpec = DWORD(m_pToolBar->GetItemID(nItem));
  185. UINT uStyle = m_pToolBar->GetButtonStyle(nItem);
  186. BOOL bEnable = m_pToolBar->GetToolBarCtrl()
  187. .IsButtonEnabled(m_CDRW.dwItemSpec);
  188. m_CDRW.uItemState = (bEnable ? 0 : CDIS_DISABLED) |
  189. (((uStyle & TBBS_PRESSED) || (uStyle & TBBS_CHECKED)) ?
  190. CDIS_CHECKED : 0);
  191. m_CDRW.lItemlParam = 0;
  192. m_ItemPrePaint = NotifyParent();
  193. if( m_ItemPrePaint & CDRF_SKIPDEFAULT )
  194. bRet = FALSE;
  195. }
  196. return bRet;
  197. }
  198. void CCustomDrawInfo :: NotifyItemPostPaint( int nItem ) {
  199. if( m_ItemPrePaint & CDRF_NOTIFYPOSTPAINT ) {
  200. m_CDRW.dwDrawStage = CDDS_ITEMPOSTPAINT;
  201. // the rest of the data has not been changed since ITEMPREPAINT
  202. // make sure it is so:
  203. ASSERT(m_pToolBar->GetItemID(nItem) == m_CDRW.dwItemSpec);
  204. NotifyParent();
  205. }
  206. }
  207. void CCustomDrawInfo :: NotifyPostPaint() {
  208. if( m_PrePaint & CDRF_NOTIFYPOSTPAINT ) {
  209. m_CDRW.dwDrawStage = CDDS_POSTPAINT;
  210. NotifyParent();
  211. }
  212. }
  213. #else // _MFC_VER < 4.2
  214. CCustomDrawInfo :: CCustomDrawInfo( CDC & dc, CToolBarEx * pParent ) {
  215. }
  216. void CCustomDrawInfo :: NotifyPrePaint() {
  217. }
  218. void CCustomDrawInfo :: NotifyPostPaint() {
  219. }
  220. BOOL CCustomDrawInfo :: NotifyItemPrePaint( int ) {
  221. return TRUE; // we always make the drawing by ourself
  222. }
  223. void CCustomDrawInfo :: NotifyItemPostPaint( int ) {
  224. }
  225. #endif // _MFC_VER
  226. /////////////////////////////////////////////////////////////////////////////
  227. // CToolBarEx
  228. CToolBarEx::CToolBarEx()
  229. : m_bFlatLook(TRUE)
  230. , m_clrBtnFace(::GetSysColor(COLOR_BTNFACE))
  231. , m_clrBtnHilight(::GetSysColor(COLOR_BTNHILIGHT))
  232. , m_clrBtnShadow(::GetSysColor(COLOR_BTNSHADOW))
  233. , m_clrBtnLight(::GetSysColor(COLOR_3DLIGHT))
  234. , m_nLastBtn(-1)
  235. , m_uTimerEvent(0)
  236. {
  237. // the systems I've tested, made no difference between
  238. // COLOR_BTNFACE and COLOR_3DLIGHT ...
  239. if( m_clrBtnFace == m_clrBtnLight )
  240. m_clrBtnLight = m_clrBtnHilight;
  241. CalculateOffset();
  242. // create the default font, used for buttons with text
  243. CFont Font;
  244. BOOL bOldSys = FALSE;
  245. if( ! Font.CreateStockObject( DEFAULT_GUI_FONT ) ) {
  246. // older versions of Windows* (NT 3.51 for instance)
  247. // fail with DEFAULT_GUI_FONT
  248. VERIFY( Font.CreateStockObject( SYSTEM_FONT ) );
  249. bOldSys = TRUE;
  250. }
  251. LOGFONT logfont ;
  252. Font.GetLogFont( &logfont ) ;
  253. if( bOldSys ) {
  254. logfont.lfWeight = 400;
  255. strcpy(logfont.lfFaceName,"MS Sans Serif");
  256. }
  257. logfont.lfHeight = 6 ;
  258. logfont.lfWidth = 0 ; // let windows compute this.
  259. VERIFY( m_GuiFont.CreateFontIndirect( &logfont ) ) ;
  260. m_bTracking = false;
  261. m_bMouseLeave = false;
  262. }
  263. CToolBarEx::~CToolBarEx()
  264. {
  265. }
  266. IMPLEMENT_DYNAMIC(CToolBarEx, CToolBar)
  267. BEGIN_MESSAGE_MAP(CToolBarEx, CDkToolBar)
  268. //{{AFX_MSG_MAP(CToolBarEx)
  269. ON_WM_PAINT()
  270. ON_WM_SYSCOLORCHANGE()
  271. ON_WM_NCCALCSIZE()
  272. ON_WM_MOUSEMOVE()
  273. ON_WM_NCPAINT()
  274. ON_WM_CREATE()
  275. ON_WM_ERASEBKGND()
  276. //}}AFX_MSG_MAP
  277. ON_WM_RBUTTONDOWN()
  278. ON_MESSAGE(TB_SETBUTTONSIZE, OnSetButtonSize)
  279. ON_MESSAGE(TB_SETBITMAPSIZE, OnSetBitmapSize)
  280. ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
  281. END_MESSAGE_MAP()
  282. /////////////////////////////////////////////////////////////////////////////
  283. // CToolBarEx message handlers
  284. void CToolBarEx::OnRButtonDown(UINT nFlags, CPoint point) 
  285. {
  286. // CToolBar::OnRButtonDown(nFlags, point);
  287. }
  288. LRESULT CToolBarEx :: OnSetButtonSize(WPARAM wParam, LPARAM lParam) 
  289. {
  290. LRESULT lResult = CDkToolBar::OnSetButtonSize(wParam, lParam);
  291. if( lResult )
  292. CalculateOffset();
  293. return lResult;
  294. }
  295. LRESULT CToolBarEx :: OnSetBitmapSize(WPARAM wParam, LPARAM lParam) 
  296. {
  297. LRESULT lResult = CDkToolBar::OnSetBitmapSize(wParam, lParam);
  298. if( lResult )
  299. CalculateOffset();
  300. return lResult;
  301. }
  302. void CToolBarEx::OnPaint() 
  303. {
  304. // DbgGuiLeak dbgGui;
  305. // HIMAGELIST hImg = GetImageList(TB_GETIMAGELIST);
  306. /*
  307. #ifdef _DEBUG
  308. if( hImg == 0 ) {
  309. TRACE0("CToolBarEx::OnPaint(): could not get image listn");
  310. }
  311. #endif
  312. //*/
  313. if( m_bFlatLook) 
  314. {
  315. CRect rcUpdate;
  316. if( ! GetUpdateRect(rcUpdate) )
  317. return;
  318. if( HasButtonText() )
  319. CalculateOffset(); // strings may have been added
  320. // attach image-list for even more MFC feeling :)
  321. CImageList& imglist = *GetToolBarCtrl().GetImageList();
  322. CImageList& imglistHot = *GetToolBarCtrl().GetHotImageList();
  323. CImageList& imglistDisable = *GetToolBarCtrl().GetDisabledImageList();
  324. POINT cursor;
  325. ::GetCursorPos(&cursor);
  326. ScreenToClient(&cursor);
  327. CPaintDC dc(this); // device context for painting
  328. CFont * pOldFont = dc.SelectObject(&m_GuiFont);
  329. // Now it's time for the first custom-draw-notification...
  330. CCustomDrawInfo cdrw(dc, this);
  331. cdrw.NotifyPrePaint();
  332. bool bMouseLeavePaint = false;
  333. register const int nBtn = GetToolBarCtrl().GetButtonCount();
  334. for( register int i = 0; i < nBtn; ++i ) 
  335. {
  336. CRect rc;
  337. GetItemRect(i, rc);
  338. int nBitmap; UINT uID, uStyleState;
  339. GetButtonInfo(i, uID, uStyleState, nBitmap);
  340. WORD wStyle = LOWORD(uStyleState);
  341. WORD wState = HIWORD(uStyleState);
  342. if( wState & TBSTATE_HIDDEN )
  343. continue;
  344. if( wStyle == TBSTYLE_SEP ) 
  345. {
  346. if( !(wState & TBSTATE_WRAP) || ! IsFloating() )
  347. {
  348. DrawSeparator(dc, rc);
  349. }
  350. }
  351. else 
  352. {
  353. if( ! CRect().IntersectRect(rcUpdate, rc) )
  354. continue; // this button needs no repaint
  355. BOOL bBtnDown = (wState & TBSTATE_CHECKED) || (wState & TBSTATE_PRESSED);
  356. BOOL bBtnEnabled = GetToolBarCtrl().IsButtonEnabled(int(uID));
  357. BOOL bHasCursor = rc.PtInRect(cursor);
  358. COLORREF clrRect = (bBtnDown && !bHasCursor) ? m_clrBtnLight : m_clrBtnFace;
  359. // maybe the button has text
  360. dc.SetTextColor(RGB(0,0,0));
  361. dc.SetBkColor(clrRect);
  362. // There is a bug in CToolBar: If there are texts assigned
  363. // to buttons, then the button-widths may change transparently
  364. // (without notified by CToolBar), so we recalculate the
  365. // horizontal offset here:
  366. m_sizeOffset.cx = (rc.Width() - m_sizeImage.cx) / 2;
  367. if( ! cdrw.NotifyItemPrePaint(i) )
  368. continue; // parent has already drawn the button
  369. bMouseLeavePaint = true;
  370. // dc.FillSolidRect(rc, clrRect);
  371. //CBrush brush(clrRect);
  372. //dc.FillRect(rc, &brush);
  373. // it seems, that CDC::Draw3dRect() changes the background color
  374. COLORREF clrBk = dc.GetBkColor();
  375. if( bBtnDown ) 
  376. {
  377. // draw a pressed button
  378. /*
  379. dc.Draw3dRect(rc, m_clrBtnShadow, m_clrBtnHilight);
  380. if( ! bHasCursor ) 
  381. {
  382. // draw an invisible frame around the hilighted area
  383. CRect rcCheck = rc;
  384. rcCheck.DeflateRect(1,1);
  385. dc.Draw3dRect(rcCheck, m_clrBtnFace, m_clrBtnFace);
  386. }
  387. //*/
  388. }
  389. else if( bHasCursor && ! bBtnDown && bBtnEnabled )
  390. {
  391. // draw a normal button
  392. // dc.Draw3dRect(rc, RGB(0, 255, 0), RGB(0, 255, 0));
  393. // dc.Draw3dRect(rc, m_clrBtnHilight, m_clrBtnShadow);
  394. }
  395. else if( ! bBtnDown && bBtnEnabled )
  396. // Draw an invisible rect around the button.
  397. // This prevents us from erasing the background
  398. // if the button was formed before
  399. // (that would cause the button to flicker ...)
  400. {
  401. // dc.Draw3dRect(rc, m_clrBtnFace, m_clrBtnFace);
  402. /*
  403. CBrush brush;
  404. brush.CreatePatternBrush(&m_bkBmp);
  405. dc.FillRect(rc, &brush);
  406. //*/
  407. }
  408. dc.SetBkColor(clrBk);
  409. // the point where to start with the image
  410. //CPoint pt(rc.left + m_sizeOffset.cx + bBtnDown,
  411. //   rc.top + m_sizeOffset.cy + bBtnDown);
  412. CPoint pt(rc.left + bBtnDown, rc.top + bBtnDown);
  413. pt.Offset(4, 4);
  414. if(!bBtnEnabled)
  415. {
  416. if (&imglistDisable)
  417. imglistDisable.Draw(&dc, nBitmap, pt, ILD_TRANSPARENT);
  418. else
  419. {
  420. imglist.Draw(&dc, nBitmap, pt, ILD_TRANSPARENT);
  421. // DrawDisabledButton(dc, rc);
  422. }
  423. }
  424. else if (bHasCursor && !m_bMouseLeave)
  425. {
  426. if (&imglistHot)
  427. {
  428. CRect rcItem = rc;
  429. DrawFace(RGB(255, 212, 139), RGB(255, 174, 86), rcItem, rcItem, &dc);
  430. DrawFrame(RGB(100, 100, 100), RGB(100, 100, 100), RGB(100, 100, 100), rcItem , &dc);
  431. imglistHot.Draw(&dc, nBitmap, pt, ILD_TRANSPARENT);
  432. }
  433. }
  434. else
  435. {
  436. if (&imglist)
  437. imglist.Draw(&dc, nBitmap, pt, ILD_TRANSPARENT);
  438. }
  439. CString strText = GetButtonText(i);
  440. if( strText.GetLength() ) 
  441. {
  442. CRect rectText(
  443. rc.left+3+bBtnDown,
  444. rc.top+m_sizeOffset.cy+m_sizeImage.cy+1+bBtnDown,
  445. rc.right-3+bBtnDown,
  446. rc.bottom-3+bBtnDown
  447. );
  448. dc.DrawText(strText, rectText, DT_CENTER|DT_VCENTER|DT_NOCLIP);
  449. }
  450. /*
  451. if( ! bBtnEnabled )
  452. // gray out that button
  453. DrawDisabledButton(dc, rc);
  454. //*/
  455. cdrw.NotifyItemPostPaint(i);
  456. }
  457. }
  458. dc.SelectObject(pOldFont);
  459. if( ! m_bDeleteImgList )
  460. {
  461. imglist.Detach();
  462. imglistHot.Detach();
  463. imglistDisable.Detach();
  464. }
  465. // last but not least: inform the parent for end of painting
  466. cdrw.NotifyPostPaint();
  467. if (m_bMouseLeave)
  468. TRACE("rb****on paint(%d, %d, %d)rn", cursor.x, cursor.y, bMouseLeavePaint);
  469. else
  470. {
  471. // classic mode (or couldn't receive imagelist)
  472. CDkToolBar::OnPaint();
  473. }
  474. if (m_bMouseLeave)
  475. m_bMouseLeave = false;
  476. }
  477. void CToolBarEx :: DrawDisabledButton( CDC & dc, const CRect & rc ) const {
  478. // create a monochrome memory DC
  479. CDC ddc;
  480. ddc.CreateCompatibleDC(0);
  481. CBitmap bmp;
  482. bmp.CreateCompatibleBitmap(&ddc, rc.Width(), rc.Height());
  483. CBitmap * pOldBmp = ddc.SelectObject(&bmp);
  484. // build a mask
  485. ddc.PatBlt(0, 0, rc.Width(), rc.Height(), WHITENESS);
  486. dc.SetBkColor(m_clrBtnFace);
  487. ddc.BitBlt(0, 0, rc.Width(), rc.Height(), &dc, rc.left, rc.top, SRCCOPY);
  488. dc.SetBkColor(m_clrBtnHilight);
  489. ddc.BitBlt(0, 0, rc.Width(), rc.Height(), &dc, rc.left, rc.top, SRCPAINT);
  490. // Copy the image from the toolbar into the memory DC
  491. // and draw it (grayed) back into the toolbar.
  492. dc.FillSolidRect(rc.left, rc.top, rc.Width(), rc.Height(), m_clrBtnFace);
  493. dc.SetBkColor(RGB(0, 0, 0));
  494. dc.SetTextColor(RGB(255, 255, 255));
  495. CBrush brShadow, brHilight;
  496. brHilight.CreateSolidBrush(m_clrBtnHilight);
  497. brShadow.CreateSolidBrush(m_clrBtnShadow);
  498. CBrush * pOldBrush = dc.SelectObject(&brHilight);
  499. dc.BitBlt(rc.left+1, rc.top+1, rc.Width(), rc.Height(), &ddc, 0, 0, 0x00E20746L);
  500. dc.SelectObject(&brShadow);
  501. dc.BitBlt(rc.left, rc.top, rc.Width(), rc.Height(), &ddc, 0, 0, 0x00E20746L);
  502. // reset DCs
  503. dc.SelectObject(pOldBrush);
  504. ddc.SelectObject(pOldBmp);
  505. ddc.DeleteDC();
  506. bmp.DeleteObject();
  507. }
  508. void CToolBarEx :: DrawSeparator( CDC & dc, CRect & rc ) const 
  509. {
  510.     BOOL bHorz = ((m_dwStyle & CBRS_ORIENT_HORZ) != 0) ? TRUE : FALSE;
  511. // make sure, this separator is not a placeholder for
  512. // another control.
  513. if( rc.Width() <= 8 ) 
  514. {
  515. {
  516. /*
  517. CDC memdc;
  518. memdc.CreateCompatibleDC(&dc);
  519. CBitmap* pold = memdc.SelectObject((CBitmap*)&m_bmpBack);
  520. BOOL bRet = dc.BitBlt(rc.left, rc.top, rc.Width(), rc.Height(), &memdc, 0, 0, SRCCOPY);
  521. ASSERT(bRet);
  522. memdc.SelectObject(pold);
  523. //*/
  524. }
  525. if( bHorz ) 
  526. {
  527. // draw the separator bar in the middle
  528. int x = (rc.left + rc.right) / 2;
  529. rc.left = x-1; rc.right = x+1;
  530. dc.Draw3dRect(
  531. rc,
  532. m_clrBtnShadow,
  533. m_clrBtnHilight
  534. );
  535. }
  536. else 
  537. {
  538. // draw the separator bar in the middle
  539. rc.left = rc.left - m_sizeButton.cx;
  540. rc.right = rc.left + m_sizeButton.cx;
  541. rc.top = rc.bottom+1;
  542. rc.bottom = rc.top+3;
  543. int y = (rc.top+rc.bottom)/2;
  544. rc.top = y-1; rc.bottom = y+1;
  545. dc.Draw3dRect(
  546. rc,
  547. m_clrBtnShadow,
  548. m_clrBtnHilight
  549. );
  550. }
  551. }
  552. }
  553. void CToolBarEx :: DrawGripper( CDC & dc ) const 
  554.     if( m_dwStyle & CBRS_FLOATING )
  555. return; // no gripper if floating
  556. CRect gripper;
  557. GetWindowRect(gripper);
  558. ScreenToClient(gripper);
  559. gripper.OffsetRect(-gripper.left, -gripper.top);
  560. if( m_dwStyle & CBRS_ORIENT_HORZ ) {
  561. // gripper at left
  562. gripper.DeflateRect(4, 4);
  563. gripper.right = gripper.left+3;
  564.         dc.Draw3dRect(
  565. gripper,
  566. m_clrBtnHilight,
  567.             m_clrBtnShadow
  568. );
  569. gripper.OffsetRect(3, 0);
  570.         dc.Draw3dRect(
  571. gripper,
  572. m_clrBtnHilight,
  573.             m_clrBtnShadow
  574. );
  575. } else {
  576. // gripper at top
  577. gripper.DeflateRect(4, 4);
  578. gripper.bottom = gripper.top+3;
  579. dc.Draw3dRect(
  580. gripper,
  581. m_clrBtnHilight,
  582.             m_clrBtnShadow
  583. );
  584. gripper.OffsetRect(0, 3);
  585.         dc.Draw3dRect(
  586. gripper,
  587. m_clrBtnHilight,
  588.             m_clrBtnShadow
  589. );
  590. }
  591. }
  592. void CToolBarEx :: OnUpdateCmdUI( CFrameWnd* pTarget, BOOL bDisableIfNoHndler ) {
  593. if( m_bFlatLook ) {
  594. // save current styles
  595. register const int nBtn = GetToolBarCtrl().GetButtonCount();
  596. register int nIdx;
  597. for( nIdx = 0; nIdx < nBtn; ++nIdx )
  598. m_Styles.SetAtGrow(nIdx, GetButtonStyle(nIdx));
  599. // do base class processing
  600. CDkToolBar::OnUpdateCmdUI(pTarget,bDisableIfNoHndler);
  601. //check wether styles have been changed
  602. for( nIdx = 0; nIdx < nBtn; ++nIdx ) {
  603. if( m_Styles[nIdx] != GetButtonStyle(nIdx) ) {
  604. // invalidate that button
  605. CRect rc;
  606. GetItemRect(nIdx, rc);
  607. InvalidateRect(rc);
  608. }
  609. }
  610. } else
  611. // simply delegate
  612. CDkToolBar::OnUpdateCmdUI(pTarget,bDisableIfNoHndler);
  613. }
  614. void CToolBarEx::OnSysColorChange() 
  615. {
  616. CDkToolBar::OnSysColorChange();
  617. m_clrBtnFace    = ::GetSysColor(COLOR_BTNFACE);
  618. m_clrBtnHilight = ::GetSysColor(COLOR_BTNHILIGHT);
  619. m_clrBtnShadow  = ::GetSysColor(COLOR_BTNSHADOW);
  620. m_clrBtnLight   = ::GetSysColor(COLOR_3DLIGHT);
  621. if( m_clrBtnFace == m_clrBtnLight )
  622. m_clrBtnLight = m_clrBtnHilight;
  623. }
  624. void CToolBarEx::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp) 
  625. {
  626. CDkToolBar::OnNcCalcSize(bCalcValidRects, lpncsp);
  627. return;
  628. // adjust non-client area for gripper at left or top
  629. if( m_dwStyle & CBRS_ORIENT_HORZ ) 
  630. {
  631. lpncsp->rgrc[0].left += 4;
  632. lpncsp->rgrc[0].right += 4;
  633. } else {
  634. lpncsp->rgrc[0].top += 6;
  635. lpncsp->rgrc[0].bottom += 6;
  636. }
  637. }
  638. void CToolBarEx::OnMouseMove(UINT nFlags, CPoint point) 
  639. {
  640. if (!m_bTracking)
  641. {
  642. TRACKMOUSEEVENT tme;
  643. tme.cbSize = sizeof(tme);
  644. tme.hwndTrack = GetSafeHwnd();
  645. tme.dwFlags = TME_LEAVE;
  646. tme.dwHoverTime = HOVER_DEFAULT;
  647. m_bTracking = _TrackMouseEvent(&tme);
  648. }
  649. if( m_bFlatLook ) 
  650. {
  651. register const int nBtn = GetToolBarCtrl().GetButtonCount();
  652. const int nLastBtn = m_nLastBtn;
  653. m_nLastBtn = -1;
  654. for( register int i = 0 ; i < nBtn ; ++i ) 
  655. {
  656. CRect rc;
  657. GetItemRect(i, rc);
  658. const BOOL bBtnEnabled = GetToolBarCtrl().IsButtonEnabled(int(GetItemID(i)));
  659. const BOOL bSep = GetButtonStyle(i) & TBBS_SEPARATOR;
  660. if( bSep || ! bBtnEnabled )
  661. continue;
  662. const BOOL bHasCursor = rc.PtInRect(point);
  663. if( bHasCursor && bBtnEnabled ) 
  664. {
  665. if( nLastBtn != i ) 
  666. {
  667. // force a repaint of the button with the cursor on it
  668. InvalidateRect(rc, FALSE);
  669. }
  670. m_nLastBtn = i;
  671. }
  672. else if( !bHasCursor && i == nLastBtn ) 
  673. {
  674. // force a repaint of the last formed button
  675. InvalidateRect(rc, FALSE);
  676. }
  677. }
  678. // One problem occures with WM_MOUSEMOVE: we cannot detect
  679. // that the mouse leaves the window. If the mouse moves quick
  680. // enough, then the last formed button stays visible. To
  681. // resolve this problem, we set a timer and check, wether
  682. // the mouse is outside the window ...
  683. // KillTimer(m_uTimerEvent);
  684. // m_uTimerEvent = SetTimer(1, 250, 0);
  685. }
  686. CDkToolBar::OnMouseMove(nFlags, point);
  687. }
  688. LRESULT CToolBarEx::OnMouseLeave(WPARAM wParam, LPARAM lParam)
  689. {
  690. m_bTracking = false;
  691. if (m_nLastBtn >= 0)
  692. {
  693. m_bMouseLeave = true;
  694. CRect rc;
  695. GetItemRect(m_nLastBtn, rc);
  696. InvalidateRect(rc, TRUE);
  697. m_nLastBtn = -1;
  698. /*
  699. POINT pt;
  700. ::GetCursorPos(&pt);
  701. ScreenToClient(&pt);
  702. TRACE("rb****mouse leave(%d, %d)rn", pt.x, pt.y);
  703. //*/
  704. }
  705. else
  706. {
  707. /*
  708. CRect rc;
  709. GetClientRect(rc);
  710. // InvalidateRect(rc, TRUE);
  711. TRACE("rb****mouse leave(%d, %d)rn", 12, 12);
  712. //*/
  713. }
  714. return 0;
  715. }
  716. void CToolBarEx::OnNcPaint() 
  717. {
  718. // DbgGuiLeak dbgGui;
  719. if( m_bFlatLook ) 
  720. {
  721. CDkToolBar::EraseNonClient();
  722. CWindowDC dc(this);
  723. // DrawGripper(dc);
  724. /*
  725. CRect rc;
  726. GetWindowRect(rc);
  727. ScreenToClient(rc);
  728. rc.OffsetRect(-rc.left, -rc.top);
  729. CDC memdc;
  730. memdc.CreateCompatibleDC(&dc);
  731. CBitmap bmptemp;
  732. bmptemp.CreateCompatibleBitmap(&memdc, rc.right - rc.left, rc.bottom - rc.top);
  733. CBitmap* pold = memdc.SelectObject(&bmptemp);
  734. CRect temprc = rc;
  735. temprc.OffsetRect(-temprc.left, -temprc.top);
  736. DrawFace(RGB(255, 255, 255), RGB(0, 0, 0), temprc, temprc, &memdc);
  737. memdc.FillRect(temprc, &CBrush(RGB(233, 233, 233)));
  738. BOOL bRet = dc.BitBlt(rc.left, rc.top, rc.Width(), rc.Height(), &memdc, 0, 0, SRCCOPY);
  739. ASSERT(bRet);
  740. memdc.SelectObject(pold);
  741. //*/
  742. /*
  743. CDC memdc;
  744. memdc.CreateCompatibleDC(&dc);
  745. CBitmap* pold = memdc.SelectObject(&m_bmpBack);
  746. BOOL bRet = dc.BitBlt(rc.left, rc.top, rc.Width(), rc.Height(), &memdc, 0, 0, SRCCOPY);
  747. ASSERT(bRet);
  748. memdc.SelectObject(pold);
  749. //*/
  750. else
  751. CDkToolBar::OnNcPaint();
  752. }
  753. /*
  754. void CToolBarEx::OnTimer(UINT nIDEvent) 
  755. {
  756. if( nIDEvent == m_uTimerEvent && m_nLastBtn >= 0 ) {
  757. POINT pt;
  758. ::GetCursorPos(&pt);
  759. CRect rc;
  760. GetWindowRect(rc);
  761. if( ! rc.PtInRect(pt) ) {
  762. GetItemRect(m_nLastBtn, rc);
  763. InvalidateRect(rc, FALSE);
  764. m_nLastBtn = -1;
  765. KillTimer(nIDEvent);
  766. }
  767. } else
  768. CDkToolBar::OnTimer(nIDEvent);
  769. }
  770. //*/
  771. int CToolBarEx::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  772. {
  773. if (CDkToolBar::OnCreate(lpCreateStruct) == -1)
  774. return -1;
  775. // Save the parent at creation time. It may change, if
  776. // the toolbar is floating; but we want to know of the
  777. // "real" parent (for notification messages)!
  778. m_hwndParent = lpCreateStruct->hwndParent;
  779. int iRet = m_bmpBack.LoadBitmap(IDB_BITMAP_REBAR_BK);
  780. ASSERT(iRet);
  781. // LoadBitmap(::AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP_REBAR_BK));
  782. return 0;
  783. }
  784. #define PADWIDTH(x) (((x)*8+31)&~31)/8
  785. HIMAGELIST CToolBarEx :: GetImageList(UINT nImageType) 
  786. {
  787. m_bDeleteImgList = FALSE;
  788. HIMAGELIST hImg = 0;
  789. #ifdef TB_GETIMAGELIST
  790. // Some older versions of VC++ do not know of
  791. // the TB_GETIMAGELIST macro (defined in commctrl.h).
  792. hImg = HIMAGELIST(SendMessage(nImageType));
  793. #ifdef _DEBUG
  794. if( hImg == 0 ) {
  795. TRACE0("CToolBarEx::OnPaint(): could not get image listn");
  796. }
  797. #endif
  798. #endif // TB_GETIMAGELIST
  799. if( ! hImg ) 
  800. {
  801. // comctl32.dll version prior to 4.70 doesn't know
  802. // anything of the TB_GETIMAGELIST message
  803. if( m_hbmImageWell != 0 ) 
  804. {
  805. // Yup - we have a valid image.
  806. // But beware: Do not use this bitmap directly.
  807. // We make the copy by ourself. CopyImage() (for
  808. // instace) produces inacceptable copies under
  809. // some circumstances ...
  810. CImageList imglist;
  811. CBitmap bmp;
  812. // retrieve the size of the bitmap
  813. BITMAP bmHdr;
  814. ::GetObject(m_hbmImageWell, sizeof(BITMAP), &bmHdr);
  815. DWORD dwWidth, dwHeight = bmHdr.bmHeight;
  816. if (bmHdr.bmBitsPixel > 8)
  817. dwWidth = PADWIDTH(bmHdr.bmWidth * 3);
  818. else
  819. dwWidth = PADWIDTH(bmHdr.bmWidth);
  820. // copy the bitmap
  821. CClientDC cdc(this);
  822. CDC dc1, dc2;
  823. dc1.CreateCompatibleDC(&cdc);
  824. dc2.CreateCompatibleDC(&cdc);
  825. bmp.CreateCompatibleBitmap(&cdc, dwWidth, dwHeight);
  826. CBitmap * pOBmp = dc1.SelectObject(&bmp);
  827. HGDIOBJ hOObj = ::SelectObject(dc2.GetSafeHdc(), m_hbmImageWell);
  828. dc1.BitBlt(0,0,dwWidth,dwHeight,&dc2,0,0,SRCCOPY);
  829. ::SelectObject(dc2.GetSafeHdc(), hOObj);
  830. dc1.SelectObject(pOBmp);
  831. dc1.DeleteDC();
  832. dc2.DeleteDC();
  833. imglist.Create(m_sizeImage.cx, m_sizeImage.cy,TRUE,dwWidth/m_sizeImage.cx,1);
  834. imglist.SetBkColor(m_clrBtnFace);
  835. imglist.Add(&bmp,m_clrBtnFace);
  836. hImg = imglist.Detach();
  837. bmp.DeleteObject();
  838. m_bDeleteImgList = TRUE;
  839. }
  840. }
  841. return hImg;
  842. }
  843. void CToolBarEx::DrawFace(COLORREF Top, COLORREF Bottom, CRect& rc, CRect CalRc, CDC* pDC)
  844. {
  845. if (!CalRc.Height())
  846. return;
  847. int R, G, B;
  848. R = (GetRValue(Top) - GetRValue(Bottom)) / CalRc.Height();
  849. G = (GetGValue(Top) - GetGValue(Bottom)) / CalRc.Height();
  850. B = (GetBValue(Top) - GetBValue(Bottom)) / CalRc.Height();
  851. int ColR = GetRValue(Top), ColG = GetGValue(Top), ColB = GetBValue(Top);
  852. COLORREF ColMax = Top > Bottom ? Top : Bottom;
  853. COLORREF ColMin = Top > Bottom ? Bottom: Top;
  854. for(int i=0; i<rc.Height(); i++)
  855. {
  856. ColR -= R;
  857. ColG -= G;
  858. ColB -= B;
  859. CPen Pen;
  860. Pen.CreatePen(PS_SOLID, 1, RGB(ColR, ColG, ColB));
  861. CPen* pOldPen = pDC->SelectObject(&Pen);
  862. // pDC->SelectObject(&Pen);
  863. pDC->MoveTo(rc.left, rc.top+i);
  864. pDC->LineTo(rc.right, rc.top+i);
  865. pDC->SelectObject(pOldPen);
  866. Pen.DeleteObject();
  867. }
  868. }
  869. void CToolBarEx::DrawFrame(COLORREF HeightLight, COLORREF ShadowLight, COLORREF FrameColor, CRect& rc, CDC* pDC)
  870. {
  871. CBrush NullBrush;
  872. NullBrush.CreateStockObject(NULL_BRUSH);
  873. CBrush* pOldBrush = pDC->SelectObject(&NullBrush);
  874. CPen Pen;
  875. Pen.CreatePen(PS_SOLID, 1, FrameColor);
  876. CPen* pOldPen = pDC->SelectObject(&Pen);
  877. pDC->RoundRect(rc, CPoint(3, 3));
  878. // rc.DeflateRect(1, 1, 1, 1); 
  879. // pDC->Draw3dRect(rc, HeightLight, ShadowLight);
  880. pDC->SelectObject(pOldPen);
  881. pDC->SelectObject(pOldBrush);
  882. }
  883. BOOL CToolBarEx::OnEraseBkgnd(CDC* pDC) 
  884. {
  885. // DbgGuiLeak dbgGui;
  886. CRect rc;
  887. pDC->GetClipBox(rc);
  888. if (rc.right < 0 || rc.bottom < 0)
  889. {
  890. ASSERT(FALSE);
  891. return FALSE;
  892. }
  893. CDC memdc, memdcbmp;
  894. BOOL bRet = memdc.CreateCompatibleDC(pDC);
  895. if (!bRet)
  896. {
  897. DWORD dwErr = GetLastError();
  898. ASSERT(false);
  899. return FALSE;
  900. }
  901. CBitmap bmptemp;
  902. bRet = bmptemp.CreateCompatibleBitmap(pDC, rc.right, rc.bottom);
  903. if (!bRet)
  904. {
  905. DWORD dwErr = GetLastError();
  906. ASSERT(false);
  907. return FALSE;
  908. }
  909. CBitmap* pold = memdc.SelectObject(&bmptemp);
  910. bRet = memdcbmp.CreateCompatibleDC(&memdc);
  911. if (!bRet)
  912. {
  913. DWORD dwErr = GetLastError();
  914. ASSERT(false);
  915. return FALSE;
  916. }
  917. CBitmap* pOldBmp = memdcbmp.SelectObject(&m_bmpBack);
  918. // CRect rctemp = rc;
  919. // rctemp.left = rctemp.top = 0;
  920. // DrawFace(RGB(243, 243, 241), RGB(217, 214, 217), rctemp, rctemp, &memdc);
  921. // memdc.FillRect(temprc, &CBrush(RGB(255, 0, 0)));
  922. for (int i=0; i<(rc.Width()/50 + 1); i++)
  923. {
  924. memdc.BitBlt(rc.left + i*50, rc.top, 100, rc.Height(), &memdcbmp, 0, rc.top, SRCCOPY);
  925. }
  926. memdcbmp.SelectObject(pOldBmp);
  927. bRet = memdcbmp.DeleteDC();
  928. ASSERT(bRet);
  929. bRet = pDC->BitBlt(rc.left, rc.top, rc.Width(), rc.Height(), &memdc, rc.left, rc.top, SRCCOPY);
  930. ASSERT(bRet);
  931. bRet = bmptemp.DeleteObject();
  932. ASSERT(bRet);
  933. memdc.SelectObject(pold);
  934. bRet = memdc.DeleteDC();
  935. ASSERT(bRet);
  936. #ifdef _DEBUG
  937. CString strText;
  938. strText.Format("rnerase rect = %d, %d, %d, %d rn", rc.left, rc.top, rc.right, rc.bottom);
  939. TRACE(strText);
  940. #endif
  941. return TRUE;
  942. return CDkToolBar::OnEraseBkgnd(pDC);
  943. }