BTNST.CPP
上传用户:gt3658
上传日期:2022-07-09
资源大小:97k
文件大小:58k
源码类别:

棋牌游戏

开发平台:

Visual C++

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