MFC自制进度条

来源:互联网 发布:车解码器软件 编辑:程序博客网 时间:2024/05/01 14:21

改变进度条的颜色http://www.codefans.net/articles/1454.shtml

使用方法

1.将三个文件添加到工程
2.在对话框上添加一个进度条;
新建一个类CGradientProgressCtrl,其基类为CProgressCtrl
3.
为进度条添加变量,变量类型CGradientProgressCtrl,否则运行不成功

 

添加方法:进度条右键-->添加变量



 添加变量后,系统会自动在.h文件中添加变量定义CGradientProgressCtrl  progress;

在.c文件中的DoDataExchange函数中进行控件绑定并添加关联DDX_Control代码




4.
应用:
m_process1.SetRange(0, 100);
m_process1.ShowPercent(TRUE);
m_process1.SetStartColor(RGB(0, 0, 255));
m_process1.SetEndColor(RGB(255, 255, 0));
m_process1.SetTextColor(RGB(0, 0, 255));
m_process1.SetBkColor(RGB(125, 125, 125));
m_process1.SetPos(50);//设置百分比

5、其中GradientProgressCtrl.h

[cpp] view plain copy
  1. #if !defined(AFX_ENHPROGRESSCTRL_H__12909D73_C393_11D1_9FAE_8192554015AD__INCLUDED_)  
  2. #define AFX_ENHPROGRESSCTRL_H__12909D73_C393_11D1_9FAE_8192554015AD__INCLUDED_  
  3.   
  4. #if _MSC_VER >= 1000  
  5. #pragma once  
  6. #endif // _MSC_VER >= 1000  
  7. // EnhProgressCtrl.h : header file  
  8.   
  9. // GradientProgressCtrl.h : header file  
  10.   
  11. #include "MemDC.h"  
  12.   
  13. /////////////////////////////////////////////////////////////////////////////  
  14. // CGradientProgressCtrl window  
  15.   
  16. class CGradientProgressCtrl : public CProgressCtrl  
  17. {  
  18. // Construction  
  19. public:  
  20.     CGradientProgressCtrl();  
  21.   
  22. // Attributes  
  23. public:  
  24. // Attributes  
  25.       
  26.     void SetRange(int nLower, int nUpper);  
  27.     void SetRange32( int nLower, int nUpper );  
  28.     int SetPos(int nPos);  
  29.     int SetStep(int nStep);  
  30.     int StepIt(void);  
  31.   
  32. // Operations  
  33. public:  
  34.       
  35.     // Set Functions  
  36.     void SetTextColor(COLORREF color)   {m_clrText = color;}  
  37.     void SetBkColor(COLORREF color)      {m_clrBkGround = color;}  
  38.     void SetStartColor(COLORREF color)  {m_clrStart = color;}  
  39.     void SetEndColor(COLORREF color)    {m_clrEnd = color;}  
  40.   
  41.     // Show the percent caption  
  42.     void ShowPercent(BOOL bShowPercent = TRUE)  {m_bShowPercent = bShowPercent;}  
  43.       
  44.     // Get Functions  
  45.     COLORREF GetTextColor(void) {return m_clrText;}  
  46.     COLORREF GetBkColor(void)        {return m_clrBkGround;}  
  47.     COLORREF GetStartColor(void)    {return m_clrStart;}  
  48.     COLORREF GetEndColor(void)  {return m_clrEnd;}  
  49.   
  50.   
  51. // Overrides  
  52.     // ClassWizard generated virtual function overrides  
  53.     //{{AFX_VIRTUAL(CGradientProgressCtrl)  
  54.     protected:  
  55.     //}}AFX_VIRTUAL  
  56.   
  57. // Implementation  
  58. public:  
  59.     virtual ~CGradientProgressCtrl();  
  60.   
  61.     // Generated message map functions  
  62. protected:  
  63.     void DrawGradient(CPaintDC *pDC, const RECT &rectClient, const int &nMaxWidth, const BOOL &bVertical);    
  64.     int m_nLower, m_nUpper, m_nStep, m_nCurrentPosition;  
  65.     COLORREF    m_clrStart, m_clrEnd, m_clrBkGround, m_clrText;  
  66.     BOOL m_bShowPercent;  
  67.     //{{AFX_MSG(CGradientProgressCtrl)  
  68.     afx_msg void OnPaint();  
  69.     afx_msg BOOL OnEraseBkgnd(CDC* pDC);  
  70.     //}}AFX_MSG  
  71.   
  72.     DECLARE_MESSAGE_MAP()  
  73. };  
  74.   
  75. /////////////////////////////////////////////////////////////////////////////  
  76.   
  77. //{{AFX_INSERT_LOCATION}}  
  78. // Microsoft Developer Studio will insert additional declarations immediately before the previous line.  
  79.   
  80. #endif // !defined(AFX_ENHPROGRESSCTRL_H__12909D73_C393_11D1_9FAE_8192554015AD__INCLUDED_)  


5、其中GradientProgressCtrl.c

[cpp] view plain copy
  1. // GradientProgressCtrl.cpp : implementation file  
  2.   
  3. #include "stdafx.h"  
  4. #include "GradientProgressCtrl.h"  
  5.   
  6. #ifdef _DEBUG  
  7. #define new DEBUG_NEW  
  8. #undef THIS_FILE  
  9. static char THIS_FILE[] = __FILE__;  
  10. #endif  
  11.   
  12. /////////////////////////////////////////////////////////////////////////////  
  13. // CGradientProgressCtrl  
  14.   
  15. CGradientProgressCtrl::CGradientProgressCtrl()  
  16. {  
  17.     // Defaults assigned by CProgressCtrl()  
  18.     m_nLower = 0;  
  19.     m_nUpper = 100;  
  20.     m_nCurrentPosition = 0;  
  21.     m_nStep = 10;     
  22.   
  23.     // Initial colors  
  24.     m_clrStart  = COLORREF(RGB(255, 0,0));  
  25.     m_clrEnd =   COLORREF(RGB(0,0,255));  
  26.     m_clrBkGround = COLORREF(RGB(0, 0, 0)); //::GetSysColor(COLOR_3DFACE);  
  27.     m_clrText = COLORREF(RGB(255, 255, 255));  
  28.   
  29.     // Initial show percent  
  30.     m_bShowPercent = FALSE;  
  31. }  
  32.   
  33. CGradientProgressCtrl::~CGradientProgressCtrl()  
  34. {  
  35. }  
  36.   
  37.   
  38. BEGIN_MESSAGE_MAP(CGradientProgressCtrl, CProgressCtrl)  
  39.     //{{AFX_MSG_MAP(CGradientProgressCtrl)  
  40.     ON_WM_PAINT()  
  41.     ON_WM_ERASEBKGND()  
  42.     //}}AFX_MSG_MAP  
  43. END_MESSAGE_MAP()  
  44.   
  45. /////////////////////////////////////////////////////////////////////////////  
  46. // CGradientProgressCtrl message handlers  
  47.   
  48. /////////////////////////////////////////////////////////////////////////////  
  49. /*  
  50.     OnPaint 
  51.  
  52.     The main drawing routine.  Consists of two parts 
  53.     (1) Call the DrawGradient routine to draw the visible part of the progress gradient 
  54.     (2) If needed, show the percentage text 
  55.  
  56.  */  
  57. /////////////////////////////////////////////////////////////////////////////  
  58. void CGradientProgressCtrl::OnPaint()   
  59. {  
  60.     CPaintDC dc(this); // device context for painting  
  61.   
  62.     // TODO: Add your message handler code here  
  63.     CRect rectClient;  
  64.     GetClientRect(&rectClient);  
  65.     // If the current positionis  invalid then we should fade into the  background  
  66.     if (m_nCurrentPosition <= m_nLower || m_nCurrentPosition > m_nUpper)  
  67.     {  
  68.         CRect rect;  
  69.         GetClientRect(rect);  
  70.         CBrush brush;  
  71.         brush.CreateSolidBrush(COLORREF(RGB(0, 0, 0)));// ::GetSysColor(COLOR_3DFACE));  
  72.         dc.FillRect(&rect, &brush);  
  73.         VERIFY(brush.DeleteObject());  
  74.         return;  
  75.     }  
  76.       
  77.     // The actions to take depend on whether or not we are a vertical control  
  78.     DWORD dwStyles = GetStyle();  
  79.     BOOL bVertical = (BOOL)(dwStyles & PBS_VERTICAL);  
  80.       
  81.       
  82.     // Figure out what part should be visible so we can stop the gradient when needed  
  83.     float maxWidth;  
  84.     if (bVertical)  
  85.         maxWidth = ((float)m_nCurrentPosition/(float)m_nUpper * (float)rectClient.bottom);        
  86.     else  
  87.         maxWidth = ((float)m_nCurrentPosition/(float)m_nUpper * (float)rectClient.right);  
  88.       
  89.       
  90.     // Draw the gradient  
  91.         DrawGradient(&dc, rectClient, (int)maxWidth, bVertical);  
  92.   
  93.     // Show percent indicator if needed  
  94.     if (m_bShowPercent)  
  95.     {  
  96.         CString strPercent;  
  97.         float fp = 100.0f;   
  98.         fp *= (float)(m_nCurrentPosition-m_nLower);   
  99.         fp /= (float)(m_nUpper-m_nLower);   
  100.         strPercent.Format(_T("%3.0f %%"), fp);  
  101.           
  102.         dc.SetTextColor(m_clrText);  
  103.         dc.SetBkMode(TRANSPARENT);  
  104.         dc.DrawText(strPercent, &rectClient, DT_VCENTER |  DT_CENTER | DT_SINGLELINE);  
  105.     }  
  106.   
  107.     // Do not call CProgressCtrl::OnPaint() for painting messages  
  108. }  
  109.   
  110.   
  111. /////////////////////////////////////////////////////////////////////////////  
  112. /* 
  113.     SetRange 
  114.  
  115.     Overridden base class member to remember where the indicator thinks  
  116.     it is and the boundary range of the control. 
  117.  
  118.     Params 
  119.         nLower      lower bound 
  120.         nUpper      uppoer bound 
  121.  
  122. */  
  123. /////////////////////////////////////////////////////////////////////////////  
  124. void CGradientProgressCtrl:: SetRange(int nLower, int nUpper)  
  125. {  
  126.     m_nLower = nLower;  
  127.     m_nUpper = nUpper;  
  128.     m_nCurrentPosition = nLower;  
  129.     CProgressCtrl::SetRange(nLower, nUpper);  
  130. }  
  131.   
  132. /////////////////////////////////////////////////////////////////////////////  
  133. /* 
  134.     SetRange32 
  135.  
  136.     Overridden base class member to remember where the indicator thinks  
  137.     it is and the boundary range of the control. 
  138.  
  139.     Params 
  140.         nLower      lower bound 
  141.         nUpper      uppoer bound 
  142.  
  143. */  
  144. /////////////////////////////////////////////////////////////////////////////  
  145. void CGradientProgressCtrl:: SetRange32( int nLower, int nUpper )  
  146. {  
  147.     m_nLower = nLower;  
  148.     m_nUpper = nUpper;  
  149.     m_nCurrentPosition = nLower;  
  150.     CProgressCtrl::SetRange(nLower, nUpper);  
  151. }  
  152.   
  153.   
  154. /////////////////////////////////////////////////////////////////////////////  
  155. /* 
  156.     SetPos 
  157.  
  158.     Overridden base class member to retain where the current progress indicator 
  159.     is located. 
  160.  
  161.     Params 
  162.         nPos        Current position in range 
  163.  
  164. */  
  165. /////////////////////////////////////////////////////////////////////////////  
  166. int CGradientProgressCtrl:: SetPos(int nPos)  
  167. {  
  168.     m_nCurrentPosition = nPos;  
  169.     return (CProgressCtrl::SetPos(nPos));  
  170. }  
  171.   
  172. /////////////////////////////////////////////////////////////////////////////  
  173. /* 
  174.     SetStep 
  175.  
  176.     Overridden base class member to retain the step interval used when  
  177.     filling the progress control 
  178.  
  179.     Params 
  180.         nStep       step interval for filling progress control 
  181.  
  182. */  
  183. /////////////////////////////////////////////////////////////////////////////  
  184. int CGradientProgressCtrl:: SetStep(int nStep)  
  185. {  
  186.     m_nStep = nStep;  
  187.     return (CProgressCtrl::SetStep(nStep));  
  188. }  
  189.   
  190. /////////////////////////////////////////////////////////////////////////////  
  191. /* 
  192.     StepIt 
  193.  
  194.     Overridden base class member to increment the control according to the 
  195.     current position and the step interval 
  196.  
  197.     Params 
  198.         nStep       step interval for filling progress control 
  199.  
  200. */  
  201. /////////////////////////////////////////////////////////////////////////////  
  202. int CGradientProgressCtrl:: StepIt(void)  
  203. {  
  204.     m_nCurrentPosition += m_nStep;  
  205.     return (CProgressCtrl::StepIt());  
  206. }  
  207.   
  208.   
  209. /////////////////////////////////////////////////////////////////////////////  
  210. /* 
  211.     DrawGradient 
  212.  
  213.     Called from OnPaint, it does most of the work of filling in the client  
  214.     rectangle with the appropriate colors.  The normal routine would fill 
  215.     the entire client rectangle, but we truncate the drawing to reflect 
  216.     the current position in the progress control 
  217.  
  218.     Params 
  219.         pDC         pointer to CPaintDC for rendering 
  220.         rectClient  client rectangle where we should draw 
  221.         nMaxWidth   where we should stop drawing the gradient 
  222. */  
  223. /////////////////////////////////////////////////////////////////////////////  
  224. void CGradientProgressCtrl::DrawGradient(CPaintDC *pDC, const RECT &rectClient, const int &nMaxWidth, const BOOL &bVertical)  
  225. {  
  226.     RECT rectFill;             // Rectangle for filling band  
  227.     float fStep;              // How wide is each band?  
  228.     CBrush brush;           // Brush to fill in the bar   
  229.   
  230.       
  231.     CMYMemDC memDC(pDC);  
  232.   
  233.     // First find out the largest color distance between the start and end colors.  This distance  
  234.     // will determine how many steps we use to carve up the client region and the size of each  
  235.     // gradient rect.  
  236.     int r, g, b;                    // First distance, then starting value  
  237.     float rStep, gStep, bStep;      // Step size for each color  
  238.           
  239.     BOOL  bSameColor = FALSE;       // Handle case if start color == end color  
  240.   
  241.     // Get the color differences  
  242.     r = (GetRValue(m_clrEnd) - GetRValue(m_clrStart));  
  243.     g = (GetGValue(m_clrEnd) - GetGValue(m_clrStart));  
  244.     b =  (GetBValue(m_clrEnd) - GetBValue(m_clrStart));  
  245.   
  246.     // Check to see if colors are same  
  247.     if((r == 0) && (g == 0) && (b == 0))  
  248.     {  
  249.         bSameColor = TRUE;  
  250.         //Added the three lines below to fix the drawing   
  251.         //problem which used to occur when both the start   
  252.         //and end colors are same.  
  253.         r = GetRValue(m_clrStart);  
  254.         g = GetGValue(m_clrStart);  
  255.         b = GetBValue(m_clrStart);  
  256.     }  
  257.   
  258.     int nSteps;  
  259.     //Select max. possible value for nSteps if the colors are equal  
  260.     if(bSameColor && m_clrStart == 0)  
  261.         nSteps = 255;  
  262.     else    // Make the number of steps equal to the greatest distance  
  263.         nSteps = max(abs(r), max(abs(g), abs(b)));    
  264.       
  265.     // Determine how large each band should be in order to cover the  
  266.     // client with nSteps bands (one for every color intensity level)  
  267.     if (bVertical)  
  268.         fStep = (float)rectClient.bottom / (float)nSteps;     
  269.     else  
  270.         fStep = (float)rectClient.right / (float)nSteps;  
  271.   
  272.     // Calculate the step size for each color  
  273.     rStep = r/(float)nSteps;  
  274.     gStep = g/(float)nSteps;  
  275.     bStep = b/(float)nSteps;//这三个变量都设置为0就不会出现渐变颜色  
  276.   
  277.     // Reset the colors to the starting position  
  278.     r = GetRValue(m_clrStart);  
  279.     g = GetGValue(m_clrStart);  
  280.     b = GetBValue(m_clrStart);  
  281.       
  282.     // Start filling bands  
  283.     for (int iOnBand = 0; iOnBand < nSteps; iOnBand++)   
  284.     {  
  285.         // Fill the vertical control  
  286.         if (bVertical)  
  287.         {  
  288.             ::SetRect(&rectFill,  
  289.                         0,                          // Upper left X  
  290.                         (int)(iOnBand * fStep),     // Upper left Y  
  291.                         rectClient.right+1,     // Lower right X  
  292.                         (int)((iOnBand+1) * fStep));// Lower right Y  
  293.           
  294.             // CDC::FillSolidRect is faster, but it does not handle 8-bit color depth  
  295.             VERIFY(brush.CreateSolidBrush(RGB(r+rStep*iOnBand, g + gStep*iOnBand, b + bStep *iOnBand)));  
  296.             memDC.FillRect(&rectFill,&brush);  
  297.             VERIFY(brush.DeleteObject());  
  298.   
  299.   
  300.             // If we are past the maximum for the current position we need to get out of the loop.  
  301.             // Before we leave, we repaint the remainder of the client area with the background color.  
  302.             if (rectFill.bottom > nMaxWidth)  
  303.             {  
  304.                 ::SetRect(&rectFill, 0, rectFill.bottom, rectClient.right, rectClient.bottom);  
  305.                 VERIFY(brush.CreateSolidBrush(m_clrBkGround));  
  306.                 memDC.FillRect(&rectFill, &brush);  
  307.                 VERIFY(brush.DeleteObject());  
  308.                 return;  
  309.             }  
  310.         }  
  311.   
  312.         else // Fill the horizontal control  
  313.         {  
  314.             ::SetRect(&rectFill,  
  315.                         (int)(iOnBand * fStep),     // Upper left X  
  316.                          0,                         // Upper left Y  
  317.                         (int)((iOnBand+1) * fStep), // Lower right X  
  318.                         rectClient.bottom+1);       // Lower right Y  
  319.           
  320.             // CDC::FillSolidRect is faster, but it does not handle 8-bit color depth  
  321.             VERIFY(brush.CreateSolidBrush(RGB(r+rStep*iOnBand, g + gStep*iOnBand, b + bStep *iOnBand)));  
  322.             memDC.FillRect(&rectFill,&brush);  
  323.             VERIFY(brush.DeleteObject());  
  324.   
  325.   
  326.             // If we are past the maximum for the current position we need to get out of the loop.  
  327.             // Before we leave, we repaint the remainder of the client area with the background color.  
  328.             if (rectFill.right > nMaxWidth)  
  329.             {  
  330.                 ::SetRect(&rectFill, rectFill.right, 0, rectClient.right, rectClient.bottom);  
  331.                 VERIFY(brush.CreateSolidBrush(m_clrBkGround));  
  332.                 memDC.FillRect(&rectFill, &brush);  
  333.                 VERIFY(brush.DeleteObject());  
  334.                 return;  
  335.             }  
  336.         }  
  337.   
  338.     }  
  339. }  
  340.   
  341.   
  342.   
  343. /////////////////////////////////////////////////////////////////////////////  
  344. /* 
  345.     OnEraseBkgnd 
  346.  
  347.     Overridden CWnd function so that all drawing is done in the OnPaint call. 
  348.     We return TRUE so that CWnd doesn't try to erase our background. 
  349.  
  350.     Params 
  351.         pDC         pointer to CDC for rendering 
  352. */  
  353. /////////////////////////////////////////////////////////////////////////////  
  354. BOOL CGradientProgressCtrl::OnEraseBkgnd(CDC* pDC)   
  355. {  
  356.     // TODO: Add your message handler code here and/or call default  
  357.     return TRUE;  
  358. }  


6、其中MemDC.h

[cpp] view plain copy
  1. #if !defined(AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_)  
  2. #define AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_  
  3.   
  4. #if _MSC_VER >= 1000  
  5. #pragma once  
  6. #endif // _MSC_VER >= 1000  
  7. // MemDC.h : header file  
  8. //  
  9.   
  10. //////////////////////////////////////////////////  
  11. // CMemDC - memory DC  
  12. //  
  13. // Author: Keith Rule  
  14. // Email:  keithr@europa.com  
  15. // Copyright 1996-1997, Keith Rule  
  16. //  
  17. // You may freely use or modify this code provided this  
  18. // Copyright is included in all derived versions.  
  19. //  
  20. // History - 10/3/97 Fixed scrolling bug.  
  21. //                   Added print support.  
  22. //           25 feb 98 - fixed minor assertion bug  
  23. //  
  24. // This class implements a memory Device Context  
  25.   
  26. class CMYMemDC : public CDC  
  27. {  
  28. public:  
  29.       
  30.     // constructor sets up the memory DC  
  31.     CMYMemDC(CDC* pDC) : CDC()  
  32.     {  
  33.         ASSERT(pDC != NULL);  
  34.           
  35.         m_pDC = pDC;  
  36.         m_pOldBitmap = NULL;  
  37.         m_bMemDC = !pDC->IsPrinting();  
  38.           
  39.         if (m_bMemDC)   // Create a Memory DC  
  40.         {  
  41.             pDC->GetClipBox(&m_rect);  
  42.             CreateCompatibleDC(pDC);  
  43.             m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());  
  44.             m_pOldBitmap = SelectObject(&m_bitmap);  
  45.             SetWindowOrg(m_rect.left, m_rect.top);  
  46.         }  
  47.         else        // Make a copy of the relevent parts of the current DC for printing  
  48.         {  
  49.             m_bPrinting = pDC->m_bPrinting;  
  50.             m_hDC       = pDC->m_hDC;  
  51.             m_hAttribDC = pDC->m_hAttribDC;  
  52.         }  
  53.     }  
  54.       
  55.     // Destructor copies the contents of the mem DC to the original DC  
  56.     ~CMYMemDC()  
  57.     {  
  58.         if (m_bMemDC) {   
  59.             // Copy the offscreen bitmap onto the screen.  
  60.             m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),  
  61.                 this, m_rect.left, m_rect.top, SRCCOPY);  
  62.               
  63.             //Swap back the original bitmap.  
  64.             SelectObject(m_pOldBitmap);  
  65.         } else {  
  66.             // All we need to do is replace the DC with an illegal value,  
  67.             // this keeps us from accidently deleting the handles associated with  
  68.             // the CDC that was passed to the constructor.  
  69.             m_hDC = m_hAttribDC = NULL;  
  70.         }  
  71.     }  
  72.       
  73.     // Allow usage as a pointer  
  74.     CMYMemDC* operator->() {return this;}  
  75.       
  76.     // Allow usage as a pointer  
  77.     operator CMYMemDC*() {return this;}  
  78.   
  79. private:  
  80.     CBitmap  m_bitmap;      // Offscreen bitmap  
  81.     CBitmap* m_pOldBitmap;  // bitmap originally found in CMYMemDC  
  82.     CDC*     m_pDC;         // Saves CDC passed in constructor  
  83.     CRect    m_rect;        // Rectangle of drawing area.  
  84.     BOOL     m_bMemDC;      // TRUE if CDC really is a Memory DC.  
  85. };  
  86.   
  87. /////////////////////////////////////////////////////////////////////////////  
  88.   
  89. //{{AFX_INSERT_LOCATION}}  
  90. // Microsoft Developer Studio will insert additional declarations immediately before the previous line.  
  91.   
  92. #endif // !defined(AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_)