// ButtonExt.cpp: implementation of the CButtonExt class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "ButtonExt.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif UINT CButtonExt::m_nStatus = STATUS_BUTTON_NORMAL; WNDPROC CButtonExt::m_cWndProc = NULL; CArrayg_btnarray; //按钮的状态 BOOL m_bOver=0; //鼠标位于按钮之上时该值为true,反之为flase BOOL m_bTracking=0; //在鼠标按下没有释放时该值为true BOOL m_bSelected=0; //按钮被按下是该值为true BOOL m_bFocus=0; //按钮为当前焦点所在时该值为true //按钮的外边框 extern CPen m_BoundryPen; //鼠标指针置于按钮之上时按钮的内边框 extern CPen m_InsideBoundryPenLeft; extern CPen m_InsideBoundryPenRight; extern CPen m_InsideBoundryPenTop; extern CPen m_InsideBoundryPenBottom; //按钮获得焦点时按钮的内边框 extern CPen m_InsideBoundryPenLeftSel; extern CPen m_InsideBoundryPenRightSel; extern CPen m_InsideBoundryPenTopSel; extern CPen m_InsideBoundryPenBottomSel; //按钮的底色,包括有效和无效两种状态 extern CBrush m_FillActive; extern CBrush m_FillInactive; //绘制按钮的底色 void CButtonExt::DoGradientFill(CDC *pDC, CRect* rect) { return; CBrush brBk[64]; int nWidth = rect->Width(); int nHeight = rect->Height(); CRect rct; int i = 0; for ( i = 0; i < 64; i ++) { if (m_bOver) { if (m_bFocus) brBk[i].CreateSolidBrush(RGB(255 - (i / 4), 255 - (i / 4), 255 - (i / 3))); else brBk[i].CreateSolidBrush(RGB(255 - (i / 4), 255 - (i / 4), 255 - (i / 5))); } else { if (m_bFocus) brBk[i].CreateSolidBrush(RGB(255 - (i / 3), 255 - (i / 3), 255 - (i / 4))); else brBk[i].CreateSolidBrush(RGB(255 - (i / 3), 255 - (i / 3), 255 - (i / 5))); } } for (i = rect->top; i <= nHeight + 2; i ++) { rct.SetRect(rect->left, i, nWidth + 2, i + 1); pDC->FillRect(&rct, &brBk[((i * 63) / nHeight)]); } for (i = 0; i < 64; i ++) brBk[i].DeleteObject(); } //绘制按钮的内边框 void CButtonExt::DrawInsideBorder(CDC *pDC, CRect* rect) { CPen *pLeft, *pRight, *pTop, *pBottom; if (m_bSelected && !m_bOver) { pLeft = & m_InsideBoundryPenLeftSel; pRight = &m_InsideBoundryPenRightSel; pTop = &m_InsideBoundryPenTopSel; pBottom = &m_InsideBoundryPenBottomSel; } else { pLeft = &m_InsideBoundryPenLeft; pRight = &m_InsideBoundryPenRight; pTop = &m_InsideBoundryPenTop; pBottom = &m_InsideBoundryPenBottom; } CPoint oldPoint = pDC->MoveTo(rect->left, rect->bottom - 1); CPen* pOldPen = pDC->SelectObject(pLeft); pDC->LineTo(rect->left, rect->top + 1); pDC->SelectObject(pRight); pDC->MoveTo(rect->right - 1, rect->bottom - 1); pDC->LineTo(rect->right - 1, rect->top); pDC->SelectObject(pTop); pDC->MoveTo(rect->left - 1, rect->top); pDC->LineTo(rect->right - 1, rect->top); pDC->SelectObject(pBottom); pDC->MoveTo(rect->left, rect->bottom); pDC->LineTo(rect->right - 1, rect->bottom); pDC->SelectObject(pOldPen); pDC->MoveTo(oldPoint); if (m_bSelected && !m_bOver) DrawFocusRect(pDC->m_hDC,rect); } ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// int FindBtnPos(int hwnd) { for(int i=0; iInvalidate(); } break; case WM_MOUSEHOVER: { int pos=FindBtnPos((int)hWnd); m_bOver = 1; g_btnarray.SetAt (pos+1, m_bOver); pWnd->Invalidate(); } break; case WM_PAINT: // case WM_LBUTTONDBLCLK: return OnPaint( pWnd ); break; /* case WM_LBUTTONDOWN: point.x = LOWORD(lParam); point.y = HIWORD(lParam); return OnLButtonDown( pWnd, 0, point ); break; case WM_LBUTTONUP: point.x = LOWORD(lParam); point.y = HIWORD(lParam); return OnLButtonUp( pWnd, 0, point ); break; case WM_MOUSEMOVE: point.x = LOWORD(lParam); point.y = HIWORD(lParam); return OnMouseMove( pWnd, 0, point ); break; case WM_ERASEBKGND: return TRUE; break; case WM_ENABLE: { pWnd->Invalidate(); return FALSE; } break;*/ default: break; } return CallWindowProc( m_cWndProc, hWnd, message, wParam, lParam ); } LRESULT CButtonExt::OnLButtonDown( CWnd *pWnd, UINT nFlags, CPoint point ) { m_nStatus = STATUS_BUTTON_DOWN; // m_bOver=1; //鼠标位于按钮之上时该值为true,反之为flase // m_bTracking=1; //在鼠标按下没有释放时该值为true // m_bSelected=1; //按钮被按下是该值为true // m_bFocus=1; //按钮为当前焦点所在时该值为true pWnd->Invalidate(); pWnd->UpdateWindow(); return TRUE; } LRESULT CButtonExt::OnLButtonUp( CWnd *pWnd, UINT nFlags, CPoint point ) { ReleaseCapture(); m_nStatus = STATUS_BUTTON_NORMAL; pWnd->Invalidate(); pWnd->UpdateWindow(); SendMessage( pWnd->GetParent()->m_hWnd, WM_COMMAND, pWnd->GetDlgCtrlID(), (LPARAM) (pWnd->m_hWnd) ); return TRUE; } LRESULT CButtonExt::OnMouseMove( CWnd *pWnd, UINT nFlags, CPoint point ) { HRGN hRgn = CreateRectRgn( 0, 0, 0, 0 ); pWnd->GetWindowRgn( hRgn ); BOOL bIn = PtInRegion( hRgn, point.x, point.y ); if( bIn ) { if(CWnd::GetCapture()==pWnd)return 1; if( m_nStatus != STATUS_BUTTON_HOVER ) { m_nStatus = STATUS_BUTTON_HOVER; pWnd->Invalidate(); pWnd->UpdateWindow(); pWnd->SetCapture(); } } else { //if ( m_nStatus == STATUS_BUTTON_HOVER ) //{ m_nStatus = STATUS_BUTTON_NORMAL; pWnd->Invalidate(); pWnd->UpdateWindow(); ReleaseCapture(); //} } DeleteObject( hRgn ); return TRUE; } LRESULT CButtonExt::OnPaint( CWnd *pWnd ) { CRect rect ;//= lpDrawItemStruct->rcItem; pWnd->GetClientRect( &rect ); CPaintDC dc(pWnd); CDC *pDC=&dc; int nSaveDC=pDC->SaveDC(); int pos=FindBtnPos((int)pWnd->GetSafeHwnd ()); m_bOver=g_btnarray.ElementAt (pos+1); m_bTracking=g_btnarray.ElementAt (pos+2); m_bSelected=g_btnarray.ElementAt (pos+3); m_bFocus=g_btnarray.ElementAt (pos+4); POINT pt ; TCHAR strText[MAX_PATH + 1]; ::GetWindowText(pWnd->GetSafeHwnd (), strText, MAX_PATH); //画按钮的外边框,它是一个半径为5的圆角矩形 pt.x = 5; pt.y = 5; CPen* hOldPen = pDC->SelectObject(&m_BoundryPen); pDC->RoundRect(&rect, pt); pDC->SelectObject(hOldPen); rect.DeflateRect(CSize(GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE))); //根据按钮的状态填充按钮的底色 CBrush* pOldBrush; if (m_bOver) { pOldBrush = pDC->SelectObject(&m_FillActive); DoGradientFill(pDC, &rect); } else { pOldBrush = pDC->SelectObject(&m_FillInactive); DoGradientFill(pDC, &rect); } //根据按钮的状态绘制内边框 if (m_bOver || m_bSelected) DrawInsideBorder(pDC, &rect); pDC->SelectObject(pOldBrush); //显示按钮的文本 if (strText!=NULL) { CFont* hFont = pWnd->GetFont(); CFont* hOldFont = pDC->SelectObject(hFont); CSize szExtent = pDC->GetTextExtent(strText, lstrlen(strText)); CPoint pt( rect.CenterPoint().x - szExtent.cx / 2, rect.CenterPoint().y - szExtent.cy / 2); short state=GetKeyState(VK_LBUTTON); BYTE sta=(BYTE)(state>>8); if (m_bTracking && sta)//state & ODS_SELECTED) pt.Offset(1, 1); int nMode = pDC->SetBkMode(TRANSPARENT); if (pWnd->IsWindowEnabled ()==0) pDC->DrawState(pt, szExtent, strText, DSS_DISABLED, TRUE, 0, (HBRUSH)NULL); else pDC->DrawState(pt, szExtent, strText, DSS_NORMAL, TRUE, 0, (HBRUSH)NULL); pDC->SelectObject(hOldFont); pDC->SetBkMode(nMode); } pDC->RestoreDC(nSaveDC); /* CPaintDC dc(pWnd); CString cs; RECT rc; CFont Font; CFont *pOldFont; CBrush Brush; CBrush *pOldBrush; CPen Pen; CPen *pOldPen; POINT pt; pt.x = 2; pt.y = 2; if(!pWnd->IsWindowEnabled ())m_nStatus = STATUS_BUTTON_DOWN; dc.SetBkMode( TRANSPARENT ); Font.CreateFont( 14, 0, 0, 0, FW_HEAVY, 0, 0, 0, ANSI_CHARSET, \ OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, \ VARIABLE_PITCH | FF_SWISS, "黑体" ); pOldFont = dc.SelectObject( &Font ); if( m_nStatus == STATUS_BUTTON_DOWN ) { Brush.CreateSolidBrush( RGB( 160, 160, 160 ) ); Pen.CreatePen( PS_SOLID, 1, RGB( 100, 100, 100 ) ); dc.SetTextColor( RGB( 50, 50, 250 ) ); } else if( m_nStatus == STATUS_BUTTON_HOVER ) { Brush.CreateSolidBrush( RGB( 60, 60, 180 ) ); Pen.CreatePen( PS_SOLID, 1, RGB( 0, 0, 0 ) ); dc.SetTextColor( RGB( 250, 250, 50 ) ); } else if( m_nStatus == STATUS_BUTTON_NORMAL ) { Brush.CreateSolidBrush( RGB( 240, 240, 240 ) ); Pen.CreatePen( PS_SOLID, 1, RGB( 120, 120, 120 ) ); dc.SetTextColor( RGB( 50, 50, 50 ) ); } pOldBrush = dc.SelectObject( &Brush ); pOldPen = dc.SelectObject( &Pen ); pWnd->GetClientRect( &rc ); dc.RoundRect( &rc, pt ); HRGN hRgn = CreateRectRgn( rc.left, rc.top, rc.right, rc.bottom ); pWnd->SetWindowRgn( hRgn, TRUE ); DeleteObject( hRgn ); pWnd->GetWindowText( cs ); dc.DrawText( cs, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE ); dc.SelectObject( pOldFont ); dc.SelectObject( pOldBrush ); dc.SelectObject( pOldPen ); m_nStatus = STATUS_BUTTON_NORMAL;*/ return TRUE; }