SkinButton.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. #include "stdafx.h"
  2. #include "SkinButton.h"
  3. // CSkinButton
  4. #define IDC_CURSOR_HAND 132
  5. IMPLEMENT_DYNAMIC(CSkinButton, CButton)
  6. CSkinButton::CSkinButton()
  7. {
  8. m_state = NORMAL;
  9. m_pFont = new CFont();
  10. m_pFont->CreatePointFont(90, _T("Arial"));
  11. m_fg = RGB(0, 0, 0);
  12. m_bg = RGB(255, 255, 255);
  13. m_crBack = RGB(255, 0, 255);
  14. m_bMouseOver = false;
  15. m_bEnabled = true;
  16. m_bDCStored = false;
  17. m_bShowOwnerText = FALSE;
  18. m_textPos = CPoint(0, 0);
  19. m_iconRect = CRect(0, 0, 16, 16);
  20. m_bmpIconButton.LoadImage(_T("Skin\\IconButton.bmp"));
  21. }
  22. CSkinButton::~CSkinButton()
  23. {
  24. delete m_pFont;
  25. m_memDC.DeleteDC();
  26. }
  27. BEGIN_MESSAGE_MAP(CSkinButton, CButton)
  28. ON_WM_MOUSEMOVE()
  29. ON_WM_TIMER()
  30. ON_WM_ERASEBKGND()
  31. ON_WM_SETCURSOR()
  32. ON_WM_ENABLE()
  33. ON_WM_LBUTTONUP()
  34. END_MESSAGE_MAP()
  35. void CSkinButton::DrawItem(LPDRAWITEMSTRUCT lpDIS)
  36. {
  37. //CDC* pDC = CDC::FromHandle(lpDIS->hDC);
  38. UINT state = lpDIS->itemState;
  39. //CRect rect;
  40. //rect.CopyRect(&lpDIS->rcItem);
  41. m_state = NORMAL;
  42. if (state & ODS_FOCUS)
  43. {
  44. if (state & ODS_SELECTED)
  45. {
  46. m_state = DOWN;
  47. }
  48. else
  49. {
  50. if (m_bMouseOver)
  51. m_state = HOVER;
  52. }
  53. }
  54. else
  55. {
  56. m_state = NORMAL;
  57. }
  58. if (state & ODS_DISABLED)
  59. {
  60. m_state = DISABLE;
  61. m_bEnabled = false;
  62. }
  63. DrawButton();
  64. }
  65. void CSkinButton::DrawButton()
  66. {
  67. CClientDC dc(this);
  68. CRect rect;
  69. GetClientRect(&rect);
  70. CDC memDC;
  71. memDC.CreateCompatibleDC(&dc);
  72. CBitmap Screen;
  73. Screen.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());
  74. memDC.SelectObject(&Screen);
  75. Screen.DeleteObject();
  76. //画背景;
  77. memDC.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &m_memDC, 0, 0, SRCCOPY);
  78. CString strText;
  79. GetWindowText(strText);
  80. memDC.SetBkMode(TRANSPARENT);
  81. memDC.SelectObject(m_pFont);
  82. switch (m_state)
  83. {
  84. case NORMAL:
  85. {
  86. //memDC.TextOutW(m_textPos.x,m_textPos.y,str);
  87. if (m_bmpNormal.m_hObject != 0)
  88. m_bmpNormal.TransparentBlt(memDC, rect, m_crBack);
  89. if (!m_hMouseOutIcon.IsNull())
  90. {
  91. m_hMouseOutIcon.TransparentBlt(memDC, m_iconRect.left + 2, m_iconRect.top + 2,
  92. m_iconRect.Width(), m_iconRect.Height(), RGB(0, 0, 0));
  93. memDC.SetTextColor(GetFGColor());
  94. memDC.TextOut(m_textPos.x + 2, m_textPos.y + 2, strText);
  95. _tprintf(_T("Normal-Icon:%d,%d\n"), m_textPos.x + 2, m_textPos.y + 2);
  96. }
  97. else if (m_bShowOwnerText)
  98. {
  99. DrawButtonText(&memDC, rect, strText, GetFGColor());
  100. _tprintf(_T("Normal-UnIcon:%d,%d,%d,%d\n"), rect.left, rect.top, rect.right, rect.bottom);
  101. }
  102. }
  103. break;
  104. case HOVER:
  105. {
  106. //DrawFilledRect(&memDC, rect, RGB(255,255,0));
  107. if (m_bmpHover.m_hObject != 0)
  108. m_bmpHover.TransparentBlt(memDC, rect, m_crBack);
  109. if (!m_hMouseInIcon.IsNull())
  110. {
  111. if (m_bmpIconButton.m_hObject != 0)
  112. {
  113. CEnBitmap bmpHover;
  114. m_bmpIconButton.DrawImage(bmpHover, 1, 1, 2, 1);
  115. bmpHover.ExtendDraw(&memDC, rect, 10, 10, TRUE);
  116. }
  117. m_hMouseInIcon.TransparentBlt(memDC, m_iconRect.left + 2, m_iconRect.top + 2,
  118. m_iconRect.Width(), m_iconRect.Height(), RGB(0, 0, 0));
  119. memDC.SetTextColor(GetBGColor());
  120. memDC.TextOut(m_textPos.x + 2, m_textPos.y + 2, strText);
  121. _tprintf(_T("Hover-Icon:%d,%d\n"), m_textPos.x + 2, m_textPos.y + 2);
  122. }
  123. else if (m_bShowOwnerText)
  124. {
  125. rect.OffsetRect(-1, -1);
  126. DrawButtonText(&memDC, rect, strText, GetFGColor());
  127. _tprintf(_T("Hover-UnIcon:%d,%d,%d,%d\n"), rect.left, rect.top, rect.right, rect.bottom);
  128. rect.OffsetRect(1, 1);
  129. }
  130. }
  131. break;
  132. case DOWN:
  133. {
  134. //DrawFilledRect(&memDC, rect, RGB(0,0,255));
  135. if (m_bmpDown.m_hObject != 0)
  136. m_bmpDown.TransparentBlt(memDC, rect, m_crBack);
  137. if (!m_hMouseOutIcon.IsNull())
  138. {
  139. if (m_bmpIconButton.m_hObject != 0)
  140. {
  141. CEnBitmap bmpDown;
  142. m_bmpIconButton.DrawImage(bmpDown, 2, 1, 2, 1);
  143. bmpDown.ExtendDraw(&memDC, rect, 10, 10, TRUE);
  144. }
  145. m_hMouseOutIcon.TransparentBlt(memDC, m_iconRect.left + 3, m_iconRect.top + 3,
  146. m_iconRect.Width(), m_iconRect.Height(), RGB(0, 0, 0));
  147. memDC.SetTextColor(GetBGColor());
  148. memDC.TextOut(m_textPos.x + 3, m_textPos.y + 3, strText);
  149. _tprintf(_T("Down-Icon:%d,%d\n"), m_textPos.x + 2, m_textPos.y + 2);
  150. }
  151. else if (m_bShowOwnerText)
  152. {
  153. rect.OffsetRect(1, 1);
  154. DrawButtonText(&memDC, rect, strText, GetFGColor());
  155. _tprintf(_T("Down-UnIcon:%d,%d,%d,%d\n"), rect.left, rect.top, rect.right, rect.bottom);
  156. rect.OffsetRect(-1, -1);
  157. }
  158. }
  159. break;
  160. case DISABLE:
  161. {
  162. if (m_bmpDisable.m_hObject != 0)
  163. m_bmpDisable.TransparentBlt(memDC, rect, m_crBack);
  164. if (!m_hMouseOutIcon.IsNull())
  165. {
  166. m_hMouseOutIcon.TransparentBlt(memDC, m_iconRect.left + 2, m_iconRect.top + 2,
  167. m_iconRect.Width(), m_iconRect.Height(), RGB(0, 0, 0));
  168. memDC.SetTextColor(GetFGColor());
  169. memDC.TextOut(m_textPos.x + 2, m_textPos.y + 2, strText);
  170. }
  171. else if (m_bShowOwnerText)
  172. DrawButtonText(&memDC, rect, strText, RGB(128, 128, 128));
  173. }
  174. break;
  175. default:
  176. break;
  177. }
  178. dc.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
  179. ::DeleteDC(memDC);
  180. }
  181. void CSkinButton::DrawFilledRect(CDC *DC, CRect R, COLORREF color)
  182. {
  183. CBrush B;
  184. B.CreateSolidBrush(color);
  185. DC->FillRect(R, &B);
  186. }
  187. void CSkinButton::DrawButtonText(CDC *DC, CRect R, CString str, COLORREF TextColor)
  188. {
  189. COLORREF prevColor = DC->SetTextColor(TextColor);
  190. DC->SetBkMode(TRANSPARENT);
  191. DC->SelectObject(m_pFont);
  192. if (m_hMouseOutIcon.IsNull() && m_hMouseInIcon.IsNull())
  193. {
  194. //int iconwidth=::GetSystemMetrics(SM_CXICON);
  195. R.right = R.right - m_textPos.x;
  196. _tprintf(_T("DrawText:%d\n"), m_textPos.x);
  197. DC->DrawText(str, str.GetLength(), R, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  198. }
  199. else
  200. {
  201. DC->DrawText(str, str.GetLength(), R, DT_RIGHT | DT_VCENTER | DT_SINGLELINE);
  202. }
  203. DC->SetTextColor(prevColor);
  204. }
  205. void CSkinButton::OnMouseMove(UINT nFlags, CPoint point)
  206. {
  207. // TODO: 在此添加消息处理程序代码和/或调用默认值
  208. //if (nFlags & MK_LBUTTON && m_bMouseOver == FALSE)
  209. // return;
  210. if (!m_bMouseOver&&m_bEnabled)
  211. {
  212. m_bMouseOver = true;
  213. m_state = HOVER;
  214. CPoint point;
  215. CRect rect;
  216. GetWindowRect(&rect);
  217. GetCursorPos(&point);
  218. if (!rect.PtInRect(point) && m_bMouseOver&&m_bEnabled)
  219. {
  220. SetTimer(1, 10, NULL);
  221. return;
  222. }
  223. DrawButton();
  224. SetTimer(1, 10, NULL);
  225. }
  226. CButton::OnMouseMove(nFlags, point);
  227. }
  228. void CSkinButton::OnTimer(UINT_PTR nIDEvent)
  229. {
  230. // TODO: 在此添加消息处理程序代码和/或调用默认值
  231. CPoint point;
  232. CRect rect;
  233. GetWindowRect(&rect);
  234. GetCursorPos(&point);
  235. if (!rect.PtInRect(point) && m_bMouseOver&&m_bEnabled)
  236. {
  237. KillTimer(1);
  238. m_bMouseOver = false;
  239. m_state = NORMAL;
  240. DrawButton();
  241. }
  242. CButton::OnTimer(nIDEvent);
  243. }
  244. void CSkinButton::PreSubclassWindow()
  245. {
  246. // TODO: 在此添加专用代码和/或调用基类
  247. SetOwnerDraw(true);
  248. CButton::PreSubclassWindow();
  249. }
  250. void CSkinButton::SetOwnerDraw(bool IsDraw)
  251. {
  252. if (IsDraw)
  253. {
  254. ModifyStyle(NULL, BS_OWNERDRAW);
  255. Invalidate();
  256. }
  257. else
  258. {
  259. ModifyStyle(BS_OWNERDRAW, NULL);
  260. Invalidate();
  261. }
  262. }
  263. void CSkinButton::SetStatusBmp()
  264. {
  265. if (m_bmpButton.m_hObject != 0)
  266. {
  267. if (m_bmpNormal.m_hObject != NULL) m_bmpNormal.DeleteObject();
  268. if (m_bmpHover.m_hObject != NULL) m_bmpHover.DeleteObject();
  269. if (m_bmpDown.m_hObject != NULL) m_bmpDown.DeleteObject();
  270. if (m_bmpDisable.m_hObject != NULL) m_bmpDisable.DeleteObject();
  271. m_bmpButton.DrawImage(m_bmpNormal, 1, 1, 4, 1);
  272. m_bmpButton.DrawImage(m_bmpHover, 2, 1, 4, 1);
  273. m_bmpButton.DrawImage(m_bmpDown, 3, 1, 4, 1);
  274. m_bmpButton.DrawImage(m_bmpDisable, 4, 1, 4, 1);
  275. m_bmpButton.DeleteObject();
  276. }
  277. }
  278. //设置区域和大小
  279. void CSkinButton::ResetButtonSize(BOOL bResetSize)
  280. {
  281. SetWindowRgn(m_bmpNormal.BitmapToRegion(m_crBack), TRUE);
  282. SetWindowPos(NULL, 0, 0, m_bmpNormal.Width(), m_bmpNormal.Height(), SWP_NOMOVE);
  283. }
  284. void CSkinButton::LoadImage(LPCTSTR szImagePath, COLORREF crBack, BOOL bResetSize)
  285. {
  286. if (m_bmpButton.m_hObject != NULL)
  287. m_bmpButton.DeleteObject();
  288. m_bmpButton.LoadImage(szImagePath, RGB(255, 0, 255));
  289. m_crBack = crBack;
  290. SetStatusBmp();
  291. ResetButtonSize(bResetSize);
  292. }
  293. void CSkinButton::loadHoverBGBmp(LPCTSTR szImagePath)
  294. {
  295. m_bmpIconButton.LoadImage(szImagePath, RGB(255, 0, 255));
  296. }
  297. BOOL CSkinButton::LoadBitmap(UINT uIDRes, COLORREF crBack, BOOL bResetSize)
  298. {
  299. if (m_bmpButton.LoadBitmap(uIDRes))
  300. {
  301. m_bmpButton.DrawImage(m_bmpNormal, 1, 1, 4, 1);
  302. m_crBack = crBack;
  303. SetStatusBmp();
  304. ResetButtonSize(bResetSize);
  305. return TRUE;
  306. }
  307. return FALSE;
  308. }
  309. void CSkinButton::SetImage(CString strNormal, CString strHover, CString strDown, CString strDisable)
  310. {
  311. m_bmpNormal.LoadImage(strNormal);
  312. m_bmpHover.LoadImage(strHover);
  313. m_bmpDown.LoadImage(strDown);
  314. m_bmpDisable.LoadImage(strDisable);
  315. }
  316. void CSkinButton::SetImage(UINT nNormalID, UINT nHoverID, UINT nDownID, UINT nDisableID)
  317. {
  318. m_bmpNormal.LoadBitmap(nNormalID);
  319. m_bmpHover.LoadBitmap(nHoverID);
  320. m_bmpDown.LoadBitmap(nDownID);
  321. m_bmpDisable.LoadBitmap(nDisableID);
  322. }
  323. BOOL CSkinButton::OnEraseBkgnd(CDC* pDC)
  324. {
  325. // TODO: 在此添加消息处理程序代码和/或调用默认值
  326. //保存按钮背景
  327. if (!m_bDCStored)
  328. {
  329. CRect rect;
  330. GetClientRect(&rect);
  331. m_memDC.CreateCompatibleDC(pDC);
  332. CBitmap btScreen;
  333. btScreen.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
  334. m_memDC.SelectObject(&btScreen);
  335. m_memDC.BitBlt(0, 0, rect.Width(), rect.Height(), pDC, 0, 0, SRCCOPY);
  336. m_bDCStored = true;
  337. CRgn rgn;
  338. rgn.CreateRectRgn(0, 0, rect.Width(), rect.Height());
  339. SetWindowRgn(rgn, TRUE);
  340. btScreen.DeleteObject();
  341. }
  342. return TRUE;// CButton::OnEraseBkgnd(pDC);//
  343. }
  344. BOOL CSkinButton::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  345. {
  346. // TODO: 在此添加消息处理程序代码和/或调用默认值
  347. ::SetCursor(AfxGetApp()->LoadCursor(IDC_CURSOR_HAND));
  348. return TRUE;
  349. //return CButton::OnSetCursor(pWnd, nHitTest, message);
  350. }
  351. void CSkinButton::SetIcon(CString strMouseOut, CString strMouseIn)
  352. {
  353. m_hMouseOutIcon.Load(strMouseOut);
  354. m_hMouseInIcon.Load(strMouseIn);
  355. SetWindowPos(NULL, 0, 0, 20, 20, SWP_NOMOVE);
  356. }
  357. void CSkinButton::SetColor(COLORREF fgcolor, COLORREF bgcolor)
  358. {
  359. m_fg = fgcolor;
  360. m_bg = bgcolor;
  361. DrawButton();
  362. }
  363. void CSkinButton::SetTextPos(CPoint point)
  364. {
  365. m_textPos = point;
  366. DrawButton();
  367. }
  368. CRect CSkinButton::GetRectInParent()
  369. {
  370. CRect rcWindowParent;
  371. GetParent()->GetWindowRect(rcWindowParent);//client
  372. CRect rcWindow;
  373. GetWindowRect(&rcWindow);
  374. CRect rect;
  375. rect.left = rcWindow.left - rcWindowParent.left;
  376. rect.top = rcWindow.top - rcWindowParent.top;
  377. rect.right = rcWindow.right - rcWindowParent.left;
  378. rect.bottom = rcWindow.bottom - rcWindowParent.top;
  379. return rect;
  380. }
  381. void CSkinButton::OnEnable(BOOL bEnable)
  382. {
  383. CButton::OnEnable(bEnable);
  384. // TODO: 在此处添加消息处理程序代码
  385. if (bEnable)
  386. m_bEnabled = true;
  387. else
  388. m_bEnabled = false;
  389. }