PushButton.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. // PushButton.cpp : 实现文件
  2. //
  3. #include "stdafx.h"
  4. #include "PushButton.h"
  5. #include "CacheDC.h"
  6. // CPushButton
  7. IMPLEMENT_DYNAMIC(CPushButton, CButton)
  8. CPushButton::CPushButton()
  9. : m_strPathIcon(_T(""))
  10. , m_bSelected(FALSE)
  11. {
  12. m_bkColor = RGB(65, 188, 131); // 文本按钮的背景颜色
  13. m_pImage = nullptr; // 位图按钮的背景图片
  14. m_bHover = m_bPress = m_bFocus = m_bMouseTracking = FALSE; // 初始化鼠标的相关状态
  15. m_bEnable = TRUE;
  16. m_nRounded = 3; // 圆角的大小
  17. m_dwStyle = WS_VISIBLE | WS_CHILD | BS_CENTER | BS_VCENTER; // 按钮样式
  18. m_bFillet = TRUE;
  19. m_image = nullptr;
  20. // 初始化字体
  21. m_font.CreatePointFont(110 ,L"微软雅黑");
  22. }
  23. CPushButton::~CPushButton()
  24. {
  25. if(m_pImage != nullptr)
  26. delete m_pImage;
  27. if(m_image != nullptr)
  28. delete m_image;
  29. }
  30. BEGIN_MESSAGE_MAP(CPushButton, CButton)
  31. ON_WM_PAINT()
  32. ON_WM_SETCURSOR()
  33. ON_WM_MOUSEMOVE()
  34. ON_WM_MOUSEHOVER()
  35. ON_WM_MOUSELEAVE()
  36. ON_WM_LBUTTONDOWN()
  37. ON_WM_LBUTTONUP()
  38. ON_WM_LBUTTONDBLCLK()
  39. ON_WM_ERASEBKGND()
  40. END_MESSAGE_MAP()
  41. // CPushButton 消息处理程序
  42. BOOL CPushButton::Create(CWnd* pParentWnd, UINT nID, CRect& rect, DWORD btnType, LPCTSTR lpszCaption
  43. ,COLORREF bkColor/* = RGB(65,188,131)*/
  44. ,COLORREF fontColor/* = RGB(255,255,255)*/
  45. ,COLORREF bordercolor/* = NULL*/)
  46. {
  47. // TODO: 在此添加专用代码和/或调用基类
  48. m_btn_type = btnType;
  49. m_bkColor = bkColor;
  50. m_fontcolor = fontColor;
  51. if(bordercolor == NULL)
  52. m_bordercolor = m_bkColor;
  53. if (m_btn_type&BUTTON_TYPE_IMAGE)
  54. m_pImage = new CImageEx(lpszCaption);
  55. if (m_btn_type&BUTTON_TYPE_SUPTAB)
  56. m_dwStyle |= WS_TABSTOP;
  57. m_lpszText = lpszCaption;
  58. if (m_btn_type&BUTTON_TYPE_IMAGE)
  59. {
  60. lpszCaption = L"";
  61. m_lpszText= L"";
  62. }
  63. if (m_btn_type&BUTTON_TYPE_IMAGE2 && m_strPathIcon != "")
  64. {
  65. m_image = new CImageEx(m_strPathIcon);
  66. }
  67. BOOL ret = CButton::Create(lpszCaption, m_dwStyle, rect, pParentWnd, nID);
  68. if (m_btn_type&BUTTON_TYPE_TEXT && m_bFillet)
  69. {
  70. // 裁剪成圆角按钮
  71. CRgn rgnClient;
  72. rgnClient.CreateRoundRectRgn(0,0,rect.Width(),rect.Height(),m_nRounded,m_nRounded);
  73. SetWindowRgn(rgnClient,TRUE);
  74. }
  75. return ret;
  76. }
  77. BOOL CPushButton::Create(CWnd* pParentWnd, UINT nID, CPoint& point, CSize& size, DWORD btnType, LPCTSTR lpszCaption
  78. ,COLORREF bkColor/* = RGB(65,188,131)*/
  79. ,COLORREF fontColor/* = RGB(65,188,131)*/
  80. ,COLORREF bordercolor/* = NULL*/)
  81. {
  82. return Create(pParentWnd,nID,CRect(point.x, point.y, point.x + size.cx, point.y + size.cy),btnType,lpszCaption,bkColor,fontColor,bordercolor);
  83. }
  84. void CPushButton::OnPaint()
  85. {
  86. CPaintDC dc(this);
  87. CRect rcClient;
  88. GetClientRect(rcClient);
  89. CCacheDC pCacheDC(&dc,rcClient);
  90. if(m_btn_type&BUTTON_TYPE_TEXT)
  91. DrawTextButton(pCacheDC,rcClient);
  92. else if(m_btn_type&BUTTON_TYPE_ICON)
  93. DrawIconButton(pCacheDC,rcClient);
  94. else if (m_btn_type&BUTTON_TYPE_IMAGE)
  95. DrawBitmapButton(pCacheDC,rcClient);
  96. else if (m_btn_type&BUTTON_TYPE_IMAGE2)
  97. DrawIconButton2(pCacheDC,rcClient);
  98. }
  99. void CPushButton::DrawTextButton(CDC* pDC, CRect& rcClient)
  100. {
  101. //////////////////////////////////////////////////////////////////////////
  102. // 设置按钮背景颜色
  103. // 获取背景颜色值
  104. BYTE bkRed = GetRValue(m_bkColor);
  105. BYTE bkGreen = GetGValue(m_bkColor);
  106. BYTE bkBlue = GetBValue(m_bkColor);
  107. // 获取文本颜色
  108. BYTE fontRed = GetRValue(m_fontcolor);
  109. BYTE fontGreen = GetGValue(m_fontcolor);
  110. BYTE fontBlue = GetBValue(m_fontcolor);
  111. // 获取边框颜色
  112. BYTE borderRed = GetRValue(m_bordercolor);
  113. BYTE borderGreen = GetGValue(m_bordercolor);
  114. BYTE borderBlue = GetBValue(m_bordercolor);
  115. COLORREF fontColor, bkColor, borderColor;
  116. if(!m_bEnable)
  117. {
  118. fontColor = RGB(150,150,150);
  119. bkColor = RGB(200,200,200);
  120. borderColor = RGB(200,200,200);
  121. }
  122. else if(m_bHover)
  123. {
  124. fontColor = RGB(fontRed, fontGreen, fontBlue);
  125. if(m_bPress)
  126. {
  127. bkColor = RGB(bkRed-10, bkGreen-10, bkBlue-10);
  128. borderColor = RGB(borderRed - 10, borderGreen - 10, borderBlue - 10);
  129. }
  130. else
  131. {
  132. bkColor = RGB(bkRed+10, bkGreen+10, bkBlue+10);
  133. borderColor = RGB(borderRed + 10, borderGreen + 10, borderBlue + 10);
  134. }
  135. }
  136. else
  137. {
  138. bkColor = RGB(bkRed,bkGreen,bkBlue);
  139. fontColor = RGB(fontRed,fontGreen,fontBlue);
  140. borderColor = RGB(borderRed,borderGreen,borderBlue);
  141. }
  142. if(m_bFillet)
  143. {
  144. // 画圆角背景
  145. CRgn rgnClient;
  146. rgnClient.CreateRoundRectRgn(0,0,rcClient.Width(),rcClient.Height(),m_nRounded,m_nRounded);
  147. pDC->FillRgn(&rgnClient,&CBrush(bkColor));
  148. pDC->FrameRgn(&rgnClient,&CBrush(borderColor),1,1);
  149. }
  150. else
  151. {
  152. pDC->FillSolidRect(rcClient,bkColor);
  153. pDC->FrameRect(rcClient,&CBrush(borderColor));
  154. }
  155. //////////////////////////////////////////////////////////////////////////
  156. // 画文本
  157. // 修改文本显示区域(实现按下的效果)
  158. if(m_bPress)
  159. {
  160. rcClient.left += 2;
  161. rcClient.top += 2;
  162. }
  163. pDC->SelectObject(m_font);
  164. pDC->SetBkMode(TRANSPARENT);
  165. pDC->SetTextColor(fontColor);
  166. // 获取按钮文本
  167. CString sText;
  168. GetWindowText(sText);
  169. pDC->DrawText(sText,rcClient,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_END_ELLIPSIS);
  170. }
  171. void CPushButton::DrawIconButton2(CDC* pDC, CRect& rcClient)
  172. {
  173. INT nWidth = rcClient.Width();
  174. INT nLeft = 0;
  175. if(m_bSelected)
  176. {
  177. nLeft = m_bSelected ? nWidth * -1 : m_bHover ? nWidth * 1 * -1: 0;
  178. }
  179. else
  180. {
  181. nLeft = m_bSelected ? nWidth * 2 * -1 : m_bHover ? nWidth * 1 * -1: 0;
  182. }
  183. m_image->DrawImage(pDC,nLeft,rcClient.top);
  184. }
  185. void CPushButton::DrawIconButton(CDC* pDC, CRect& rcClient)
  186. {
  187. //////////////////////////////////////////////////////////////////////////
  188. // 设置按钮背景颜色
  189. // 获取背景颜色值
  190. BYTE bkRed = GetRValue(m_bkColor);
  191. BYTE bkGreen = GetGValue(m_bkColor);
  192. BYTE bkBlue = GetBValue(m_bkColor);
  193. // 获取文本颜色
  194. BYTE fontRed = GetRValue(m_fontcolor);
  195. BYTE fontGreen = GetGValue(m_fontcolor);
  196. BYTE fontBlue = GetBValue(m_fontcolor);
  197. // 获取边框颜色
  198. BYTE borderRed = GetRValue(m_bordercolor);
  199. BYTE borderGreen = GetGValue(m_bordercolor);
  200. BYTE borderBlue = GetBValue(m_bordercolor);
  201. COLORREF fontColor, bkColor, borderColor;
  202. if(!m_bEnable)
  203. {
  204. fontColor = RGB(50,50,50);
  205. bkColor = RGB(200,200,200);
  206. borderColor = RGB(200,200,200);
  207. }
  208. else if(m_bHover)
  209. {
  210. fontColor = RGB(fontRed, fontGreen, fontBlue);
  211. if(m_bPress)
  212. {
  213. bkColor = RGB(bkRed-10, bkGreen-10, bkBlue-10);
  214. borderColor = RGB(borderRed - 10, borderGreen - 10, borderBlue - 10);
  215. }
  216. else
  217. {
  218. bkColor = RGB(bkRed+10, bkGreen+10, bkBlue+10);
  219. borderColor = RGB(borderRed + 10, borderGreen + 10, borderBlue + 10);
  220. }
  221. }
  222. else
  223. {
  224. bkColor = RGB(bkRed,bkGreen,bkBlue);
  225. fontColor = RGB(fontRed,fontGreen,fontBlue);
  226. borderColor = RGB(borderRed,borderGreen,borderBlue);
  227. }
  228. if(m_bFillet)
  229. {
  230. // 画圆角背景
  231. CRgn rgnClient;
  232. rgnClient.CreateRoundRectRgn(0,0,rcClient.Width(),rcClient.Height(),m_nRounded,m_nRounded);
  233. pDC->FillRgn(&rgnClient,&CBrush(bkColor));
  234. pDC->FrameRgn(&rgnClient,&CBrush(borderColor),1,1);
  235. }
  236. else
  237. {
  238. pDC->FillSolidRect(rcClient,bkColor);
  239. pDC->FrameRect(rcClient,&CBrush(borderColor));
  240. }
  241. if(m_bSelected)
  242. {
  243. CRgn rgnClient;
  244. rgnClient.CreateRoundRectRgn(0,0,rcClient.Width(),rcClient.Height(),m_nRounded,m_nRounded);
  245. pDC->FillRgn(&rgnClient,&CBrush(RGB(19,94,64)));
  246. pDC->FrameRgn(&rgnClient,&CBrush(borderColor),1,1);
  247. }
  248. else
  249. {
  250. CRgn rgnClient;
  251. rgnClient.CreateRoundRectRgn(0,0,rcClient.Width(),rcClient.Height(),m_nRounded,m_nRounded);
  252. pDC->FillRgn(&rgnClient,&CBrush(RGB(25,174,104)));
  253. pDC->FrameRgn(&rgnClient,&CBrush(borderColor),1,1);
  254. }
  255. Graphics graphics( pDC->m_hDC);
  256. Image image(m_strPathIcon, FALSE);
  257. graphics.DrawImage(&image,rcClient.left,rcClient.top);
  258. //////////////////////////////////////////////////////////////////////////
  259. // 画文本
  260. // 修改文本显示区域(实现按下的效果)
  261. if(m_bPress)
  262. {
  263. rcClient.left += 2;
  264. rcClient.top += 2;
  265. }
  266. pDC->SelectObject(m_font);
  267. pDC->SetBkMode(TRANSPARENT);
  268. pDC->SetTextColor(fontColor);
  269. // 获取按钮文本
  270. CString sText;
  271. GetWindowText(sText);
  272. if(pDC->GetTextExtent(sText).cx < rcClient.Width())
  273. {
  274. pDC->DrawText(sText,rcClient,DT_CENTER|DT_BOTTOM|DT_SINGLELINE|DT_END_ELLIPSIS);
  275. }
  276. else
  277. {
  278. CFont font;
  279. font.CreatePointFont(80,L"微软雅黑");
  280. CFont *font1;
  281. font1 = pDC->SelectObject(&font);
  282. pDC->DrawText(sText,rcClient,DT_CENTER|DT_BOTTOM|DT_SINGLELINE|DT_END_ELLIPSIS);
  283. pDC->SelectObject(font1); // 复原画笔
  284. font.DeleteObject();
  285. }
  286. }
  287. void CPushButton::DrawBitmapButton(CDC* pDC, CRect& rcClient)
  288. {
  289. // 绘画背景图案
  290. if(m_bHover)
  291. {
  292. m_pImage->DrawImage(pDC,rcClient.Width() * (m_bPress ? 2 : 1) * -1, 0);
  293. }
  294. else
  295. {
  296. m_pImage->DrawImage(pDC,0,0);
  297. }
  298. }
  299. BOOL CPushButton::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  300. {
  301. // TODO: 在此添加消息处理程序代码和/或调用默认值
  302. ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_HAND));
  303. //return CButton::OnSetCursor(pWnd, nHitTest, message);
  304. return TRUE;
  305. }
  306. void CPushButton::OnMouseMove(UINT nFlags, CPoint point)
  307. {
  308. // TODO: 在此添加消息处理程序代码和/或调用默认值
  309. if (!m_bMouseTracking){
  310. TRACKMOUSEEVENT tme;
  311. tme.cbSize = sizeof(tme);
  312. tme.hwndTrack = m_hWnd;
  313. tme.dwFlags = TME_LEAVE | TME_HOVER;
  314. tme.dwHoverTime = 1;
  315. m_bMouseTracking = _TrackMouseEvent(&tme);
  316. }
  317. //CButton::OnMouseMove(nFlags, point);
  318. }
  319. void CPushButton::OnMouseHover(UINT nFlags, CPoint point)
  320. {
  321. // TODO: 在此添加消息处理程序代码和/或调用默认值
  322. m_bHover = m_bMouseTracking = TRUE;
  323. Invalidate();
  324. //CButton::OnMouseHover(nFlags, point);
  325. }
  326. void CPushButton::OnMouseLeave()
  327. {
  328. // TODO: 在此添加消息处理程序代码和/或调用默认值
  329. m_bHover = m_bMouseTracking = FALSE;
  330. Invalidate();
  331. //CButton::OnMouseLeave();
  332. }
  333. void CPushButton::OnLButtonDown(UINT nFlags, CPoint point)
  334. {
  335. // TODO: 在此添加消息处理程序代码和/或调用默认值
  336. m_bPress = TRUE;
  337. this->SetFocus();
  338. Invalidate();
  339. SetCapture();
  340. //CButton::OnLButtonDown(nFlags, point);
  341. }
  342. static DWORD g_tick_count =0;
  343. void CPushButton::OnLButtonUp(UINT nFlags, CPoint point)
  344. {
  345. // TODO: 在此添加消息处理程序代码和/或调用默认值
  346. m_bPress = FALSE;
  347. Invalidate();
  348. ReleaseCapture();
  349. CRect rcClient;
  350. GetClientRect(rcClient);
  351. if(rcClient.PtInRect(point))
  352. {
  353. if (g_tick_count - GetTickCount()> 250 || g_tick_count == 0){
  354. this->GetParent()->PostMessage(WM_BUTTON_CLICKED,(WPARAM)this->GetDlgCtrlID(),0);
  355. g_tick_count = GetTickCount();
  356. }
  357. }
  358. }
  359. void CPushButton::OnLButtonDblClk(UINT nFlags, CPoint point)
  360. {
  361. // TODO: 在此添加消息处理程序代码和/或调用默认值
  362. // 取消按钮的双击事件
  363. //CButton::OnLButtonDblClk(nFlags, point);
  364. }
  365. void CPushButton::PreSubclassWindow()
  366. {
  367. // TODO: 在此添加专用代码和/或调用基类
  368. CButton::PreSubclassWindow();
  369. }
  370. BOOL CPushButton::PreTranslateMessage(MSG* pMsg)
  371. {
  372. // TODO: 在此添加专用代码和/或调用基类
  373. if(pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN)
  374. {
  375. this->GetParent()->PostMessage(WM_BUTTON_CLICKED,(WPARAM)this->GetDlgCtrlID(),0);
  376. return TRUE;
  377. }
  378. return CButton::PreTranslateMessage(pMsg);
  379. }
  380. void CPushButton::EnableWindow(BOOL bEnable/* = TRUE*/)
  381. {
  382. m_bEnable = bEnable;
  383. // 禁用前,先绘制禁用时的样式(禁用后,就无效了)
  384. if(!bEnable)
  385. Invalidate();
  386. CButton::EnableWindow(bEnable);
  387. // 启用后,在绘制一次,不然会以系统默认状态显示
  388. if(bEnable)
  389. Invalidate();
  390. }
  391. void CPushButton::SetWindowText(LPCTSTR lpszString)
  392. {
  393. m_lpszText = lpszString;
  394. Invalidate(FALSE);
  395. }
  396. void CPushButton::GetWindowText(CString& rString)
  397. {
  398. rString = m_lpszText;
  399. }
  400. // 当画图板中某个功能被选择时,用于设置其背景色为绿色;当失去功能时,显示为白色
  401. void CPushButton::setBkColor(BOOL bSelected)
  402. {
  403. m_bSelected = bSelected;
  404. Invalidate(false);
  405. }
  406. void CPushButton::SetBkColor(COLORREF bk)
  407. {
  408. m_bkColor=bk;
  409. Invalidate(TRUE);
  410. }