ButtonExt.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. // ButtonExt.cpp: implementation of the CButtonExt class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "ButtonExt.h"
  6. #ifdef _DEBUG
  7. #undef THIS_FILE
  8. static char THIS_FILE[]=__FILE__;
  9. #define new DEBUG_NEW
  10. #endif
  11. UINT CButtonExt::m_nStatus = STATUS_BUTTON_NORMAL;
  12. WNDPROC CButtonExt::m_cWndProc = NULL;
  13. CArray<int,int>g_btnarray;
  14. //按钮的状态
  15. BOOL m_bOver=0; //鼠标位于按钮之上时该值为true,反之为flase
  16. BOOL m_bTracking=0; //在鼠标按下没有释放时该值为true
  17. BOOL m_bSelected=0; //按钮被按下是该值为true
  18. BOOL m_bFocus=0; //按钮为当前焦点所在时该值为true
  19. //按钮的外边框
  20. extern CPen m_BoundryPen;
  21. //鼠标指针置于按钮之上时按钮的内边框
  22. extern CPen m_InsideBoundryPenLeft;
  23. extern CPen m_InsideBoundryPenRight;
  24. extern CPen m_InsideBoundryPenTop;
  25. extern CPen m_InsideBoundryPenBottom;
  26. //按钮获得焦点时按钮的内边框
  27. extern CPen m_InsideBoundryPenLeftSel;
  28. extern CPen m_InsideBoundryPenRightSel;
  29. extern CPen m_InsideBoundryPenTopSel;
  30. extern CPen m_InsideBoundryPenBottomSel;
  31. //按钮的底色,包括有效和无效两种状态
  32. extern CBrush m_FillActive;
  33. extern CBrush m_FillInactive;
  34. //绘制按钮的底色
  35. void CButtonExt::DoGradientFill(CDC *pDC, CRect* rect)
  36. {
  37. return;
  38. CBrush brBk[64];
  39. int nWidth = rect->Width();
  40. int nHeight = rect->Height();
  41. CRect rct;
  42. int i = 0;
  43. for ( i = 0; i < 64; i ++)
  44. {
  45. if (m_bOver)
  46. {
  47. if (m_bFocus)
  48. brBk[i].CreateSolidBrush(RGB(255 - (i / 4), 255 - (i / 4), 255 - (i / 3)));
  49. else
  50. brBk[i].CreateSolidBrush(RGB(255 - (i / 4), 255 - (i / 4), 255 - (i / 5)));
  51. }
  52. else
  53. {
  54. if (m_bFocus)
  55. brBk[i].CreateSolidBrush(RGB(255 - (i / 3), 255 - (i / 3), 255 - (i / 4)));
  56. else
  57. brBk[i].CreateSolidBrush(RGB(255 - (i / 3), 255 - (i / 3), 255 - (i / 5)));
  58. }
  59. }
  60. for (i = rect->top; i <= nHeight + 2; i ++)
  61. {
  62. rct.SetRect(rect->left, i, nWidth + 2, i + 1);
  63. pDC->FillRect(&rct, &brBk[((i * 63) / nHeight)]);
  64. }
  65. for (i = 0; i < 64; i ++)
  66. brBk[i].DeleteObject();
  67. }
  68. //绘制按钮的内边框
  69. void CButtonExt::DrawInsideBorder(CDC *pDC, CRect* rect)
  70. {
  71. CPen *pLeft, *pRight, *pTop, *pBottom;
  72. if (m_bSelected && !m_bOver)
  73. {
  74. pLeft = & m_InsideBoundryPenLeftSel;
  75. pRight = &m_InsideBoundryPenRightSel;
  76. pTop = &m_InsideBoundryPenTopSel;
  77. pBottom = &m_InsideBoundryPenBottomSel;
  78. }
  79. else
  80. {
  81. pLeft = &m_InsideBoundryPenLeft;
  82. pRight = &m_InsideBoundryPenRight;
  83. pTop = &m_InsideBoundryPenTop;
  84. pBottom = &m_InsideBoundryPenBottom;
  85. }
  86. CPoint oldPoint = pDC->MoveTo(rect->left, rect->bottom - 1);
  87. CPen* pOldPen = pDC->SelectObject(pLeft);
  88. pDC->LineTo(rect->left, rect->top + 1);
  89. pDC->SelectObject(pRight);
  90. pDC->MoveTo(rect->right - 1, rect->bottom - 1);
  91. pDC->LineTo(rect->right - 1, rect->top);
  92. pDC->SelectObject(pTop);
  93. pDC->MoveTo(rect->left - 1, rect->top);
  94. pDC->LineTo(rect->right - 1, rect->top);
  95. pDC->SelectObject(pBottom);
  96. pDC->MoveTo(rect->left, rect->bottom);
  97. pDC->LineTo(rect->right - 1, rect->bottom);
  98. pDC->SelectObject(pOldPen);
  99. pDC->MoveTo(oldPoint);
  100. if (m_bSelected && !m_bOver)
  101. DrawFocusRect(pDC->m_hDC,rect);
  102. }
  103. //////////////////////////////////////////////////////////////////////
  104. // Construction/Destruction
  105. //////////////////////////////////////////////////////////////////////
  106. int FindBtnPos(int hwnd)
  107. {
  108. for(int i=0; i<g_btnarray.GetSize (); i++)
  109. {
  110. if(hwnd==g_btnarray.ElementAt (i))return i;
  111. }
  112. return -1;
  113. }
  114. LRESULT CButtonExt::DefWindowProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
  115. {
  116. CWnd *pWnd = NULL;
  117. CPoint point;
  118. pWnd = CWnd::FromHandle( hWnd );
  119. switch( message )
  120. {
  121. case WM_CREATE:
  122. g_btnarray.Add ((int)hWnd);
  123. g_btnarray.Add (0);
  124. g_btnarray.Add (0);
  125. g_btnarray.Add (0);
  126. g_btnarray.Add (0);
  127. break;
  128. case WM_DESTROY:
  129. {
  130. int pos=FindBtnPos((int)hWnd);
  131. g_btnarray.RemoveAt(pos);
  132. g_btnarray.RemoveAt(pos);
  133. g_btnarray.RemoveAt(pos);
  134. g_btnarray.RemoveAt(pos);
  135. g_btnarray.RemoveAt(pos);
  136. }
  137. break;
  138. case WM_MOUSEMOVE:
  139. {
  140. int pos=FindBtnPos((int)hWnd);
  141. m_bTracking=g_btnarray.ElementAt (pos+2);
  142. if (!m_bTracking)
  143. {
  144. TRACKMOUSEEVENT tme;
  145. tme.cbSize = sizeof(tme);
  146. tme.hwndTrack = hWnd;
  147. tme.dwFlags = TME_LEAVE | TME_HOVER;
  148. tme.dwHoverTime = 1;
  149. m_bTracking = _TrackMouseEvent(&tme);
  150. g_btnarray.SetAt (pos+2, m_bTracking);
  151. }
  152. }
  153. break;
  154. case WM_MOUSELEAVE:
  155. {
  156. int pos=FindBtnPos((int)hWnd);
  157. m_bOver = FALSE;
  158. m_bTracking = FALSE;
  159. g_btnarray.SetAt (pos+1, m_bOver);
  160. g_btnarray.SetAt (pos+2, m_bTracking);
  161. pWnd->Invalidate();
  162. }
  163. break;
  164. case WM_MOUSEHOVER:
  165. {
  166. int pos=FindBtnPos((int)hWnd);
  167. m_bOver = 1;
  168. g_btnarray.SetAt (pos+1, m_bOver);
  169. pWnd->Invalidate();
  170. }
  171. break;
  172. case WM_PAINT:
  173. // case WM_LBUTTONDBLCLK:
  174. return OnPaint( pWnd );
  175. break;
  176. /* case WM_LBUTTONDOWN:
  177. point.x = LOWORD(lParam);
  178. point.y = HIWORD(lParam);
  179. return OnLButtonDown( pWnd, 0, point );
  180. break;
  181. case WM_LBUTTONUP:
  182. point.x = LOWORD(lParam);
  183. point.y = HIWORD(lParam);
  184. return OnLButtonUp( pWnd, 0, point );
  185. break;
  186. case WM_MOUSEMOVE:
  187. point.x = LOWORD(lParam);
  188. point.y = HIWORD(lParam);
  189. return OnMouseMove( pWnd, 0, point );
  190. break;
  191. case WM_ERASEBKGND:
  192. return TRUE;
  193. break;
  194. case WM_ENABLE:
  195. {
  196. pWnd->Invalidate();
  197. return FALSE;
  198. }
  199. break;*/
  200. default:
  201. break;
  202. }
  203. return CallWindowProc( m_cWndProc, hWnd, message, wParam, lParam );
  204. }
  205. LRESULT CButtonExt::OnLButtonDown( CWnd *pWnd, UINT nFlags, CPoint point )
  206. {
  207. m_nStatus = STATUS_BUTTON_DOWN;
  208. // m_bOver=1; //鼠标位于按钮之上时该值为true,反之为flase
  209. // m_bTracking=1; //在鼠标按下没有释放时该值为true
  210. // m_bSelected=1; //按钮被按下是该值为true
  211. // m_bFocus=1; //按钮为当前焦点所在时该值为true
  212. pWnd->Invalidate();
  213. pWnd->UpdateWindow();
  214. return TRUE;
  215. }
  216. LRESULT CButtonExt::OnLButtonUp( CWnd *pWnd, UINT nFlags, CPoint point )
  217. {
  218. ReleaseCapture();
  219. m_nStatus = STATUS_BUTTON_NORMAL;
  220. pWnd->Invalidate();
  221. pWnd->UpdateWindow();
  222. SendMessage( pWnd->GetParent()->m_hWnd, WM_COMMAND, pWnd->GetDlgCtrlID(), (LPARAM) (pWnd->m_hWnd) );
  223. return TRUE;
  224. }
  225. LRESULT CButtonExt::OnMouseMove( CWnd *pWnd, UINT nFlags, CPoint point )
  226. {
  227. HRGN hRgn = CreateRectRgn( 0, 0, 0, 0 );
  228. pWnd->GetWindowRgn( hRgn );
  229. BOOL bIn = PtInRegion( hRgn, point.x, point.y );
  230. if( bIn )
  231. {
  232. if(CWnd::GetCapture()==pWnd)return 1;
  233. if( m_nStatus != STATUS_BUTTON_HOVER )
  234. {
  235. m_nStatus = STATUS_BUTTON_HOVER;
  236. pWnd->Invalidate();
  237. pWnd->UpdateWindow();
  238. pWnd->SetCapture();
  239. }
  240. }
  241. else
  242. {
  243. //if ( m_nStatus == STATUS_BUTTON_HOVER )
  244. //{
  245. m_nStatus = STATUS_BUTTON_NORMAL;
  246. pWnd->Invalidate();
  247. pWnd->UpdateWindow();
  248. ReleaseCapture();
  249. //}
  250. }
  251. DeleteObject( hRgn );
  252. return TRUE;
  253. }
  254. LRESULT CButtonExt::OnPaint( CWnd *pWnd )
  255. {
  256. CRect rect ;//= lpDrawItemStruct->rcItem;
  257. pWnd->GetClientRect( &rect );
  258. CPaintDC dc(pWnd);
  259. CDC *pDC=&dc;
  260. int nSaveDC=pDC->SaveDC();
  261. int pos=FindBtnPos((int)pWnd->GetSafeHwnd ());
  262. m_bOver=g_btnarray.ElementAt (pos+1);
  263. m_bTracking=g_btnarray.ElementAt (pos+2);
  264. m_bSelected=g_btnarray.ElementAt (pos+3);
  265. m_bFocus=g_btnarray.ElementAt (pos+4);
  266. POINT pt ;
  267. TCHAR strText[MAX_PATH + 1];
  268. ::GetWindowText(pWnd->GetSafeHwnd (), strText, MAX_PATH);
  269. //画按钮的外边框,它是一个半径为5的圆角矩形
  270. pt.x = 5;
  271. pt.y = 5;
  272. CPen* hOldPen = pDC->SelectObject(&m_BoundryPen);
  273. pDC->RoundRect(&rect, pt);
  274. pDC->SelectObject(hOldPen);
  275. rect.DeflateRect(CSize(GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE)));
  276. //根据按钮的状态填充按钮的底色
  277. CBrush* pOldBrush;
  278. if (m_bOver)
  279. {
  280. pOldBrush = pDC->SelectObject(&m_FillActive);
  281. DoGradientFill(pDC, &rect);
  282. }
  283. else
  284. {
  285. pOldBrush = pDC->SelectObject(&m_FillInactive);
  286. DoGradientFill(pDC, &rect);
  287. }
  288. //根据按钮的状态绘制内边框
  289. if (m_bOver || m_bSelected)
  290. DrawInsideBorder(pDC, &rect);
  291. pDC->SelectObject(pOldBrush);
  292. //显示按钮的文本
  293. if (strText!=NULL)
  294. {
  295. CFont* hFont = pWnd->GetFont();
  296. CFont* hOldFont = pDC->SelectObject(hFont);
  297. CSize szExtent = pDC->GetTextExtent(strText, lstrlen(strText));
  298. CPoint pt( rect.CenterPoint().x - szExtent.cx / 2, rect.CenterPoint().y - szExtent.cy / 2);
  299. short state=GetKeyState(VK_LBUTTON);
  300. BYTE sta=(BYTE)(state>>8);
  301. if (m_bTracking && sta)//state & ODS_SELECTED)
  302. pt.Offset(1, 1);
  303. int nMode = pDC->SetBkMode(TRANSPARENT);
  304. if (pWnd->IsWindowEnabled ()==0)
  305. pDC->DrawState(pt, szExtent, strText, DSS_DISABLED, TRUE, 0, (HBRUSH)NULL);
  306. else
  307. pDC->DrawState(pt, szExtent, strText, DSS_NORMAL, TRUE, 0, (HBRUSH)NULL);
  308. pDC->SelectObject(hOldFont);
  309. pDC->SetBkMode(nMode);
  310. }
  311. pDC->RestoreDC(nSaveDC);
  312. /* CPaintDC dc(pWnd);
  313. CString cs;
  314. RECT rc;
  315. CFont Font;
  316. CFont *pOldFont;
  317. CBrush Brush;
  318. CBrush *pOldBrush;
  319. CPen Pen;
  320. CPen *pOldPen;
  321. POINT pt;
  322. pt.x = 2;
  323. pt.y = 2;
  324. if(!pWnd->IsWindowEnabled ())m_nStatus = STATUS_BUTTON_DOWN;
  325. dc.SetBkMode( TRANSPARENT );
  326. Font.CreateFont( 14, 0, 0, 0, FW_HEAVY, 0, 0, 0, ANSI_CHARSET, \
  327. OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, \
  328. VARIABLE_PITCH | FF_SWISS, "黑体" );
  329. pOldFont = dc.SelectObject( &Font );
  330. if( m_nStatus == STATUS_BUTTON_DOWN ) {
  331. Brush.CreateSolidBrush( RGB( 160, 160, 160 ) );
  332. Pen.CreatePen( PS_SOLID, 1, RGB( 100, 100, 100 ) );
  333. dc.SetTextColor( RGB( 50, 50, 250 ) );
  334. } else if( m_nStatus == STATUS_BUTTON_HOVER ) {
  335. Brush.CreateSolidBrush( RGB( 60, 60, 180 ) );
  336. Pen.CreatePen( PS_SOLID, 1, RGB( 0, 0, 0 ) );
  337. dc.SetTextColor( RGB( 250, 250, 50 ) );
  338. } else if( m_nStatus == STATUS_BUTTON_NORMAL )
  339. {
  340. Brush.CreateSolidBrush( RGB( 240, 240, 240 ) );
  341. Pen.CreatePen( PS_SOLID, 1, RGB( 120, 120, 120 ) );
  342. dc.SetTextColor( RGB( 50, 50, 50 ) );
  343. }
  344. pOldBrush = dc.SelectObject( &Brush );
  345. pOldPen = dc.SelectObject( &Pen );
  346. pWnd->GetClientRect( &rc );
  347. dc.RoundRect( &rc, pt );
  348. HRGN hRgn = CreateRectRgn( rc.left, rc.top, rc.right, rc.bottom );
  349. pWnd->SetWindowRgn( hRgn, TRUE );
  350. DeleteObject( hRgn );
  351. pWnd->GetWindowText( cs );
  352. dc.DrawText( cs, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE );
  353. dc.SelectObject( pOldFont );
  354. dc.SelectObject( pOldBrush );
  355. dc.SelectObject( pOldPen );
  356. m_nStatus = STATUS_BUTTON_NORMAL;*/
  357. return TRUE;
  358. }