BtnST.cpp
上传用户:popouu88
上传日期:2013-02-11
资源大小:2894k
文件大小:68k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. #include "stdafx.h"
  2. #include "BtnST.h"
  3. #ifdef BTNST_USE_SOUND
  4. #pragma comment(lib, "winmm.lib")
  5. #include <Mmsystem.h>
  6. #endif
  7. #ifdef _DEBUG
  8. #define new DEBUG_NEW
  9. #undef THIS_FILE
  10. static char THIS_FILE[] = __FILE__;
  11. #endif
  12. /////////////////////////////////////////////////////////////////////////////
  13. // CButtonST
  14. // Mask for control's type
  15. #define BS_TYPEMASK SS_TYPEMASK
  16. #ifndef TTM_SETTITLE
  17. #define TTM_SETTITLEA           (WM_USER + 32)  // wParam = TTI_*, lParam = char* szTitle
  18. #define TTM_SETTITLEW           (WM_USER + 33)  // wParam = TTI_*, lParam = wchar* szTitle
  19. #ifdef UNICODE
  20. #define TTM_SETTITLE            TTM_SETTITLEW
  21. #else
  22. #define TTM_SETTITLE            TTM_SETTITLEA
  23. #endif
  24. #endif
  25. #ifndef TTS_BALLOON
  26. #define TTS_BALLOON 0x40
  27. #endif
  28. CButtonST::CButtonST()
  29. {
  30. m_bIsPressed = FALSE;
  31. m_bIsFocused = FALSE;
  32. m_bIsDisabled = FALSE;
  33. m_bMouseOnButton = FALSE;
  34. FreeResources(FALSE);
  35. // Default type is "flat" button
  36. m_bIsFlat = TRUE;
  37. // Button will be tracked also if when the window is inactive (like Internet Explorer)
  38. m_bAlwaysTrack = TRUE;
  39.   
  40. // By default draw border in "flat" button 
  41. m_bDrawBorder = TRUE; 
  42.   
  43. // By default icon is aligned horizontally
  44. m_byAlign = ST_ALIGN_HORIZ; 
  45. // By default use usual pressed style
  46. SetPressedStyle(BTNST_PRESSED_LEFTRIGHT, FALSE);
  47.   
  48. // By default, for "flat" button, don't draw the focus rect
  49. m_bDrawFlatFocus = FALSE;
  50. // By default the button is not the default button
  51. m_bIsDefault = FALSE;
  52. // Invalid value, since type still unknown
  53. m_nTypeStyle = BS_TYPEMASK;
  54. // By default the button is not a checkbox
  55. m_bIsCheckBox = FALSE;
  56. m_nCheck = 0;
  57. // Set default colors
  58. SetDefaultColors(FALSE);
  59. // No tooltip created
  60. m_ToolTip.m_hWnd = NULL;
  61. m_dwToolTipStyle = 0;
  62. // Do not draw as a transparent button
  63. m_bDrawTransparent = FALSE;
  64. m_pbmpOldBk = NULL;
  65. // No URL defined
  66. SetURL(NULL);
  67. // No cursor defined
  68. m_hCursor = NULL;
  69. // No associated menu
  70. #ifndef BTNST_USE_BCMENU
  71. m_hMenu = NULL;
  72. #endif
  73. m_hParentWndMenu = NULL;
  74. m_bMenuDisplayed = FALSE;
  75. m_bShowDisabledBitmap = TRUE;
  76. m_ptImageOrg.x = 3;
  77. m_ptImageOrg.y = 3;
  78. // No defined callbacks
  79. ::ZeroMemory(&m_csCallbacks, sizeof(m_csCallbacks));
  80. #ifdef BTNST_USE_SOUND
  81. // No defined sounds
  82. ::ZeroMemory(&m_csSounds, sizeof(m_csSounds));
  83. #endif
  84. } // End of CButtonST
  85. CButtonST::~CButtonST()
  86. {
  87. // Restore old bitmap (if any)
  88. if (m_dcBk.m_hDC && m_pbmpOldBk)
  89. {
  90. m_dcBk.SelectObject(m_pbmpOldBk);
  91. } // if
  92. FreeResources();
  93. // Destroy the cursor (if any)
  94. if (m_hCursor) ::DestroyCursor(m_hCursor);
  95. // Destroy the menu (if any)
  96. #ifdef BTNST_USE_BCMENU
  97. if (m_menuPopup.m_hMenu) m_menuPopup.DestroyMenu();
  98. #else
  99. if (m_hMenu) ::DestroyMenu(m_hMenu);
  100. #endif
  101. } // End of ~CButtonST
  102. BEGIN_MESSAGE_MAP(CButtonST, CButton)
  103.     //{{AFX_MSG_MAP(CButtonST)
  104. ON_WM_SETCURSOR()
  105. ON_WM_KILLFOCUS()
  106. ON_WM_MOUSEMOVE()
  107. ON_WM_SYSCOLORCHANGE()
  108. ON_CONTROL_REFLECT_EX(BN_CLICKED, OnClicked)
  109. ON_WM_ACTIVATE()
  110. ON_WM_ENABLE()
  111. ON_WM_CANCELMODE()
  112. ON_WM_GETDLGCODE()
  113. ON_WM_CTLCOLOR_REFLECT()
  114. //}}AFX_MSG_MAP
  115. #ifdef BTNST_USE_BCMENU
  116. ON_WM_MENUCHAR()
  117. ON_WM_MEASUREITEM()
  118. #endif
  119. ON_MESSAGE(BM_SETSTYLE, OnSetStyle)
  120. ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
  121. ON_MESSAGE(BM_SETCHECK, OnSetCheck)
  122. ON_MESSAGE(BM_GETCHECK, OnGetCheck)
  123. END_MESSAGE_MAP()
  124. void CButtonST::FreeResources(BOOL bCheckForNULL)
  125. {
  126. if (bCheckForNULL)
  127. {
  128. // Destroy icons
  129. // Note: the following two lines MUST be here! even if
  130. // BoundChecker says they are unnecessary!
  131. if (m_csIcons[0].hIcon) ::DestroyIcon(m_csIcons[0].hIcon);
  132. if (m_csIcons[1].hIcon) ::DestroyIcon(m_csIcons[1].hIcon);
  133. // Destroy bitmaps
  134. if (m_csBitmaps[0].hBitmap) ::DeleteObject(m_csBitmaps[0].hBitmap);
  135. if (m_csBitmaps[1].hBitmap) ::DeleteObject(m_csBitmaps[1].hBitmap);
  136. // Destroy mask bitmaps
  137. if (m_csBitmaps[0].hMask) ::DeleteObject(m_csBitmaps[0].hMask);
  138. if (m_csBitmaps[1].hMask) ::DeleteObject(m_csBitmaps[1].hMask);
  139. } // if
  140. ::ZeroMemory(&m_csIcons, sizeof(m_csIcons));
  141. ::ZeroMemory(&m_csBitmaps, sizeof(m_csBitmaps));
  142. } // End of FreeResources
  143. void CButtonST::PreSubclassWindow() 
  144. {
  145. UINT nBS;
  146. nBS = GetButtonStyle();
  147. // Set initial control type
  148. m_nTypeStyle = nBS & BS_TYPEMASK;
  149. // Check if this is a checkbox
  150. if (nBS & BS_CHECKBOX) m_bIsCheckBox = TRUE;
  151. // Set initial default state flag
  152. if (m_nTypeStyle == BS_DEFPUSHBUTTON)
  153. {
  154. // Set default state for a default button
  155. m_bIsDefault = TRUE;
  156. // Adjust style for default button
  157. m_nTypeStyle = BS_PUSHBUTTON;
  158. } // If
  159. // You should not set the Owner Draw before this call
  160. // (don't use the resource editor "Owner Draw" or
  161. // ModifyStyle(0, BS_OWNERDRAW) before calling PreSubclassWindow() )
  162. ASSERT(m_nTypeStyle != BS_OWNERDRAW);
  163. // Switch to owner-draw
  164. ModifyStyle(BS_TYPEMASK, BS_OWNERDRAW, SWP_FRAMECHANGED);
  165. CButton::PreSubclassWindow();
  166. } // End of PreSubclassWindow
  167. UINT CButtonST::OnGetDlgCode() 
  168. {
  169. UINT nCode = CButton::OnGetDlgCode();
  170. // Tell the system if we want default state handling
  171. // (losing default state always allowed)
  172. nCode |= (m_bIsDefault ? DLGC_DEFPUSHBUTTON : DLGC_UNDEFPUSHBUTTON);
  173. return nCode;
  174. } // End of OnGetDlgCode
  175. BOOL CButtonST::PreTranslateMessage(MSG* pMsg) 
  176. {
  177. InitToolTip();
  178. m_ToolTip.RelayEvent(pMsg);
  179. if (pMsg->message == WM_LBUTTONDBLCLK)
  180. pMsg->message = WM_LBUTTONDOWN;
  181. return CButton::PreTranslateMessage(pMsg);
  182. } // End of PreTranslateMessage
  183. HBRUSH CButtonST::CtlColor(CDC* pDC, UINT nCtlColor) 
  184. {
  185. return (HBRUSH)::GetStockObject(NULL_BRUSH); 
  186. } // End of CtlColor
  187. void CButtonST::OnSysColorChange() 
  188. {
  189. CButton::OnSysColorChange();
  190. m_dcBk.DeleteDC();
  191. m_bmpBk.DeleteObject();
  192. SetDefaultColors();
  193. } // End of OnSysColorChange
  194. LRESULT CButtonST::OnSetStyle(WPARAM wParam, LPARAM lParam)
  195. {
  196. UINT nNewType = (wParam & BS_TYPEMASK);
  197. // Update default state flag
  198. if (nNewType == BS_DEFPUSHBUTTON)
  199. {
  200. m_bIsDefault = TRUE;
  201. } // if
  202. else if (nNewType == BS_PUSHBUTTON)
  203. {
  204. // Losing default state always allowed
  205. m_bIsDefault = FALSE;
  206. } // if
  207. // Can't change control type after owner-draw is set.
  208. // Let the system process changes to other style bits
  209. // and redrawing, while keeping owner-draw style
  210. return DefWindowProc(BM_SETSTYLE,
  211. (wParam & ~BS_TYPEMASK) | BS_OWNERDRAW, lParam);
  212. } // End of OnSetStyle
  213. LRESULT CButtonST::OnSetCheck(WPARAM wParam, LPARAM lParam)
  214. {
  215. ASSERT(m_bIsCheckBox);
  216. switch (wParam)
  217. {
  218. case BST_CHECKED:
  219. case BST_INDETERMINATE: // Indeterminate state is handled like checked state
  220. SetCheck(1);
  221. break;
  222. default:
  223. SetCheck(0);
  224. break;
  225. } // switch
  226. return 0;
  227. } // End of OnSetCheck
  228. LRESULT CButtonST::OnGetCheck(WPARAM wParam, LPARAM lParam)
  229. {
  230. ASSERT(m_bIsCheckBox);
  231. return GetCheck();
  232. } // End of OnGetCheck
  233. #ifdef BTNST_USE_BCMENU
  234. LRESULT CButtonST::OnMenuChar(UINT nChar, UINT nFlags, CMenu* pMenu) 
  235. {
  236. LRESULT lResult;
  237. if (BCMenu::IsMenu(pMenu))
  238. lResult = BCMenu::FindKeyboardShortcut(nChar, nFlags, pMenu);
  239. else
  240. lResult = CButton::OnMenuChar(nChar, nFlags, pMenu);
  241. return lResult;
  242. } // End of OnMenuChar
  243. #endif
  244. #ifdef BTNST_USE_BCMENU
  245. void CButtonST::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct) 
  246. {
  247. BOOL bSetFlag = FALSE;
  248. if (lpMeasureItemStruct->CtlType == ODT_MENU)
  249. {
  250. if (IsMenu((HMENU)lpMeasureItemStruct->itemID) && BCMenu::IsMenu((HMENU)lpMeasureItemStruct->itemID))
  251. {
  252. m_menuPopup.MeasureItem(lpMeasureItemStruct);
  253. bSetFlag = TRUE;
  254. } // if
  255. } // if
  256. if (!bSetFlag) CButton::OnMeasureItem(nIDCtl, lpMeasureItemStruct);
  257. } // End of OnMeasureItem
  258. #endif
  259. void CButtonST::OnEnable(BOOL bEnable) 
  260. {
  261. CButton::OnEnable(bEnable);
  262. if (bEnable == FALSE)
  263. {
  264. CWnd* pWnd = GetParent()->GetNextDlgTabItem(this);
  265. if (pWnd)
  266. pWnd->SetFocus();
  267. else
  268. GetParent()->SetFocus();
  269. CancelHover();
  270. } // if
  271. } // End of OnEnable
  272. void CButtonST::OnKillFocus(CWnd * pNewWnd)
  273. {
  274. CButton::OnKillFocus(pNewWnd);
  275. CancelHover();
  276. } // End of OnKillFocus
  277. void CButtonST::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) 
  278. {
  279. CButton::OnActivate(nState, pWndOther, bMinimized);
  280. if (nState == WA_INACTIVE) CancelHover();
  281. } // End of OnActivate
  282. void CButtonST::OnCancelMode() 
  283. {
  284. CButton::OnCancelMode();
  285. CancelHover();
  286. } // End of OnCancelMode
  287. BOOL CButtonST::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
  288. {
  289. // If a cursor was specified then use it!
  290. if (m_hCursor != NULL)
  291. {
  292. ::SetCursor(m_hCursor);
  293. return TRUE;
  294. } // if
  295. return CButton::OnSetCursor(pWnd, nHitTest, message);
  296. } // End of OnSetCursor
  297. void CButtonST::CancelHover()
  298. {
  299. // Only for flat buttons
  300. if (m_bIsFlat)
  301. {
  302. if (m_bMouseOnButton)
  303. {
  304. m_bMouseOnButton = FALSE;
  305. Invalidate();
  306. } // if
  307. } // if
  308. } // End of CancelHover
  309. void CButtonST::OnMouseMove(UINT nFlags, CPoint point)
  310. {
  311. CWnd* wndUnderMouse = NULL;
  312. CWnd* wndActive = this;
  313. TRACKMOUSEEVENT csTME;
  314. CButton::OnMouseMove(nFlags, point);
  315. ClientToScreen(&point);
  316. wndUnderMouse = WindowFromPoint(point);
  317. // If the mouse enter the button with the left button pressed then do nothing
  318. if (nFlags & MK_LBUTTON && m_bMouseOnButton == FALSE) return;
  319. // If our button is not flat then do nothing
  320. if (m_bIsFlat == FALSE) return;
  321. if (m_bAlwaysTrack == FALSE) wndActive = GetActiveWindow();
  322. if (wndUnderMouse && wndUnderMouse->m_hWnd == m_hWnd && wndActive)
  323. {
  324. if (!m_bMouseOnButton)
  325. {
  326. m_bMouseOnButton = TRUE;
  327. Invalidate();
  328. #ifdef BTNST_USE_SOUND
  329. // Play sound ?
  330. if (m_csSounds[0].lpszSound)
  331. ::PlaySound(m_csSounds[0].lpszSound, m_csSounds[0].hMod, m_csSounds[0].dwFlags);
  332. #endif
  333. csTME.cbSize = sizeof(csTME);
  334. csTME.dwFlags = TME_LEAVE;
  335. csTME.hwndTrack = m_hWnd;
  336. ::_TrackMouseEvent(&csTME);
  337. } // if
  338. } else CancelHover();
  339. } // End of OnMouseMove
  340. // Handler for WM_MOUSELEAVE
  341. LRESULT CButtonST::OnMouseLeave(WPARAM wParam, LPARAM lParam)
  342. {
  343. CancelHover();
  344. return 0;
  345. } // End of OnMouseLeave
  346. BOOL CButtonST::OnClicked() 
  347. {
  348. SetFocus();
  349. #ifdef BTNST_USE_SOUND
  350. // Play sound ?
  351. if (m_csSounds[1].lpszSound)
  352. ::PlaySound(m_csSounds[1].lpszSound, m_csSounds[1].hMod, m_csSounds[1].dwFlags);
  353. #endif
  354. if (m_bIsCheckBox)
  355. {
  356. m_nCheck = !m_nCheck;
  357. Invalidate();
  358. } // if
  359. else
  360. {
  361. // Handle the menu (if any)
  362. #ifdef BTNST_USE_BCMENU
  363. if (m_menuPopup.m_hMenu)
  364. #else
  365. if (m_hMenu)
  366. #endif
  367. {
  368. CRect rWnd;
  369. GetWindowRect(rWnd);
  370. m_bMenuDisplayed = TRUE;
  371. Invalidate();
  372. #ifdef BTNST_USE_BCMENU
  373. BCMenu* psub = (BCMenu*)m_menuPopup.GetSubMenu(0);
  374. if (m_csCallbacks.hWnd) ::SendMessage(m_csCallbacks.hWnd, m_csCallbacks.nMessage, (WPARAM)psub, m_csCallbacks.lParam);
  375. DWORD dwRetValue = psub->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD, rWnd.left, rWnd.bottom, this, NULL);
  376. #else
  377. HMENU hSubMenu = ::GetSubMenu(m_hMenu, 0);
  378. if (m_csCallbacks.hWnd) ::SendMessage(m_csCallbacks.hWnd, m_csCallbacks.nMessage, (WPARAM)hSubMenu, m_csCallbacks.lParam);
  379. DWORD dwRetValue = ::TrackPopupMenuEx(hSubMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD, rWnd.left, rWnd.bottom, m_hParentWndMenu, NULL);
  380. #endif
  381. m_bMenuDisplayed = FALSE;
  382. Invalidate();
  383. if (dwRetValue)
  384. ::PostMessage(m_hParentWndMenu, WM_COMMAND, MAKEWPARAM(dwRetValue, 0), (LPARAM)NULL);
  385. } // if
  386. else
  387. {
  388. // Handle the URL (if any)
  389. if (_tcslen(m_szURL) > 0)
  390. {
  391. SHELLEXECUTEINFO csSEI;
  392. memset(&csSEI, 0, sizeof(csSEI));
  393. csSEI.cbSize = sizeof(SHELLEXECUTEINFO);
  394. csSEI.fMask = SEE_MASK_FLAG_NO_UI;
  395. csSEI.lpVerb = _T("open");
  396. csSEI.lpFile = m_szURL;
  397. csSEI.nShow = SW_SHOWMAXIMIZED;
  398. ::ShellExecuteEx(&csSEI);
  399. } // if
  400. } // else
  401. } // else
  402. return FALSE;
  403. } // End of OnClicked
  404. void CButtonST::DrawItem(LPDRAWITEMSTRUCT lpDIS)
  405. {
  406. CDC* pDC = CDC::FromHandle(lpDIS->hDC);
  407. // Checkbox?
  408. if (m_bIsCheckBox)
  409. {
  410. m_bIsPressed  =  (lpDIS->itemState & ODS_SELECTED) || (m_nCheck != 0);
  411. } // if
  412. else // Normal button OR other button style ...
  413. {
  414. m_bIsPressed = (lpDIS->itemState & ODS_SELECTED);
  415. // If there is a menu and it's displayed, draw the button as pressed
  416. if (
  417. #ifdef BTNST_USE_BCMENU
  418. m_menuPopup.m_hMenu 
  419. #else
  420. m_hMenu 
  421. #endif
  422. && m_bMenuDisplayed) m_bIsPressed = TRUE;
  423. } // else
  424. m_bIsFocused  = (lpDIS->itemState & ODS_FOCUS);
  425. m_bIsDisabled = (lpDIS->itemState & ODS_DISABLED);
  426. CRect itemRect = lpDIS->rcItem;
  427. pDC->SetBkMode(TRANSPARENT);
  428. // Prepare draw... paint button background
  429. // Draw transparent?
  430. if (m_bDrawTransparent)
  431. PaintBk(pDC);
  432. else
  433. OnDrawBackground(pDC, &itemRect);
  434. // Draw button border
  435. OnDrawBorder(pDC, &itemRect);
  436. // Read the button's title
  437. CString sTitle;
  438. GetWindowText(sTitle);
  439. CRect captionRect = lpDIS->rcItem;
  440. // Draw the icon
  441. if (m_csIcons[0].hIcon)
  442. {
  443. DrawTheIcon(pDC, !sTitle.IsEmpty(), &lpDIS->rcItem, &captionRect, m_bIsPressed, m_bIsDisabled);
  444. } // if
  445. if (m_csBitmaps[0].hBitmap)
  446. {
  447. pDC->SetBkColor(RGB(255,255,255));
  448. DrawTheBitmap(pDC, !sTitle.IsEmpty(), &lpDIS->rcItem, &captionRect, m_bIsPressed, m_bIsDisabled);
  449. } // if
  450. // Write the button title (if any)
  451. if (sTitle.IsEmpty() == FALSE)
  452. {
  453. DrawTheText(pDC, (LPCTSTR)sTitle, &lpDIS->rcItem, &captionRect, m_bIsPressed, m_bIsDisabled);
  454. } // if
  455. if (m_bIsFlat == FALSE || (m_bIsFlat && m_bDrawFlatFocus))
  456. {
  457. // Draw the focus rect
  458. if (m_bIsFocused)
  459. {
  460. CRect focusRect = itemRect;
  461. focusRect.DeflateRect(3, 3);
  462. pDC->DrawFocusRect(&focusRect);
  463. } // if
  464. } // if
  465. } // End of DrawItem
  466. void CButtonST::PaintBk(CDC* pDC)
  467. {
  468. CClientDC clDC(GetParent());
  469. CRect rect;
  470. CRect rect1;
  471. GetClientRect(rect);
  472. GetWindowRect(rect1);
  473. GetParent()->ScreenToClient(rect1);
  474. if (m_dcBk.m_hDC == NULL)
  475. {
  476. m_dcBk.CreateCompatibleDC(&clDC);
  477. m_bmpBk.CreateCompatibleBitmap(&clDC, rect.Width(), rect.Height());
  478. m_pbmpOldBk = m_dcBk.SelectObject(&m_bmpBk);
  479. m_dcBk.BitBlt(0, 0, rect.Width(), rect.Height(), &clDC, rect1.left, rect1.top, SRCCOPY);
  480. } // if
  481. pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &m_dcBk, 0, 0, SRCCOPY);
  482. } // End of PaintBk
  483. HBITMAP CButtonST::CreateBitmapMask(HBITMAP hSourceBitmap, DWORD dwWidth, DWORD dwHeight, COLORREF crTransColor)
  484. {
  485. HBITMAP hMask = NULL;
  486. HDC hdcSrc = NULL;
  487. HDC hdcDest = NULL;
  488. HBITMAP hbmSrcT = NULL;
  489. HBITMAP hbmDestT = NULL;
  490. COLORREF crSaveBk;
  491. COLORREF crSaveDestText;
  492. hMask = ::CreateBitmap(dwWidth, dwHeight, 1, 1, NULL);
  493. if (hMask == NULL) return NULL;
  494. hdcSrc = ::CreateCompatibleDC(NULL);
  495. hdcDest = ::CreateCompatibleDC(NULL);
  496. hbmSrcT = (HBITMAP)::SelectObject(hdcSrc, hSourceBitmap);
  497. hbmDestT = (HBITMAP)::SelectObject(hdcDest, hMask);
  498. crSaveBk = ::SetBkColor(hdcSrc, crTransColor);
  499. ::BitBlt(hdcDest, 0, 0, dwWidth, dwHeight, hdcSrc, 0, 0, SRCCOPY);
  500. crSaveDestText = ::SetTextColor(hdcSrc, RGB(255, 255, 255));
  501. ::SetBkColor(hdcSrc,RGB(0, 0, 0));
  502. ::BitBlt(hdcSrc, 0, 0, dwWidth, dwHeight, hdcDest, 0, 0, SRCAND);
  503. SetTextColor(hdcDest, crSaveDestText);
  504. ::SetBkColor(hdcSrc, crSaveBk);
  505. ::SelectObject(hdcSrc, hbmSrcT);
  506. ::SelectObject(hdcDest, hbmDestT);
  507. ::DeleteDC(hdcSrc);
  508. ::DeleteDC(hdcDest);
  509. return hMask;
  510. } // End of CreateBitmapMask
  511. //
  512. // Parameters:
  513. // [IN] bHasTitle
  514. // TRUE if the button has a text
  515. // [IN] rpItem
  516. // A pointer to a RECT structure indicating the allowed paint area
  517. // [IN/OUT]rpTitle
  518. // A pointer to a CRect object indicating the paint area reserved for the
  519. // text. This structure will be modified if necessary.
  520. // [IN] bIsPressed
  521. // TRUE if the button is currently pressed
  522. // [IN] dwWidth
  523. // Width of the image (icon or bitmap)
  524. // [IN] dwHeight
  525. // Height of the image (icon or bitmap)
  526. // [OUT] rpImage
  527. // A pointer to a CRect object that will receive the area available to the image
  528. //
  529. void CButtonST::PrepareImageRect(BOOL bHasTitle, RECT* rpItem, CRect* rpTitle, BOOL bIsPressed, DWORD dwWidth, DWORD dwHeight, CRect* rpImage)
  530. {
  531. CRect rBtn;
  532. rpImage->CopyRect(rpItem);
  533. switch (m_byAlign)
  534. {
  535. case ST_ALIGN_HORIZ:
  536. if (bHasTitle == FALSE)
  537. {
  538. // Center image horizontally
  539. rpImage->left += ((rpImage->Width() - (long)dwWidth)/2);
  540. }
  541. else
  542. {
  543. // Image must be placed just inside the focus rect
  544. rpImage->left += m_ptImageOrg.x;  
  545. rpTitle->left += dwWidth + m_ptImageOrg.x;
  546. }
  547. // Center image vertically
  548. rpImage->top += ((rpImage->Height() - (long)dwHeight)/2);
  549. break;
  550. case ST_ALIGN_HORIZ_RIGHT:
  551. GetClientRect(&rBtn);
  552. if (bHasTitle == FALSE)
  553. {
  554. // Center image horizontally
  555. rpImage->left += ((rpImage->Width() - (long)dwWidth)/2);
  556. }
  557. else
  558. {
  559. // Image must be placed just inside the focus rect
  560. rpTitle->right = rpTitle->Width() - dwWidth - m_ptImageOrg.x;
  561. rpTitle->left = m_ptImageOrg.x;
  562. rpImage->left = rBtn.right - dwWidth - m_ptImageOrg.x;
  563. // Center image vertically
  564. rpImage->top += ((rpImage->Height() - (long)dwHeight)/2);
  565. }
  566. break;
  567. case ST_ALIGN_VERT:
  568. // Center image horizontally
  569. rpImage->left += ((rpImage->Width() - (long)dwWidth)/2);
  570. if (bHasTitle == FALSE)
  571. {
  572. // Center image vertically
  573. rpImage->top += ((rpImage->Height() - (long)dwHeight)/2);           
  574. }
  575. else
  576. {
  577. rpImage->top = m_ptImageOrg.y;
  578. rpTitle->top += dwHeight;
  579. }
  580. break;
  581. case ST_ALIGN_OVERLAP:
  582. break;
  583. } // switch
  584.     
  585. // If button is pressed then press image also
  586. if (bIsPressed && m_bIsCheckBox == FALSE)
  587. rpImage->OffsetRect(m_ptPressedOffset.x, m_ptPressedOffset.y);
  588. } // End of PrepareImageRect
  589. void CButtonST::DrawTheIcon(CDC* pDC, BOOL bHasTitle, RECT* rpItem, CRect* rpCaption, BOOL bIsPressed, BOOL bIsDisabled)
  590. {
  591. BYTE byIndex = 0;
  592. // Select the icon to use
  593. if ((m_bIsCheckBox && bIsPressed) || (!m_bIsCheckBox && (bIsPressed || m_bMouseOnButton)))
  594. byIndex = 0;
  595. else
  596. byIndex = (m_csIcons[1].hIcon == NULL ? 0 : 1);
  597. CRect rImage;
  598. PrepareImageRect(bHasTitle, rpItem, rpCaption, bIsPressed, m_csIcons[byIndex].dwWidth, m_csIcons[byIndex].dwHeight, &rImage);
  599. // Ole'!
  600. pDC->DrawState( rImage.TopLeft(),
  601. rImage.Size(), 
  602. m_csIcons[byIndex].hIcon,
  603. (bIsDisabled ? DSS_DISABLED : DSS_NORMAL), 
  604. (CBrush*)NULL);
  605. } // End of DrawTheIcon
  606. void CButtonST::DrawTheBitmap(CDC* pDC, BOOL bHasTitle, RECT* rpItem, CRect* rpCaption, BOOL bIsPressed, BOOL bIsDisabled)
  607. {
  608. HDC hdcBmpMem = NULL;
  609. HBITMAP hbmOldBmp = NULL;
  610. HDC hdcMem = NULL;
  611. HBITMAP hbmT = NULL;
  612. BYTE byIndex = 0;
  613. // Select the bitmap to use
  614. if ((m_bIsCheckBox && bIsPressed) || (!m_bIsCheckBox && (bIsPressed || m_bMouseOnButton)))
  615. byIndex = 0;
  616. else
  617. byIndex = (m_csBitmaps[1].hBitmap == NULL ? 0 : 1);
  618. CRect rImage;
  619. PrepareImageRect(bHasTitle, rpItem, rpCaption, bIsPressed, m_csBitmaps[byIndex].dwWidth, m_csBitmaps[byIndex].dwHeight, &rImage);
  620. hdcBmpMem = ::CreateCompatibleDC(pDC->m_hDC);
  621. hbmOldBmp = (HBITMAP)::SelectObject(hdcBmpMem, m_csBitmaps[byIndex].hBitmap);
  622. hdcMem = ::CreateCompatibleDC(NULL);
  623. hbmT = (HBITMAP)::SelectObject(hdcMem, m_csBitmaps[byIndex].hMask);
  624. if (bIsDisabled && m_bShowDisabledBitmap)
  625. {
  626. HDC hDC = NULL;
  627. HBITMAP hBitmap = NULL;
  628. hDC = ::CreateCompatibleDC(pDC->m_hDC);
  629. hBitmap = ::CreateCompatibleBitmap(pDC->m_hDC, m_csBitmaps[byIndex].dwWidth, m_csBitmaps[byIndex].dwHeight);
  630. HBITMAP hOldBmp2 = (HBITMAP)::SelectObject(hDC, hBitmap);
  631. RECT rRect;
  632. rRect.left = 0;
  633. rRect.top = 0;
  634. rRect.right = rImage.right + 1;
  635. rRect.bottom = rImage.bottom + 1;
  636. ::FillRect(hDC, &rRect, (HBRUSH)RGB(255, 255, 255));
  637. COLORREF crOldColor = ::SetBkColor(hDC, RGB(255,255,255));
  638. ::BitBlt(hDC, 0, 0, m_csBitmaps[byIndex].dwWidth, m_csBitmaps[byIndex].dwHeight, hdcMem, 0, 0, SRCAND);
  639. ::BitBlt(hDC, 0, 0, m_csBitmaps[byIndex].dwWidth, m_csBitmaps[byIndex].dwHeight, hdcBmpMem, 0, 0, SRCPAINT);
  640. ::SetBkColor(hDC, crOldColor);
  641. ::SelectObject(hDC, hOldBmp2);
  642. ::DeleteDC(hDC);
  643. pDC->DrawState( CPoint(rImage.left/*+1*/, rImage.top), 
  644. CSize(m_csBitmaps[byIndex].dwWidth, m_csBitmaps[byIndex].dwHeight), 
  645. hBitmap, DST_BITMAP | DSS_DISABLED);
  646. ::DeleteObject(hBitmap);
  647. } // if
  648. else
  649. {
  650. ::BitBlt(pDC->m_hDC, rImage.left, rImage.top, m_csBitmaps[byIndex].dwWidth, m_csBitmaps[byIndex].dwHeight, hdcMem, 0, 0, SRCAND);
  651. ::BitBlt(pDC->m_hDC, rImage.left, rImage.top, m_csBitmaps[byIndex].dwWidth, m_csBitmaps[byIndex].dwHeight, hdcBmpMem, 0, 0, SRCPAINT);
  652. } // else
  653. ::SelectObject(hdcMem, hbmT);
  654. ::DeleteDC(hdcMem);
  655. ::SelectObject(hdcBmpMem, hbmOldBmp);
  656. ::DeleteDC(hdcBmpMem);
  657. } // End of DrawTheBitmap
  658. void CButtonST::DrawTheText(CDC* pDC, LPCTSTR lpszText, RECT* rpItem, CRect* rpCaption, BOOL bIsPressed, BOOL bIsDisabled)
  659. {
  660. // Draw the button's title
  661. // If button is pressed then "press" title also
  662. if (m_bIsPressed && m_bIsCheckBox == FALSE)
  663. rpCaption->OffsetRect(m_ptPressedOffset.x, m_ptPressedOffset.y);
  664. // ONLY FOR DEBUG 
  665. //CBrush brBtnShadow(RGB(255, 0, 0));
  666. //pDC->FrameRect(rCaption, &brBtnShadow);
  667. // Center text
  668. CRect centerRect = rpCaption;
  669. pDC->DrawText(lpszText, -1, rpCaption, DT_WORDBREAK | DT_CENTER | DT_CALCRECT);
  670. rpCaption->OffsetRect((centerRect.Width() - rpCaption->Width())/2, (centerRect.Height() - rpCaption->Height())/2);
  671. /* RFU
  672. rpCaption->OffsetRect(0, (centerRect.Height() - rpCaption->Height())/2);
  673. rpCaption->OffsetRect((centerRect.Width() - rpCaption->Width())-4, (centerRect.Height() - rpCaption->Height())/2);
  674. */
  675. pDC->SetBkMode(TRANSPARENT);
  676. /*
  677. pDC->DrawState(rCaption->TopLeft(), rCaption->Size(), (LPCTSTR)sTitle, (bIsDisabled ? DSS_DISABLED : DSS_NORMAL), 
  678. TRUE, 0, (CBrush*)NULL);
  679. */
  680. if (m_bIsDisabled)
  681. {
  682. rpCaption->OffsetRect(1, 1);
  683. pDC->SetTextColor(::GetSysColor(COLOR_3DHILIGHT));
  684. pDC->DrawText(lpszText, -1, rpCaption, DT_WORDBREAK | DT_CENTER);
  685. rpCaption->OffsetRect(-1, -1);
  686. pDC->SetTextColor(::GetSysColor(COLOR_3DSHADOW));
  687. pDC->DrawText(lpszText, -1, rpCaption, DT_WORDBREAK | DT_CENTER);
  688. } // if
  689. else
  690. {
  691. if (m_bMouseOnButton || m_bIsPressed) 
  692. {
  693. pDC->SetTextColor(m_crColors[BTNST_COLOR_FG_IN]);
  694. pDC->SetBkColor(m_crColors[BTNST_COLOR_BK_IN]);
  695. } // if
  696. else 
  697. {
  698. if (m_bIsFocused)
  699. pDC->SetTextColor(m_crColors[BTNST_COLOR_FG_FOCUS]); 
  700. pDC->SetBkColor(m_crColors[BTNST_COLOR_BK_FOCUS]); 
  701. } // if
  702. else 
  703. {
  704. pDC->SetTextColor(m_crColors[BTNST_COLOR_FG_OUT]); 
  705. pDC->SetBkColor(m_crColors[BTNST_COLOR_BK_OUT]); 
  706. } // else
  707. } // else
  708. pDC->DrawText(lpszText, -1, rpCaption, DT_WORDBREAK | DT_CENTER);
  709. } // if
  710. } // End of DrawTheText
  711. // This function creates a grayscale bitmap starting from a given bitmap.
  712. // The resulting bitmap will have the same size of the original one.
  713. //
  714. // Parameters:
  715. // [IN] hBitmap
  716. // Handle to the original bitmap.
  717. // [IN] dwWidth
  718. // Specifies the bitmap width, in pixels.
  719. // [IN] dwHeight
  720. // Specifies the bitmap height, in pixels.
  721. // [IN] crTrans
  722. // Color to be used as transparent color. This color will be left unchanged.
  723. //
  724. // Return value:
  725. // If the function succeeds, the return value is the handle to the newly created
  726. // grayscale bitmap.
  727. // If the function fails, the return value is NULL.
  728. //
  729. HBITMAP CButtonST::CreateGrayscaleBitmap(HBITMAP hBitmap, DWORD dwWidth, DWORD dwHeight, COLORREF crTrans)
  730. {
  731. HBITMAP hGrayBitmap = NULL;
  732. HDC hMainDC = NULL, hMemDC1 = NULL, hMemDC2 = NULL;
  733. HBITMAP hOldBmp1 = NULL, hOldBmp2 = NULL;
  734. hMainDC = ::GetDC(NULL);
  735. if (hMainDC == NULL) return NULL;
  736. hMemDC1 = ::CreateCompatibleDC(hMainDC);
  737. if (hMemDC1 == NULL)
  738. {
  739. ::ReleaseDC(NULL, hMainDC);
  740. return NULL;
  741. } // if
  742. hMemDC2 = ::CreateCompatibleDC(hMainDC);
  743. if (hMemDC2 == NULL)
  744. {
  745. ::DeleteDC(hMemDC1);
  746. ::ReleaseDC(NULL, hMainDC);
  747. return NULL;
  748. } // if
  749. hGrayBitmap = ::CreateCompatibleBitmap(hMainDC, dwWidth, dwHeight);
  750. if (hGrayBitmap)
  751. {
  752. hOldBmp1 = (HBITMAP)::SelectObject(hMemDC1, hGrayBitmap);
  753. hOldBmp2 = (HBITMAP)::SelectObject(hMemDC2, hBitmap);
  754. //::BitBlt(hMemDC1, 0, 0, dwWidth, dwHeight, hMemDC2, 0, 0, SRCCOPY);
  755. DWORD dwLoopY = 0, dwLoopX = 0;
  756. COLORREF crPixel = 0;
  757. BYTE byNewPixel = 0;
  758. for (dwLoopY = 0; dwLoopY < dwHeight; dwLoopY++)
  759. {
  760. for (dwLoopX = 0; dwLoopX < dwWidth; dwLoopX++)
  761. {
  762. crPixel = ::GetPixel(hMemDC2, dwLoopX, dwLoopY);
  763. byNewPixel = (BYTE)((GetRValue(crPixel) * 0.299) + (GetGValue(crPixel) * 0.587) + (GetBValue(crPixel) * 0.114));
  764. if (crPixel != crTrans)
  765. ::SetPixel(hMemDC1, dwLoopX, dwLoopY, RGB(byNewPixel, byNewPixel, byNewPixel));
  766. else
  767. ::SetPixel(hMemDC1, dwLoopX, dwLoopY, crPixel);
  768. } // for
  769. } // for
  770. ::SelectObject(hMemDC1, hOldBmp1);
  771. ::SelectObject(hMemDC2, hOldBmp2);
  772. } // if
  773. ::DeleteDC(hMemDC1);
  774. ::DeleteDC(hMemDC2);
  775. ::ReleaseDC(NULL, hMainDC);
  776. return hGrayBitmap;
  777. } // End of CreateGrayscaleBitmap
  778. // This function creates a bitmap that is 25% darker than the original.
  779. // The resulting bitmap will have the same size of the original one.
  780. //
  781. // Parameters:
  782. // [IN] hBitmap
  783. // Handle to the original bitmap.
  784. // [IN] dwWidth
  785. // Specifies the bitmap width, in pixels.
  786. // [IN] dwHeight
  787. // Specifies the bitmap height, in pixels.
  788. // [IN] crTrans
  789. // Color to be used as transparent color. This color will be left unchanged.
  790. //
  791. // Return value:
  792. // If the function succeeds, the return value is the handle to the newly created
  793. // darker bitmap.
  794. // If the function fails, the return value is NULL.
  795. //
  796. HBITMAP CButtonST::CreateDarkerBitmap(HBITMAP hBitmap, DWORD dwWidth, DWORD dwHeight, COLORREF crTrans)
  797. {
  798. HBITMAP hGrayBitmap = NULL;
  799. HDC hMainDC = NULL, hMemDC1 = NULL, hMemDC2 = NULL;
  800. HBITMAP hOldBmp1 = NULL, hOldBmp2 = NULL;
  801. hMainDC = ::GetDC(NULL);
  802. if (hMainDC == NULL) return NULL;
  803. hMemDC1 = ::CreateCompatibleDC(hMainDC);
  804. if (hMemDC1 == NULL)
  805. {
  806. ::ReleaseDC(NULL, hMainDC);
  807. return NULL;
  808. } // if
  809. hMemDC2 = ::CreateCompatibleDC(hMainDC);
  810. if (hMemDC2 == NULL)
  811. {
  812. ::DeleteDC(hMemDC1);
  813. ::ReleaseDC(NULL, hMainDC);
  814. return NULL;
  815. } // if
  816. hGrayBitmap = ::CreateCompatibleBitmap(hMainDC, dwWidth, dwHeight);
  817. if (hGrayBitmap)
  818. {
  819. hOldBmp1 = (HBITMAP)::SelectObject(hMemDC1, hGrayBitmap);
  820. hOldBmp2 = (HBITMAP)::SelectObject(hMemDC2, hBitmap);
  821. //::BitBlt(hMemDC1, 0, 0, dwWidth, dwHeight, hMemDC2, 0, 0, SRCCOPY);
  822. DWORD dwLoopY = 0, dwLoopX = 0;
  823. COLORREF crPixel = 0;
  824. for (dwLoopY = 0; dwLoopY < dwHeight; dwLoopY++)
  825. {
  826. for (dwLoopX = 0; dwLoopX < dwWidth; dwLoopX++)
  827. {
  828. crPixel = ::GetPixel(hMemDC2, dwLoopX, dwLoopY);
  829. if (crPixel != crTrans)
  830. ::SetPixel(hMemDC1, dwLoopX, dwLoopY, DarkenColor(crPixel, 0.25));
  831. else
  832. ::SetPixel(hMemDC1, dwLoopX, dwLoopY, crPixel);
  833. } // for
  834. } // for
  835. ::SelectObject(hMemDC1, hOldBmp1);
  836. ::SelectObject(hMemDC2, hOldBmp2);
  837. } // if
  838. ::DeleteDC(hMemDC1);
  839. ::DeleteDC(hMemDC2);
  840. ::ReleaseDC(NULL, hMainDC);
  841. return hGrayBitmap;
  842. } // End of CreateDarkerBitmap
  843. // This function creates a grayscale icon starting from a given icon.
  844. // The resulting icon will have the same size of the original one.
  845. //
  846. // Parameters:
  847. // [IN] hIcon
  848. // Handle to the original icon.
  849. //
  850. // Return value:
  851. // If the function succeeds, the return value is the handle to the newly created
  852. // grayscale icon.
  853. // If the function fails, the return value is NULL.
  854. //
  855. // Updates:
  856. // 26/Nov/2002 Restored 1 BitBlt operation
  857. // 03/May/2002 Removed dependancy from m_hWnd
  858. // Removed 1 BitBlt operation
  859. //
  860. HICON CButtonST::CreateGrayscaleIcon(HICON hIcon)
  861. {
  862. HICON hGrayIcon = NULL;
  863. HDC hMainDC = NULL, hMemDC1 = NULL, hMemDC2 = NULL;
  864. BITMAP bmp;
  865. HBITMAP hOldBmp1 = NULL, hOldBmp2 = NULL;
  866. ICONINFO csII, csGrayII;
  867. BOOL bRetValue = FALSE;
  868. bRetValue = ::GetIconInfo(hIcon, &csII);
  869. if (bRetValue == FALSE) return NULL;
  870. hMainDC = ::GetDC(NULL);
  871. hMemDC1 = ::CreateCompatibleDC(hMainDC);
  872. hMemDC2 = ::CreateCompatibleDC(hMainDC);
  873. if (hMainDC == NULL || hMemDC1 == NULL || hMemDC2 == NULL) return NULL;
  874.   
  875. if (::GetObject(csII.hbmColor, sizeof(BITMAP), &bmp))
  876. {
  877. DWORD dwWidth = csII.xHotspot*2;
  878. DWORD dwHeight = csII.yHotspot*2;
  879. csGrayII.hbmColor = ::CreateBitmap(dwWidth, dwHeight, bmp.bmPlanes, bmp.bmBitsPixel, NULL);
  880. if (csGrayII.hbmColor)
  881. {
  882. hOldBmp1 = (HBITMAP)::SelectObject(hMemDC1, csII.hbmColor);
  883. hOldBmp2 = (HBITMAP)::SelectObject(hMemDC2, csGrayII.hbmColor);
  884. //::BitBlt(hMemDC2, 0, 0, dwWidth, dwHeight, hMemDC1, 0, 0, SRCCOPY);
  885. DWORD dwLoopY = 0, dwLoopX = 0;
  886. COLORREF crPixel = 0;
  887. BYTE byNewPixel = 0;
  888. for (dwLoopY = 0; dwLoopY < dwHeight; dwLoopY++)
  889. {
  890. for (dwLoopX = 0; dwLoopX < dwWidth; dwLoopX++)
  891. {
  892. crPixel = ::GetPixel(hMemDC1, dwLoopX, dwLoopY);
  893. byNewPixel = (BYTE)((GetRValue(crPixel) * 0.299) + (GetGValue(crPixel) * 0.587) + (GetBValue(crPixel) * 0.114));
  894. if (crPixel)
  895. ::SetPixel(hMemDC2, dwLoopX, dwLoopY, RGB(byNewPixel, byNewPixel, byNewPixel));
  896. else
  897. ::SetPixel(hMemDC2, dwLoopX, dwLoopY, crPixel);
  898. } // for
  899. } // for
  900. ::SelectObject(hMemDC1, hOldBmp1);
  901. ::SelectObject(hMemDC2, hOldBmp2);
  902. csGrayII.hbmMask = csII.hbmMask;
  903. csGrayII.fIcon = TRUE;
  904. hGrayIcon = ::CreateIconIndirect(&csGrayII);
  905. } // if
  906. ::DeleteObject(csGrayII.hbmColor);
  907. //::DeleteObject(csGrayII.hbmMask);
  908. } // if
  909. ::DeleteObject(csII.hbmColor);
  910. ::DeleteObject(csII.hbmMask);
  911. ::DeleteDC(hMemDC1);
  912. ::DeleteDC(hMemDC2);
  913. ::ReleaseDC(NULL, hMainDC);
  914. return hGrayIcon;
  915. } // End of CreateGrayscaleIcon
  916. // This function creates a icon that is 25% darker than the original.
  917. // The resulting icon will have the same size of the original one.
  918. //
  919. // Parameters:
  920. // [IN] hIcon
  921. // Handle to the original icon.
  922. //
  923. // Return value:
  924. // If the function succeeds, the return value is the handle to the newly created
  925. // darker icon.
  926. // If the function fails, the return value is NULL.
  927. //
  928. HICON CButtonST::CreateDarkerIcon(HICON hIcon)
  929. {
  930. HICON hGrayIcon = NULL;
  931. HDC hMainDC = NULL, hMemDC1 = NULL, hMemDC2 = NULL;
  932. BITMAP bmp;
  933. HBITMAP hOldBmp1 = NULL, hOldBmp2 = NULL;
  934. ICONINFO csII, csGrayII;
  935. BOOL bRetValue = FALSE;
  936. bRetValue = ::GetIconInfo(hIcon, &csII);
  937. if (bRetValue == FALSE) return NULL;
  938. hMainDC = ::GetDC(NULL);
  939. hMemDC1 = ::CreateCompatibleDC(hMainDC);
  940. hMemDC2 = ::CreateCompatibleDC(hMainDC);
  941. if (hMainDC == NULL || hMemDC1 == NULL || hMemDC2 == NULL) return NULL;
  942.   
  943. if (::GetObject(csII.hbmColor, sizeof(BITMAP), &bmp))
  944. {
  945. DWORD dwWidth = csII.xHotspot*2;
  946. DWORD dwHeight = csII.yHotspot*2;
  947. csGrayII.hbmColor = ::CreateBitmap(dwWidth, dwHeight, bmp.bmPlanes, bmp.bmBitsPixel, NULL);
  948. if (csGrayII.hbmColor)
  949. {
  950. hOldBmp1 = (HBITMAP)::SelectObject(hMemDC1, csII.hbmColor);
  951. hOldBmp2 = (HBITMAP)::SelectObject(hMemDC2, csGrayII.hbmColor);
  952. //::BitBlt(hMemDC2, 0, 0, dwWidth, dwHeight, hMemDC1, 0, 0, SRCCOPY);
  953. DWORD dwLoopY = 0, dwLoopX = 0;
  954. COLORREF crPixel = 0;
  955. for (dwLoopY = 0; dwLoopY < dwHeight; dwLoopY++)
  956. {
  957. for (dwLoopX = 0; dwLoopX < dwWidth; dwLoopX++)
  958. {
  959. crPixel = ::GetPixel(hMemDC1, dwLoopX, dwLoopY);
  960. if (crPixel)
  961. ::SetPixel(hMemDC2, dwLoopX, dwLoopY, DarkenColor(crPixel, 0.25));
  962. else
  963. ::SetPixel(hMemDC2, dwLoopX, dwLoopY, crPixel);
  964. } // for
  965. } // for
  966. ::SelectObject(hMemDC1, hOldBmp1);
  967. ::SelectObject(hMemDC2, hOldBmp2);
  968. csGrayII.hbmMask = csII.hbmMask;
  969. csGrayII.fIcon = TRUE;
  970. hGrayIcon = ::CreateIconIndirect(&csGrayII);
  971. } // if
  972. ::DeleteObject(csGrayII.hbmColor);
  973. //::DeleteObject(csGrayII.hbmMask);
  974. } // if
  975. ::DeleteObject(csII.hbmColor);
  976. ::DeleteObject(csII.hbmMask);
  977. ::DeleteDC(hMemDC1);
  978. ::DeleteDC(hMemDC2);
  979. ::ReleaseDC(NULL, hMainDC);
  980. return hGrayIcon;
  981. } // End of CreateDarkerIcon
  982. COLORREF CButtonST::DarkenColor(COLORREF crColor, double dFactor)
  983. {
  984. if (dFactor > 0.0 && dFactor <= 1.0)
  985. {
  986. BYTE red,green,blue,lightred,lightgreen,lightblue;
  987. red = GetRValue(crColor);
  988. green = GetGValue(crColor);
  989. blue = GetBValue(crColor);
  990. lightred = (BYTE)(red-(dFactor * red));
  991. lightgreen = (BYTE)(green-(dFactor * green));
  992. lightblue = (BYTE)(blue-(dFactor * blue));
  993. crColor = RGB(lightred,lightgreen,lightblue);
  994. } // if
  995. return crColor;
  996. } // End of DarkenColor
  997. // This function assigns icons to the button.
  998. // Any previous icon or bitmap will be removed.
  999. //
  1000. // Parameters:
  1001. // [IN] nIconIn
  1002. // ID number of the icon resource to show when the mouse is over the button.
  1003. // Pass NULL to remove any icon from the button.
  1004. // [IN] nCxDesiredIn
  1005. // Specifies the width, in pixels, of the icon to load.
  1006. // [IN] nCyDesiredIn
  1007. // Specifies the height, in pixels, of the icon to load.
  1008. // [IN] nIconOut
  1009. // ID number of the icon resource to show when the mouse is outside the button.
  1010. // Can be NULL.
  1011. // If this parameter is the special value BTNST_AUTO_GRAY (cast to int) the second
  1012. // icon will be automatically created starting from nIconIn and converted to grayscale.
  1013. // If this parameter is the special value BTNST_AUTO_DARKER (cast to int) the second
  1014. // icon will be automatically created 25% darker starting from nIconIn.
  1015. // [IN] nCxDesiredOut
  1016. // Specifies the width, in pixels, of the icon to load.
  1017. // [IN] nCyDesiredOut
  1018. // Specifies the height, in pixels, of the icon to load.
  1019. //
  1020. // Return value:
  1021. // BTNST_OK
  1022. // Function executed successfully.
  1023. // BTNST_INVALIDRESOURCE
  1024. // Failed loading the specified resource.
  1025. //
  1026. DWORD CButtonST::SetIcon(int nIconIn, int nCxDesiredIn, int nCyDesiredIn, int nIconOut, int nCxDesiredOut, int nCyDesiredOut)
  1027. {
  1028. HICON hIconIn = NULL;
  1029. HICON hIconOut = NULL;
  1030. HINSTANCE hInstResource = NULL;
  1031. // Find correct resource handle
  1032. hInstResource = AfxFindResourceHandle(MAKEINTRESOURCE(nIconIn), RT_GROUP_ICON);
  1033. // Set icon when the mouse is IN the button
  1034. hIconIn = (HICON)::LoadImage(hInstResource, MAKEINTRESOURCE(nIconIn), IMAGE_ICON, nCxDesiredIn, nCyDesiredIn, 0);
  1035.    // Set icon when the mouse is OUT the button
  1036. switch (nIconOut)
  1037. {
  1038. case NULL:
  1039. break;
  1040. case (int)BTNST_AUTO_GRAY:
  1041. hIconOut = BTNST_AUTO_GRAY;
  1042. break;
  1043. case (int)BTNST_AUTO_DARKER:
  1044. hIconOut = BTNST_AUTO_DARKER;
  1045. break;
  1046. default:
  1047. hIconOut = (HICON)::LoadImage(hInstResource, MAKEINTRESOURCE(nIconOut), IMAGE_ICON, nCxDesiredOut, nCyDesiredOut, 0);
  1048. break;
  1049. } // switch
  1050. return SetIcon(hIconIn, hIconOut);
  1051. } // End of SetIcon
  1052. // This function assigns icons to the button.
  1053. // Any previous icon or bitmap will be removed.
  1054. //
  1055. // Parameters:
  1056. // [IN] nIconIn
  1057. // ID number of the icon resource to show when the mouse is over the button.
  1058. // Pass NULL to remove any icon from the button.
  1059. // [IN] nIconOut
  1060. // ID number of the icon resource to show when the mouse is outside the button.
  1061. // Can be NULL.
  1062. // If this parameter is the special value BTNST_AUTO_GRAY (cast to int) the second
  1063. // icon will be automatically created starting from nIconIn and converted to grayscale.
  1064. // If this parameter is the special value BTNST_AUTO_DARKER (cast to int) the second
  1065. // icon will be automatically created 25% darker starting from nIconIn.
  1066. //
  1067. // Return value:
  1068. // BTNST_OK
  1069. // Function executed successfully.
  1070. // BTNST_INVALIDRESOURCE
  1071. // Failed loading the specified resource.
  1072. //
  1073. DWORD CButtonST::SetIcon(int nIconIn, int nIconOut)
  1074. {
  1075. return SetIcon(nIconIn, 0, 0, nIconOut, 0, 0);
  1076. } // End of SetIcon
  1077. // This function assigns icons to the button.
  1078. // Any previous icon or bitmap will be removed.
  1079. //
  1080. // Parameters:
  1081. // [IN] hIconIn
  1082. // Handle fo the icon to show when the mouse is over the button.
  1083. // Pass NULL to remove any icon from the button.
  1084. // [IN] hIconOut
  1085. // Handle to the icon to show when the mouse is outside the button.
  1086. // Can be NULL.
  1087. // If this parameter is the special value BTNST_AUTO_GRAY the second
  1088. // icon will be automatically created starting from hIconIn and converted to grayscale.
  1089. // If this parameter is the special value BTNST_AUTO_DARKER the second
  1090. // icon will be automatically created 25% darker starting from hIconIn.
  1091. //
  1092. // Return value:
  1093. // BTNST_OK
  1094. // Function executed successfully.
  1095. // BTNST_INVALIDRESOURCE
  1096. // Failed loading the specified resource.
  1097. //
  1098. DWORD CButtonST::SetIcon(HICON hIconIn, HICON hIconOut)
  1099. {
  1100. BOOL bRetValue;
  1101. ICONINFO ii;
  1102. // Free any loaded resource
  1103. FreeResources();
  1104. if (hIconIn)
  1105. {
  1106. // Icon when mouse over button?
  1107. m_csIcons[0].hIcon = hIconIn;
  1108. // Get icon dimension
  1109. ::ZeroMemory(&ii, sizeof(ICONINFO));
  1110. bRetValue = ::GetIconInfo(hIconIn, &ii);
  1111. if (bRetValue == FALSE)
  1112. {
  1113. FreeResources();
  1114. return BTNST_INVALIDRESOURCE;
  1115. } // if
  1116. m_csIcons[0].dwWidth = (DWORD)(ii.xHotspot * 2);
  1117. m_csIcons[0].dwHeight = (DWORD)(ii.yHotspot * 2);
  1118. ::DeleteObject(ii.hbmMask);
  1119. ::DeleteObject(ii.hbmColor);
  1120. // Icon when mouse outside button?
  1121. if (hIconOut)
  1122. {
  1123. switch ((int)hIconOut)
  1124. {
  1125. case (int)BTNST_AUTO_GRAY:
  1126. hIconOut = CreateGrayscaleIcon(hIconIn);
  1127. break;
  1128. case (int)BTNST_AUTO_DARKER:
  1129. hIconOut = CreateDarkerIcon(hIconIn);
  1130. break;
  1131. } // switch
  1132. m_csIcons[1].hIcon = hIconOut;
  1133. // Get icon dimension
  1134. ::ZeroMemory(&ii, sizeof(ICONINFO));
  1135. bRetValue = ::GetIconInfo(hIconOut, &ii);
  1136. if (bRetValue == FALSE)
  1137. {
  1138. FreeResources();
  1139. return BTNST_INVALIDRESOURCE;
  1140. } // if
  1141. m_csIcons[1].dwWidth = (DWORD)(ii.xHotspot * 2);
  1142. m_csIcons[1].dwHeight = (DWORD)(ii.yHotspot * 2);
  1143. ::DeleteObject(ii.hbmMask);
  1144. ::DeleteObject(ii.hbmColor);
  1145. } // if
  1146. } // if
  1147. Invalidate();
  1148. return BTNST_OK;
  1149. } // End of SetIcon
  1150. // This function assigns bitmaps to the button.
  1151. // Any previous icon or bitmap will be removed.
  1152. //
  1153. // Parameters:
  1154. // [IN] nBitmapIn
  1155. // ID number of the bitmap resource to show when the mouse is over the button.
  1156. // Pass NULL to remove any bitmap from the button.
  1157. // [IN] crTransColorIn
  1158. // Color (inside nBitmapIn) to be used as transparent color.
  1159. // [IN] nBitmapOut
  1160. // ID number of the bitmap resource to show when the mouse is outside the button.
  1161. // Can be NULL.
  1162. // [IN] crTransColorOut
  1163. // Color (inside nBitmapOut) to be used as transparent color.
  1164. //
  1165. // Return value:
  1166. // BTNST_OK
  1167. // Function executed successfully.
  1168. // BTNST_INVALIDRESOURCE
  1169. // Failed loading the specified resource.
  1170. // BTNST_FAILEDMASK
  1171. // Failed creating mask bitmap.
  1172. //
  1173. DWORD CButtonST::SetBitmaps(int nBitmapIn, COLORREF crTransColorIn, int nBitmapOut, COLORREF crTransColorOut)
  1174. {
  1175. HBITMAP hBitmapIn = NULL;
  1176. HBITMAP hBitmapOut = NULL;
  1177. HINSTANCE hInstResource = NULL;
  1178. // Find correct resource handle
  1179. hInstResource = AfxFindResourceHandle(MAKEINTRESOURCE(nBitmapIn), RT_BITMAP);
  1180. // Load bitmap In
  1181. hBitmapIn = (HBITMAP)::LoadImage(hInstResource, MAKEINTRESOURCE(nBitmapIn), IMAGE_BITMAP, 0, 0, 0);
  1182. // Load bitmap Out
  1183. switch (nBitmapOut)
  1184. {
  1185. case NULL:
  1186. break;
  1187. case (int)BTNST_AUTO_GRAY:
  1188. hBitmapOut = (HBITMAP)BTNST_AUTO_GRAY;
  1189. break;
  1190. case (int)BTNST_AUTO_DARKER:
  1191. hBitmapOut = (HBITMAP)BTNST_AUTO_DARKER;
  1192. break;
  1193. default:
  1194. hBitmapOut = (HBITMAP)::LoadImage(hInstResource, MAKEINTRESOURCE(nBitmapOut), IMAGE_BITMAP, 0, 0, 0);
  1195. break;
  1196. } // if
  1197. return SetBitmaps(hBitmapIn, crTransColorIn, hBitmapOut, crTransColorOut);
  1198. } // End of SetBitmaps
  1199. // This function assigns bitmaps to the button.
  1200. // Any previous icon or bitmap will be removed.
  1201. //
  1202. // Parameters:
  1203. // [IN] hBitmapIn
  1204. // Handle fo the bitmap to show when the mouse is over the button.
  1205. // Pass NULL to remove any bitmap from the button.
  1206. // [IN] crTransColorIn
  1207. // Color (inside hBitmapIn) to be used as transparent color.
  1208. // [IN] hBitmapOut
  1209. // Handle to the bitmap to show when the mouse is outside the button.
  1210. // Can be NULL.
  1211. // [IN] crTransColorOut
  1212. // Color (inside hBitmapOut) to be used as transparent color.
  1213. //
  1214. // Return value:
  1215. // BTNST_OK
  1216. // Function executed successfully.
  1217. // BTNST_INVALIDRESOURCE
  1218. // Failed loading the specified resource.
  1219. // BTNST_FAILEDMASK
  1220. // Failed creating mask bitmap.
  1221. //
  1222. DWORD CButtonST::SetBitmaps(HBITMAP hBitmapIn, COLORREF crTransColorIn, HBITMAP hBitmapOut, COLORREF crTransColorOut)
  1223. {
  1224. int nRetValue = 0;
  1225. BITMAP csBitmapSize;
  1226. // Free any loaded resource
  1227. FreeResources();
  1228. if (hBitmapIn)
  1229. {
  1230. m_csBitmaps[0].hBitmap = hBitmapIn;
  1231. m_csBitmaps[0].crTransparent = crTransColorIn;
  1232. // Get bitmap size
  1233. nRetValue = ::GetObject(hBitmapIn, sizeof(csBitmapSize), &csBitmapSize);
  1234. if (nRetValue == 0)
  1235. {
  1236. FreeResources();
  1237. return BTNST_INVALIDRESOURCE;
  1238. } // if
  1239. m_csBitmaps[0].dwWidth = (DWORD)csBitmapSize.bmWidth;
  1240. m_csBitmaps[0].dwHeight = (DWORD)csBitmapSize.bmHeight;
  1241. // Create grayscale/darker bitmap BEFORE mask (of hBitmapIn)
  1242. switch ((int)hBitmapOut)
  1243. {
  1244. case (int)BTNST_AUTO_GRAY:
  1245. hBitmapOut = CreateGrayscaleBitmap(hBitmapIn, m_csBitmaps[0].dwWidth, m_csBitmaps[0].dwHeight, crTransColorIn);
  1246. m_csBitmaps[1].hBitmap = hBitmapOut;
  1247. crTransColorOut = crTransColorIn;
  1248. break;
  1249. case (int)BTNST_AUTO_DARKER:
  1250. hBitmapOut = CreateDarkerBitmap(hBitmapIn, m_csBitmaps[0].dwWidth, m_csBitmaps[0].dwHeight, crTransColorIn);
  1251. m_csBitmaps[1].hBitmap = hBitmapOut;
  1252. crTransColorOut = crTransColorIn;
  1253. break;
  1254. } // switch
  1255. // Create mask for bitmap In
  1256. m_csBitmaps[0].hMask = CreateBitmapMask(hBitmapIn, m_csBitmaps[0].dwWidth, m_csBitmaps[0].dwHeight, crTransColorIn);
  1257. if (m_csBitmaps[0].hMask == NULL)
  1258. {
  1259. FreeResources();
  1260. return BTNST_FAILEDMASK;
  1261. } // if
  1262. if (hBitmapOut)
  1263. {
  1264. m_csBitmaps[1].hBitmap = hBitmapOut;
  1265. m_csBitmaps[1].crTransparent = crTransColorOut;
  1266. // Get bitmap size
  1267. nRetValue = ::GetObject(hBitmapOut, sizeof(csBitmapSize), &csBitmapSize);
  1268. if (nRetValue == 0)
  1269. {
  1270. FreeResources();
  1271. return BTNST_INVALIDRESOURCE;
  1272. } // if
  1273. m_csBitmaps[1].dwWidth = (DWORD)csBitmapSize.bmWidth;
  1274. m_csBitmaps[1].dwHeight = (DWORD)csBitmapSize.bmHeight;
  1275. // Create mask for bitmap Out
  1276. m_csBitmaps[1].hMask = CreateBitmapMask(hBitmapOut, m_csBitmaps[1].dwWidth, m_csBitmaps[1].dwHeight, crTransColorOut);
  1277. if (m_csBitmaps[1].hMask == NULL)
  1278. {
  1279. FreeResources();
  1280. return BTNST_FAILEDMASK;
  1281. } // if
  1282. } // if
  1283. } // if
  1284. Invalidate();
  1285. return BTNST_OK;
  1286. } // End of SetBitmaps
  1287. // This functions sets the button to have a standard or flat style.
  1288. //
  1289. // Parameters:
  1290. // [IN] bFlat
  1291. // If TRUE the button will have a flat style, else
  1292. // will have a standard style.
  1293. // By default, CButtonST buttons are flat.
  1294. // [IN] bRepaint
  1295. // If TRUE the control will be repainted.
  1296. //
  1297. // Return value:
  1298. // BTNST_OK
  1299. // Function executed successfully.
  1300. //
  1301. DWORD CButtonST::SetFlat(BOOL bFlat, BOOL bRepaint)
  1302. {
  1303. m_bIsFlat = bFlat;
  1304. if (bRepaint) Invalidate();
  1305. return BTNST_OK;
  1306. } // End of SetFlat
  1307. // This function sets the alignment type between icon/bitmap and text.
  1308. //
  1309. // Parameters:
  1310. // [IN] byAlign
  1311. // Alignment type. Can be one of the following values:
  1312. // ST_ALIGN_HORIZ Icon/bitmap on the left, text on the right
  1313. // ST_ALIGN_VERT Icon/bitmap on the top, text on the bottom
  1314. // ST_ALIGN_HORIZ_RIGHT Icon/bitmap on the right, text on the left
  1315. // ST_ALIGN_OVERLAP Icon/bitmap on the same space as text
  1316. // By default, CButtonST buttons have ST_ALIGN_HORIZ alignment.
  1317. // [IN] bRepaint
  1318. // If TRUE the control will be repainted.
  1319. //
  1320. // Return value:
  1321. // BTNST_OK
  1322. // Function executed successfully.
  1323. // BTNST_INVALIDALIGN
  1324. // Alignment type not supported.
  1325. //
  1326. DWORD CButtonST::SetAlign(BYTE byAlign, BOOL bRepaint)
  1327. {
  1328. switch (byAlign)
  1329. {    
  1330. case ST_ALIGN_HORIZ:
  1331. case ST_ALIGN_HORIZ_RIGHT:
  1332. case ST_ALIGN_VERT:
  1333. case ST_ALIGN_OVERLAP:
  1334. m_byAlign = byAlign;
  1335. if (bRepaint) Invalidate();
  1336. return BTNST_OK;
  1337. break;
  1338. } // switch
  1339. return BTNST_INVALIDALIGN;
  1340. } // End of SetAlign
  1341. // This function sets the pressed style.
  1342. //
  1343. // Parameters:
  1344. // [IN] byStyle
  1345. // Pressed style. Can be one of the following values:
  1346. // BTNST_PRESSED_LEFTRIGHT Pressed style from left to right (as usual)
  1347. // BTNST_PRESSED_TOPBOTTOM Pressed style from top to bottom
  1348. // By default, CButtonST buttons have BTNST_PRESSED_LEFTRIGHT style.
  1349. // [IN] bRepaint
  1350. // If TRUE the control will be repainted.
  1351. //
  1352. // Return value:
  1353. // BTNST_OK
  1354. // Function executed successfully.
  1355. // BTNST_INVALIDPRESSEDSTYLE
  1356. // Pressed style not supported.
  1357. //
  1358. DWORD CButtonST::SetPressedStyle(BYTE byStyle, BOOL bRepaint)
  1359. {
  1360. switch (byStyle)
  1361. {
  1362. case BTNST_PRESSED_LEFTRIGHT:
  1363. m_ptPressedOffset.x = 1;
  1364. m_ptPressedOffset.y = 1;
  1365. break;
  1366. case BTNST_PRESSED_TOPBOTTOM:
  1367. m_ptPressedOffset.x = 0;
  1368. m_ptPressedOffset.y = 2;
  1369. break;
  1370. default:
  1371. return BTNST_INVALIDPRESSEDSTYLE;
  1372. } // switch
  1373. if (bRepaint) Invalidate();
  1374. return BTNST_OK;
  1375. } // End of SetPressedStyle
  1376. // This function sets the state of the checkbox.
  1377. // If the button is not a checkbox, this function has no meaning.
  1378. //
  1379. // Parameters:
  1380. // [IN] nCheck
  1381. // 1 to check the checkbox.
  1382. // 0 to un-check the checkbox.
  1383. // [IN] bRepaint
  1384. // If TRUE the control will be repainted.
  1385. //
  1386. // Return value:
  1387. // BTNST_OK
  1388. // Function executed successfully.
  1389. //
  1390. DWORD CButtonST::SetCheck(int nCheck, BOOL bRepaint)
  1391. {
  1392. if (m_bIsCheckBox)
  1393. {
  1394. if (nCheck == 0) m_nCheck = 0;
  1395. else m_nCheck = 1;
  1396. if (bRepaint) Invalidate();
  1397. } // if
  1398. return BTNST_OK;
  1399. } // End of SetCheck
  1400. // This function returns the current state of the checkbox.
  1401. // If the button is not a checkbox, this function has no meaning.
  1402. //
  1403. // Return value:
  1404. // The current state of the checkbox.
  1405. // 1 if checked.
  1406. // 0 if not checked or the button is not a checkbox.
  1407. //
  1408. int CButtonST::GetCheck()
  1409. {
  1410. return m_nCheck;
  1411. } // End of GetCheck
  1412. // This function sets all colors to a default value.
  1413. //
  1414. // Parameters:
  1415. // [IN] bRepaint
  1416. // If TRUE the control will be repainted.
  1417. //
  1418. // Return value:
  1419. // BTNST_OK
  1420. // Function executed successfully.
  1421. //
  1422. DWORD CButtonST::SetDefaultColors(BOOL bRepaint)
  1423. {
  1424. m_crColors[BTNST_COLOR_BK_IN] = ::GetSysColor(COLOR_BTNFACE);
  1425. m_crColors[BTNST_COLOR_FG_IN] = ::GetSysColor(COLOR_BTNTEXT);
  1426. m_crColors[BTNST_COLOR_BK_OUT] = ::GetSysColor(COLOR_BTNFACE);
  1427. m_crColors[BTNST_COLOR_FG_OUT] = ::GetSysColor(COLOR_BTNTEXT);
  1428. m_crColors[BTNST_COLOR_BK_FOCUS] = ::GetSysColor(COLOR_BTNFACE);
  1429. m_crColors[BTNST_COLOR_FG_FOCUS] = ::GetSysColor(COLOR_BTNTEXT);
  1430. if (bRepaint) Invalidate();
  1431. return BTNST_OK;
  1432. } // End of SetDefaultColors
  1433. // This function sets the color to use for a particular state.
  1434. //
  1435. // Parameters:
  1436. // [IN] byColorIndex
  1437. // Index of the color to set. Can be one of the following values:
  1438. // BTNST_COLOR_BK_IN Background color when mouse is over the button
  1439. // BTNST_COLOR_FG_IN Text color when mouse is over the button
  1440. // BTNST_COLOR_BK_OUT Background color when mouse is outside the button
  1441. // BTNST_COLOR_FG_OUT Text color when mouse is outside the button
  1442. // BTNST_COLOR_BK_FOCUS Background color when the button is focused
  1443. // BTNST_COLOR_FG_FOCUS Text color when the button is focused
  1444. // [IN] crColor
  1445. // New color.
  1446. // [IN] bRepaint
  1447. // If TRUE the control will be repainted.
  1448. //
  1449. // Return value:
  1450. // BTNST_OK
  1451. // Function executed successfully.
  1452. // BTNST_INVALIDINDEX
  1453. // Invalid color index.
  1454. //
  1455. DWORD CButtonST::SetColor(BYTE byColorIndex, COLORREF crColor, BOOL bRepaint)
  1456. {
  1457. if (byColorIndex >= BTNST_MAX_COLORS) return BTNST_INVALIDINDEX;
  1458. // Set new color
  1459. m_crColors[byColorIndex] = crColor;
  1460. if (bRepaint) Invalidate();
  1461. return BTNST_OK;
  1462. } // End of SetColor
  1463. // This functions returns the color used for a particular state.
  1464. //
  1465. // Parameters:
  1466. // [IN] byColorIndex
  1467. // Index of the color to get.
  1468. // See SetColor for the list of available colors.
  1469. // [OUT] crpColor
  1470. // A pointer to a COLORREF that will receive the color.
  1471. //
  1472. // Return value:
  1473. // BTNST_OK
  1474. // Function executed successfully.
  1475. // BTNST_INVALIDINDEX
  1476. // Invalid color index.
  1477. //
  1478. DWORD CButtonST::GetColor(BYTE byColorIndex, COLORREF* crpColor)
  1479. {
  1480. if (byColorIndex >= BTNST_MAX_COLORS) return BTNST_INVALIDINDEX;
  1481. // Get color
  1482. *crpColor = m_crColors[byColorIndex];
  1483. return BTNST_OK;
  1484. } // End of GetColor
  1485. // This function applies an offset to the RGB components of the specified color.
  1486. // This function can be seen as an easy way to make a color darker or lighter than
  1487. // its default value.
  1488. //
  1489. // Parameters:
  1490. // [IN] byColorIndex
  1491. // Index of the color to set.
  1492. // See SetColor for the list of available colors.
  1493. // [IN] shOffsetColor
  1494. // A short value indicating the offset to apply to the color.
  1495. // This value must be between -255 and 255.
  1496. // [IN] bRepaint
  1497. // If TRUE the control will be repainted.
  1498. //
  1499. // Return value:
  1500. // BTNST_OK
  1501. // Function executed successfully.
  1502. // BTNST_INVALIDINDEX
  1503. // Invalid color index.
  1504. // BTNST_BADPARAM
  1505. // The specified offset is out of range.
  1506. //
  1507. DWORD CButtonST::OffsetColor(BYTE byColorIndex, short shOffset, BOOL bRepaint)
  1508. {
  1509. BYTE byRed = 0;
  1510. BYTE byGreen = 0;
  1511. BYTE byBlue = 0;
  1512. short shOffsetR = shOffset;
  1513. short shOffsetG = shOffset;
  1514. short shOffsetB = shOffset;
  1515. if (byColorIndex >= BTNST_MAX_COLORS) return BTNST_INVALIDINDEX;
  1516. if (shOffset < -255 || shOffset > 255) return BTNST_BADPARAM;
  1517. // Get RGB components of specified color
  1518. byRed = GetRValue(m_crColors[byColorIndex]);
  1519. byGreen = GetGValue(m_crColors[byColorIndex]);
  1520. byBlue = GetBValue(m_crColors[byColorIndex]);
  1521. // Calculate max. allowed real offset
  1522. if (shOffset > 0)
  1523. {
  1524. if (byRed + shOffset > 255) shOffsetR = 255 - byRed;
  1525. if (byGreen + shOffset > 255) shOffsetG = 255 - byGreen;
  1526. if (byBlue + shOffset > 255) shOffsetB = 255 - byBlue;
  1527. shOffset = min(min(shOffsetR, shOffsetG), shOffsetB);
  1528. } // if
  1529. else
  1530. {
  1531. if (byRed + shOffset < 0) shOffsetR = -byRed;
  1532. if (byGreen + shOffset < 0) shOffsetG = -byGreen;
  1533. if (byBlue + shOffset < 0) shOffsetB = -byBlue;
  1534. shOffset = max(max(shOffsetR, shOffsetG), shOffsetB);
  1535. } // else
  1536. // Set new color
  1537. m_crColors[byColorIndex] = RGB(byRed + shOffset, byGreen + shOffset, byBlue + shOffset);
  1538. if (bRepaint) Invalidate();
  1539. return BTNST_OK;
  1540. } // End of OffsetColor
  1541. // This function sets the hilight logic for the button.
  1542. // Applies only to flat buttons.
  1543. //
  1544. // Parameters:
  1545. // [IN] bAlwaysTrack
  1546. // If TRUE the button will be hilighted even if the window that owns it, is
  1547. // not the active window.
  1548. // If FALSE the button will be hilighted only if the window that owns it,
  1549. // is the active window.
  1550. //
  1551. // Return value:
  1552. // BTNST_OK
  1553. // Function executed successfully.
  1554. //
  1555. DWORD CButtonST::SetAlwaysTrack(BOOL bAlwaysTrack)
  1556. {
  1557. m_bAlwaysTrack = bAlwaysTrack;
  1558. return BTNST_OK;
  1559. } // End of SetAlwaysTrack
  1560. // This function sets the cursor to be used when the mouse is over the button.
  1561. //
  1562. // Parameters:
  1563. // [IN] nCursorId
  1564. // ID number of the cursor resource.
  1565. // Pass NULL to remove a previously loaded cursor.
  1566. // [IN] bRepaint
  1567. // If TRUE the control will be repainted.
  1568. //
  1569. // Return value:
  1570. // BTNST_OK
  1571. // Function executed successfully.
  1572. // BTNST_INVALIDRESOURCE
  1573. // Failed loading the specified resource.
  1574. //
  1575. DWORD CButtonST::SetBtnCursor(int nCursorId, BOOL bRepaint)
  1576. {
  1577. HINSTANCE hInstResource = NULL;
  1578. // Destroy any previous cursor
  1579. if (m_hCursor)
  1580. {
  1581. ::DestroyCursor(m_hCursor);
  1582. m_hCursor = NULL;
  1583. } // if
  1584. // Load cursor
  1585. if (nCursorId)
  1586. {
  1587. hInstResource = AfxFindResourceHandle(MAKEINTRESOURCE(nCursorId), RT_GROUP_CURSOR);
  1588. // Load cursor resource
  1589. m_hCursor = (HCURSOR)::LoadImage(hInstResource, MAKEINTRESOURCE(nCursorId), IMAGE_CURSOR, 0, 0, 0);
  1590. // Repaint the button
  1591. if (bRepaint) Invalidate();
  1592. // If something wrong
  1593. if (m_hCursor == NULL) return BTNST_INVALIDRESOURCE;
  1594. } // if
  1595. return BTNST_OK;
  1596. } // End of SetBtnCursor
  1597. // This function sets if the button border must be drawn.
  1598. // Applies only to flat buttons.
  1599. //
  1600. // Parameters:
  1601. // [IN] bDrawBorder
  1602. // If TRUE the border will be drawn.
  1603. // [IN] bRepaint
  1604. // If TRUE the control will be repainted.
  1605. //
  1606. // Return value:
  1607. // BTNST_OK
  1608. // Function executed successfully.
  1609. //
  1610. DWORD CButtonST::DrawBorder(BOOL bDrawBorder, BOOL bRepaint)
  1611. {
  1612. m_bDrawBorder = bDrawBorder;
  1613. // Repaint the button
  1614. if (bRepaint) Invalidate();
  1615. return BTNST_OK;
  1616. } // End of DrawBorder
  1617. // This function sets if the focus rectangle must be drawn for flat buttons.
  1618. //
  1619. // Parameters:
  1620. // [IN] bDrawFlatFocus
  1621. // If TRUE the focus rectangle will be drawn also for flat buttons.
  1622. // [IN] bRepaint
  1623. // If TRUE the control will be repainted.
  1624. //
  1625. // Return value:
  1626. // BTNST_OK
  1627. // Function executed successfully.
  1628. //
  1629. DWORD CButtonST::DrawFlatFocus(BOOL bDrawFlatFocus, BOOL bRepaint)
  1630. {
  1631. m_bDrawFlatFocus = bDrawFlatFocus;
  1632. // Repaint the button
  1633. if (bRepaint) Invalidate();
  1634. return BTNST_OK;
  1635. } // End of DrawFlatFocus
  1636. void CButtonST::InitToolTip()
  1637. {
  1638. if (m_ToolTip.m_hWnd == NULL)
  1639. {
  1640. // Create ToolTip control
  1641. m_ToolTip.Create(this, m_dwToolTipStyle);
  1642. // Create inactive
  1643. m_ToolTip.Activate(FALSE);
  1644. // Enable multiline
  1645. m_ToolTip.SendMessage(TTM_SETMAXTIPWIDTH, 0, 400);
  1646. //m_ToolTip.SendMessage(TTM_SETTITLE, TTI_INFO, (LPARAM)_T("Title"));
  1647. } // if
  1648. } // End of InitToolTip
  1649. // This function sets the text to show in the button tooltip.
  1650. //
  1651. // Parameters:
  1652. // [IN] nText
  1653. // ID number of the string resource containing the text to show.
  1654. // [IN] bActivate
  1655. // If TRUE the tooltip will be created active.
  1656. //
  1657. void CButtonST::SetTooltipText(int nText, BOOL bActivate)
  1658. {
  1659. CString sText;
  1660. // Load string resource
  1661. sText.LoadString(nText);
  1662. // If string resource is not empty
  1663. if (sText.IsEmpty() == FALSE) SetTooltipText((LPCTSTR)sText, bActivate);
  1664. } // End of SetTooltipText
  1665. // This function sets the text to show in the button tooltip.
  1666. //
  1667. // Parameters:
  1668. // [IN] lpszText
  1669. // Pointer to a null-terminated string containing the text to show.
  1670. // [IN] bActivate
  1671. // If TRUE the tooltip will be created active.
  1672. //
  1673. void CButtonST::SetTooltipText(LPCTSTR lpszText, BOOL bActivate)
  1674. {
  1675. // We cannot accept NULL pointer
  1676. if (lpszText == NULL) return;
  1677. // Initialize ToolTip
  1678. InitToolTip();
  1679. // If there is no tooltip defined then add it
  1680. if (m_ToolTip.GetToolCount() == 0)
  1681. {
  1682. CRect rectBtn; 
  1683. GetClientRect(rectBtn);
  1684. m_ToolTip.AddTool(this, lpszText, rectBtn, 1);
  1685. } // if
  1686. // Set text for tooltip
  1687. m_ToolTip.UpdateTipText(lpszText, this, 1);
  1688. m_ToolTip.Activate(bActivate);
  1689. } // End of SetTooltipText
  1690. // This function enables or disables the button tooltip.
  1691. //
  1692. // Parameters:
  1693. // [IN] bActivate
  1694. // If TRUE the tooltip will be activated.
  1695. //
  1696. void CButtonST::ActivateTooltip(BOOL bActivate)
  1697. {
  1698. // If there is no tooltip then do nothing
  1699. if (m_ToolTip.GetToolCount() == 0) return;
  1700. // Activate tooltip
  1701. m_ToolTip.Activate(bActivate);
  1702. } // End of EnableTooltip
  1703. // This function enables the tooltip to be displayed using the balloon style.
  1704. // This function must be called before any call to SetTooltipText is made.
  1705. //
  1706. // Return value:
  1707. // BTNST_OK
  1708. // Function executed successfully.
  1709. //
  1710. DWORD CButtonST::EnableBalloonTooltip()
  1711. {
  1712. m_dwToolTipStyle |= TTS_BALLOON;
  1713. return BTNST_OK;
  1714. } // End of EnableBalloonTooltip
  1715. // This function returns if the button is the default button.
  1716. //
  1717. // Return value:
  1718. // TRUE
  1719. // The button is the default button.
  1720. // FALSE
  1721. // The button is not the default button.
  1722. //
  1723. BOOL CButtonST::GetDefault()
  1724. {
  1725. return m_bIsDefault;
  1726. } // End of GetDefault
  1727. // This function enables the transparent mode.
  1728. // Note: this operation is not reversible.
  1729. // DrawTransparent should be called just after the button is created.
  1730. // Do not use trasparent buttons until you really need it (you have a bitmapped
  1731. // background) since each transparent button makes a copy in memory of its background.
  1732. // This may bring unnecessary memory use and execution overload.
  1733. //
  1734. // Parameters:
  1735. // [IN] bRepaint
  1736. // If TRUE the control will be repainted.
  1737. //
  1738. void CButtonST::DrawTransparent(BOOL bRepaint)
  1739. {
  1740. m_bDrawTransparent = TRUE;
  1741. // Restore old bitmap (if any)
  1742. if (m_dcBk.m_hDC != NULL && m_pbmpOldBk != NULL)
  1743. {
  1744. m_dcBk.SelectObject(m_pbmpOldBk);
  1745. } // if
  1746. m_bmpBk.DeleteObject();
  1747. m_dcBk.DeleteDC();
  1748. // Repaint the button
  1749. if (bRepaint) Invalidate();
  1750. } // End of DrawTransparent
  1751. DWORD CButtonST::SetBk(CDC* pDC)
  1752. {
  1753. if (m_bDrawTransparent && pDC)
  1754. {
  1755. // Restore old bitmap (if any)
  1756. if (m_dcBk.m_hDC != NULL && m_pbmpOldBk != NULL)
  1757. {
  1758. m_dcBk.SelectObject(m_pbmpOldBk);
  1759. } // if
  1760. m_bmpBk.DeleteObject();
  1761. m_dcBk.DeleteDC();
  1762. CRect rect;
  1763. CRect rect1;
  1764. GetClientRect(rect);
  1765. GetWindowRect(rect1);
  1766. GetParent()->ScreenToClient(rect1);
  1767. m_dcBk.CreateCompatibleDC(pDC);
  1768. m_bmpBk.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
  1769. m_pbmpOldBk = m_dcBk.SelectObject(&m_bmpBk);
  1770. m_dcBk.BitBlt(0, 0, rect.Width(), rect.Height(), pDC, rect1.left, rect1.top, SRCCOPY);
  1771. return BTNST_OK;
  1772. } // if
  1773. return BTNST_BADPARAM;
  1774. } // End of SetBk
  1775. // This function sets the URL that will be opened when the button is clicked.
  1776. //
  1777. // Parameters:
  1778. // [IN] lpszURL
  1779. // Pointer to a null-terminated string that contains the URL.
  1780. // Pass NULL to removed any previously specified URL.
  1781. //
  1782. // Return value:
  1783. // BTNST_OK
  1784. // Function executed successfully.
  1785. //
  1786. DWORD CButtonST::SetURL(LPCTSTR lpszURL)
  1787. {
  1788. // Remove any existing URL
  1789. memset(m_szURL, 0, sizeof(m_szURL));
  1790. if (lpszURL)
  1791. {
  1792. // Store the URL
  1793. _tcsncpy(m_szURL, lpszURL, _MAX_PATH);
  1794. } // if
  1795. return BTNST_OK;
  1796. } // End of SetURL
  1797. // This function associates a menu to the button.
  1798. // The menu will be displayed clicking the button.
  1799. //
  1800. // Parameters:
  1801. // [IN] nMenu
  1802. // ID number of the menu resource.
  1803. // Pass NULL to remove any menu from the button.
  1804. // [IN] hParentWnd
  1805. // Handle to the window that owns the menu.
  1806. // This window receives all messages from the menu.
  1807. // [IN] bRepaint
  1808. // If TRUE the control will be repainted.
  1809. //
  1810. // Return value:
  1811. // BTNST_OK
  1812. // Function executed successfully.
  1813. // BTNST_INVALIDRESOURCE
  1814. // Failed loading the specified resource.
  1815. //
  1816. #ifndef BTNST_USE_BCMENU
  1817. DWORD CButtonST::SetMenu(UINT nMenu, HWND hParentWnd, BOOL bRepaint)
  1818. {
  1819. HINSTANCE hInstResource = NULL;
  1820. // Destroy any previous menu
  1821. if (m_hMenu)
  1822. {
  1823. ::DestroyMenu(m_hMenu);
  1824. m_hMenu = NULL;
  1825. m_hParentWndMenu = NULL;
  1826. m_bMenuDisplayed = FALSE;
  1827. } // if
  1828. // Load menu
  1829. if (nMenu)
  1830. {
  1831. // Find correct resource handle
  1832. hInstResource = AfxFindResourceHandle(MAKEINTRESOURCE(nMenu), RT_MENU);
  1833. // Load menu resource
  1834. m_hMenu = ::LoadMenu(hInstResource, MAKEINTRESOURCE(nMenu));
  1835. m_hParentWndMenu = hParentWnd;
  1836. // If something wrong
  1837. if (m_hMenu == NULL) return BTNST_INVALIDRESOURCE;
  1838. } // if
  1839. // Repaint the button
  1840. if (bRepaint) Invalidate();
  1841. return BTNST_OK;
  1842. } // End of SetMenu
  1843. #endif
  1844. // This function associates a menu to the button.
  1845. // The menu will be displayed clicking the button.
  1846. // The menu will be handled by the BCMenu class.
  1847. //
  1848. // Parameters:
  1849. // [IN] nMenu
  1850. // ID number of the menu resource.
  1851. // Pass NULL to remove any menu from the button.
  1852. // [IN] hParentWnd
  1853. // Handle to the window that owns the menu.
  1854. // This window receives all messages from the menu.
  1855. // [IN] bWinXPStyle
  1856. // If TRUE the menu will be displayed using the new Windows XP style.
  1857. // If FALSE the menu will be displayed using the standard style.
  1858. // [IN] nToolbarID
  1859. // Resource ID of the toolbar to be associated to the menu.
  1860. // [IN] sizeToolbarIcon
  1861. // A CSize object indicating the size (in pixels) of each icon into the toolbar.
  1862. // All icons into the toolbar must have the same size.
  1863. // [IN] crToolbarBk
  1864. // A COLORREF value indicating the color to use as background for the icons into the toolbar.
  1865. // This color will be used as the "transparent" color.
  1866. // [IN] bRepaint
  1867. // If TRUE the control will be repainted.
  1868. //
  1869. // Return value:
  1870. // BTNST_OK
  1871. // Function executed successfully.
  1872. // BTNST_INVALIDRESOURCE
  1873. // Failed loading the specified resource.
  1874. //
  1875. #ifdef BTNST_USE_BCMENU
  1876. DWORD CButtonST::SetMenu(UINT nMenu, HWND hParentWnd, BOOL bWinXPStyle, UINT nToolbarID, CSize sizeToolbarIcon, COLORREF crToolbarBk, BOOL bRepaint)
  1877. {
  1878. BOOL bRetValue = FALSE;
  1879. // Destroy any previous menu
  1880. if (m_menuPopup.m_hMenu)
  1881. {
  1882. m_menuPopup.DestroyMenu();
  1883. m_hParentWndMenu = NULL;
  1884. m_bMenuDisplayed = FALSE;
  1885. } // if
  1886. // Load menu
  1887. if (nMenu)
  1888. {
  1889. m_menuPopup.SetMenuDrawMode(bWinXPStyle);
  1890. // Load menu
  1891. bRetValue = m_menuPopup.LoadMenu(nMenu);
  1892. // If something wrong
  1893. if (bRetValue == FALSE) return BTNST_INVALIDRESOURCE;
  1894. // Load toolbar
  1895. if (nToolbarID)
  1896. {
  1897. m_menuPopup.SetBitmapBackground(crToolbarBk);
  1898. m_menuPopup.SetIconSize(sizeToolbarIcon.cx, sizeToolbarIcon.cy);
  1899. bRetValue = m_menuPopup.LoadToolbar(nToolbarID);
  1900. // If something wrong
  1901. if (bRetValue == FALSE) 
  1902. {
  1903. m_menuPopup.DestroyMenu();
  1904. return BTNST_INVALIDRESOURCE;
  1905. } // if
  1906. } // if
  1907. m_hParentWndMenu = hParentWnd;
  1908. } // if
  1909. // Repaint the button
  1910. if (bRepaint) Invalidate();
  1911. return BTNST_OK;
  1912. } // End of SetMenu
  1913. #endif
  1914. // This function sets the callback message that will be sent to the
  1915. // specified window just before the menu associated to the button is displayed.
  1916. //
  1917. // Parameters:
  1918. // [IN] hWnd
  1919. // Handle of the window that will receive the callback message.
  1920. // Pass NULL to remove any previously specified callback message.
  1921. // [IN] nMessage
  1922. // Callback message to send to window.
  1923. // [IN] lParam
  1924. // A 32 bits user specified value that will be passed to the callback function.
  1925. //
  1926. // Remarks:
  1927. // the callback function must be in the form:
  1928. // LRESULT On_MenuCallback(WPARAM wParam, LPARAM lParam)
  1929. // Where:
  1930. // [IN] wParam
  1931. // If support for BCMenu is enabled: a pointer to BCMenu
  1932. // else a HMENU handle to the menu that is being to be displayed.
  1933. // [IN] lParam
  1934. // The 32 bits user specified value.
  1935. //
  1936. // Return value:
  1937. // BTNST_OK
  1938. // Function executed successfully.
  1939. //
  1940. DWORD CButtonST::SetMenuCallback(HWND hWnd, UINT nMessage, LPARAM lParam)
  1941. {
  1942. m_csCallbacks.hWnd = hWnd;
  1943. m_csCallbacks.nMessage = nMessage;
  1944. m_csCallbacks.lParam = lParam;
  1945. return BTNST_OK;
  1946. } // End of SetMenuCallback
  1947. // This function resizes the button to the same size of the image.
  1948. // To get good results both the IN and OUT images should have the same size.
  1949. //
  1950. void CButtonST::SizeToContent()
  1951. {
  1952. if (m_csIcons[0].hIcon)
  1953. {
  1954. m_ptImageOrg.x = 0;
  1955. m_ptImageOrg.y = 0;
  1956.     SetWindowPos( NULL, -1, -1, m_csIcons[0].dwWidth, m_csIcons[0].dwHeight,
  1957. SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE);
  1958. } // if
  1959. else
  1960. if (m_csBitmaps[0].hBitmap)
  1961. {
  1962. m_ptImageOrg.x = 0;
  1963. m_ptImageOrg.y = 0;
  1964.     SetWindowPos( NULL, -1, -1, m_csBitmaps[0].dwWidth, m_csBitmaps[0].dwHeight,
  1965. SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE);
  1966. } // if
  1967. } // End of SizeToContent
  1968. // This function sets the sound that must be played on particular button states.
  1969. //
  1970. // Parameters:
  1971. // [IN] lpszSound
  1972. // A string that specifies the sound to play.
  1973. // If hMod is NULL this string is interpreted as a filename, else it
  1974. // is interpreted as a resource identifier.
  1975. // Pass NULL to remove any previously specified sound.
  1976. // [IN] hMod
  1977. // Handle to the executable file that contains the resource to be loaded.
  1978. // This parameter must be NULL unless lpszSound specifies a resource identifier.
  1979. // [IN] bPlayOnClick
  1980. // TRUE if the sound must be played when the button is clicked.
  1981. // FALSE if the sound must be played when the mouse is moved over the button.
  1982. // [IN] bPlayAsync
  1983. // TRUE if the sound must be played asynchronously.
  1984. // FALSE if the sound must be played synchronously. The application takes control
  1985. // when the sound is completely played.
  1986. //
  1987. // Return value:
  1988. // BTNST_OK
  1989. // Function executed successfully.
  1990. //
  1991. #ifdef BTNST_USE_SOUND
  1992. DWORD CButtonST::SetSound(LPCTSTR lpszSound, HMODULE hMod, BOOL bPlayOnClick, BOOL bPlayAsync)
  1993. {
  1994. BYTE byIndex = bPlayOnClick ? 1 : 0;
  1995. // Store new sound
  1996. if (lpszSound)
  1997. {
  1998. if (hMod) // From resource identifier ?
  1999. {
  2000. m_csSounds[byIndex].lpszSound = lpszSound;
  2001. } // if
  2002. else
  2003. {
  2004. _tcscpy(m_csSounds[byIndex].szSound, lpszSound);
  2005. m_csSounds[byIndex].lpszSound = m_csSounds[byIndex].szSound;
  2006. } // else
  2007. m_csSounds[byIndex].hMod = hMod;
  2008. m_csSounds[byIndex].dwFlags = SND_NODEFAULT | SND_NOWAIT;
  2009. m_csSounds[byIndex].dwFlags |= hMod ? SND_RESOURCE : SND_FILENAME;
  2010. m_csSounds[byIndex].dwFlags |= bPlayAsync ? SND_ASYNC : SND_SYNC;
  2011. } // if
  2012. else
  2013. {
  2014. // Or remove any existing
  2015. ::ZeroMemory(&m_csSounds[byIndex], sizeof(STRUCT_SOUND));
  2016. } // else
  2017. return BTNST_OK;
  2018. } // End of SetSound
  2019. #endif
  2020. // This function is called every time the button background needs to be painted.
  2021. // If the button is in transparent mode this function will NOT be called.
  2022. // This is a virtual function that can be rewritten in CButtonST-derived classes
  2023. // to produce a whole range of buttons not available by default.
  2024. //
  2025. // Parameters:
  2026. // [IN] pDC
  2027. // Pointer to a CDC object that indicates the device context.
  2028. // [IN] pRect
  2029. // Pointer to a CRect object that indicates the bounds of the
  2030. // area to be painted.
  2031. //
  2032. // Return value:
  2033. // BTNST_OK
  2034. // Function executed successfully.
  2035. //
  2036. DWORD CButtonST::OnDrawBackground(CDC* pDC, CRect* pRect)
  2037. {
  2038. COLORREF crColor;
  2039. if (m_bIsFlat == FALSE)
  2040. {
  2041. if (m_bIsFocused || m_bIsDefault)
  2042. {
  2043. CBrush br(RGB(0,0,0));  
  2044. pDC->FrameRect(pRect, &br);
  2045. pRect->DeflateRect(1, 1);
  2046. } // if
  2047. } // if
  2048. if (m_bMouseOnButton || m_bIsPressed)
  2049. crColor = m_crColors[BTNST_COLOR_BK_IN];
  2050. else
  2051. {
  2052. if (m_bIsFocused)
  2053. crColor = m_crColors[BTNST_COLOR_BK_FOCUS];
  2054. else
  2055. crColor = m_crColors[BTNST_COLOR_BK_OUT];
  2056. } // else
  2057. CBrush brBackground(crColor);
  2058. pDC->FillRect(pRect, &brBackground);
  2059. return BTNST_OK;
  2060. } // End of OnDrawBackground
  2061. // This function is called every time the button border needs to be painted.
  2062. // This is a virtual function that can be rewritten in CButtonST-derived classes
  2063. // to produce a whole range of buttons not available by default.
  2064. //
  2065. // Parameters:
  2066. // [IN] pDC
  2067. // Pointer to a CDC object that indicates the device context.
  2068. // [IN] pRect
  2069. // Pointer to a CRect object that indicates the bounds of the
  2070. // area to be painted.
  2071. //
  2072. // Return value:
  2073. // BTNST_OK
  2074. // Function executed successfully.
  2075. //
  2076. DWORD CButtonST::OnDrawBorder(CDC* pDC, CRect* pRect)
  2077. {
  2078. // Draw pressed button
  2079. if (m_bIsPressed)
  2080. {
  2081. if (m_bIsFlat)
  2082. {
  2083. if (m_bDrawBorder)
  2084. pDC->Draw3dRect(pRect, ::GetSysColor(COLOR_BTNSHADOW), ::GetSysColor(COLOR_BTNHILIGHT));
  2085. }
  2086. else    
  2087. {
  2088. CBrush brBtnShadow(GetSysColor(COLOR_BTNSHADOW));
  2089. pDC->FrameRect(pRect, &brBtnShadow);
  2090. }
  2091. }
  2092. else // ...else draw non pressed button
  2093. {
  2094. CPen penBtnHiLight(PS_SOLID, 0, GetSysColor(COLOR_BTNHILIGHT)); // White
  2095. CPen pen3DLight(PS_SOLID, 0, GetSysColor(COLOR_3DLIGHT));       // Light gray
  2096. CPen penBtnShadow(PS_SOLID, 0, GetSysColor(COLOR_BTNSHADOW));   // Dark gray
  2097. CPen pen3DDKShadow(PS_SOLID, 0, GetSysColor(COLOR_3DDKSHADOW)); // Black
  2098. if (m_bIsFlat)
  2099. {
  2100. if (m_bMouseOnButton && m_bDrawBorder)
  2101. pDC->Draw3dRect(pRect, ::GetSysColor(COLOR_BTNHILIGHT), ::GetSysColor(COLOR_BTNSHADOW));
  2102. }
  2103. else
  2104. {
  2105. // Draw top-left borders
  2106. // White line
  2107. CPen* pOldPen = pDC->SelectObject(&penBtnHiLight);
  2108. pDC->MoveTo(pRect->left, pRect->bottom-1);
  2109. pDC->LineTo(pRect->left, pRect->top);
  2110. pDC->LineTo(pRect->right, pRect->top);
  2111. // Light gray line
  2112. pDC->SelectObject(pen3DLight);
  2113. pDC->MoveTo(pRect->left+1, pRect->bottom-1);
  2114. pDC->LineTo(pRect->left+1, pRect->top+1);
  2115. pDC->LineTo(pRect->right, pRect->top+1);
  2116. // Draw bottom-right borders
  2117. // Black line
  2118. pDC->SelectObject(pen3DDKShadow);
  2119. pDC->MoveTo(pRect->left, pRect->bottom-1);
  2120. pDC->LineTo(pRect->right-1, pRect->bottom-1);
  2121. pDC->LineTo(pRect->right-1, pRect->top-1);
  2122. // Dark gray line
  2123. pDC->SelectObject(penBtnShadow);
  2124. pDC->MoveTo(pRect->left+1, pRect->bottom-2);
  2125. pDC->LineTo(pRect->right-2, pRect->bottom-2);
  2126. pDC->LineTo(pRect->right-2, pRect->top);
  2127. //
  2128. pDC->SelectObject(pOldPen);
  2129. } // else
  2130. } // else
  2131. return BTNST_OK;
  2132. } // End of OnDrawBorder
  2133. #undef BS_TYPEMASK