BtnST.cpp
上传用户:dengkfang
上传日期:2008-12-30
资源大小:5233k
文件大小:58k
源码类别:

CA认证

开发平台:

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