MacButtons.cpp
上传用户:wpp2016
上传日期:2010-02-01
资源大小:1250k
文件大小:76k
源码类别:

Telnet服务器

开发平台:

Visual C++

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // MacButtons.cpp : implementation file
  4. //
  5. // Feel free to modifiy and/or distribute this file, but
  6. // do not remove this header.
  7. //
  8. // I would appreciate a notification of any bugs discovered or 
  9. // improvements that could be made.
  10. //
  11. // This file is provided "as is" with no expressed or implied warranty.
  12. //
  13. /////////////////////////////////////////////////////////////////////////////
  14. #include "stdafx.h"
  15. #include "MacButtons.h"
  16. #ifdef _DEBUG
  17. #define new DEBUG_NEW
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21. /////////////////////////////////////////////////////////////////////////////
  22. //
  23. // CMacButton class, version 2.0
  24. //
  25. // Copyright (c) 1999 Paul Meidinger (pmmeidinger@yahoo.com)
  26. //
  27. // History:
  28. // PMM 12/13/1999 Initial implementation.
  29. //
  30. // PMM 12/29/1999 Minor changes made.
  31. //
  32. /////////////////////////////////////////////////////////////////////////////
  33. //-------------------------------------------------------------------
  34. //
  35. CMacButton::CMacButton()
  36. //
  37. // Return Value: None.
  38. //
  39. // Parameters : None.
  40. //
  41. // Remarks : Standard constructor.
  42. //
  43. {
  44. m_nType = TYPE_STANDARD;
  45. m_nCheck = 0;
  46. m_bMouseDown = FALSE;
  47. m_bBold = FALSE;
  48. m_hIcon = NULL;
  49. m_hBitmap = NULL;
  50. m_sizeImage = CSize(0, 0);
  51. m_nImageEffect = 0;
  52. GetColors();
  53. CreatePens();
  54. } // CMacButton
  55. //-------------------------------------------------------------------
  56. //
  57. CMacButton::~CMacButton()
  58. //
  59. // Return Value: None.
  60. //
  61. // Parameters : None.
  62. //
  63. // Remarks : Destructor.
  64. //
  65. {
  66. DeletePens();
  67. } // ~CMacButton
  68. BEGIN_MESSAGE_MAP(CMacButton, CButton)
  69. //{{AFX_MSG_MAP(CMacButton)
  70. ON_WM_SYSCOLORCHANGE()
  71. ON_WM_LBUTTONDBLCLK()
  72. //}}AFX_MSG_MAP
  73. END_MESSAGE_MAP()
  74. /////////////////////////////////////////////////////////////////////////////
  75. // CMacButton message handlers
  76. //-------------------------------------------------------------------
  77. //
  78. void CMacButton::PreSubclassWindow() 
  79. //
  80. // Return Value: None.
  81. //
  82. // Parameters : None.
  83. //
  84. // Remarks : This member function is called by the framework to 
  85. // allow other necessary subclassing to occur before the 
  86. // window is subclassed. Adds the BS_OWNERDRAW style.
  87. //
  88. {
  89. CButton::PreSubclassWindow();
  90. ModifyStyle(0, BS_OWNERDRAW);
  91. } // PreSubclassWindow
  92. //-------------------------------------------------------------------
  93. //
  94. void CMacButton::DrawItem(LPDRAWITEMSTRUCT lpDIS) 
  95. //
  96. // Return Value: None.
  97. //
  98. // Parameters : lpDIS - A long pointer to a DRAWITEMSTRUCT structure.
  99. //
  100. // Remarks : Called by the framework when a visual aspect of an 
  101. // owner-drawn button has changed.
  102. //
  103. {
  104. DrawButton(lpDIS);
  105. } // DrawItem
  106. //-------------------------------------------------------------------
  107. //
  108. void CMacButton::DrawButton(LPDRAWITEMSTRUCT lpDIS)
  109. //
  110. // Return Value: None.
  111. //
  112. // Parameters : lpDIS - A long pointer to a DRAWITEMSTRUCT structure.
  113. //
  114. // Remarks : Draws a Mac button.
  115. //
  116. {
  117. CDC* pDC = CDC::FromHandle(lpDIS->hDC);
  118. CRect rectItem(lpDIS->rcItem);
  119. UINT nState = lpDIS->itemState;
  120. UINT nStyle = GetStyle();
  121. BOOL bPushLike = BOOL(nStyle & BS_PUSHLIKE);
  122. // Create a mem DC for drawing
  123. CDC dcMem;
  124. dcMem.CreateCompatibleDC(pDC);
  125. CBitmap bmp;
  126. bmp.CreateCompatibleBitmap(pDC, rectItem.Width(), rectItem.Height());
  127. CBitmap *pOldBmp = dcMem.SelectObject(&bmp);
  128. int nSaveDC = dcMem.SaveDC();
  129. CBrush *pOldBrush = (CBrush *)dcMem.SelectStockObject(NULL_BRUSH);
  130. dcMem.FillSolidRect(rectItem, m_crFace);
  131. // If the button is standard or pushlike, draw it now.
  132. // Wait until after drawing the text/image and focus to draw
  133. // the radio button or check box. This way, the text or image
  134. // will not cover the radio or check.
  135. if (m_nType == TYPE_STANDARD)
  136. DrawStandardButton(&dcMem, rectItem, nStyle, nState);
  137. else if (bPushLike)
  138. DrawPushLikeButton(&dcMem, rectItem, nStyle, nState);
  139. CRect rectText(rectItem);
  140. CRect rectImage(rectItem);
  141. CString sText;
  142. GetWindowText(sText);
  143. // Draw an image or the text.
  144. if (m_hIcon || m_hBitmap)
  145. DrawImage(&dcMem, rectImage, nStyle, nState);
  146. else
  147. DrawButtonText(&dcMem, rectText, sText, nStyle, nState);
  148. // Draw the focus rect.
  149. if (nState & ODS_FOCUS)
  150. {
  151. if ((m_nType == TYPE_STANDARD) || bPushLike)
  152. {
  153. rectText = lpDIS->rcItem;
  154. rectText.DeflateRect(4, 4, 4, 4);
  155. dcMem.DrawFocusRect(rectText);
  156. }
  157. else if (m_hIcon || m_hBitmap)
  158. {
  159. rectImage.InflateRect(1, 1, 1, 1);
  160. if (rectImage.top < rectItem.top)
  161. rectImage.top = rectItem.top;
  162. if (rectImage.bottom > rectItem.bottom)
  163. rectImage.bottom = rectItem.bottom;
  164. if (rectImage.left < rectItem.left)
  165. rectImage.left = rectItem.left;
  166. if (rectImage.right > rectItem.right)
  167. rectImage.right = rectItem.right;
  168. dcMem.DrawFocusRect(rectImage);
  169. }
  170. else
  171. {
  172. rectText.InflateRect(1, 1, 1, 2);
  173. if (rectText.top < rectItem.top)
  174. rectText.top = rectItem.top;
  175. if (rectText.bottom > rectItem.bottom)
  176. rectText.bottom = rectItem.bottom;
  177. if (rectText.left < rectItem.left)
  178. rectText.left = rectItem.left;
  179. if (rectText.right > rectItem.right)
  180. rectText.right = rectItem.right;
  181. dcMem.DrawFocusRect(rectText); 
  182. }
  183. } // if the button has focus
  184. // Draw the check box or radio button now.
  185. if (!bPushLike)
  186. {
  187. // Determine the rect for the check mark.
  188. CRect rectCheck = GetCheckRect(rectItem, nStyle);
  189. if (m_nType == TYPE_CHECKBOX)
  190. DrawCheckBox(&dcMem, rectCheck, nStyle, nState);
  191. else if (m_nType == TYPE_RADIO)
  192. DrawRadioButton(&dcMem, rectCheck, nStyle, nState);
  193. }
  194. pDC->BitBlt(rectItem.left, rectItem.top, rectItem.Width(), rectItem.Height(), &dcMem, rectItem.left, rectItem.top, SRCCOPY);
  195. // Clean up.
  196. dcMem.SelectObject(pOldBrush);
  197. dcMem.SelectObject(pOldBmp);
  198. dcMem.RestoreDC(nSaveDC);
  199. dcMem.DeleteDC();
  200. bmp.DeleteObject();
  201. } // DrawButton
  202. //-------------------------------------------------------------------
  203. //
  204. void CMacButton::DrawStandardButton(CDC *pDC, const CRect &rect, UINT nStyle, UINT nState)
  205. //
  206. // Return Value: None.
  207. //
  208. // Parameters : pDC - A pointer to the DC to draw on.
  209. // rect - The button rectangle.
  210. // nStyle - The button's style.
  211. // nState - The button's state.
  212. //
  213. // Remarks : Draws the button.
  214. //
  215. {
  216. // Draw a flat button.
  217. if (nStyle & BS_FLAT)
  218. {
  219. COLORREF crFill = ::GetSysColor(COLOR_WINDOW);
  220. CBrush brFill(nState & ODS_SELECTED ? ~crFill : crFill);
  221. CBrush *pOldBrush = (CBrush *)pDC->SelectObject(&brFill);
  222. CPen pen;
  223. if (nState & ODS_DISABLED)
  224. pen.CreatePen(PS_SOLID, 1, m_crShadow);
  225. else if (m_nCheck || m_bMouseDown)
  226. pen.CreatePen(PS_SOLID, 1, crFill);
  227. else
  228. pen.CreatePen(PS_SOLID, 1, ~crFill);
  229. CPen *pOldPen = (CPen *)pDC->SelectObject(&pen);
  230. pDC->RoundRect(rect, CPoint(6, 6));
  231. pDC->SelectObject(pOldBrush);
  232. pDC->SelectObject(pOldPen);
  233. pen.DeleteObject();
  234. return;
  235. } // if flat
  236. CBrush brFill(nState & ODS_SELECTED ? m_crLiteShadow : m_crFace);
  237. CBrush *pOldBrush = (CBrush *)pDC->SelectObject(&brFill);
  238. CPen penFrame(PS_SOLID, 1, ::GetSysColor(COLOR_WINDOWFRAME));
  239. CPen *pOldPen = (CPen *)pDC->SelectObject(nState & ODS_DISABLED ? &m_penShadow : &penFrame);
  240. // Draw a 3D button.
  241. if (nState & ODS_DISABLED)
  242. pDC->RoundRect(rect, CPoint(6, 6));
  243. else if (nState & ODS_SELECTED)
  244. DrawPressedPushButton(pDC, rect);
  245. else
  246. DrawUnpressedPushButton(pDC, rect);
  247. pDC->SelectObject(pOldBrush);
  248. pDC->SelectObject(pOldPen);
  249. } // DrawStandardButton
  250. //-------------------------------------------------------------------
  251. //
  252. void CMacButton::DrawCheckBox(CDC *pDC, CRect rect, UINT nStyle, UINT nState)
  253. //
  254. // Return Value: None.
  255. //
  256. // Parameters : pDC - A pointer to the DC to draw on.
  257. // rect - The check mark's rectangle.
  258. // nStyle - The button's style.
  259. // nState - The button's state.
  260. //
  261. // Remarks : Draws the check mark.
  262. //
  263. {
  264. BOOL bDisabled = nState & ODS_DISABLED;
  265. // Deflate the rect by two on the right (for the check mark's shadow).
  266. rect.DeflateRect(0, 0, 2, 0);
  267. CPen *pOldPen = pDC->GetCurrentPen();
  268. CBrush *pOldBrush = pDC->GetCurrentBrush();
  269. // Draw a flat checkbox.
  270. if (nStyle & BS_FLAT)
  271. {
  272. COLORREF crFrame = ::GetSysColor(COLOR_WINDOW);
  273. CPen penFrame(PS_SOLID, 1, ::GetSysColor(COLOR_WINDOWFRAME));
  274. CBrush brFill(crFrame);
  275. pDC->SelectObject(&penFrame);
  276. pDC->SelectObject(&brFill);
  277. pDC->Rectangle(rect);
  278. if (bDisabled)
  279. {
  280. for (int i = rect.left + 1, j = rect.top + 1; i < rect.right; i += 2, j += 2)
  281. {
  282. pDC->SetPixel(i, rect.top, crFrame);
  283. pDC->SetPixel(i - 1, rect.bottom - 1, crFrame);
  284. pDC->SetPixel(rect.left, j, crFrame);
  285. pDC->SetPixel(rect.right - 1, j - 1, crFrame);
  286. }
  287. }
  288. rect.DeflateRect(1, 1, 1, 1);
  289. if (m_bMouseDown)
  290. pDC->Rectangle(rect);
  291. // Inflate the rect by two on the right (for the check mark's shadow).
  292. rect.InflateRect(0, 0, 2, 0);
  293. int nLeft = rect.left;
  294. int nTop = rect.top;
  295. CPen penDkShadow(PS_SOLID, 1, m_crDkShadow);
  296. pDC->SelectObject(&penDkShadow);
  297. // Draw the check, cross, or tri-state mark.
  298. if (m_nCheck == 1)
  299. {
  300. if (m_nCheckStyle == CHECK_STYLE_CHECK)
  301. {
  302. if (!bDisabled)
  303. {
  304. pDC->MoveTo(nLeft + 1, nTop + 4);
  305. pDC->LineTo(nLeft + 4, nTop + 7);
  306. pDC->LineTo(nLeft + 12,nTop - 1);
  307. }
  308. pDC->MoveTo(nLeft + 2, nTop + 4);
  309. pDC->LineTo(nLeft + 4, nTop + 6);
  310. pDC->LineTo(nLeft + 11, nTop -1);
  311. }
  312. else if (m_nCheckStyle == CHECK_STYLE_CROSS)
  313. {
  314. pDC->MoveTo(nLeft, nTop);
  315. pDC->LineTo(nLeft + 10, nTop + 10);
  316. int nAdjust = bDisabled ? 1 : 0;
  317. pDC->MoveTo(nLeft + nAdjust, nTop + 9 - nAdjust);
  318. pDC->LineTo(nLeft + 10 - nAdjust, nTop - 1 + nAdjust);
  319. }
  320. }
  321. else if (m_nCheck == 2)
  322. {
  323. pDC->SelectObject(&m_penDkShadow);
  324. pDC->MoveTo(nLeft + 2, nTop + 4);
  325. pDC->LineTo(nLeft + 8, nTop + 4);
  326. pDC->MoveTo(nLeft + 2, nTop + 5);
  327. pDC->LineTo(nLeft + 8, nTop + 5);
  328. }
  329. } // if flat
  330. // Else draw a 3D checkbox.
  331. else
  332. {
  333. CBrush brFrame(bDisabled ? m_crShadow : ::GetSysColor(COLOR_WINDOWFRAME));
  334. pDC->FrameRect(rect, &brFrame);
  335. rect.DeflateRect(1, 1);
  336. if (m_bMouseDown)
  337. {
  338. CBrush brShadow(m_crLiteShadow);
  339. pDC->FillRect(rect, &brShadow);
  340. pDC->Draw3dRect(rect, m_crShadow, m_crLiteFace);
  341. }
  342. else
  343. {
  344. pDC->FillSolidRect(rect, m_crFace);
  345. if (!bDisabled)
  346. pDC->Draw3dRect(rect, m_crHilight, m_crShadow);
  347. }
  348. pDC->SetPixel(CPoint(rect.right - 1, rect.top), m_crFace);
  349. pDC->SetPixel(CPoint(rect.left, rect.bottom - 1), m_crFace);
  350. // Inflate the rect by two on the right (for the check mark's shadow).
  351. rect.InflateRect(0, 0, 2, 0);
  352. int nLeft = rect.left;
  353. int nTop = rect.top;
  354. // Draw the check, cross, or tri-state mark.
  355. if (m_nCheck == 1)
  356. {
  357. // Draw the check mark's shadow
  358. if (m_nCheckStyle == CHECK_STYLE_CHECK)
  359. {
  360. // Draw the check mark's shadow
  361. pDC->SelectObject(bDisabled ? &m_penLiteShadow : &m_penShadow);
  362. pDC->MoveTo(nLeft + 4, nTop + 8);
  363. pDC->LineTo(nLeft + 9, nTop + 3);
  364. pDC->LineTo(nLeft + 9, nTop + 5);
  365. pDC->SelectObject(&m_penLiteShadow);
  366. pDC->MoveTo(nLeft + 2, nTop + 6);
  367. pDC->LineTo(nLeft + 4, nTop + 8);
  368. pDC->MoveTo(nLeft + 5, nTop + 8);
  369. pDC->LineTo(nLeft + 9, nTop + 4);
  370. pDC->SetPixel(nLeft + 11, nTop + 1, bDisabled ? m_crLiteShadow : m_crShadow);
  371. pDC->SetPixel(nLeft + 12, nTop + 1, m_crLiteShadow);
  372. pDC->SetPixel(nLeft + 11, nTop + 2, m_crLiteShadow);
  373. // Draw the check mark.
  374. pDC->SelectObject(bDisabled ? &m_penShadow : &m_penDkShadow);
  375. pDC->MoveTo(nLeft + 1, nTop + 4);
  376. pDC->LineTo(nLeft + 4, nTop + 7);
  377. pDC->LineTo(nLeft + 12,nTop - 1);
  378. pDC->MoveTo(nLeft + 2, nTop + 4);
  379. pDC->LineTo(nLeft + 4, nTop + 6);
  380. pDC->LineTo(nLeft + 11, nTop -1);
  381. }
  382. else if (m_nCheckStyle == CHECK_STYLE_CROSS)
  383. {
  384. // Draw the check mark's shadow
  385. pDC->SelectObject(bDisabled ? &m_penLiteShadow : &m_penShadow);
  386. pDC->MoveTo(nLeft + 3, nTop + 7);
  387. pDC->LineTo(nLeft + 9, nTop + 1);
  388. pDC->SelectObject(&m_penLiteShadow);
  389. pDC->MoveTo(nLeft + 3, nTop + 8);
  390. pDC->LineTo(nLeft + 9, nTop + 2);
  391. pDC->SetPixel(nLeft + 8, nTop + 7, bDisabled ? m_crLiteShadow : m_crShadow);
  392. pDC->SetPixel(nLeft + 8, nTop + 8, m_crLiteShadow);
  393. // Draw the check mark.
  394. pDC->SelectObject(bDisabled ? &m_penShadow : &m_penDkShadow);
  395. pDC->MoveTo(nLeft + 2, nTop + 1);
  396. pDC->LineTo(nLeft + 8, nTop + 7);
  397. pDC->MoveTo(nLeft + 2, nTop + 2);
  398. pDC->LineTo(nLeft + 8, nTop + 8);
  399. pDC->MoveTo(nLeft + 2, nTop + 6);
  400. pDC->LineTo(nLeft + 8, nTop);
  401. pDC->MoveTo(nLeft + 2, nTop + 7);
  402. pDC->LineTo(nLeft + 8, nTop + 1);
  403. }
  404. } // if checked
  405. else if (m_nCheck == 2)
  406. {
  407. pDC->SelectObject(&m_penLiteShadow);
  408. pDC->MoveTo(nLeft + 3, nTop + 6);
  409. pDC->LineTo(nLeft + 9, nTop + 6);
  410. pDC->SetPixel(nLeft + 8, nTop + 5, m_crLiteShadow);
  411. pDC->SelectObject(bDisabled ? &m_penShadow : &m_penDkShadow);
  412. pDC->MoveTo(nLeft + 2, nTop + 4);
  413. pDC->LineTo(nLeft + 8, nTop + 4);
  414. pDC->MoveTo(nLeft + 2, nTop + 5);
  415. pDC->LineTo(nLeft + 8, nTop + 5);
  416. }
  417. } // else draw 3D checkbox
  418. // Restore the pen and brush.
  419. pDC->SelectObject(pOldPen);
  420. pDC->SelectObject(pOldBrush);
  421. } // DrawCheckBox
  422. //-------------------------------------------------------------------
  423. //
  424. void CMacButton::DrawRadioButton(CDC *pDC, CRect rect, UINT nStyle, UINT nState)
  425. //
  426. // Return Value: None.
  427. //
  428. // Parameters : pDC - A pointer to the DC to draw on.
  429. // rect - The radio's rectangle.
  430. // nStyle - The button's style.
  431. // nState - The button's state.
  432. //
  433. // Remarks : Draws the radio button.
  434. //
  435. {
  436. // Give the user a visual indication that the button is pressed by darkening some colors.
  437. BOOL bDarkened = FALSE;
  438. if (m_bMouseDown && !(nStyle & BS_FLAT))
  439. {
  440. m_crFace = DarkenColor(m_crFace, 40);
  441. m_crShadow = DarkenColor(m_crShadow, 40);
  442. m_crHilight = DarkenColor(m_crHilight, 40);
  443. m_crLiteShadow = DarkenColor(m_crLiteShadow, 40);
  444. m_crLiteFace = DarkenColor(m_crLiteFace, 40);
  445. CreatePens();
  446. bDarkened = TRUE;
  447. }
  448. BOOL bDisabled = nState & ODS_DISABLED;
  449. // Draw the outer round rect.
  450. CPen penFrame;
  451. CBrush br;
  452. if (nStyle & BS_FLAT)
  453. {
  454. penFrame.CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_WINDOWFRAME));
  455. br.CreateSolidBrush(::GetSysColor(COLOR_WINDOW));
  456. }
  457. else
  458. {
  459. penFrame.CreatePen(PS_SOLID, 1, bDisabled ? m_crShadow : ::GetSysColor(COLOR_WINDOWFRAME));
  460. br.CreateSolidBrush(m_crFace);
  461. }
  462. CPen *pOldPen = (CPen *)pDC->SelectObject(&penFrame);
  463. CBrush *pOldBrush = (CBrush *)pDC->SelectObject(&br);
  464. pDC->RoundRect(rect, CPoint(10, 10));
  465. if ((nStyle & BS_FLAT) && m_bMouseDown)
  466. {
  467. rect.DeflateRect(1, 1, 1, 1);
  468. pDC->RoundRect(rect, CPoint(8, 8));
  469. rect.InflateRect(1, 1, 1, 1);
  470. }
  471. pDC->SelectObject(pOldBrush);
  472. br.DeleteObject();
  473. penFrame.DeleteObject();
  474. // Draw some shadowing
  475. if (!(nStyle & BS_FLAT))
  476. {
  477. int nLeft = rect.left;
  478. int nTop = rect.top;
  479. int nAdjust = (m_nCheck || m_bMouseDown ? -11 : 0);
  480. int nSign = (m_nCheck || m_bMouseDown ? -1 : 1);
  481. if (!bDisabled)
  482. {
  483. pDC->SelectObject(&m_penDarkDkShadow);
  484. pDC->MoveTo(nLeft + 0, nTop + 4);
  485. pDC->LineTo(nLeft + 5, nTop - 1);
  486. pDC->MoveTo(nLeft + 7, nTop);
  487. pDC->LineTo(nLeft + 12, nTop + 5);
  488. pDC->MoveTo(nLeft + 11, nTop + 7);
  489. pDC->LineTo(nLeft + 6, nTop + 12);
  490. pDC->MoveTo(nLeft + 4, nTop + 11);
  491. pDC->LineTo(nLeft - 1, nTop + 6);
  492. }
  493. if (!bDisabled)
  494. {
  495. pDC->SelectObject(&m_penLiteFace);
  496. pDC->MoveTo(nLeft + (nSign * (nAdjust + 1)), nTop + (nSign * (nAdjust + 6)));
  497. pDC->LineTo(nLeft + (nSign * (nAdjust + 1)), nTop + (nSign * (nAdjust + 4)));
  498. pDC->LineTo(nLeft + (nSign * (nAdjust + 4)), nTop + (nSign * (nAdjust + 1)));
  499. pDC->LineTo(nLeft + (nSign * (nAdjust + 7)), nTop + (nSign * (nAdjust + 1)));
  500. pDC->MoveTo(nLeft + (nSign * (nAdjust + 2)), nTop + (nSign * (nAdjust + 8)));
  501.    pDC->LineTo(nLeft + (nSign * (nAdjust + 9)), nTop + (nSign * (nAdjust + 1)));
  502. pDC->MoveTo(nLeft + (nSign * (nAdjust + 3)), nTop + (nSign * (nAdjust + 8)));
  503.    pDC->LineTo(nLeft + (nSign * (nAdjust + 9)), nTop + (nSign * (nAdjust + 2)));
  504. pDC->MoveTo(nLeft + (nSign * (nAdjust + 4)), nTop + (nSign * (nAdjust + 8)));
  505.    pDC->LineTo(nLeft + (nSign * (nAdjust + 9)), nTop + (nSign * (nAdjust + 3)));
  506. pDC->SelectObject(&m_penHilight);
  507. pDC->MoveTo(nLeft + (nSign * (nAdjust + 2)), nTop + (nSign * (nAdjust + 7)));
  508. pDC->LineTo(nLeft + (nSign * (nAdjust + 2)), nTop + (nSign * (nAdjust + 4)));
  509. pDC->LineTo(nLeft + (nSign * (nAdjust + 6)), nTop + (nSign * (nAdjust + 4)));
  510. pDC->MoveTo(nLeft + (nSign * (nAdjust + 4)), nTop + (nSign * (nAdjust + 5)));
  511. pDC->LineTo(nLeft + (nSign * (nAdjust + 4)), nTop + (nSign * (nAdjust + 2)));
  512. pDC->LineTo(nLeft + (nSign * (nAdjust + 8)), nTop + (nSign * (nAdjust + 2)));
  513. pDC->SelectObject(&m_penLiteShadow);
  514. pDC->MoveTo(nLeft + (nSign * (nAdjust + 6)), nTop + (nSign * (nAdjust + 9))); 
  515. pDC->LineTo(nLeft + (nSign * (nAdjust + 10)), nTop + (nSign * (nAdjust + 5))); 
  516. pDC->MoveTo(nLeft + (nSign * (nAdjust + 7)), nTop + (nSign * (nAdjust + 9))); 
  517. pDC->LineTo(nLeft + (nSign * (nAdjust + 10)), nTop + (nSign * (nAdjust + 6))); 
  518. pDC->SelectObject(&m_penShadow);
  519. pDC->MoveTo(nLeft + (nSign * (nAdjust + 4)), nTop + (nSign * (nAdjust + 10)));
  520. pDC->LineTo(nLeft + (nSign * (nAdjust + 7)), nTop + (nSign * (nAdjust + 10))); 
  521. pDC->LineTo(nLeft + (nSign * (nAdjust + 10)), nTop + (nSign * (nAdjust + 7))); 
  522. pDC->LineTo(nLeft + (nSign * (nAdjust + 10)), nTop + (nSign * (nAdjust + 3))); 
  523. pDC->SetPixel(nLeft + (nSign * (nAdjust + 3)), nTop + (nSign * (nAdjust + 5)), m_crHilight);
  524. pDC->SetPixel(nLeft + (nSign * (nAdjust + 5)), nTop + (nSign * (nAdjust + 3)), m_crHilight);
  525. pDC->SetPixel(nLeft + (nSign * (nAdjust + 2)), nTop + (nSign * (nAdjust + 2)), m_crFace);
  526. pDC->SetPixel(nLeft + (nSign * (nAdjust + 3)), nTop + (nSign * (nAdjust + 3)), m_crLiteFace);
  527. pDC->SetPixel(nLeft + (nSign * (nAdjust + 3)), nTop + (nSign * (nAdjust + 6)), m_crLiteFace);
  528. pDC->SetPixel(nLeft + (nSign * (nAdjust + 6)), nTop + (nSign * (nAdjust + 3)), m_crLiteFace);
  529. }
  530. // Do a little "touch-up" top make the radios look better.
  531. COLORREF crTemp = bDisabled ? m_crLiteShadow : m_crShadow;
  532. pDC->SetPixel(nLeft, nTop + 3, crTemp);
  533. pDC->SetPixel(nLeft + 3, nTop, crTemp);
  534. pDC->SetPixel(nLeft + 8, nTop, crTemp);
  535. pDC->SetPixel(nLeft + 11, nTop + 3, crTemp);
  536. pDC->SetPixel(nLeft + 11, nTop + 8, crTemp);
  537. pDC->SetPixel(nLeft + 8, nTop + 11, crTemp);
  538. pDC->SetPixel(nLeft + 3, nTop + 11, crTemp);
  539. pDC->SetPixel(nLeft, nTop + 8, crTemp);
  540. } // if not disabled and not flat
  541. // Draw the check if necessary.
  542. if (m_nCheck)
  543. {
  544. COLORREF crTemp = (bDisabled && !(nStyle & BS_FLAT) ? m_crShadow : m_crDkShadow);
  545. CBrush br(crTemp);
  546. CPen pen(PS_SOLID, 1, crTemp);
  547. CBrush *pOldBrush = pDC->SelectObject(&br);
  548. pDC->SelectObject(&pen);
  549. rect.DeflateRect(3, 3, 3, 3);
  550. pDC->RoundRect(rect, CPoint(2, 2));
  551. pDC->SelectObject(pOldBrush);
  552. }
  553. // Lighten the colors if they were darkened.
  554. if (bDarkened)
  555. {
  556. m_crFace = LightenColor(m_crFace, 40);
  557. m_crShadow = LightenColor(m_crShadow, 40);
  558. m_crHilight = LightenColor(m_crHilight, 40);
  559. m_crLiteShadow = LightenColor(m_crLiteShadow, 40);
  560. m_crLiteFace = LightenColor(m_crLiteFace, 40);
  561. CreatePens();
  562. }
  563. pDC->SelectObject(pOldPen);
  564. } // DrawRadioButton
  565. //-------------------------------------------------------------------
  566. //
  567. void CMacButton::OnLButtonDblClk(UINT /*nFlags*/, CPoint point) 
  568. //
  569. // Return Value: None.
  570. //
  571. // Parameters : nFlags - Indicates whether various virtual keys are down.
  572. // point - Specifies the x- and y-coordinate of the cursor. 
  573. // These coordinates are always relative to the upper-left
  574. //  corner of the window.
  575. //
  576. // Remarks : The framework calls this member function when the user 
  577. // double-clicks the left mouse button. The WM_LBUTTONDOWN
  578. // message is sent to simulate a single click.
  579. //
  580. {
  581. SendMessage(WM_LBUTTONDOWN, 0, MAKELPARAM(point.x, point.y));
  582. } // OnLButtonDblClk
  583. //-------------------------------------------------------------------
  584. //
  585. void CMacButton::OnSysColorChange() 
  586. //
  587. // Return Value: None.
  588. //
  589. // Parameters : None.
  590. //
  591. // Remarks : The framework calls this member function for all 
  592. // top-level windows when a change is made in the 
  593. // system color setting
  594. //
  595. {
  596. CButton::OnSysColorChange();
  597. GetColors();
  598. CreatePens();
  599. } // OnSysColorChange
  600. //-------------------------------------------------------------------
  601. //
  602. void CMacButton::GetColors()
  603. //
  604. // Return Value: None.
  605. //
  606. // Parameters : None.
  607. //
  608. // Remarks : Sets the COLORREF member variables.
  609. //
  610. {
  611. if (m_nType == TYPE_MORE)
  612. {
  613. m_crDkShadow = ::GetSysColor(COLOR_WINDOWFRAME);
  614. m_crShadow = ::GetSysColor(COLOR_3DSHADOW);
  615. m_crLiteFace = LightenColor(m_crFace, 51);
  616. m_crLiteShadow = DarkenColor(m_crFace, 51);
  617. }
  618. else
  619. {
  620. m_crHilight = ::GetSysColor(COLOR_3DHILIGHT);
  621. m_crLiteFace = ::GetSysColor(COLOR_3DLIGHT);
  622. m_crFace = ::GetSysColor(COLOR_3DFACE);
  623. m_crShadow = ::GetSysColor(COLOR_3DSHADOW);
  624. m_crDkShadow = ::GetSysColor(COLOR_3DDKSHADOW);
  625. // Create some intermediate colors. This is done by averaging two colors.
  626. BYTE byRedFace = GetRValue(m_crFace);
  627. BYTE byGreenFace = GetGValue(m_crFace);
  628. BYTE byBlueFace = GetBValue(m_crFace);
  629. BYTE byRedShadow = GetRValue(m_crShadow);
  630. BYTE byGreenShadow = GetGValue(m_crShadow);
  631. BYTE byBlueShadow = GetBValue(m_crShadow);
  632. BYTE byRedDkShadow = GetRValue(m_crDkShadow);
  633. BYTE byGreenDkShadow = GetGValue(m_crDkShadow);
  634. BYTE byBlueDkShadow = GetBValue(m_crDkShadow);
  635. m_crLiteShadow = RGB(byRedFace + ((byRedShadow - byRedFace) >> 1),
  636. byGreenFace + ((byGreenShadow - byGreenFace) >> 1),
  637. byBlueFace + ((byBlueShadow - byBlueFace) >> 1));
  638. m_crDarkDkShadow = RGB(byRedShadow + ((byRedDkShadow - byRedShadow) >> 1),
  639. byGreenShadow + ((byGreenDkShadow - byGreenShadow) >> 1),
  640. byBlueShadow + ((byBlueDkShadow - byBlueShadow) >> 1));
  641. }
  642. } // GetColors
  643. //-------------------------------------------------------------------
  644. //
  645. COLORREF CMacButton::LightenColor(const COLORREF crColor, BYTE byIncreaseVal)
  646. //
  647. // Return Value: None.
  648. //
  649. // Parameters : crColor - References a COLORREF structure.
  650. // byReduceVal - The amount to reduce the RGB values by.
  651. //
  652. // Remarks : Lightens a color by increasing the RGB values by the given number.
  653. //  
  654. {
  655. BYTE byRed = GetRValue(crColor);
  656. BYTE byGreen = GetGValue(crColor);
  657. BYTE byBlue = GetBValue(crColor);
  658. byRed = (byRed + byIncreaseVal) <= 255 ? BYTE(byRed + byIncreaseVal) : 255;;
  659. byGreen = (byGreen + byIncreaseVal) <= 255 ? BYTE(byGreen + byIncreaseVal) : 255;
  660. byBlue = (byBlue + byIncreaseVal) <= 255 ? BYTE(byBlue + byIncreaseVal) : 255;
  661. /* if ((byRed + byIncreaseVal) <= 255)
  662. byRed = BYTE(byRed + byIncreaseVal);
  663. if ((byGreen + byIncreaseVal) <= 255)
  664. byGreen = BYTE(byGreen + byIncreaseVal);
  665. if ((byBlue + byIncreaseVal) <= 255)
  666. byBlue = BYTE(byBlue + byIncreaseVal);
  667. */
  668. return RGB(byRed, byGreen, byBlue);
  669. } // LightenColor
  670. //-------------------------------------------------------------------
  671. //
  672. COLORREF CMacButton::DarkenColor(const COLORREF crColor, BYTE byReduceVal)
  673. //
  674. // Return Value: None.
  675. //
  676. // Parameters : crColor - References a COLORREF structure.
  677. // byReduceVal - The amount to reduce the RGB values by.
  678. //
  679. // Remarks : Darkens a color by reducing the RGB values by the given number.
  680. //
  681. {
  682. BYTE byRed = GetRValue(crColor);
  683. BYTE byGreen = GetGValue(crColor);
  684. BYTE byBlue = GetBValue(crColor);
  685. byRed = byRed >= byReduceVal ? BYTE(byRed - byReduceVal) : 0;
  686. byGreen = byGreen >= byReduceVal ? BYTE(byGreen - byReduceVal) : 0;
  687. byBlue = (byBlue >= byReduceVal) ? BYTE(byBlue - byReduceVal) : 0;
  688. /* if (byRed >= byReduceVal)
  689. byRed = BYTE(byRed - byReduceVal);
  690. if (byGreen >= byReduceVal)
  691. byGreen = BYTE(byGreen - byReduceVal);
  692. if (byBlue >= byReduceVal)
  693. byBlue = BYTE(byBlue - byReduceVal);
  694. */
  695. return RGB(byRed, byGreen, byBlue);
  696. } // DarkenColor
  697. //-------------------------------------------------------------------
  698. //
  699. void CMacButton::CreatePens()
  700. //
  701. // Return Value: None.
  702. //
  703. // Parameters : None.
  704. //
  705. // Remarks : Deletes the pen objects, if necessary, and creates them.
  706. //
  707. {
  708. DeletePens();
  709. m_penFace.CreatePen(PS_SOLID, 1, m_crFace);
  710. m_penLiteFace.CreatePen(PS_SOLID, 1, m_crLiteFace);
  711. m_penLiteShadow.CreatePen(PS_SOLID, 1, m_crLiteShadow);
  712. m_penShadow.CreatePen(PS_SOLID, 1, m_crShadow);
  713. m_penDkShadow.CreatePen(PS_SOLID, 1, m_crDkShadow);
  714. if (m_nType != TYPE_MORE)
  715. {
  716. m_penHilight.CreatePen(PS_SOLID, 1, m_crHilight);
  717. m_penDarkDkShadow.CreatePen(PS_SOLID, 1, m_crDarkDkShadow);
  718. }
  719. } // CreatePens
  720. //-------------------------------------------------------------------
  721. //
  722. void CMacButton::DeletePens()
  723. //
  724. // Return Value: None.
  725. //
  726. // Parameters : None.
  727. //
  728. // Remarks : Deletes the pen objects.
  729. //
  730. {
  731. if (m_penHilight.m_hObject)
  732. m_penHilight.DeleteObject();
  733. if (m_penFace.m_hObject)
  734. m_penFace.DeleteObject();
  735. if (m_penLiteFace.m_hObject)
  736. m_penLiteFace.DeleteObject();
  737. if (m_penLiteShadow.m_hObject)
  738. m_penLiteShadow.DeleteObject();
  739. if (m_penShadow.m_hObject)
  740. m_penShadow.DeleteObject();
  741. if (m_penDkShadow.m_hObject)
  742. m_penDkShadow.DeleteObject();
  743. if (m_penDarkDkShadow.m_hObject)
  744. m_penDarkDkShadow.DeleteObject();
  745. } // DeletePens
  746. //-------------------------------------------------------------------
  747. //
  748. void CMacButton::DrawImage(CDC *pDC, CRect &rect, UINT nStyle, UINT nState)
  749. //
  750. // Return Value: None.
  751. //
  752. // Parameters : pDC - A pointer to the DC to draw on.
  753. // sText - The text on the button.
  754. // rect - The button rectangle.
  755. // nStyle - The button's style.
  756. // nState - The button's state.
  757. //
  758. // Remarks : Draws an icon or bitmap on the button.
  759. //
  760. {
  761. // Calculate the left and right sides of the rect.
  762. if ((m_nType == TYPE_STANDARD) || (nStyle & BS_PUSHLIKE))
  763. {
  764. if (nStyle & BS_LEFT)
  765. rect.left += 5;
  766. else if (nStyle & BS_RIGHT)
  767. rect.left = rect.right - m_sizeImage.cx - 5;
  768. else
  769. rect.left = (rect.Width() - m_sizeImage.cx) >> 1;
  770. } // if the button is standard or push-like
  771. else
  772. {
  773. if (nStyle & BS_LEFT)
  774. rect.left = (nStyle & BS_LEFTTEXT ? 2 : CHECKBOX_HEIGHT + 5);
  775. else if (nStyle & BS_RIGHT)
  776. rect.left = rect.right - m_sizeImage.cx - (nStyle & BS_LEFTTEXT ? CHECKBOX_HEIGHT + 7 : 2);
  777. // Else use the default vertical alignment (left for radios & checkboxes, center for push buttons).
  778. else
  779. {
  780. if (m_nType == TYPE_CHECKBOX || m_nType == TYPE_RADIO)
  781. rect.left = (nStyle & BS_LEFTTEXT ? 2 : CHECKBOX_HEIGHT + 5);
  782. else
  783. rect.left = (rect.Width() - m_sizeImage.cx) >> 1;
  784. }
  785. }
  786. rect.right = rect.left + m_sizeImage.cx;
  787. // Calculate the top and bottom of the rect.
  788. if (nStyle & BS_TOP)
  789. rect.top += ((m_nType == TYPE_STANDARD) || (nStyle & BS_PUSHLIKE) ? 4 : 1);
  790. else if (nStyle & BS_BOTTOM)
  791. rect.top = rect.bottom - m_sizeImage.cy - ((m_nType == TYPE_STANDARD) || (nStyle & BS_PUSHLIKE) ? 4 : 1);
  792. else
  793. rect.top = (rect.Height() - m_sizeImage.cy) >> 1;
  794. rect.bottom = rect.top + m_sizeImage.cy;
  795. // Adjust the image's rectangle depending on the effect
  796. if (m_nImageEffect == IMAGE_EFFECT_RAISED || m_nImageEffect == IMAGE_EFFECT_SUNKEN)
  797. {
  798. if ((m_nType == TYPE_STANDARD) || (nStyle & BS_PUSHLIKE))
  799. {
  800. if (nStyle & BS_LEFT)
  801. {
  802. rect.left++;
  803. rect.right++;
  804. }
  805. else if (nStyle & BS_RIGHT)
  806. {
  807. rect.left--;
  808. rect.right--;
  809. }
  810. }
  811. if (nStyle & BS_TOP)
  812. {
  813. rect.top++;
  814. rect.bottom++;
  815. }
  816. else if (nStyle & BS_BOTTOM)
  817. {
  818. rect.top--;
  819. rect.bottom--;
  820. }
  821. }
  822. // Draw the image.
  823. if (m_hIcon)
  824. pDC->DrawState(rect.TopLeft(), m_sizeImage, 
  825. m_hIcon, nState & ODS_DISABLED ? DSS_DISABLED : DSS_NORMAL, (HBRUSH)NULL);
  826. else if (m_hBitmap)
  827. pDC->DrawState(rect.TopLeft(), m_sizeImage, 
  828. m_hBitmap, nState & ODS_DISABLED ? DSS_DISABLED : DSS_NORMAL, (HBRUSH)NULL);
  829. if (m_nImageEffect)
  830. {
  831. rect.InflateRect(1, 1, 1, 1);
  832. if (m_nImageEffect == IMAGE_EFFECT_RAISED)
  833. pDC->Draw3dRect(rect, m_crHilight, m_crShadow);
  834. if (m_nImageEffect == IMAGE_EFFECT_SUNKEN)
  835. pDC->Draw3dRect(rect, m_crShadow, m_crHilight);
  836. }
  837. } // DrawImage
  838. //-------------------------------------------------------------------
  839. //
  840. HICON CMacButton::SetIcon(HICON hIcon)
  841. //
  842. // Return Value: The handle of an icon previously associated with the button.
  843. //
  844. // Parameters : hIcon - The handle of an icon.
  845. //
  846. // Remarks : Call this member function to associate a new icon with the button.
  847. //
  848. {
  849. m_hIcon = hIcon;
  850. m_hBitmap = 0;
  851. if (hIcon)
  852. {
  853. // Get icon dimensions.
  854. ICONINFO iconInfo;
  855. ::ZeroMemory(&iconInfo, sizeof(ICONINFO));
  856. ::GetIconInfo(m_hIcon, &iconInfo);
  857. m_sizeImage.cx = iconInfo.xHotspot << 1;
  858. m_sizeImage.cy = iconInfo.yHotspot << 1;
  859. }
  860. RedrawWindow();
  861. return CButton::SetIcon(hIcon);
  862. } // SetIcon
  863. //-------------------------------------------------------------------
  864. //
  865. HBITMAP CMacButton::SetBitmap(HBITMAP hBitmap)
  866. //
  867. // Return Value: The handle of a bitmap previously associated with the button.
  868. //
  869. // Parameters : hBitmap - The handle of a bitmap.
  870. //
  871. // Remarks : Call this member function to associate a new bitmap with the button.
  872. //
  873. {
  874. m_hBitmap = hBitmap;
  875. m_hIcon = 0;
  876. if (hBitmap)
  877. {
  878. // Get bitmap dimensions.
  879. CBitmap *pBmp = CBitmap::FromHandle(hBitmap);
  880. ASSERT(pBmp);
  881. BITMAP bmp;
  882. ::ZeroMemory(&bmp, sizeof(BITMAP));
  883. pBmp->GetBitmap(&bmp);
  884. m_sizeImage.cx = bmp.bmWidth;
  885. m_sizeImage.cy = bmp.bmHeight;
  886. }
  887. RedrawWindow();
  888. return CButton::SetBitmap(hBitmap);
  889. } // SetBitmap
  890. //-------------------------------------------------------------------
  891. //
  892. CRect CMacButton::GetCheckRect(const CRect &rect, UINT nStyle)
  893. //
  894. // Return Value: A CRect containing the dimensions of the radio/check box.
  895. //
  896. // Parameters : rect - The rectangle of the entire button.
  897. // nStyle - The button's style.
  898. //
  899. // Remarks : Returns a rectangle containing the dimensions of the 
  900. // radio/check box. Only used with radio buttons or check boxes.
  901. //
  902. {
  903. CRect rectCheck(rect);
  904. // Calculate the left and right sides of the rect.
  905. if (nStyle & BS_LEFTTEXT)
  906. {
  907. rectCheck.left = rect.right - CHECKBOX_HEIGHT - (m_nType == TYPE_RADIO ? 0 : 2);
  908. }
  909. else
  910. {
  911. rectCheck.left += (m_nType == TYPE_RADIO ? 1 : 0);
  912. rectCheck.right = rect.left + CHECKBOX_HEIGHT + (m_nType == TYPE_RADIO ? 1 : 2);
  913. }
  914. // Calculate the top and bottom sides of the rect.
  915. if (nStyle & BS_TOP)
  916. rectCheck.top += 1;
  917. else if (nStyle & BS_BOTTOM)
  918. rectCheck.top = rect.bottom - CHECKBOX_HEIGHT - 3;
  919. else
  920. rectCheck.top = ((rect.Height() - CHECKBOX_HEIGHT) >> 1) - 1;
  921. rectCheck.bottom = rectCheck.top + CHECKBOX_HEIGHT;
  922. return rectCheck;
  923. } // GetCheckRect
  924. //-------------------------------------------------------------------
  925. //
  926. void CMacButton::DrawUnpressedPushButton(CDC *pDC, const CRect &rect)
  927. //
  928. // Return Value: None.
  929. //
  930. // Parameters : pDC - A pointer to the DC to draw on.
  931. // rect - The button's rectangle.
  932. //
  933. // Remarks : Draws an unpressed push button.
  934. //
  935. {
  936. pDC->RoundRect(rect, CPoint(6, 6));
  937. // Save myself some typing.
  938. int nLeft = rect.left;
  939. int nTop = rect.top;
  940. int nRight = rect.right;
  941. int nBottom = rect.bottom;
  942. pDC->SelectObject(&m_penHilight);
  943. pDC->MoveTo(nLeft + 2, nBottom - 4);
  944. pDC->LineTo(nLeft + 2, nTop + 2);
  945. pDC->LineTo(nRight - 3, nTop + 2);
  946. pDC->SetPixel(nLeft + 3, nTop + 3, m_crHilight);
  947. pDC->SelectObject(&m_penLiteShadow);
  948. pDC->MoveTo(nLeft + 3, nBottom - 3);
  949. pDC->LineTo(nRight - 4, nBottom - 3);
  950. pDC->LineTo(nRight - 4, nBottom - 4);
  951. pDC->LineTo(nRight - 3, nBottom - 4);
  952. pDC->LineTo(nRight - 3, nTop + 2);
  953. pDC->SelectObject(&m_penShadow);
  954. pDC->MoveTo(nLeft + 3, nBottom - 2);
  955. pDC->LineTo(nRight - 3, nBottom - 2);
  956. pDC->LineTo(nRight - 3, nBottom - 3);
  957. pDC->LineTo(nRight - 2, nBottom - 3);
  958. pDC->LineTo(nRight - 2, nTop + 2);
  959. pDC->SetPixel(nLeft, nTop + 2, m_crDarkDkShadow);
  960. pDC->SetPixel(nLeft + 2, nTop, m_crDarkDkShadow);
  961. pDC->SetPixel(nRight - 3, nTop, m_crDarkDkShadow);
  962. pDC->SetPixel(nRight - 1, nTop + 2, m_crDarkDkShadow);
  963. pDC->SetPixel(nRight - 1, nBottom - 3, m_crDarkDkShadow);
  964. pDC->SetPixel(nRight - 3, nBottom - 1, m_crDarkDkShadow);
  965. pDC->SetPixel(nLeft + 2, nBottom - 1, m_crDarkDkShadow);
  966. pDC->SetPixel(nLeft, nBottom - 3, m_crDarkDkShadow);
  967. pDC->SetPixel(nLeft + 1, nTop + 2, m_crLiteShadow);
  968. pDC->SetPixel(nLeft + 2, nTop + 1, m_crLiteShadow);
  969. pDC->SetPixel(nRight - 3, nTop + 1, m_crLiteShadow);
  970. pDC->SetPixel(nRight - 2, nTop + 2, m_crLiteShadow);
  971. pDC->SetPixel(nLeft + 2, nBottom - 2, m_crLiteShadow);
  972. pDC->SetPixel(nLeft + 1, nBottom - 3, m_crLiteShadow);
  973. DrawCornerShadows(pDC, rect);
  974. } // DrawUnpressedPushButton
  975. //-------------------------------------------------------------------
  976. //
  977. void CMacButton::DrawPressedPushButton(CDC *pDC, const CRect &rect)
  978. //
  979. // Return Value: None.
  980. //
  981. // Parameters : pDC - A pointer to the DC to draw on.
  982. // rect - The button's rectangle.
  983. //
  984. // Remarks : Draws a pressed push button.
  985. //
  986. {
  987. pDC->RoundRect(rect, CPoint(6, 6));
  988. // Save myself some typing.
  989. int nLeft = rect.left;
  990. int nTop = rect.top;
  991. int nRight = rect.right;
  992. int nBottom = rect.bottom;
  993. pDC->SelectObject((m_nType == TYPE_STANDARD) || m_bMouseDown ? &m_penDarkDkShadow : &m_penShadow);
  994. pDC->MoveTo(nLeft + 1, nBottom - 4);
  995. pDC->LineTo(nLeft + 1, nTop + 2);
  996. pDC->LineTo(nLeft + 2, nTop + 2);
  997. pDC->LineTo(nLeft + 2, nTop + 1);
  998. pDC->LineTo(nRight - 3, nTop + 1);
  999. pDC->SelectObject((m_nType == TYPE_STANDARD) || m_bMouseDown ? &m_penShadow : &m_penLiteShadow);
  1000. pDC->MoveTo(nLeft + 2, nBottom - 4);
  1001. pDC->LineTo(nLeft + 2, nTop + 3);
  1002. pDC->LineTo(nLeft + 3, nTop + 3);
  1003. pDC->LineTo(nLeft + 3, nTop + 2);
  1004. pDC->LineTo(nRight - 3, nTop + 2);
  1005. pDC->SelectObject((m_nType == TYPE_STANDARD) || !(m_nCheck && !m_bMouseDown) ? &m_penLiteFace : &m_penHilight);
  1006. pDC->MoveTo(nLeft + 3, nBottom - 2);
  1007. pDC->LineTo(nRight - 4, nBottom - 2);
  1008. pDC->LineTo(nRight - 2, nBottom - 4);
  1009. pDC->LineTo(nRight - 2, nTop + 2);
  1010. pDC->SelectObject((m_nType == TYPE_STANDARD) || !(m_nCheck && !m_bMouseDown) ? &m_penFace : &m_penLiteFace);
  1011. pDC->MoveTo(nLeft + 3, nBottom - 3);
  1012. pDC->LineTo(nRight - 4, nBottom - 3);
  1013. pDC->LineTo(nRight - 4, nBottom - 4);
  1014. pDC->LineTo(nRight - 3, nBottom - 4);
  1015. pDC->LineTo(nRight - 3, nTop + 2);
  1016. pDC->SetPixel(nRight - 2, nTop + 2, ((m_nType == TYPE_STANDARD) || m_bMouseDown ? m_crFace : m_crLiteFace));
  1017. pDC->SetPixel(nLeft + 2, nBottom - 2, ((m_nType == TYPE_STANDARD) || m_bMouseDown ? m_crFace : m_crLiteFace));
  1018. pDC->SetPixel(nRight - 3, nTop + 1, m_crShadow);
  1019. pDC->SetPixel(nLeft + 1, nBottom - 3, m_crShadow);
  1020. DrawCornerShadows(pDC, rect);
  1021. } // DrawPressedPushButton
  1022. //-------------------------------------------------------------------
  1023. //
  1024. void CMacButton::DrawCornerShadows(CDC *pDC, const CRect &rect)
  1025. //
  1026. // Return Value: None.
  1027. //
  1028. // Parameters : pDC - A pointer to the DC to draw on.
  1029. // rect - The button's rectangle.
  1030. //
  1031. // Remarks : Draws the little "shadows" on the corners of push buttons.
  1032. //
  1033. {
  1034. pDC->SetPixel(rect.left, rect.top + 2, m_crDarkDkShadow);
  1035. pDC->SetPixel(rect.left + 2, rect.top, m_crDarkDkShadow);
  1036. pDC->SetPixel(rect.right - 3, rect.top, m_crDarkDkShadow);
  1037. pDC->SetPixel(rect.right - 1, rect.top + 2, m_crDarkDkShadow);
  1038. pDC->SetPixel(rect.right - 1, rect.bottom - 3, m_crDarkDkShadow);
  1039. pDC->SetPixel(rect.right - 3, rect.bottom - 1, m_crDarkDkShadow);
  1040. pDC->SetPixel(rect.left + 2, rect.bottom - 1, m_crDarkDkShadow);
  1041. pDC->SetPixel(rect.left, rect.bottom - 3, m_crDarkDkShadow);
  1042. } // DrawCornerShadows
  1043. //-------------------------------------------------------------------
  1044. //
  1045. void CMacButton::DrawPushLikeButton(CDC *pDC, const CRect &rect, UINT nStyle, UINT nState)
  1046. //
  1047. // Return Value: None.
  1048. //
  1049. // Parameters : pDC - A pointer to the DC to draw on.
  1050. // rect - The button's rectangle.
  1051. // nStyle - The button's style.
  1052. // nState - The button's state.
  1053. //
  1054. // Remarks : Draws a push-like check box. This function is only used
  1055. // to draw radio buttons and check boxes that have the 
  1056. // BS_PUSHLIKE style.
  1057. //
  1058. {
  1059. CBrush brFill;
  1060. // Draw a flat button.
  1061. if (nStyle & BS_FLAT)
  1062. {
  1063. COLORREF crFill = ::GetSysColor(COLOR_WINDOW);
  1064. HBITMAP hBmp = GetDitherBitmap(pDC, crFill, ~crFill);
  1065. CBitmap *pBmp = (hBmp ? CBitmap::FromHandle(hBmp) : NULL);
  1066. ASSERT(pBmp);
  1067. // If the mouse is down, use a pattern brush to fill with. 
  1068. // If the button is checked, use the inverted window color.
  1069. if (m_bMouseDown)
  1070. brFill.CreatePatternBrush(pBmp);
  1071. else if (m_nCheck)
  1072. brFill.CreateSolidBrush(~crFill);
  1073. else
  1074. brFill.CreateSolidBrush(crFill);
  1075. CBrush *pOldBrush = (CBrush *)pDC->SelectObject(&brFill);
  1076. CPen pen;
  1077. if (nState & ODS_DISABLED)
  1078. pen.CreatePen(PS_SOLID, 1, m_crDarkDkShadow);
  1079. else if (m_nCheck || m_bMouseDown)
  1080. pen.CreatePen(PS_SOLID, 1, crFill);
  1081. else
  1082. pen.CreatePen(PS_SOLID, 1, ~crFill);
  1083. CPen *pOldPen = (CPen *)pDC->SelectObject(&pen);
  1084. pDC->RoundRect(rect, CPoint(6, 6));
  1085. pDC->SelectObject(pOldBrush);
  1086. pDC->SelectObject(pOldPen);
  1087. pen.DeleteObject();
  1088. brFill.DeleteObject();
  1089. return;
  1090. } // if flat
  1091. HBITMAP hBmp = GetDitherBitmap(pDC, m_crHilight, m_crFace);
  1092. CBitmap *pBmp = (hBmp ? CBitmap::FromHandle(hBmp) : NULL);
  1093. ASSERT(pBmp);
  1094. // Create the brush to fill with.
  1095. if (m_bMouseDown)
  1096. brFill.CreateSolidBrush(m_crLiteShadow);
  1097. else if (m_nCheck)
  1098. brFill.CreatePatternBrush(pBmp);
  1099. else
  1100. brFill.CreateSolidBrush(m_crFace);
  1101. ::DeleteObject(hBmp);
  1102. CBrush *pOldBrush = (CBrush *)pDC->SelectObject(&brFill);
  1103. CPen penBorder(PS_SOLID, 1, nState & ODS_DISABLED ? m_crShadow : ::GetSysColor(COLOR_WINDOWFRAME));
  1104. CPen *pOldPen = (CPen *)pDC->SelectObject(&penBorder);
  1105. // Draw the pressed or unpressed button
  1106. if (nState & ODS_DISABLED)
  1107. pDC->RoundRect(rect, CPoint(6, 6));
  1108. else if (m_bMouseDown || m_nCheck)
  1109. DrawPressedPushButton(pDC, rect);
  1110. else
  1111. DrawUnpressedPushButton(pDC, rect);
  1112. pDC->SelectObject(pOldBrush);
  1113. pDC->SelectObject(pOldPen);
  1114. brFill.DeleteObject();
  1115. } // DrawPushLikeButton
  1116. //-------------------------------------------------------------------
  1117. //
  1118. HBITMAP CMacButton::GetDitherBitmap(CDC *pDC, COLORREF crColor1, COLORREF crColor2)
  1119. //
  1120. // Return Value: An HBITMAP.
  1121. //
  1122. // Parameters : pDC - A pointer to the DC being drawn on.
  1123. // crColor1, crColor2 - Specify the colors used to create a 
  1124. // dither bitmap
  1125. //
  1126. // Remarks : Returns a dithered HBITMAP that is used to create
  1127. // a patter brush for filling a push-like radio button or
  1128. // check box when it is checked.
  1129. //
  1130. {
  1131. struct  // BITMAPINFO with 16 colors
  1132. {
  1133. BITMAPINFOHEADER    bmiHeader;
  1134. RGBQUAD             bmiColors[16];
  1135. } bmi;
  1136. DWORD patGray[8];
  1137. bmi.bmiHeader.biSize         = sizeof(BITMAPINFOHEADER);
  1138. bmi.bmiHeader.biWidth        = 2;
  1139. bmi.bmiHeader.biHeight       = 2;
  1140. bmi.bmiHeader.biPlanes       = 1;
  1141. bmi.bmiHeader.biBitCount     = 1;
  1142. bmi.bmiHeader.biCompression  = BI_RGB;
  1143. bmi.bmiHeader.biSizeImage    = 0;
  1144. bmi.bmiHeader.biXPelsPerMeter= 0;
  1145. bmi.bmiHeader.biYPelsPerMeter= 0;
  1146. bmi.bmiHeader.biClrUsed      = 0;
  1147. bmi.bmiHeader.biClrImportant = 0;
  1148. bmi.bmiColors[0].rgbRed      = GetRValue(crColor1);
  1149. bmi.bmiColors[0].rgbGreen    = GetGValue(crColor1);
  1150. bmi.bmiColors[0].rgbBlue     = GetBValue(crColor1);
  1151. bmi.bmiColors[0].rgbReserved = 0;
  1152. bmi.bmiColors[1].rgbRed      = GetRValue(crColor2);
  1153. bmi.bmiColors[1].rgbGreen    = GetGValue(crColor2);
  1154. bmi.bmiColors[1].rgbBlue     = GetBValue(crColor2);
  1155. bmi.bmiColors[1].rgbReserved = 0;
  1156.    // Create the byte array for CreateDIBitmap.
  1157.    patGray[6] = patGray[4] = patGray[2] = patGray[0] = 0x5555AAAAL;
  1158.    patGray[7] = patGray[5] = patGray[3] = patGray[1] = 0xAAAA5555L;
  1159. return CreateDIBitmap(pDC->m_hDC, &bmi.bmiHeader, CBM_INIT, patGray, 
  1160. (LPBITMAPINFO)&bmi, DIB_RGB_COLORS);
  1161. } // GetDitherBitmap
  1162. //-------------------------------------------------------------------
  1163. //
  1164. void CMacButton::RedrawCheck()
  1165. //
  1166. // Return Value: None.
  1167. //
  1168. // Parameters : None.
  1169. //
  1170. // Remarks : Invalidates the check rectangle of a radio button or check box.
  1171. //
  1172. {
  1173. CRect rect;
  1174. GetClientRect(rect);
  1175. InvalidateRect(GetCheckRect(rect, GetStyle()));
  1176. } // RedrawCheck
  1177. //-------------------------------------------------------------------
  1178. //
  1179. void CMacButton::DrawButtonText(CDC *pDC, CRect &rect, const CString &sText, UINT nStyle, UINT nState)
  1180. //
  1181. // Return Value: None.
  1182. //
  1183. // Parameters : pDC - A pointer to the DC being drawn on.
  1184. // rect - The button's rectangle.
  1185. // sText - The button's text.
  1186. // nStyle - The button's style.
  1187. // nState - The button's state.
  1188. //
  1189. // Remarks : Draws the text on the button.
  1190. //
  1191. {
  1192. CFont *pFont = GetFont();
  1193. CFont *pOldFont = (CFont *)pDC->SelectObject(pFont);
  1194. CFont fontBold;
  1195. if (m_bBold)
  1196. {
  1197. LOGFONT lf;
  1198. pFont->GetLogFont(&lf);
  1199. lf.lfWeight = FW_BOLD;
  1200. fontBold.CreateFontIndirect(&lf);
  1201. pDC->SelectObject(&fontBold);
  1202. }
  1203. CSize sizeText = pDC->GetTextExtent(sText);
  1204. // Determine the rect for the text.
  1205. if ((m_nType == TYPE_STANDARD) || (nStyle & BS_PUSHLIKE))
  1206. {
  1207. if (nStyle & BS_LEFT)
  1208. rect.left += 5;
  1209. else if (nStyle & BS_RIGHT)
  1210. rect.left = rect.right - sizeText.cx - 5;
  1211. else
  1212. rect.left = (rect.Width() - sizeText.cx) >> 1;
  1213. rect.right = rect.left + sizeText.cx;
  1214. if (nStyle & BS_TOP)
  1215. rect.top += (m_nType == TYPE_RADIO? 4 : 5);
  1216. else if (nStyle & BS_BOTTOM)
  1217. rect.top = rect.bottom - sizeText.cy - 5;
  1218. else
  1219. rect.top = (rect.Height() - sizeText.cy) >> 1;
  1220. rect.bottom = rect.top + sizeText.cy;
  1221. }
  1222. else
  1223. {
  1224. if (nStyle & BS_LEFT)
  1225. rect.left = (nStyle & BS_LEFTTEXT ? 2 : CHECKBOX_HEIGHT + 5);
  1226. else if (nStyle & BS_RIGHT)
  1227. rect.left = rect.right - sizeText.cx - (nStyle & BS_LEFTTEXT ? CHECKBOX_HEIGHT + 10 : 5);
  1228. else
  1229. {
  1230. if (m_nType == TYPE_CHECKBOX || m_nType == TYPE_RADIO)
  1231. rect.left = (nStyle & BS_LEFTTEXT ? 2 : CHECKBOX_HEIGHT + 5);
  1232. else
  1233. rect.left = (rect.Width() - sizeText.cx) >> 1;
  1234. }
  1235. rect.right = rect.left + sizeText.cx + (nStyle & BS_LEFTTEXT ? 2 : 0);
  1236. if (nStyle & BS_TOP)
  1237. rect.top = rect.top;
  1238. else if (nStyle & BS_BOTTOM)
  1239. rect.top = rect.bottom - sizeText.cy - 3;
  1240. else
  1241. rect.top = ((rect.Height() - sizeText.cy) >> 1) - 1;
  1242. rect.bottom = rect.top + sizeText.cy;
  1243. }
  1244. if (((m_nType == TYPE_STANDARD) && (nState & ODS_SELECTED)) || 
  1245.  (nStyle & BS_PUSHLIKE) && (m_bMouseDown || ((nStyle & BS_FLAT) && m_nCheck)))
  1246. pDC->SetTextColor(m_crHilight);
  1247. if ((m_nType == TYPE_CHECKBOX) && (nStyle & BS_PUSHLIKE) && (m_nCheck == 2))
  1248. pDC->SetTextColor(m_crShadow);
  1249. // Draw the text.
  1250. pDC->SetBkMode(TRANSPARENT);
  1251. if (nState & ODS_DISABLED)
  1252. {
  1253. pDC->SetTextColor(m_crShadow);
  1254. pDC->DrawText(sText, rect, DT_CENTER);
  1255. }
  1256. else
  1257. pDC->DrawText(sText, rect, DT_CENTER);
  1258. // Restore the original font.
  1259. pDC->SelectObject(pOldFont);
  1260. if (m_bBold)
  1261. fontBold.DeleteObject();
  1262. } // DrawButtonText
  1263. //-------------------------------------------------------------------
  1264. //
  1265. void CMacButton::SetImageEffect(int nEffect)
  1266. //
  1267. // Return Value: None.
  1268. //
  1269. // Parameters : nEffect - The effect to add when drawing the image.
  1270. // Can be one of the following values: 
  1271. // - IMAGE_EFFECT_NONE - No effect is added to the image.
  1272. // - IMAGE_EFFECT_RAISED - The image will appear raised.
  1273. // - IMAGE_EFFECT_SUNKEN - The image will appear sunken.
  1274. //
  1275. // Remarks : Sets the image effect member.
  1276. //
  1277. {
  1278. m_nImageEffect = nEffect;
  1279. RedrawWindow();
  1280. } // SetImageEffect
  1281. //-------------------------------------------------------------------
  1282. //
  1283. void CMacButton::SetCheck(int nCheck)
  1284. //
  1285. // Return Value: None.
  1286. //
  1287. // Parameters : nCheck - Specifies the check state. This parameter 
  1288. // can be one of the following:
  1289. // Value Meaning 
  1290. // 0 Set the button state to unchecked. 
  1291. // 1 Set the button state to checked. 
  1292. // 2 Set the button state to indeterminate.
  1293. //
  1294. // Remarks : Sets or resets the check state of a radio button or 
  1295. // check box. This member function has no effect on a pushbutton.
  1296. //
  1297. {
  1298. if (m_nType == TYPE_STANDARD)
  1299. return;
  1300. int nOldCheck = m_nCheck;
  1301. m_nCheck = nCheck;
  1302. if (m_nCheck != nOldCheck)
  1303. {
  1304. if (GetStyle() & BS_PUSHLIKE)
  1305. RedrawWindow();
  1306. else
  1307. RedrawCheck();
  1308. }
  1309. } // SetCheck
  1310. //-------------------------------------------------------------------
  1311. //
  1312. int CMacButton::GetCheck() const
  1313. //
  1314. // Return Value: 1 if checked, 0 otherwise.
  1315. //
  1316. // Parameters : None.
  1317. //
  1318. // Remarks : Retrieves the check state of button.
  1319. //
  1320. {
  1321. return m_nCheck;
  1322. } // GetCheck
  1323. //-------------------------------------------------------------------
  1324. //
  1325. void CMacButton::SetBold(BOOL bBold /*= TRUE*/)
  1326. //
  1327. // Return Value: None.
  1328. //
  1329. // Parameters : bBold - Used to sed the m_bBold flag. Default value: TRUE.
  1330. //
  1331. // Remarks : Sets the m_bBold flag.
  1332. //
  1333. {
  1334. m_bBold = bBold;
  1335. RedrawWindow();
  1336. } // SetBold
  1337. //-------------------------------------------------------------------
  1338. //
  1339. BOOL CMacButton::GetBold() const
  1340. //
  1341. // Return Value: The bold flag.
  1342. //
  1343. // Parameters : None.
  1344. //
  1345. // Remarks : Returns the bold flag.
  1346. //
  1347. {
  1348. return m_bBold;
  1349. } // GetBold
  1350. /////////////////////////////////////////////////////////////////////////////
  1351. //
  1352. // CMacCheckBox class, version 2.0
  1353. //
  1354. // Copyright (c) 1999, 2000 Paul M. Meidinger (pmmeidinger@yahoo.com)
  1355. //
  1356. // Thanks to:
  1357. // Eric Hwang <erichw@21cn.com>
  1358. // For fixing the problem that was not sending a message
  1359. // to the parent when the button was clicked.
  1360. //
  1361. // History:
  1362. // PMM 12/13/1999 Initial implementation.
  1363. //
  1364. // PMM 12/17/1999 Modified drawing code to use a memory DC. 
  1365. // Added CPen member variables in an attempt to 
  1366. // speed up drawing. Made other minor changes.
  1367. //
  1368. // PMM 12/29/1999 Fixed a bug that would not send a message to the parent
  1369. // when the button was clicked (fix by Eric Hwang). Added
  1370. // code to draw a push-like button when that style is used.
  1371. //
  1372. /////////////////////////////////////////////////////////////////////////////
  1373. //-------------------------------------------------------------------
  1374. //
  1375. CMacCheckBox::CMacCheckBox()
  1376. : CMacButton()
  1377. //
  1378. // Return Value: None.
  1379. //
  1380. // Parameters : None.
  1381. //
  1382. // Remarks : Standard constructor.
  1383. //
  1384. {
  1385. m_nType = TYPE_CHECKBOX;
  1386. m_nCheckStyle = CHECK_STYLE_CHECK;
  1387. } // CMacCheckBox
  1388. //-------------------------------------------------------------------
  1389. //
  1390. CMacCheckBox::~CMacCheckBox()
  1391. //
  1392. // Return Value: None.
  1393. //
  1394. // Parameters : None.
  1395. //
  1396. // Remarks : Destructor. Does nothing.
  1397. //
  1398. {
  1399. } // ~CMacCheckBox
  1400. BEGIN_MESSAGE_MAP(CMacCheckBox, CMacButton)
  1401. //{{AFX_MSG_MAP(CMacCheckBox)
  1402. ON_WM_LBUTTONDOWN()
  1403. ON_WM_LBUTTONUP()
  1404. ON_WM_KEYUP()
  1405. ON_WM_MOUSEMOVE()
  1406. ON_WM_LBUTTONDBLCLK()
  1407. ON_WM_KEYDOWN()
  1408. //}}AFX_MSG_MAP
  1409. END_MESSAGE_MAP()
  1410. /////////////////////////////////////////////////////////////////////////////
  1411. // CMacCheckBox message handlers
  1412. //-------------------------------------------------------------------
  1413. //
  1414. void CMacCheckBox::DrawItem(LPDRAWITEMSTRUCT lpDIS) 
  1415. //
  1416. // Return Value: None.
  1417. //
  1418. // Parameters : lpDIS - A long pointer to a DRAWITEMSTRUCT structure.
  1419. //
  1420. // Remarks : Called by the framework when a visual aspect of an 
  1421. // owner-drawn button has changed.
  1422. //
  1423. {
  1424. DrawButton(lpDIS);
  1425. } // DrawItem
  1426. //-------------------------------------------------------------------
  1427. //
  1428. void CMacCheckBox::OnLButtonUp(UINT /*nFlags*/, CPoint point) 
  1429. //
  1430. // Return Value: None.
  1431. //
  1432. // Parameters : nFlags - Indicates whether various virtual keys are down. 
  1433. // point - Specifies the x- and y-coordinate of the cursor. 
  1434. // These coordinates are always relative to the upper-left 
  1435. // corner of the window.
  1436. //
  1437. // Remarks : The framework calls this member function when the user 
  1438. // releases the left mouse button. Checks to see if the mouse
  1439. // was released over the button. If so, check it.
  1440. //
  1441. {
  1442. ReleaseCapture();
  1443. UINT nStyle = GetStyle();
  1444. if (!(nStyle & BS_AUTOCHECKBOX))
  1445. return;
  1446. CRect rect;
  1447. GetClientRect(rect);
  1448. if (rect.PtInRect(point))
  1449. {
  1450. m_nCheck = (m_nCheck == 0 ? 1 : 0);
  1451. // Send notify message to parent window.
  1452. // Added by Eric Hwang.
  1453. GetParent()->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)GetSafeHwnd());
  1454. }
  1455. m_bMouseDown = FALSE;
  1456. if (nStyle & BS_PUSHLIKE)
  1457. RedrawWindow();
  1458. else
  1459. RedrawCheck();
  1460. } // OnLButtonUp
  1461. //-------------------------------------------------------------------
  1462. //
  1463. void CMacCheckBox::OnLButtonDown(UINT /*nFlags*/, CPoint /*point*/) 
  1464. //
  1465. // Return Value: None.
  1466. //
  1467. // Parameters : nFlags - Indicates whether various virtual keys are down. 
  1468. // point - Specifies the x- and y-coordinate of the cursor. 
  1469. // These coordinates are always relative to the upper-left 
  1470. // corner of the window.
  1471. //
  1472. // Remarks : The framework calls this member function when the user 
  1473. // presses the left mouse button. Sets focus to this button,
  1474. // captures the mouse, and redraws the check.
  1475. //
  1476. {
  1477. m_bMouseDown = TRUE;
  1478. SetFocus();
  1479. SetCapture();
  1480. if (GetStyle() & BS_PUSHLIKE)
  1481. RedrawWindow();
  1482. else
  1483. RedrawCheck();
  1484. } // OnLButtonDown 
  1485. //-------------------------------------------------------------------
  1486. //
  1487. void CMacCheckBox::OnLButtonDblClk(UINT /*nFlags*/, CPoint point) 
  1488. //
  1489. // Return Value: None.
  1490. //
  1491. // Parameters : nFlags - Indicates whether various virtual keys are down.
  1492. // point - Specifies the x- and y-coordinate of the cursor. 
  1493. // These coordinates are always relative to the upper-left
  1494. //  corner of the window.
  1495. //
  1496. // Remarks : The framework calls this member function when the user 
  1497. // double-clicks the left mouse button. The WM_LBUTTONDOWN
  1498. // message is sent to simulate a single click.
  1499. //
  1500. {
  1501. SendMessage(WM_LBUTTONDOWN, 0, MAKELPARAM(point.x, point.y));
  1502. } // OnLButtonDblClk
  1503. //-------------------------------------------------------------------
  1504. //
  1505. void CMacCheckBox::OnMouseMove(UINT /*nFlags*/, CPoint point) 
  1506. //
  1507. // Return Value: None.
  1508. //
  1509. // Parameters : nFlags - Indicates whether various virtual keys are down. 
  1510. // point - Specifies the x- and y-coordinate of the cursor. 
  1511. // These coordinates are always relative to the upper-left 
  1512. // corner of the window.
  1513. //
  1514. // Remarks : The framework calls this member function when the 
  1515. // mouse cursor moves. Checks to see if the mouse is over
  1516. // the button, and redraws the check if it is, but wasn't previously.
  1517. //
  1518. {
  1519. if (GetCapture() != this)
  1520. return;
  1521. BOOL bWasMouseDown = m_bMouseDown;
  1522. CRect rect;
  1523. GetClientRect(rect);
  1524. m_bMouseDown = rect.PtInRect(point);
  1525. if (bWasMouseDown != m_bMouseDown)
  1526. {
  1527. if (GetStyle() & BS_PUSHLIKE)
  1528. RedrawWindow();
  1529. else
  1530. RedrawCheck();
  1531. }
  1532. } // OnMouseMove
  1533. //-------------------------------------------------------------------
  1534. //
  1535. void CMacCheckBox::OnKeyUp(UINT nChar, UINT /*nRepCnt*/, UINT /*nFlags*/) 
  1536. //
  1537. // Return Value: None.
  1538. //
  1539. // Parameters : nChar - Specifies the virtual-key code of the given key.
  1540. // nRepCnt - Repeat count (the number of times the keystroke
  1541. // is repeated as a result of the user holding down the key).
  1542. // nFlags - Specifies the scan code, key-transition code, previous 
  1543. // key state, and context code
  1544. //
  1545. // Remarks : The framework calls this member function when a nonsystem 
  1546. // key is released. Checks/unchecks the button when the space bar
  1547. // is pressed.
  1548. //
  1549. {
  1550. if (nChar == VK_SPACE)
  1551. {
  1552. m_bMouseDown = FALSE;
  1553. m_nCheck = (m_nCheck == 0 ? 1 : 0);
  1554. // Send notify message to parent window.
  1555. // Added by Eric Hwang.
  1556. GetParent()->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)GetSafeHwnd());
  1557. if (GetStyle() & BS_PUSHLIKE)
  1558. RedrawWindow();
  1559. else
  1560. RedrawCheck();
  1561. }
  1562. } // OnKeyUp
  1563. //-------------------------------------------------------------------
  1564. //
  1565. void CMacCheckBox::OnKeyDown(UINT nChar, UINT /*nRepCnt*/, UINT /*nFlags*/) 
  1566. //
  1567. // Return Value: None.
  1568. //
  1569. // Parameters : nChar - Specifies the virtual-key code of the given key.
  1570. // nRepCnt - Repeat count (the number of times the keystroke 
  1571. // is repeated as a result of the user holding down the key).
  1572. // nFlags - Specifies the scan code, key-transition code, 
  1573. // previous key state, and context code
  1574. //
  1575. // Remarks : The framework calls this member function when a 
  1576. // nonsystem key is pressed.
  1577. //
  1578. {
  1579. if (nChar == VK_SPACE)
  1580. {
  1581. if (!m_bMouseDown)
  1582. {
  1583. m_bMouseDown = TRUE;
  1584. if (GetStyle() & BS_PUSHLIKE)
  1585. RedrawWindow();
  1586. else
  1587. RedrawCheck();
  1588. }
  1589. }
  1590. } // OnKeyDown
  1591. //-------------------------------------------------------------------
  1592. //
  1593. void CMacCheckBox::SetCheckStyle(int nStyle /* = CHECK_STYLE_CHECK*/)
  1594. //
  1595. // Return Value: None.
  1596. //
  1597. // Parameters : nStyle - The check style to set. Can be one of the
  1598. // following values:
  1599. // CHECK_STYLE_CHECK Check mark style.
  1600. // CHECK_STYLE_CROSS "X" style.
  1601. //
  1602. // Remarks : Sets the check style.
  1603. //
  1604. {
  1605. m_nCheckStyle = nStyle;
  1606. RedrawCheck();
  1607. } // SetCheckStyle
  1608. //-------------------------------------------------------------------
  1609. //
  1610. int CMacCheckBox::GetCheckStyle() const
  1611. //
  1612. // Return Value: The current check style.
  1613. //
  1614. // Parameters : None.
  1615. //
  1616. // Remarks : Gets the current check style.
  1617. //
  1618. {
  1619. return m_nCheckStyle;
  1620. } // GetCheckStyle
  1621. /////////////////////////////////////////////////////////////////////////////
  1622. //
  1623. // CMacRadioButton class, version 2.0
  1624. //
  1625. // Copyright (c) 1999, 2000 Paul M. Meidinger (pmmeidinger@yahoo.com)
  1626. //
  1627. // Thanks to:
  1628. // Eric Hwang <erichw@21cn.com>
  1629. // For fixing the problem that was not sending a message
  1630. // to the parent when the button was clicked.
  1631. //
  1632. // History:
  1633. // PMM 12/13/1999 Initial implementation.
  1634. //
  1635. // PMM 12/17/1999 Modified drawing code to use a memory DC. 
  1636. // Added CPen member variables in an attempt to 
  1637. // speed up drawing. Made other minor changes.
  1638. //
  1639. // PMM 12/29/1999 Fixed a bug that was not checking the radio
  1640. // and unchecking others when the space bar is pressed.
  1641. // Fixed a bug that would not send a message to the parent
  1642. // when the button was clicked (fix by Eric Hwang). Added
  1643. // code to draw a push-like button when that style is used.
  1644. //
  1645. /////////////////////////////////////////////////////////////////////////////
  1646. //-------------------------------------------------------------------
  1647. //
  1648. CMacRadioButton::CMacRadioButton()
  1649. : CMacButton()
  1650. //
  1651. // Return Value: None.
  1652. //
  1653. // Parameters : None.
  1654. //
  1655. // Remarks : Standard constructor.
  1656. //
  1657. {
  1658. m_nType = TYPE_RADIO;
  1659. } // CMacRadioButton
  1660. //-------------------------------------------------------------------
  1661. //
  1662. CMacRadioButton::~CMacRadioButton()
  1663. //
  1664. // Return Value: None.
  1665. //
  1666. // Parameters : None.
  1667. //
  1668. // Remarks : Destructor. Does nothing.
  1669. //
  1670. {
  1671. } // ~CMacRadioButton
  1672. BEGIN_MESSAGE_MAP(CMacRadioButton, CMacButton)
  1673. //{{AFX_MSG_MAP(CMacRadioButton)
  1674. ON_WM_LBUTTONUP()
  1675. ON_WM_LBUTTONDOWN()
  1676. ON_WM_MOUSEMOVE()
  1677. ON_WM_LBUTTONDBLCLK()
  1678. ON_WM_SYSCOLORCHANGE()
  1679. ON_WM_KEYDOWN()
  1680. ON_WM_KEYUP()
  1681. ON_WM_SETFOCUS()
  1682. //}}AFX_MSG_MAP
  1683. END_MESSAGE_MAP()
  1684. /////////////////////////////////////////////////////////////////////////////
  1685. // CMacRadioButton message handlers
  1686. //-------------------------------------------------------------------
  1687. //
  1688. void CMacRadioButton::DrawItem(LPDRAWITEMSTRUCT lpDIS) 
  1689. //
  1690. // Return Value: None.
  1691. //
  1692. // Parameters : lpDIS - A long pointer to a DRAWITEMSTRUCT structure.
  1693. //
  1694. // Remarks : Called by the framework when a visual aspect of an 
  1695. // owner-drawn button has changed.
  1696. //
  1697. {
  1698. DrawButton(lpDIS);
  1699. } // DrawItem
  1700. //-------------------------------------------------------------------
  1701. //
  1702. BOOL CMacRadioButton::PreTranslateMessage(MSG* pMsg) 
  1703. //
  1704. // Return Value: Nonzero if the message was translated and should not 
  1705. // be dispatched; 0 if the message was not translated 
  1706. // and should be dispatched.
  1707. //
  1708. // Parameters : pMsg - Points to a MSG structure that contains the 
  1709. // message to process.
  1710. //
  1711. // Remarks : Used by class CWinApp to translate window messages 
  1712. // before they are dispatched to theTranslateMessage 
  1713. // andDispatchMessage Windows functions. Catches the 
  1714. // WM_KEYDOWN message and handles the up, down, left
  1715. // and right arrows.
  1716. //
  1717. {
  1718. if (pMsg->message == WM_KEYDOWN)
  1719. {
  1720. if (pMsg->wParam == VK_DOWN || pMsg->wParam == VK_UP ||
  1721.  pMsg->wParam == VK_LEFT || pMsg->wParam == VK_RIGHT)
  1722. {
  1723. UncheckOtherRadios();
  1724. // Get the previous/next button and check it.
  1725. CWnd *pParent = GetParent();
  1726. ASSERT(pParent);
  1727. CWnd *pWnd = pParent->GetNextDlgGroupItem((CWnd *)this, (pMsg->wParam == VK_LEFT || pMsg->wParam == VK_UP ? TRUE : FALSE));
  1728. if (pWnd && (((CButton*)pWnd)->GetButtonStyle() & BS_AUTORADIOBUTTON) && ((CMacRadioButton *)pWnd)->m_nType == TYPE_RADIO)
  1729. {
  1730. ((CMacRadioButton *)pWnd)->SetCheck(1);
  1731. // Send notify message to parent window.
  1732. // Added by Eric Hwang.
  1733. pParent->SendMessage(WM_COMMAND, MAKEWPARAM(pWnd->GetDlgCtrlID(), BN_CLICKED), (LPARAM)pWnd->GetSafeHwnd());
  1734. }
  1735. SetCheck(0);
  1736. return FALSE;
  1737. }
  1738. }
  1739. return CMacButton::PreTranslateMessage(pMsg);
  1740. } // PreTranslateMessage
  1741. //-------------------------------------------------------------------
  1742. //
  1743. void CMacRadioButton::OnLButtonUp(UINT /*nFlags*/, CPoint point) 
  1744. //
  1745. // Return Value: None.
  1746. //
  1747. // Parameters : nFlags - Indicates whether various virtual keys are down. 
  1748. // point - Specifies the x- and y-coordinate of the cursor. 
  1749. // These coordinates are always relative to the upper-left 
  1750. // corner of the window.
  1751. //
  1752. // Remarks : The framework calls this member function when the user 
  1753. // releases the left mouse button. Checks to see if the mouse
  1754. // was released over the button. If so, check it and uncheck others.
  1755. //
  1756. {
  1757. ReleaseCapture();
  1758. UINT nStyle = GetStyle();
  1759. CRect rect;
  1760. GetClientRect(rect);
  1761. if (rect.PtInRect(point))
  1762. {
  1763. if (!m_nCheck)
  1764. m_nCheck = 1;
  1765. // Uncheck all other radios in the group
  1766. if ((nStyle & BS_AUTORADIOBUTTON) && m_nCheck)
  1767. {
  1768. UncheckOtherRadios();
  1769. }
  1770. // Send notify message to parent window.
  1771. // Added by Eric Hwang
  1772. GetParent()->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)GetSafeHwnd());
  1773. }
  1774. m_bMouseDown = FALSE;
  1775. if (nStyle & BS_PUSHLIKE)
  1776. RedrawWindow();
  1777. else
  1778. RedrawCheck();
  1779. // CMacButton::OnLButtonUp(nFlags, point);
  1780. } // OnLButtonUp
  1781. //-------------------------------------------------------------------
  1782. //
  1783. void CMacRadioButton::OnLButtonDown(UINT /*nFlags*/, CPoint /*point*/) 
  1784. //
  1785. // Return Value: None.
  1786. //
  1787. // Parameters : nFlags - Indicates whether various virtual keys are down. 
  1788. // point - Specifies the x- and y-coordinate of the cursor. 
  1789. // These coordinates are always relative to the upper-left 
  1790. // corner of the window.
  1791. //
  1792. // Remarks : The framework calls this member function when the user 
  1793. // presses the left mouse button. Sets focus to this button,
  1794. // captures the mouse, and redraws the check.
  1795. //
  1796. {
  1797. m_bMouseDown = TRUE;
  1798. SetFocus();
  1799. SetCapture();
  1800. if (GetStyle() & BS_PUSHLIKE)
  1801. RedrawWindow();
  1802. else
  1803. RedrawCheck();
  1804. // CMacButton::OnLButtonDown(nFlags, point);
  1805. } // OnLButtonDown
  1806. //-------------------------------------------------------------------
  1807. //
  1808. void CMacRadioButton::OnMouseMove(UINT nFlags, CPoint point) 
  1809. //
  1810. // Return Value: None.
  1811. //
  1812. // Parameters : nFlags - Indicates whether various virtual keys are down. 
  1813. // point - Specifies the x- and y-coordinate of the cursor. 
  1814. // These coordinates are always relative to the upper-left 
  1815. // corner of the window.
  1816. //
  1817. // Remarks : The framework calls this member function when the 
  1818. // mouse cursor moves. Checks to see if the mouse is over
  1819. // the button, and redraws the check if it is, but wasn't previously.
  1820. //
  1821. {
  1822. if (GetCapture() != this)
  1823. return;
  1824. BOOL bWasMouseDown = m_bMouseDown;
  1825. CRect rect;
  1826. GetClientRect(rect);
  1827. m_bMouseDown = rect.PtInRect(point);
  1828. if (bWasMouseDown != m_bMouseDown)
  1829. {
  1830. if (GetStyle() & BS_PUSHLIKE)
  1831. RedrawWindow();
  1832. else
  1833. RedrawCheck();
  1834. }
  1835. CMacButton::OnMouseMove(nFlags, point);
  1836. } // OnMouseMove
  1837. //-------------------------------------------------------------------
  1838. //
  1839. void CMacRadioButton::OnLButtonDblClk(UINT /*nFlags*/, CPoint point) 
  1840. //
  1841. // Return Value: None.
  1842. //
  1843. // Parameters : nFlags - Indicates whether various virtual keys are down.
  1844. // point - Specifies the x- and y-coordinate of the cursor. 
  1845. // These coordinates are always relative to the upper-left
  1846. //  corner of the window.
  1847. //
  1848. // Remarks : The framework calls this member function when the user 
  1849. // double-clicks the left mouse button. The WM_LBUTTONDOWN
  1850. // message is sent to simulate a single click.
  1851. //
  1852. {
  1853. SendMessage(WM_LBUTTONDOWN, 0, MAKELPARAM(point.x, point.y));
  1854. } // OnLButtonDblClk
  1855. //-------------------------------------------------------------------
  1856. //
  1857. void CMacRadioButton::OnKeyUp(UINT nChar, UINT /*nRepCnt*/, UINT /*nFlags*/) 
  1858. //
  1859. // Return Value: None.
  1860. //
  1861. // Parameters : nChar - Specifies the virtual-key code of the given key.
  1862. // nRepCnt - Repeat count (the number of times the keystroke 
  1863. // is repeated as a result of the user holding down the key).
  1864. // nFlags - Specifies the scan code, key-transition code, 
  1865. // previous key state, and context code
  1866. //
  1867. // Remarks : The framework calls this member function when a 
  1868. // nonsystem key is released. 
  1869. //
  1870. {
  1871. if (nChar == VK_SPACE)
  1872. {
  1873. m_nCheck = 1;
  1874. // Send notify message to parent window.
  1875. // Added by Eric Hwang.
  1876. GetParent()->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)GetSafeHwnd());
  1877. UncheckOtherRadios();
  1878. m_bMouseDown = FALSE;
  1879. if (GetStyle() & BS_PUSHLIKE)
  1880. RedrawWindow();
  1881. else
  1882. RedrawCheck();
  1883. }
  1884. } // OnKeyUp
  1885. //-------------------------------------------------------------------
  1886. //
  1887. void CMacRadioButton::OnKeyDown(UINT nChar, UINT /*nRepCnt*/, UINT /*nFlags*/) 
  1888. //
  1889. // Return Value: None.
  1890. //
  1891. // Parameters : nChar - Specifies the virtual-key code of the given key.
  1892. // nRepCnt - Repeat count (the number of times the keystroke 
  1893. // is repeated as a result of the user holding down the key).
  1894. // nFlags - Specifies the scan code, key-transition code, 
  1895. // previous key state, and context code
  1896. //
  1897. // Remarks : The framework calls this member function when a 
  1898. // nonsystem key is pressed.
  1899. //
  1900. {
  1901. if (nChar == VK_SPACE)
  1902. {
  1903. if (!m_bMouseDown)
  1904. {
  1905. m_bMouseDown = TRUE;
  1906. if (GetStyle() & BS_PUSHLIKE)
  1907. RedrawWindow();
  1908. else
  1909. RedrawCheck();
  1910. }
  1911. }
  1912. } // OnKeyDown
  1913. //-------------------------------------------------------------------
  1914. //
  1915. void CMacRadioButton::OnSysColorChange() 
  1916. //
  1917. // Return Value: None.
  1918. //
  1919. // Parameters : None.
  1920. //
  1921. // Remarks : The framework calls this member function for all 
  1922. // top-level windows when a change is made in the 
  1923. // system color setting
  1924. //
  1925. {
  1926. CMacButton::OnSysColorChange();
  1927. GetColors();
  1928. CreatePens();
  1929. } // OnSysColorChange
  1930. //-------------------------------------------------------------------
  1931. //
  1932. void CMacRadioButton::UncheckOtherRadios()
  1933. //
  1934. // Return Value: None.
  1935. //
  1936. // Parameters : None.
  1937. //
  1938. // Remarks : Attempts to uncheck all other radio buttons in the group.
  1939. //
  1940. {
  1941. // Go backwards (GetNextDlgItem will wrap around to the end of the group).
  1942. CWnd *pParent = GetParent();
  1943. ASSERT(pParent);
  1944. CWnd *pWnd = pParent->GetNextDlgGroupItem((CWnd *)this);
  1945. while (pWnd && (pWnd != this))
  1946. {
  1947. if ((((CButton*)pWnd)->GetButtonStyle() & BS_AUTORADIOBUTTON) && 
  1948.  ((CMacRadioButton *)pWnd)->m_nType == TYPE_RADIO)
  1949. {
  1950. ((CMacRadioButton *)pWnd)->SetCheck(0);
  1951. }
  1952. pWnd = pParent->GetNextDlgGroupItem(pWnd);
  1953. }
  1954. } // UncheckOtherRadios
  1955. //-------------------------------------------------------------------
  1956. //
  1957. void CMacRadioButton::OnSetFocus(CWnd* pOldWnd) 
  1958. //
  1959. // Return Value: None.
  1960. //
  1961. // Parameters : pOldWnd - Contains the CWnd object that loses the 
  1962. // input focus (may be NULL). The pointer may be 
  1963. // temporary and should not be stored for later use.
  1964. //
  1965. // Remarks : The framework calls this member function after gaining 
  1966. // the input focus.
  1967. //
  1968. {
  1969. CMacButton::OnSetFocus(pOldWnd);
  1970. if (m_nCheck || m_bMouseDown)
  1971. return;
  1972. // If another button in this group is checked, set the 
  1973. // focus to that button; if not, set the focus to this button.
  1974. // Get the previous/next button and check it.
  1975. CWnd *pParent = GetParent();
  1976. ASSERT(pParent);
  1977. CWnd *pWnd = pParent->GetNextDlgGroupItem((CWnd *)this);
  1978. while (pWnd && (pWnd != this) && (((CButton*)pWnd)->GetButtonStyle() & BS_AUTORADIOBUTTON) && ((CMacRadioButton *)pWnd)->m_nType == TYPE_RADIO)
  1979. {
  1980. if (((CMacRadioButton*)pWnd)->GetCheck())
  1981. {
  1982. pWnd->SetFocus();
  1983. break;
  1984. }
  1985. pWnd = pParent->GetNextDlgGroupItem(pWnd);
  1986. }
  1987. } // OnSetFocus
  1988. /////////////////////////////////////////////////////////////////////////////
  1989. //
  1990. // CMacMoreButton class, version 2.0
  1991. //
  1992. // Copyright (c) 2000 Paul M. Meidinger (pmmeidinger@yahoo.com)
  1993. //
  1994. // History:
  1995. // PMM 1/21/2000 Initial implementation.
  1996. //
  1997. /////////////////////////////////////////////////////////////////////////////
  1998. //-------------------------------------------------------------------
  1999. //
  2000. CMacMoreButton::CMacMoreButton()
  2001. //
  2002. // Return Value: None.
  2003. //
  2004. // Parameters : None.
  2005. //
  2006. // Remarks : Standard constructor.
  2007. //
  2008. {
  2009. m_nType = TYPE_MORE;
  2010. m_nAlignText = ALIGN_TEXT_LEFT;
  2011. m_bMouseDown = FALSE;
  2012. m_bDoEffect = FALSE;
  2013. m_bMoreShown = FALSE;
  2014. SetColor(::GetSysColor(COLOR_3DFACE));
  2015. } // CMacMoreButton
  2016. //-------------------------------------------------------------------
  2017. //
  2018. CMacMoreButton::~CMacMoreButton()
  2019. //
  2020. // Return Value: None.
  2021. //
  2022. // Parameters : None.
  2023. //
  2024. // Remarks : Destructor. Does nothing.
  2025. //
  2026. {
  2027. } // ~CMacMoreButton
  2028. BEGIN_MESSAGE_MAP(CMacMoreButton, CButton)
  2029. //{{AFX_MSG_MAP(CMacMoreButton)
  2030. ON_WM_LBUTTONDBLCLK()
  2031. ON_WM_LBUTTONUP()
  2032. ON_WM_SYSCOLORCHANGE()
  2033. ON_WM_LBUTTONDOWN()
  2034. //}}AFX_MSG_MAP
  2035. END_MESSAGE_MAP()
  2036. /////////////////////////////////////////////////////////////////////////////
  2037. // CMacMoreButton message handlers
  2038. //-------------------------------------------------------------------
  2039. //
  2040. void CMacMoreButton::PreSubclassWindow()
  2041. //
  2042. // Return Value: None.
  2043. //
  2044. // Parameters : None.
  2045. //
  2046. // Remarks : This member function is called by the framework to 
  2047. // allow other necessary subclassing to occur before the 
  2048. // window is subclassed. Adds the BS_OWNERDRAW style and
  2049. // resizes the button.
  2050. //
  2051. {
  2052. CMacButton::PreSubclassWindow();
  2053. // Add length to the right of the button to accommodate the arrow.
  2054. CRect rect;
  2055. GetClientRect(rect);
  2056. rect.right += 12;
  2057. // Convert the button's client coordinates to the parent's client coordinates.
  2058. ClientToScreen(rect);
  2059. CWnd* pParent = GetParent();
  2060. if (pParent)
  2061. pParent->ScreenToClient(rect);
  2062. // Resize the window.
  2063. MoveWindow(rect, TRUE);
  2064. } // PreSubclassWindow
  2065. //-------------------------------------------------------------------
  2066. //
  2067. void CMacMoreButton::DrawItem(LPDRAWITEMSTRUCT lpDIS) 
  2068. //
  2069. // Return Value: None.
  2070. //
  2071. // Parameters : lpDIS - A long pointer to a DRAWITEMSTRUCT structure.
  2072. //
  2073. // Remarks : Called by the framework when a visual aspect of an 
  2074. // owner-drawn button has changed.
  2075. //
  2076. {
  2077. CDC* pDC = CDC::FromHandle(lpDIS->hDC);
  2078. CRect rectItem(lpDIS->rcItem);
  2079. // Create a mem DC for drawing
  2080. CDC dcMem;
  2081. dcMem.CreateCompatibleDC(pDC);
  2082. CBitmap bmp;
  2083. bmp.CreateCompatibleBitmap(pDC, rectItem.Width(), rectItem.Height());
  2084. CBitmap *pOldBmp = dcMem.SelectObject(&bmp);
  2085. int nSaveDC = dcMem.SaveDC();
  2086. dcMem.SelectStockObject(NULL_BRUSH);
  2087. dcMem.FillSolidRect(rectItem, ::GetSysColor(COLOR_3DFACE));
  2088. // Draw the text, if any.
  2089. CString sText;
  2090. GetWindowText(sText);
  2091. if (!sText.IsEmpty())
  2092. {
  2093. CFont *pOldFont = (CFont *)dcMem.SelectObject(GetFont());
  2094. CSize sizeText = dcMem.GetTextExtent(sText);
  2095. dcMem.SetBkMode(TRANSPARENT);
  2096. CRect rectText(rectItem);
  2097. rectText.top = (rectText.Height() - sizeText.cy) >> 1;
  2098. dcMem.SetTextColor(lpDIS->itemState & ODS_DISABLED ? m_crShadow : m_crDkShadow);
  2099. if (m_nAlignText == ALIGN_TEXT_RIGHT)
  2100. rectText.left += 16;
  2101. dcMem.DrawText(sText, rectText, DT_LEFT | DT_VCENTER);
  2102. dcMem.SelectObject(pOldFont);
  2103. }
  2104. int nRight = (sText.IsEmpty() || (m_nAlignText == ALIGN_TEXT_RIGHT) ? 
  2105. rectItem.left + 10 : rectItem.right - 2);
  2106. int nTop = (rectItem.Height() - 11) >> 1;
  2107. if (lpDIS->itemState & ODS_DISABLED)
  2108. {
  2109. // Select the frame pen, since we always draw with that first.
  2110. CPen penShadow(PS_SOLID, 1, m_crShadow);
  2111. CPen *pOldPen = (CPen *)dcMem.SelectObject(&penShadow);
  2112. if (m_bMoreShown)
  2113. {
  2114. for (int i = 0; i < 6; i++)
  2115. {
  2116. dcMem.MoveTo(nRight - i, nTop + 3 + i);
  2117. dcMem.LineTo((nRight - 11) + i, nTop + 3 + i);
  2118. }
  2119. }
  2120. else
  2121. {
  2122. for (int i = 0; i < 6; i++)
  2123. {
  2124. dcMem.MoveTo((nRight - 7) + i, nTop + i);
  2125. dcMem.LineTo((nRight - 7) + i, nTop + 11 - i);
  2126. }
  2127. }
  2128. rectItem = lpDIS->rcItem;
  2129. pDC->BitBlt(rectItem.left, rectItem.top, rectItem.Width(), rectItem.Height(), &dcMem, rectItem.left, rectItem.top, SRCCOPY);
  2130. dcMem.SelectObject(pOldPen);
  2131. dcMem.SelectObject(pOldBmp);
  2132. dcMem.RestoreDC(nSaveDC);
  2133. dcMem.DeleteDC();
  2134. bmp.DeleteObject();
  2135. return;
  2136. } // if disabled
  2137. // Give the effect of the button "turning" by drawing an intermediate step.
  2138. if (m_bDoEffect)
  2139. {
  2140. // Select the frame pen, since we always draw with that first.
  2141. CPen *pOldPen = (CPen *)dcMem.SelectObject(&m_penDkShadow);
  2142. m_bDoEffect = FALSE;
  2143. dcMem.MoveTo(nRight - 10, nTop + 7);
  2144. dcMem.LineTo(nRight - 3, nTop);
  2145. dcMem.LineTo(nRight - 3, nTop + 7);
  2146. dcMem.LineTo(nRight - 10, nTop + 7);
  2147. dcMem.SelectObject(&m_penShadow);
  2148. dcMem.MoveTo(nRight - 9, nTop + 8);
  2149. dcMem.LineTo(nRight - 2, nTop + 8);
  2150. dcMem.LineTo(nRight - 2, nTop);
  2151. dcMem.SelectObject(&m_penFace);
  2152. dcMem.MoveTo(nRight - 7, nTop + 6);
  2153. dcMem.LineTo(nRight - 4, nTop + 3);
  2154. dcMem.SetPixel(nRight - 5, nTop + 5, m_crFace);
  2155. dcMem.SelectObject(&m_penLiteFace);
  2156. dcMem.MoveTo(nRight - 8, nTop + 6);
  2157. dcMem.LineTo(nRight - 3, nTop + 1);
  2158. dcMem.SelectObject(&m_penLiteShadow);
  2159. dcMem.MoveTo(nRight - 6, nTop + 6);
  2160. dcMem.LineTo(nRight - 4, nTop + 6);
  2161. dcMem.LineTo(nRight - 4, nTop + 2);
  2162. rectItem = lpDIS->rcItem;
  2163. pDC->BitBlt(rectItem.left, rectItem.top, rectItem.Width(), rectItem.Height(), &dcMem, rectItem.left, rectItem.top, SRCCOPY);
  2164. dcMem.SelectObject(pOldPen);
  2165. dcMem.SelectObject(pOldBmp);
  2166. dcMem.RestoreDC(nSaveDC);
  2167. dcMem.DeleteDC();
  2168. bmp.DeleteObject();
  2169. Sleep(50);
  2170. RedrawWindow();
  2171. return;
  2172. } // if drawing effect
  2173. // Darken the colors if the mouse is down.
  2174. COLORREF crSaved = m_crFace;
  2175. if (lpDIS->itemState & ODS_SELECTED)
  2176. {
  2177. m_crFace = DarkenColor(m_crFace, 51);
  2178. GetColors();
  2179. CreatePens();
  2180. }
  2181. // Select the frame pen, since we always draw with that first.
  2182. CPen *pOldPen = (CPen *)dcMem.SelectObject(&m_penDkShadow);
  2183. // If "more" is shown, draw the arrow in the "more" position.
  2184. if (m_bMoreShown)
  2185. {
  2186. nTop += 3;
  2187. dcMem.MoveTo(nRight, nTop);
  2188. dcMem.LineTo(nRight - 10, nTop);
  2189. dcMem.LineTo(nRight - 5, nTop + 5);
  2190. dcMem.LineTo(nRight, nTop);
  2191. dcMem.SelectObject(&m_penShadow);
  2192. dcMem.MoveTo(nRight - 4, nTop + 5);
  2193. dcMem.LineTo(nRight + 1, nTop);
  2194. dcMem.SelectObject(&m_penFace);
  2195. dcMem.MoveTo(nRight - 7, nTop + 2);
  2196. dcMem.LineTo(nRight - 3, nTop + 2);
  2197. dcMem.MoveTo(nRight - 6, nTop + 3);
  2198. dcMem.LineTo(nRight - 4, nTop + 3);
  2199. dcMem.SetPixel(nRight - 2, nTop + 1, m_crFace);
  2200. dcMem.SelectObject(&m_penLiteFace);
  2201. dcMem.MoveTo(nRight - 8, nTop + 1);
  2202. dcMem.LineTo(nRight - 2, nTop + 1);
  2203. dcMem.SelectObject(&m_penLiteShadow);
  2204. dcMem.MoveTo(nRight - 5, nTop + 4);
  2205. dcMem.LineTo(nRight - 2, nTop + 1);
  2206. }
  2207. // Else draw the button in the normal position.
  2208. else
  2209. {
  2210. dcMem.MoveTo(nRight - 7, nTop);
  2211. dcMem.LineTo(nRight - 7, nTop + 10);
  2212. dcMem.LineTo(nRight - 2, nTop + 5);
  2213. dcMem.LineTo(nRight - 7, nTop);
  2214. dcMem.SelectObject(&m_penShadow);
  2215. dcMem.MoveTo(nRight - 6, nTop + 10);
  2216. dcMem.LineTo(nRight - 1, nTop + 5);
  2217. dcMem.SelectObject(&m_penFace);
  2218. dcMem.MoveTo(nRight - 5, nTop + 3);
  2219. dcMem.LineTo(nRight - 5, nTop + 7);
  2220. dcMem.MoveTo(nRight - 4, nTop + 4);
  2221. dcMem.LineTo(nRight - 4, nTop + 6);
  2222. dcMem.SetPixel(nRight - 6, nTop + 8, m_crFace);
  2223. dcMem.SelectObject(&m_penLiteFace);
  2224. dcMem.MoveTo(nRight - 6, nTop + 2);
  2225. dcMem.LineTo(nRight - 6, nTop + 8);
  2226. dcMem.SelectObject(&m_penLiteShadow);
  2227. dcMem.MoveTo(nRight - 5, nTop + 7);
  2228. dcMem.LineTo(nRight - 2, nTop + 4);
  2229. } // else draw normal button
  2230. rectItem = lpDIS->rcItem;
  2231. pDC->BitBlt(rectItem.left, rectItem.top, rectItem.Width(), rectItem.Height(), &dcMem, rectItem.left, rectItem.top, SRCCOPY);
  2232. // Restore the colors if they were darkened.
  2233. if (lpDIS->itemState & ODS_SELECTED)
  2234. {
  2235. m_crFace = crSaved;
  2236. GetColors();
  2237. CreatePens();
  2238. }
  2239. // Clean up.
  2240. dcMem.SelectObject(pOldPen);
  2241. dcMem.SelectObject(pOldBmp);
  2242. dcMem.RestoreDC(nSaveDC);
  2243. dcMem.DeleteDC();
  2244. bmp.DeleteObject();
  2245. } // DrawItem
  2246. //-------------------------------------------------------------------
  2247. //
  2248. void CMacMoreButton::SetColor(COLORREF crColor)
  2249. //
  2250. // Return Value: None.
  2251. //
  2252. // Parameters : crColor - Used to set m_crFace.
  2253. //
  2254. // Remarks : Sets m_crFace and gets the other colors.
  2255. //
  2256. {
  2257. m_crFace = crColor;
  2258. GetColors();
  2259. CreatePens();
  2260. } // SetColor
  2261. //-------------------------------------------------------------------
  2262. //
  2263. void CMacMoreButton::OnLButtonUp(UINT nFlags, CPoint point) 
  2264. //
  2265. // Return Value: None.
  2266. //
  2267. // Parameters : nFlags - Indicates whether various virtual keys are down. 
  2268. // point - Specifies the x- and y-coordinate of the cursor. 
  2269. // These coordinates are always relative to the upper-left 
  2270. // corner of the window.
  2271. //
  2272. // Remarks : The framework calls this member function when the user 
  2273. // releases the left mouse button. Checks to see if the mouse
  2274. // was released over the button. If so, check it.
  2275. //
  2276. {
  2277. CMacButton::OnLButtonUp(nFlags, point);
  2278. CRect rect;
  2279. GetClientRect(rect);
  2280. if (m_bMouseDown && rect.PtInRect(point))
  2281. {
  2282. m_bMoreShown = !m_bMoreShown;
  2283. m_bDoEffect = TRUE;
  2284. RedrawWindow();
  2285. }
  2286. m_bMouseDown = FALSE;
  2287. } // OnLButtonUp
  2288. //-------------------------------------------------------------------
  2289. //
  2290. void CMacMoreButton::OnLButtonDown(UINT nFlags, CPoint point) 
  2291. //
  2292. // Return Value: None.
  2293. //
  2294. // Parameters : nFlags - Indicates whether various virtual keys are down. 
  2295. // point - Specifies the x- and y-coordinate of the cursor. 
  2296. // These coordinates are always relative to the upper-left 
  2297. // corner of the window.
  2298. //
  2299. // Remarks : The framework calls this member function when the user 
  2300. // presses the left mouse button. Sets focus to this button,
  2301. // captures the mouse, and redraws the check.
  2302. //
  2303. {
  2304. m_bMouseDown = TRUE;
  2305. CMacButton::OnLButtonDown(nFlags, point);
  2306. } // OnLButtonDown
  2307. //-------------------------------------------------------------------
  2308. //
  2309. BOOL CMacMoreButton::GetMoreShown() const
  2310. //
  2311. // Return Value: m_bMoreShown.
  2312. //
  2313. // Parameters : None.
  2314. //
  2315. // Remarks : Returns m_bMoreShown.
  2316. //
  2317. {
  2318. return m_bMoreShown;
  2319. } // GetMoreShown
  2320. //-------------------------------------------------------------------
  2321. //
  2322. void CMacMoreButton::SetTextAlign(int nAlign)
  2323. //
  2324. // Return Value: None.
  2325. //
  2326. // Parameters : nAlign - Specifies the text alignment. Can be one of
  2327. // the following values:
  2328. // ALIGN_TEXT_LEFT Aligns text to the left of the button.
  2329. // ALIGN_TEXT_RIGHT Aligns text to the right of the button
  2330. //
  2331. // Remarks : Sets the text alignment.
  2332. //
  2333. {
  2334. m_nAlignText = nAlign;
  2335. RedrawWindow();
  2336. } // SetTextAlign