Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

320 lines
10 KiB

  1. #include "priv.h"
  2. #include "button.h"
  3. const static TCHAR c_szCoolButtonProp[] = TEXT("CCoolButton_This");
  4. /////////////////////////////////////////////////////////////////////////////
  5. // CCoolButton
  6. BOOL CCoolButton::Create(HWND hwndParent, INT_PTR nID, DWORD dwExStyle, DWORD dwStyle)
  7. {
  8. m_hwndButton = ::CreateWindowEx( dwExStyle, WC_BUTTON, NULL, dwStyle | WS_CHILD | WS_VISIBLE,
  9. 0, 0, 0, 0, hwndParent, (HMENU)nID, HINST_THISDLL, NULL);
  10. if (m_hwndButton && SetProp(m_hwndButton, c_szCoolButtonProp, this))
  11. {
  12. SetWindowLongPtr(m_hwndButton, GWLP_USERDATA, (LPARAM)(WNDPROC)(GetWindowLongPtr(m_hwndButton, GWLP_WNDPROC)));
  13. SetWindowLongPtr(m_hwndButton, GWLP_WNDPROC, (LPARAM)s_ButtonWndSubclassProc);
  14. }
  15. DWORD dwBtnStyle = GetWindowLong(m_hwndButton, GWL_STYLE);
  16. dwBtnStyle |= BS_PUSHBUTTON | BS_OWNERDRAW;
  17. SetWindowLong(m_hwndButton, GWL_STYLE, dwBtnStyle);
  18. ShowWindow(m_hwndButton, SW_SHOW);
  19. return m_hwndButton == NULL ? FALSE : TRUE;
  20. }
  21. CCoolButton::~CCoolButton()
  22. {
  23. if (m_hwndButton)
  24. DestroyWindow(m_hwndButton);
  25. if (m_hImageList)
  26. ImageList_Destroy(m_hImageList);
  27. if (m_bstrText)
  28. SysFreeString(m_bstrText);
  29. if (m_fIsCapture)
  30. ReleaseCapture();
  31. if (m_hFont)
  32. DeleteObject(m_hFont);
  33. }
  34. LRESULT CALLBACK CCoolButton::s_ButtonWndSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  35. {
  36. CCoolButton* pThis = (CCoolButton*)GetProp(hwnd, c_szCoolButtonProp);
  37. if (!pThis)
  38. return DefWindowProcWrap(hwnd, uMsg, wParam, lParam);
  39. WNDPROC pfnOldWndProc = (WNDPROC)(GetWindowLongPtr(hwnd, GWLP_USERDATA));
  40. switch (uMsg)
  41. {
  42. case WM_ERASEBKGND:
  43. return (LRESULT)1;
  44. case WM_MEASUREITEM:
  45. {
  46. LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT)lParam;
  47. IMAGEINFO imgInfo ;
  48. ImageList_GetImageInfo(pThis->m_hImageList, 0, &imgInfo);
  49. if (!pThis->m_bstrText)
  50. {
  51. lpmis->itemWidth = RECTWIDTH(imgInfo.rcImage) ;
  52. lpmis->itemHeight= RECTHEIGHT(imgInfo.rcImage) ;
  53. }
  54. else
  55. {
  56. lpmis->itemWidth = RECTWIDTH(imgInfo.rcImage) + 200;
  57. lpmis->itemHeight= RECTHEIGHT(imgInfo.rcImage) ;
  58. }
  59. }
  60. return TRUE;
  61. case WM_DRAWITEM:
  62. {
  63. LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
  64. HDC hdc = lpdis->hDC;
  65. int nIndex = ((lpdis->itemState & ODS_DISABLED) ? 2 :
  66. ((lpdis->itemState & ODS_SELECTED) ? 1 :
  67. ((lpdis->itemState & ODS_FOCUS) ? 1 :
  68. (pThis->m_fHover) ? 1 : 0)));
  69. RECT rcClient;
  70. GetClientRect(hwnd,&rcClient);
  71. HDC hdcMem = CreateCompatibleDC(hdc);
  72. HBITMAP hbmp = CreateCompatibleBitmap(hdc, RECTWIDTH(rcClient),RECTHEIGHT(rcClient));
  73. HBITMAP hOldBmp = (HBITMAP)SelectObject(hdcMem, hbmp);
  74. // fill rgn
  75. HBRUSH hBrush = CreateSolidBrush(RGB(244,244,240));
  76. if (hBrush)
  77. {
  78. FillRect(hdcMem, &rcClient, hBrush);
  79. DeleteObject(hBrush);
  80. }
  81. BOOL fEnabled = (lpdis->itemState & ODS_DISABLED) ? FALSE : TRUE ;
  82. // Draw Button to the screen
  83. IMAGEINFO imgInfo ;
  84. ImageList_GetImageInfo(pThis->m_hImageList, nIndex, &imgInfo);
  85. ImageList_Draw(pThis->m_hImageList, nIndex, hdcMem, RECTWIDTH(rcClient) - RECTWIDTH(imgInfo.rcImage), 0, ILD_NORMAL);
  86. RECT rcFormat = { rcClient.left+2, rcClient.top , RECTWIDTH(rcClient)- RECTWIDTH(imgInfo.rcImage)-8, RECTHEIGHT(rcClient) };
  87. if (pThis->m_bstrText)
  88. {
  89. // Get the caption to draw
  90. LPWSTR pszText = L"";
  91. pszText = pThis->m_bstrText;
  92. int nBkMode = SetBkMode(hdcMem, TRANSPARENT);
  93. HFONT hFontOld = (HFONT) SelectObject(hdcMem, pThis->m_hFont);
  94. int nOldTextColor = SetTextColor(hdcMem, RGB(0,255,0));
  95. ::DrawText(hdcMem, pszText, -1, &rcFormat, pThis->GetDrawTextFlags());
  96. /*
  97. int nOldTextColor = 0;
  98. // draw button caption depending upon button state
  99. if (fEnabled)
  100. {
  101. nOldTextColor = SetTextColor(hdcMem, GetSysColor(COLOR_BTNTEXT));
  102. ::DrawText(hdcMem, pszText, -1, &rcFormat, pThis->GetDrawTextFlags());
  103. }
  104. else
  105. {
  106. nOldTextColor = SetTextColor(hdcMem, GetSysColor(COLOR_3DHILIGHT));
  107. ::DrawText(hdcMem, pszText, -1, &rcFormat, pThis->GetDrawTextFlags());
  108. SetTextColor(hdcMem, nOldTextColor);
  109. nOldTextColor = SetTextColor(hdcMem, GetSysColor(COLOR_3DSHADOW));
  110. ::DrawText(hdcMem, pszText, -1, &rcFormat, pThis->GetDrawTextFlags());
  111. SetTextColor(hdcMem, nOldTextColor);
  112. }
  113. */
  114. SelectObject(hdcMem, hFontOld);
  115. SetBkMode(hdcMem, nBkMode);
  116. }
  117. BitBlt(hdc, 0, 0, RECTWIDTH(rcClient), RECTHEIGHT(rcClient),hdcMem, 0, 0,SRCCOPY);
  118. SelectObject(hdcMem, hOldBmp);
  119. DeleteObject(hbmp);
  120. DeleteDC(hdcMem);
  121. }
  122. return TRUE;
  123. case WM_LBUTTONDBLCLK :
  124. case WM_LBUTTONDOWN:
  125. {
  126. POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
  127. pThis->CheckHover(pt);
  128. if (pThis->m_fHover && (UINT)wParam & MK_LBUTTON && !pThis->m_fMouseDown)
  129. {
  130. pThis->m_fMouseDown = TRUE;
  131. CallWindowProc(pfnOldWndProc, hwnd, uMsg, wParam, lParam);
  132. if (BT_MENU == pThis->GetButtonType())
  133. {
  134. SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd),BN_CLICKED), (LPARAM)(hwnd));
  135. }
  136. return 0;
  137. }
  138. }
  139. break;
  140. case WM_LBUTTONUP:
  141. {
  142. CallWindowProc(pfnOldWndProc, hwnd, uMsg, wParam, lParam);
  143. pThis->m_fMouseDown = FALSE;
  144. if (pThis->m_fIsCapture)
  145. {
  146. ReleaseCapture();
  147. pThis->m_fIsCapture = FALSE;
  148. }
  149. POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
  150. pThis->CheckHover(pt);
  151. }
  152. return 0;
  153. case WM_MOUSEMOVE:
  154. {
  155. CallWindowProc(pfnOldWndProc, hwnd, uMsg, wParam, lParam);
  156. POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
  157. pThis->CheckHover(pt);
  158. if (pThis->m_fHover && (UINT)wParam & MK_LBUTTON)
  159. {
  160. pThis->m_fMouseDown = TRUE;
  161. }
  162. RedrawWindow(hwnd,NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
  163. }
  164. break;
  165. case WM_KEYDOWN:
  166. {
  167. SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd),BN_CLICKED), (LPARAM)(pThis->m_hwndButton));
  168. RedrawWindow(hwnd,NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
  169. }
  170. break;
  171. case WM_KILLFOCUS:
  172. {
  173. if (pThis->m_fIsCapture)
  174. {
  175. ReleaseCapture();
  176. pThis->m_fIsCapture = FALSE;
  177. }
  178. pThis->m_fHover = FALSE ;
  179. pThis->m_fHasFocus = FALSE ;
  180. pThis->m_fMouseDown = FALSE ;
  181. RedrawWindow(hwnd,NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
  182. }
  183. break;
  184. case WM_SETFOCUS:
  185. {
  186. if (!pThis->m_fIsCapture)
  187. {
  188. SetCapture(hwnd);
  189. pThis->m_fIsCapture = TRUE;
  190. }
  191. pThis->m_fHasFocus = TRUE ;
  192. RedrawWindow(hwnd,NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
  193. }
  194. break;
  195. case WM_DESTROY:
  196. {
  197. //
  198. // Unsubclass myself.
  199. //
  200. RemoveProp(hwnd, c_szCoolButtonProp);
  201. if (pfnOldWndProc)
  202. {
  203. SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) pfnOldWndProc);
  204. }
  205. }
  206. break;
  207. }
  208. return CallWindowProc(pfnOldWndProc, hwnd, uMsg, wParam, lParam);
  209. }
  210. BOOL CCoolButton::LoadBitmaps(UINT nImageList, UINT iImageWidth)
  211. {
  212. if (m_hImageList)
  213. ImageList_Destroy(m_hImageList);
  214. m_hImageList = ImageList_LoadImage(HINST_THISDLL, MAKEINTRESOURCE(nImageList),
  215. iImageWidth, 0, CLR_NONE, IMAGE_BITMAP, LR_CREATEDIBSECTION);
  216. SizeToContent();
  217. return m_hImageList != NULL;
  218. }
  219. // SizeToContent will resize the button to the size of the bitmap
  220. HRESULT
  221. CCoolButton::SizeToContent()
  222. {
  223. SIZE sizeContent ;
  224. GetButtonSize(sizeContent);
  225. if (SetWindowPos(m_hwndButton,HWND_TOP, 0, 0, sizeContent.cx,sizeContent.cy,
  226. SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOACTIVATE))
  227. {
  228. return S_OK;
  229. }
  230. return S_FALSE;
  231. }
  232. VOID
  233. CCoolButton::CheckHover(POINT pt)
  234. {
  235. if (HitTest(pt))
  236. {
  237. if (!m_fIsCapture || GetCapture() != m_hwndButton)
  238. {
  239. SetCapture(m_hwndButton);
  240. m_fIsCapture = TRUE;
  241. }
  242. if (!m_fHover)
  243. {
  244. m_fHover = TRUE;
  245. RedrawWindow(m_hwndButton,NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
  246. }
  247. }
  248. else
  249. {
  250. if (m_fIsCapture)
  251. {
  252. m_fIsCapture = FALSE;
  253. ReleaseCapture();
  254. }
  255. m_fHover = FALSE;
  256. RedrawWindow(m_hwndButton,NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
  257. }
  258. }
  259. BOOL CCoolButton::HitTest(POINT point)
  260. {
  261. RECT rcClient;
  262. GetClientRect(m_hwndButton, &rcClient);
  263. return ::PtInRect(&rcClient, point);
  264. }