我要用一个进度条,其进度的颜色在不同位置颜色不同,比如,前1/3为蓝色,中间1/3为紫色,后1/3为红色。请问应该怎样设置。

解决方案 »

  1.   

    从CProgressCtrl派生一个类,重载OnPaint,自己画
      

  2.   

    http://www.codeproject.com/miscctrl/gradientprogressctrl.asp
      

  3.   

    自己派生一个Cprogressctrl类,自己判断当前进度画
      

  4.   

    重载WM_CTRLCOLOR消息,然后根据当前进度来选不同画刷
      

  5.   

    借别人的#if !defined(AFX_ENHPROGRESSCTRL_H__12909D73_C393_11D1_9FAE_8192554015AD__INCLUDED_)
    #define AFX_ENHPROGRESSCTRL_H__12909D73_C393_11D1_9FAE_8192554015AD__INCLUDED_#if _MSC_VER >= 1000
    #pragma once
    #endif // _MSC_VER >= 1000
    // EnhProgressCtrl.h : header file/*
    Modified by 徐景周 2000.12
    功能:渐变色进度条显示效果
    */
    //
    #include "MemDC.h"/////////////////////////////////////////////////////////////////////////////
    // CGradientProgressCtrl windowclass CGradientProgressCtrl : public CProgressCtrl
    {
    // Construction
    public:
    CGradientProgressCtrl();// Attributes
    public:
    // Attributes

    void SetRange(int nLower, int nUpper);
    void SetRange32( int nLower, int nUpper );
    int SetPos(int nPos);
    int SetStep(int nStep);
    int StepIt(void);// Operations
    public:

    // Set Functions
    void SetTextColor(COLORREF color) {m_clrText = color;}
    void SetBkColor(COLORREF color)  {m_clrBkGround = color;}
    void SetStartColor(COLORREF color) {m_clrStart = color;}
    void SetEndColor(COLORREF color) {m_clrEnd = color;} // Show the percent caption
    void ShowPercent(BOOL bShowPercent = TRUE) {m_bShowPercent = bShowPercent;}

    // Get Functions
    COLORREF GetTextColor(void) {return m_clrText;}
    COLORREF GetBkColor(void)  {return m_clrBkGround;}
    COLORREF GetStartColor(void) {return m_clrStart;}
    COLORREF GetEndColor(void) {return m_clrEnd;}
    // Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CGradientProgressCtrl)
    protected:
    //}}AFX_VIRTUAL// Implementation
    public:
    virtual ~CGradientProgressCtrl(); // Generated message map functions
    protected:
    void DrawGradient(CPaintDC *pDC, const RECT &rectClient, const int &nMaxWidth, const BOOL &bVertical);
    int m_nLower, m_nUpper, m_nStep, m_nCurrentPosition;
    COLORREF m_clrStart, m_clrEnd, m_clrBkGround, m_clrText;
    BOOL m_bShowPercent;
    //{{AFX_MSG(CGradientProgressCtrl)
    afx_msg void OnPaint();
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    //}}AFX_MSG DECLARE_MESSAGE_MAP()
    };///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}}
    // Microsoft Developer Studio will insert additional declarations immediately before the previous line.#endif // !defined(AFX_ENHPROGRESSCTRL_H__12909D73_C393_11D1_9FAE_8192554015AD__INCLUDED_)
      

  6.   

    #include "stdafx.h"
    #include "GradientProgressCtrl.h"#ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif/*
    Modified by 徐景周 2000.12
    功能:渐变色进度条显示效果
    *//////////////////////////////////////////////////////////////////////////////
    // CGradientProgressCtrlCGradientProgressCtrl::CGradientProgressCtrl()
    {
    // Defaults assigned by CProgressCtrl()
    m_nLower = 0;
    m_nUpper = 100;
    m_nCurrentPosition = 0;
    m_nStep = 10;

    // Initial colors
    m_clrStart = COLORREF(RGB(255, 0,0));
    m_clrEnd =  COLORREF(RGB(0,0,255));
    //改变渐变色进度条背景色
    m_clrBkGround = ::GetSysColor(COLOR_3DFACE);
    m_clrText = COLORREF(RGB(255, 255, 255)); // Initial show percent
    m_bShowPercent = true;
    }CGradientProgressCtrl::~CGradientProgressCtrl()
    {
    }
    BEGIN_MESSAGE_MAP(CGradientProgressCtrl, CProgressCtrl)
    //{{AFX_MSG_MAP(CGradientProgressCtrl)
    ON_WM_PAINT()
    ON_WM_ERASEBKGND()
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
    // CGradientProgressCtrl message handlers/////////////////////////////////////////////////////////////////////////////
    /* 
    OnPaint The main drawing routine.  Consists of two parts
    (1) Call the DrawGradient routine to draw the visible part of the progress gradient
    (2) If needed, show the percentage text */
    /////////////////////////////////////////////////////////////////////////////
    void CGradientProgressCtrl::OnPaint() 
    {
    CPaintDC dc(this); // device context for painting // TODO: Add your message handler code here
    CRect rectClient;
    GetClientRect(&rectClient);
    // If the current positionis  invalid then we should fade into the  background
    if (m_nCurrentPosition <= m_nLower || m_nCurrentPosition > m_nUpper)
    {
    CRect rect;
    GetClientRect(rect);
    CBrush brush;
    //重画时渐变色进度条设为自定义颜色
    brush.CreateSolidBrush(m_clrBkGround);//::GetSysColor(COLOR_3DFACE));
    dc.FillRect(&rect, &brush);
    VERIFY(brush.DeleteObject());
    return;
    }

    // The actions to take depend on whether or not we are a vertical control
    DWORD dwStyles = GetStyle();
    BOOL bVertical = (BOOL)(dwStyles & PBS_VERTICAL);


    // Figure out what part should be visible so we can stop the gradient when needed
    float maxWidth;
    if (bVertical)
    maxWidth = ((float)m_nCurrentPosition/(float)m_nUpper * (float)rectClient.bottom);
    else
    maxWidth = ((float)m_nCurrentPosition/(float)m_nUpper * (float)rectClient.right);


    // Draw the gradient
    DrawGradient(&dc, rectClient, (int)maxWidth, bVertical); // Show percent indicator if needed
    if (m_bShowPercent)
    {
    CString strPercent;
    float fp = 100.0f; 
    fp *= (float)(m_nCurrentPosition-m_nLower); 
    fp /= (float)(m_nUpper-m_nLower); 
    strPercent.Format(_T("%3.0f %%"), fp);

    dc.SetTextColor(m_clrText);
    dc.SetBkMode(TRANSPARENT);
    dc.DrawText(strPercent, &rectClient, DT_VCENTER |  DT_CENTER | DT_SINGLELINE);
    } // Do not call CProgressCtrl::OnPaint() for painting messages
    }
    /////////////////////////////////////////////////////////////////////////////
    /*
    SetRange Overridden base class member to remember where the indicator thinks 
    it is and the boundary range of the control. Params
    nLower lower bound
    nUpper uppoer bound*/
    /////////////////////////////////////////////////////////////////////////////
    void CGradientProgressCtrl:: SetRange(int nLower, int nUpper)
    {
    m_nLower = nLower;
    m_nUpper = nUpper;
    m_nCurrentPosition = nLower;
    CProgressCtrl::SetRange(nLower, nUpper);
    }/////////////////////////////////////////////////////////////////////////////
    /* SetRange32 Overridden base class member to remember where the indicator thinks 
    it is and the boundary range of the control. Params
    nLower lower bound
    nUpper uppoer bound*/
    /////////////////////////////////////////////////////////////////////////////
    void CGradientProgressCtrl:: SetRange32( int nLower, int nUpper )
    {
    m_nLower = nLower;
    m_nUpper = nUpper;
    m_nCurrentPosition = nLower;
    CProgressCtrl::SetRange(nLower, nUpper);
    }
    /////////////////////////////////////////////////////////////////////////////
    /*
    SetPos Overridden base class member to retain where the current progress indicator
    is located. Params
    nPos Current position in range*/
    /////////////////////////////////////////////////////////////////////////////
    int CGradientProgressCtrl:: SetPos(int nPos)
    {
    m_nCurrentPosition = nPos;
    return (CProgressCtrl::SetPos(nPos));
    }
      

  7.   

    /////////////////////////////////////////////////////////////////////////////
    /*
    SetStep Overridden base class member to retain the step interval used when 
    filling the progress control Params
    nStep step interval for filling progress control*/
    /////////////////////////////////////////////////////////////////////////////
    int CGradientProgressCtrl:: SetStep(int nStep)
    {
    m_nStep = nStep;
    return (CProgressCtrl::SetStep(nStep));
    }/////////////////////////////////////////////////////////////////////////////
    /*
    StepIt Overridden base class member to increment the control according to the
    current position and the step interval Params
    nStep step interval for filling progress control*/
    /////////////////////////////////////////////////////////////////////////////
    int CGradientProgressCtrl:: StepIt(void)
    {
    m_nCurrentPosition += m_nStep;
    return (CProgressCtrl::StepIt());
    }
    /////////////////////////////////////////////////////////////////////////////
    /*
    DrawGradient Called from OnPaint, it does most of the work of filling in the client 
    rectangle with the appropriate colors.  The normal routine would fill
    the entire client rectangle, but we truncate the drawing to reflect
    the current position in the progress control Params
    pDC pointer to CPaintDC for rendering
    rectClient client rectangle where we should draw
    nMaxWidth where we should stop drawing the gradient
    */
    /////////////////////////////////////////////////////////////////////////////
    void CGradientProgressCtrl::DrawGradient(CPaintDC *pDC, const RECT &rectClient, const int &nMaxWidth, const BOOL &bVertical)
    {
    RECT rectFill;    // Rectangle for filling band
    float fStep;              // How wide is each band?
    CBrush brush; // Brush to fill in the bar
    CMemDC1 memDC(pDC); // First find out the largest color distance between the start and end colors.  This distance
    // will determine how many steps we use to carve up the client region and the size of each
    // gradient rect.
    int r, g, b; // First distance, then starting value
    float rStep, gStep, bStep; // Step size for each color

    BOOL  bSameColor = FALSE; // Handle case if start color == end color // Get the color differences
    r = (GetRValue(m_clrEnd) - GetRValue(m_clrStart));
    g = (GetGValue(m_clrEnd) - GetGValue(m_clrStart));
    b =  (GetBValue(m_clrEnd) - GetBValue(m_clrStart)); // Check to see if colors are same
    if((r == 0) && (g == 0) && (b == 0))
    {
    bSameColor = TRUE;
    //Added the three lines below to fix the drawing 
    //problem which used to occur when both the start 
    //and end colors are same.
    r = GetRValue(m_clrStart);
    g = GetGValue(m_clrStart);
    b = GetBValue(m_clrStart);
    } int nSteps;
    //Select max. possible value for nSteps if the colors are equal
    if(bSameColor && m_clrStart == 0)
    nSteps = 255;
    else  // Make the number of steps equal to the greatest distance
    nSteps = max(abs(r), max(abs(g), abs(b)));

    // Determine how large each band should be in order to cover the
    // client with nSteps bands (one for every color intensity level)
    if (bVertical)
    fStep = (float)rectClient.bottom / (float)nSteps;
    else
    fStep = (float)rectClient.right / (float)nSteps; // Calculate the step size for each color
    rStep = r/(float)nSteps;
    gStep = g/(float)nSteps;
    bStep = b/(float)nSteps; // Reset the colors to the starting position
    r = GetRValue(m_clrStart);
    g = GetGValue(m_clrStart);
    b = GetBValue(m_clrStart);

    // Start filling bands
    for (int iOnBand = 0; iOnBand < nSteps; iOnBand++) 
    {
    // Fill the vertical control
    if (bVertical)
    {
    ::SetRect(&rectFill,
    0, // Upper left X
    (int)(iOnBand * fStep), // Upper left Y
    rectClient.right+1, // Lower right X
    (int)((iOnBand+1) * fStep));// Lower right Y

    // CDC::FillSolidRect is faster, but it does not handle 8-bit color depth
    VERIFY(brush.CreateSolidBrush(RGB(r+rStep*iOnBand, g + gStep*iOnBand, b + bStep *iOnBand)));
    memDC.FillRect(&rectFill,&brush);
    VERIFY(brush.DeleteObject());
    // If we are past the maximum for the current position we need to get out of the loop.
    // Before we leave, we repaint the remainder of the client area with the background color.
    if (rectFill.bottom > nMaxWidth)
    {
    ::SetRect(&rectFill, 0, rectFill.bottom, rectClient.right, rectClient.bottom);
    VERIFY(brush.CreateSolidBrush(m_clrBkGround));
    memDC.FillRect(&rectFill, &brush);
    VERIFY(brush.DeleteObject());
    return;
    }
    } else // Fill the horizontal control
    {
    ::SetRect(&rectFill,
    (int)(iOnBand * fStep),     // Upper left X
     0, // Upper left Y
    (int)((iOnBand+1) * fStep), // Lower right X
    rectClient.bottom+1); // Lower right Y

    // CDC::FillSolidRect is faster, but it does not handle 8-bit color depth
    VERIFY(brush.CreateSolidBrush(RGB(r+rStep*iOnBand, g + gStep*iOnBand, b + bStep *iOnBand)));
    memDC.FillRect(&rectFill,&brush);
    VERIFY(brush.DeleteObject());
    // If we are past the maximum for the current position we need to get out of the loop.
    // Before we leave, we repaint the remainder of the client area with the background color.
    if (rectFill.right > nMaxWidth)
    {
    ::SetRect(&rectFill, rectFill.right, 0, rectClient.right, rectClient.bottom);
    VERIFY(brush.CreateSolidBrush(m_clrBkGround));
    memDC.FillRect(&rectFill, &brush);
    VERIFY(brush.DeleteObject());
    return;
    }
    } }
    }/////////////////////////////////////////////////////////////////////////////
    /*
    OnEraseBkgnd Overridden CWnd function so that all drawing is done in the OnPaint call.
    We return TRUE so that CWnd doesn't try to erase our background. Params
    pDC pointer to CDC for rendering
    */
    /////////////////////////////////////////////////////////////////////////////
    BOOL CGradientProgressCtrl::OnEraseBkgnd(CDC* pDC) 
    {
    // TODO: Add your message handler code here and/or call default
    return TRUE;
    }