首页 > 代码库 > vc 按钮自绘

vc 按钮自绘

按钮自绘,将按钮区域分成三部分,左边、右边、中间都由贴图绘制,可用于手动进度条按钮,或者左右选择项按钮

cpp代码部分:

 

[cpp] view plaincopy
 
  1. // LRSkinButton.cpp : implementation file  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include "CRedrawButtonDemo.h"  
  6. #include "LRSkinButton.h"  
  7.   
  8. #ifdef _DEBUG  
  9. #define new DEBUG_NEW  
  10. #undef THIS_FILE  
  11. static char THIS_FILE[] = __FILE__;  
  12. #endif  
  13.   
  14. /////////////////////////////////////////////////////////////////////////////  
  15. // CLRSkinButton  
  16.   
  17. CLRSkinButton::CLRSkinButton()  
  18. {  
  19.     m_nWidth = 17;  
  20.     m_nHeight = 16;  
  21.     m_bDrawBorder = TRUE;  
  22. }  
  23.   
  24. CLRSkinButton::~CLRSkinButton()  
  25. {  
  26. }  
  27.   
  28.   
  29. BEGIN_MESSAGE_MAP(CLRSkinButton, CButton)  
  30.     //{{AFX_MSG_MAP(CLRSkinButton)  
  31.         // NOTE - the ClassWizard will add and remove mapping macros here.  
  32.     //}}AFX_MSG_MAP  
  33.     ON_WM_CAPTURECHANGED()  
  34.     ON_WM_MOUSEMOVE()  
  35.     ON_WM_SETCURSOR()  
  36.     ON_WM_KILLFOCUS()  
  37. END_MESSAGE_MAP()  
  38.   
  39. void CLRSkinButton::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )  
  40. {  
  41. //  TRACE("DrawItem\n");  
  42.       
  43.     // TODO:  添加您的代码以绘制指定项  
  44.     CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);  
  45.     HDC hDC = pDC->GetSafeHdc();  
  46.     // 按钮客户区域  
  47.     CRect rectItem(lpDrawItemStruct->rcItem);  
  48.     m_nHeight = rectItem.Height();  
  49.     m_nWidth = 26;  
  50.     CRect rectCenter(rectItem.left+m_nWidth, rectItem.top, rectItem.right-m_nWidth, rectItem.bottom);  
  51.     CRect rectLeft(rectItem.left, rectItem.top, rectItem.left+m_nWidth, rectItem.top+m_nHeight);  
  52.     CRect rectRight(rectItem.right-m_nWidth,rectItem.top,rectItem.right,rectItem.bottom);  
  53.     static int nClrWidth = rectCenter.Width()/10;  
  54.     CRect rectColor(rectCenter.left, rectCenter.top, rectCenter.left, rectCenter.bottom);  
  55.     rectCenter.DeflateRect(0,1,0,1);  
  56. //  pDC->SetBkMode(TRANSPARENT);  
  57.       
  58.     HPEN hOldPen;  
  59.     UINT action, state;  
  60.     action = lpDrawItemStruct->itemAction;  
  61.     state  = lpDrawItemStruct->itemState;  
  62.   
  63.     BOOL bIsPressed, bIsFocus, bIsDisabled;  
  64.     bIsPressed = state & ODS_SELECTED;  
  65.     bIsDisabled = state & ODS_DISABLED;  
  66.     bIsFocus = (state & ODS_FOCUS) == ODS_FOCUS; // ::GetFocus() == m_hWnd;  
  67.   
  68.     ::SetBkColor(hDC, RGB(22, 33, 55));  
  69.     // Draw pressed button  
  70.     if (bIsPressed)  
  71.     {// 按钮按下状态  
  72.         /* 
  73.         HPEN penBtnHiLight = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DHILIGHT));//COLOR_3DLIGHT)); // Bianco 
  74.         HPEN penBtnShadow = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DSHADOW));   // Grigio scuro 
  75.          
  76.         // draw darkline of left-top conner 
  77.         hOldPen = (HPEN)SelectObject(hDC,penBtnShadow); 
  78.         MoveToEx(hDC,rectItem.left, rectItem.bottom-1,NULL); 
  79.         LineTo(hDC,rectItem.left, rectItem.top); 
  80.         LineTo(hDC,rectItem.right, rectItem.top); 
  81.         // draw hilight line of right-bottom conner 
  82.         SelectObject(hDC,penBtnHiLight); 
  83.         MoveToEx(hDC,rectItem.left, rectItem.bottom-1,NULL); 
  84.         LineTo(hDC,rectItem.right-1, rectItem.bottom-1); 
  85.         LineTo(hDC,rectItem.right-1, rectItem.top-1); 
  86.         //release resource 
  87.         SelectObject(hDC,hOldPen); 
  88.         DeleteObject(penBtnShadow); 
  89.         DeleteObject(penBtnHiLight); 
  90.         */  
  91.   
  92.         // 判断点击的是左区域还是右区域  
  93.         POINT pos;  
  94.         GetCursorPos( &pos );  
  95.         ScreenToClient(&pos);  
  96.         if (PtInRect( &rectLeft, pos))  
  97.         {// 左键  
  98.             TRACE(_T("Clicked Left...\n"));  
  99.             nClrWidth -= 5;  
  100.             if (nClrWidth <=0)  
  101.             {  
  102.                 nClrWidth = 0;  
  103.             }  
  104.         }  
  105.         if (PtInRect( &rectRight, pos))  
  106.         {// 右键  
  107.             TRACE(_T("Clicked Right...\n"));  
  108.             nClrWidth += 5;  
  109.             if (nClrWidth >= rectCenter.Width())  
  110.             {  
  111.                 nClrWidth = rectCenter.Width();  
  112.             }  
  113.         }  
  114.           
  115.     }  
  116.     else // ...else draw non pressed button  
  117.     {  
  118.         if(!m_bIsFlat || (m_bIsFlat && m_MouseOnButton))  
  119.         {// 鼠标移动到按钮上面时的状态  
  120.             /* 
  121.             HPEN pen3DLight = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DHILIGHT));//COLOR_3DLIGHT));       // Light gray 
  122.             HPEN penBtnShadow = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DSHADOW));   // Dark gray 
  123.             // White line 
  124.             hOldPen = (HPEN)SelectObject(hDC,pen3DLight); 
  125.             MoveToEx(hDC,rectItem.left, rectItem.bottom-1,NULL); 
  126.             LineTo(hDC,rectItem.left, rectItem.top); 
  127.             LineTo(hDC,rectItem.right, rectItem.top); 
  128.             // Dark gray line 
  129.             SelectObject(hDC,penBtnShadow); 
  130.             MoveToEx(hDC,rectItem.left, rectItem.bottom-1,NULL); 
  131.             LineTo(hDC,rectItem.right-1, rectItem.bottom-1); 
  132.             LineTo(hDC,rectItem.right-1, rectItem.top-1); 
  133.             // 
  134.             SelectObject(hDC,hOldPen); 
  135.             DeleteObject(pen3DLight);  
  136.             DeleteObject(penBtnShadow); 
  137.             */  
  138.         }  
  139.         else{// FLAT 属性  
  140.             if(m_bDrawBorder)  
  141.             { // 失去焦点的时候绘制按钮边框  
  142.                 HPEN penBorder = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNTEXT));  
  143.                 hOldPen = (HPEN)SelectObject(hDC,penBorder);  
  144.                 SelectObject(hDC,GetStockObject(NULL_BRUSH));  
  145.                 // 绘制按钮边框  
  146.                 Rectangle(hDC,rectItem.left, rectItem.top, rectItem.right, rectItem.bottom);  
  147.                 SelectObject(hDC, hOldPen);  
  148.                 DeleteObject(penBorder);  
  149.             }  
  150.         }  
  151.     }  
  152.   
  153. //  if (lpDrawItemStruct->itemData != NULL)  
  154. //  {  
  155.         // 画图标  
  156.         CRect rect(rectCenter);  
  157.     //  rect.DeflateRect(0,5,0,0); // 改变矩形范围  
  158.         CDC dcMem;  
  159.         dcMem.CreateCompatibleDC(pDC);  
  160.           
  161.         // 背景图  
  162.         CBitmap bmp;  
  163.         BITMAP bitmap;  
  164.           
  165.         bmp.LoadBitmap(m_nBmpBK);  
  166.         bmp.GetBitmap( &bitmap );  
  167.         CBitmap* pOldBmp = dcMem.SelectObject(&bmp);  
  168.         pDC->StretchBlt(rectCenter.left, rectCenter.top, rectCenter.Width(), rectCenter.Height(), &dcMem, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY);  
  169.         bmp.DeleteObject();  
  170.   
  171.         // 左按钮图  
  172.         bmp.LoadBitmap( m_nBmpLeft );  
  173.         dcMem.SelectObject( &bmp );  
  174.         bmp.GetBitmap( &bitmap );  
  175.     //  pDC->BitBlt(rectLeft.left,rectLeft.top,rectLeft.Width(),rectLeft.Height(),&dcMem,0,0,SRCCOPY);  
  176.         pDC->StretchBlt(rectLeft.left, rectLeft.top, rectLeft.Width(), rectLeft.Height(), &dcMem, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY);  
  177.         bmp.DeleteObject();  
  178.   
  179.         // 右按钮图  
  180.         bmp.LoadBitmap( m_nBmpRight );  
  181.         bmp.GetBitmap( &bitmap );  
  182.         dcMem.SelectObject( &bmp );  
  183.     //  pDC->BitBlt(rectRight.left,rectRight.top,rectRight.Width(),rectRight.Height(),&dcMem,0,0,SRCCOPY);  
  184.         pDC->StretchBlt(rectRight.left, rectRight.top, rectRight.Width(), rectRight.Height(), &dcMem, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY);  
  185.         bmp.DeleteObject();  
  186.         dcMem.SelectObject(pOldBmp);  
  187.   
  188.         // 绘制颜色进度条  
  189.         bmp.LoadBitmap(IDB_BMP_BTNLEFT);  
  190.     //  CBrush brush(&bmp);   //RGB(255, 255, 0)  
  191.         CBrush brush(RGB(255, 255, 0));   //  
  192.         rectColor.right = rectColor.left+nClrWidth;  
  193.         pDC->FillRect(rectColor, &brush);  
  194. //      CBrush *pOldBrush = (CBrush*)pDC->SelectObject(&brush);  
  195. //      pDC->Rectangle(&rectColor);  
  196. //      pDC->SelectObject(pOldBrush);  
  197.         bmp.DeleteObject();  
  198.   
  199.         // 绘制文字  
  200.         rect = rectCenter;  
  201.         //  rect.DeflateRect(0,5,0,0);  // 调整矩形大小  
  202.         rect.InflateRect(0,1,0,1);  
  203.         pDC->SetTextColor(RGB(0,0,0));  
  204. //      rect.OffsetRect(2,1); // 平行移动矩形位置  
  205.           
  206.         //  char zsCaption[64] = {0};  
  207.         CString str;  
  208.         GetWindowText( str );  
  209.         COLORREF clr = GetSysColor( COLOR_3DHILIGHT);  
  210.         clr = RGB(55, 155, 55);  
  211.         if (bIsPressed)  
  212.         {  
  213.             clr = RGB(155, 55, 55);  
  214.         }  
  215.         else if (bIsFocus /*|| m_MouseOnButton*/)  
  216.         {  
  217.             clr = RGB(55, 55, 155);  
  218.   
  219.             HPEN penBorder = CreatePen(PS_SOLID, 1, RGB(255,0,255));  
  220.             hOldPen = (HPEN)SelectObject(hDC,penBorder);  
  221.             SelectObject(hDC,GetStockObject(NULL_BRUSH));  
  222.             // 绘制按钮边框  
  223.             Rectangle(hDC,rect.left, rect.top, rect.right, rect.bottom);  
  224.             SelectObject(hDC, hOldPen);  
  225.             DeleteObject(penBorder);  
  226.         }  
  227.         pDC->SetBkColor(clr);  
  228.         pDC->SetTextColor( RGB(255, 0, 0) );  
  229.         pDC->DrawText(str, str.GetLength(),rect, DT_CENTER | DT_VCENTER| DT_SINGLELINE);  
  230.   
  231. //  }  
  232.           
  233.   
  234. }  
  235.   
  236. void CLRSkinButton::SetBtnBmps( UINT uBmpBK, UINT uBmpLeft, UINT uBmpRight )  
  237. {  
  238.     m_nBmpBK = uBmpBK;  
  239.     m_nBmpLeft = uBmpLeft;  
  240.     m_nBmpRight = uBmpRight;  
  241. }  
  242.   
  243. void CLRSkinButton::PreSubclassWindow()  
  244. {  
  245.     UINT nBS = GetButtonStyle();  
  246.     if(nBS & BS_DEFPUSHBUTTON)  
  247.         m_bDefaultBtn = TRUE;  
  248.     else  
  249.         m_bDefaultBtn = FALSE;  
  250.     SetButtonStyle(nBS | BS_OWNERDRAW);   
  251.       
  252.     CButton::PreSubclassWindow();     
  253. }  
  254. /////////////////////////////////////////////////////////////////////////////  
  255. // CLRSkinButton message handlers  
  256. void CLRSkinButton::OnCaptureChanged(CWnd *pWnd)   
  257. {  
  258.     if(m_MouseOnButton == TRUE)  
  259.     {  
  260.         ReleaseCapture();  
  261.         Invalidate();  
  262.     }  
  263.       
  264.     CButton::OnCaptureChanged(pWnd);  
  265. }  
  266.   
  267. void CLRSkinButton::OnMouseMove(UINT nFlags, CPoint point)   
  268. {  
  269.     CButton::OnMouseMove(nFlags, point);  
  270.       
  271.     HWND hParent; // Finestra che contiene il bottone  
  272.       
  273.     // If the mouse enter the button with the left button pressed then do nothing  
  274.     if (nFlags & MK_LBUTTON && !m_MouseOnButton)   
  275.         return;  
  276.       
  277.     // If our button is not flat then do nothing  
  278.     if (m_bIsFlat)   
  279.     {  
  280.         hParent = ::GetParent(m_hWnd);  
  281.         if ((::GetCapture() != m_hWnd) &&   (hParent != NULL))   
  282.         {  
  283.             m_MouseOnButton = TRUE;  
  284.             SetCapture();  
  285.             Invalidate();  
  286.         }  
  287.         else  
  288.         {  
  289.             RECT rc;  
  290.             GetClientRect(&rc);  
  291.             if (!PtInRect(&rc,point))  
  292.             {  
  293.                 // Redraw only if mouse goes out  
  294.                 if (m_MouseOnButton == TRUE)  
  295.                 {  
  296.                     m_MouseOnButton = FALSE;  
  297.                     Invalidate();  
  298.                 }  
  299.                 // If user is NOT pressing left button then release capture!  
  300.                 if (!(nFlags & MK_LBUTTON))   
  301.                     ReleaseCapture();  
  302.             }  
  303.         }  
  304.     }  
  305. }  
  306.   
  307. BOOL CLRSkinButton::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)   
  308. {  
  309.     if (m_hBtnCursor != NULL)  
  310.     {  
  311.         ::SetCursor(m_hBtnCursor);  
  312.         return TRUE;  
  313.     }  
  314.       
  315.     return CButton::OnSetCursor(pWnd, nHitTest, message);  
  316. }  
  317.   
  318. void CLRSkinButton::OnKillFocus(CWnd* pNewWnd)   
  319. {  
  320.     CButton::OnKillFocus(pNewWnd);  
  321.       
  322.     if(!m_bIsFlat)   
  323.     {  
  324.         m_MouseOnButton = FALSE;  
  325.         Invalidate();  
  326.     }  
  327. }