实例081 渐变颜色的进度条(MFC对话框)

本文仅供学习交流,严禁用于商业用途,如本文涉及侵权请及时联系本人将于及时删除

目录

1.实例内容

2.技术要点

3.实现过程

4.实例结果

5.示例拓展

1.实例内容

       在使用进度条时,除了用文字显示进度以外,也可以通过渐变色来显示。本实例实现了一个渐变颜色的进度条(一个原进度条做对比),实例运行结果如图所示。

2.技术要点

CProgressCtrl类控件

       进度条(Progress Bar)是一个向用户显示较长操作过程进度的控件,它由一个矩形窗口组成,随着操作的进行而逐渐被填充。

2.1进展条的风格

       打开进展条的属性对话框,如图所示,可以看到它的风格属性并不是很多。其中,“边框”(Border)用来指定进展条是否有边框,“垂直”(Vertical)用来指定进展条是水平还是垂直的,不选中该属性,表示进展条从左到右水平显示。“平滑”(Smooth)表示平滑地填充进展条,若不选中则表示将用块来填充

2.2进展条的基本操作

(1) 设置进度条的范围

SetRange():用来设置进度条的范围。其函数原型为:

void SetRange(int nLower,int nUpper);
其中,参数nLow和nUpper分别指定了进度条范围的最小和最大值。

(2) 设置进度条的当前进度

SetPos():用来设置进度条的当前进度。其函数原型为:

int SetPos(int nPos);    
函数的返回值为进度条的前一个进度。

(3) 使进度条增加一个步长

StepIt():使进度增加一个步长。其函数原型为:

int StepIt();
其中,步长值是由SetStep函数设置的,缺省的步长值是10。函数的返回值为进度条的前一个进度。

(4) 设置进度条的步长值。

SetStep():用来设置进度条的步长值。其函数原型为:

int SetStep(int nStep);
其中,参数nStep为要设置的新步长值。函数的返回值为原来的步长值。

(5) 使进度条前进给定值。

OffsetPos():使进度条前进给定值。其函数原型为:

int OffsetPos(int nStep);
其中,参数nStep为前进的步长值。

2.3进度条渐变

     在进度条控件中显示渐变色比较简单,只需要在进度条控件的OnPaint方法中使用循环控制颜色,然后使用FillRect填充区域就可以了。FillRect方法用指定的画刷填充区域,语法如下:

void FillRect(LPCRECT lpRect,CBrush* pBrush);
参数说明:

● lpRect:指向RECT结构的指针,包含被填充的矩形的逻辑坐标,可以为该参数传递CRect对象。

● pBrush:标识填充矩形的画刷。

3.实现过程

(1)新建一个基于对话框的应用程序。

(2)从CProgressCtrl类派生一个子类CColorProgress。(在项目文件头文件处右击菜单添加类)

(3)向对话框中添加一个进度条控件,设置控件的Border和Smooth属性,关联变量m_Progress,其类型为CColorProgress。(注意在dlg.cpp文件中引用相应头文件#include "ColorProgress.h")一个新进度条控件,设置控件的Border和Smooth属性,关联变量m_ProgressOriginal,其类型为CProgressCtrl。

(4)处理进度条的WM_PAINT消息,在其消息处理函数中绘制进度条的文本和当前进度。代码如下:

void CColorProgress::OnPaint()
{
	// CPaintDC dc(this); // device context for painting
	// TODO:  在此处添加消息处理程序代码
	// 不为绘图消息调用 CProgressCtrl::OnPaint()

	PAINTSTRUCT ps;
	CDC*pDC = BeginPaint(&ps);                                //开始绘制
	int nPos = GetPos();                                       //获取当前进度条的位置
	CRect clientRC;
	GetClientRect(clientRC);                                //获取客户区域
	pDC->SetBkMode(TRANSPARENT);                            //将设备上下文的背景模式设置为透明
	int nMin, nMax;
	GetRange(nMin, nMax);                                    //获取进度条的显示范围
	//获取单位刻度
	double dFraction = (double)clientRC.Width() / (nMax - nMin);
	int nLeft = nPos*dFraction;                                //计算左边距
	CRect leftRC = clientRC;
	leftRC.right = nLeft;
	CRect rightRC = clientRC;
	rightRC.left = nLeft;
	//以渐变色填充区域
	for (int m = 255; m>0; m--)
	{
		int x, y;
		x = leftRC.Width() * m / 255;
		pDC->FillRect(CRect(0, 0, x, leftRC.Height()), &CBrush(RGB(255, m, 0)));
	}
	pDC->FillRect(rightRC, &CBrush(RGB(255, 255, 255)));         //使用白色标识剩余的部分
	ReleaseDC(pDC);                                           //释放设备上下文
	EndPaint(&ps);                                            //结束窗口绘制
}

(5)处理主窗口的WM_TIMER消息,在该消息的处理函数中设置进度条的显示进度。代码如下:

void CMFC_进度条Dlg::OnTimer(UINT_PTR nIDEvent)
{
	// TODO:  在此添加消息处理程序代码和/或调用默认值
                       //设置进度条的位置
	
	if(nIDEvent==1)
	{
	 int nCurPos = m_Progress.GetPos();             //获取进度条的当前位置
	 m_Progress.SetPos(nCurPos + 1);    
	 if(m_progress.GetPos()>=100)
		{
			KillTimer(1);
			MessageBox("进程完毕");
		}
	}
	
	if (nIDEvent == 2)
	{
		int nCurPos1 = m_ProgressOriginal.GetPos();          //获取进度条的当前位置
	    m_ProgressOriginal.SetPos(nCurPos1 + 1);             //设置进度条的位置
		if (m_p.GetPos() >= 100)
		{
			KillTimer(2);
			MessageBox("进程完毕");
		}
	}

	CDialog::OnTimer(nIDEvent);

	//CDialogEx::OnTimer(nIDEvent);

}

(6)在CMFC_进度条Dlg::OnInitDialog()中添加相应的初始化代码,代码如下:

BOOL CMFC_进度条Dlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO:  在此添加额外的初始化代码
	m_Progress.SetRange(0, 100);		// 设置进展条范围
	//m_Progress.SetStep(5);
	m_Progress.SetPos(0);

	m_ProgressOriginal.SetRange(0, 100);
	//m_ProgressOriginal.SetStep(5);
	m_ProgressOriginal.SetPos(0);

	SetTimer(1, 1000, NULL);
    SetTimer(2, 1000, NULL);

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

4.实例结果

5.示例拓展

根据本实例,读者可以:自绘进度条控件。

6.自定义控件类参考

/
//
// SuperProgressCtrl.h
// Interface file of the CSuperProgressCtrl class
//
//	Modified:
//		01-30-02	JWhite
//					Added the ability to get the dimensions of the bitmap.
//
/

#ifndef __SUPERPROGRESSCTRL_H__
#define __SUPERPROGRESSCTRL_H__

/
// CSuperProgressCtrl window
/

#define SP_FILL_VERT		(1)		// Vertical solid fill
#define SP_FILL_HORZ		(2)		// Horizontal solid fill
#define SP_FILL_VERTGRAD	(3)		// Vertical gradient fill
#define SP_FILL_HORZGRAD	(4)		// Horizontal gradient fill

#define ALLOC_UNIT	100


class CSuperProgressCtrl : public CWnd
{
	// Construction
	public:
		CSuperProgressCtrl();

	// Static members
	public:
		static void	RegisterClass();
	protected:
		static		CString s_Class; 

	// Attributes
	public:
		BOOL		Create( CWnd* pParent, int x, int y, HBITMAP hbmArea, UINT nID );

	// Operations
	public:
		COLORREF	GetBackColour() const;								// Gets the current background colour.
		int			GetFillStyle() const;								// Gets the current fill style.
		int			GetHeight() { return m_nHeight; }					// Returns the height of the bitmap.
		int			GetWidth() { return m_nWidth; }						// Returns the width of the bitmap.
		int			OffsetPos( int nOffset );							// Offsets the current position of the progress control.
		COLORREF	SetBackColour( COLORREF Colour );					// Sets the background colour.
		void		SetColours( COLORREF Colour1, COLORREF Colour2 );	// Sets the current colours.
		int			SetFillStyle( int nStyle );							// Sets the fill style.
		int			SetPos( int nPos );									// Sets the current position of the progress control.
		void		SetRange( int nMin, int nMax );						// Sets the range of the progress control.
		int			SetStep( int nStep );								// Sets the step count of the progress control.
		int			StepIt();											// Steps the progress control.

		// Gets the current colours.
		// If Colour1 or Colour2 are NULL, the corresponding colour is not returned
		void		GetColours( COLORREF* Colour1, COLORREF* Colour2 ) const;

		// Performs an MFC-compatible message loop, returns FALSE if a WM_QUIT is received
		BOOL		MessageLoop() const;

	// Overrides
		// ClassWizard generated virtual function overrides
		//{{AFX_VIRTUAL( CSuperProgressCtrl )
		//}}AFX_VIRTUAL

	// Implementation
	public:
		virtual		~CSuperProgressCtrl();

	// Data Members
	protected:
		long		m_lMin;												// Minimum range
		long		m_lMax;												// Maximum range
		int			m_nStep;											// Step size
		int			m_nPosition;										// The current position
		COLORREF	m_Colour1;											// First colour of gradient
		COLORREF	m_Colour2;											// Second colour of gradient
		COLORREF	m_Background;										// Background colour
		HBITMAP		m_hbmArea;											// The window area bitmap
		HRGN		m_hRegion;											// The window region
		int			m_nFillStyle;										// What style is used for filling?
		int			m_nHeight;											// The height of the current bitmap.
		int			m_nWidth;											// The width of the current bitmap.

		// Generated message map functions
	protected:
		//{{AFX_MSG(CSuperProgressCtrl)
		afx_msg void OnPaint();
		//}}AFX_MSG
		DECLARE_MESSAGE_MAP()
};

/

#endif	// __SUPERPROGRESSCTRL_H__
/
// SuperProgressCtrl.cpp
// Implementation file of the CSuperProgressCtrlCtrl class
/

#include "stdafx.h"
#include "SuperProgressCtrl.h"

/
//
// CSuperProgressCtrl implementation
//
/

/
//
// Converts a bitmap to a region
//
//	BitmapToRegion :	Create a region from the "non-transparent" pixels of a bitmap
//	Author :			Jean-Edouard Lachand-Robert (http://www.geocities.com/Paris/LeftBank/1160/resume.htm), June 1998.
//
//	hBmp :				Source bitmap
//	cTransparentColor :	Color base for the "transparent" pixels (default is black)
//	cTolerance :		Color tolerance for the "transparent" pixels.
//
//	A pixel is assumed to be transparent if the value of each of its 3 components (blue, green and red) is 
//	greater or equal to the corresponding value in cTransparentColor and is lower or equal to the 
//	corresponding value in cTransparentColor + cTolerance.
//
/
static HRGN BitmapToRegion( HBITMAP hBmp, COLORREF cTransparentColor = 0, COLORREF cTolerance = 0x101010 )
{
	HRGN	hRgn	= NULL;
	VOID*	pbits32	= NULL; 
	HBITMAP	hbm32	= NULL;
	HDC		hMemDC	= NULL;

	if( hBmp )
	{
		// Create a memory DC inside which we will scan the bitmap content
		hMemDC = CreateCompatibleDC(NULL);
		if(hMemDC)
		{
			// Get bitmap size
			BITMAP bm;
			GetObject(hBmp, sizeof(bm), &bm);

			// Create a 32 bits depth bitmap and select it into the memory DC 
			BITMAPINFOHEADER RGB32BITSBITMAPINFO = {sizeof(BITMAPINFOHEADER),	// biSize 
													bm.bmWidth,					// biWidth; 
													bm.bmHeight,				// biHeight; 
													1,							// biPlanes; 
													32,							// biBitCount 
													BI_RGB,						// biCompression; 
													0,							// biSizeImage; 
													0,							// biXPelsPerMeter; 
													0,							// biYPelsPerMeter; 
													0,							// biClrUsed; 
													0							// biClrImportant; 
												};

			hbm32 = CreateDIBSection(hMemDC, (BITMAPINFO *)&RGB32BITSBITMAPINFO, DIB_RGB_COLORS, &pbits32, NULL, 0);
			if(hbm32)
			{
				HBITMAP holdBmp = (HBITMAP)SelectObject(hMemDC, hbm32);

				// Create a DC just to copy the bitmap into the memory DC
				HDC hDC = CreateCompatibleDC(hMemDC);
				if(hDC)
				{
					// Get how many bytes per row we have for the bitmap bits (rounded up to 32 bits)
					BITMAP bm32;
					GetObject(hbm32, sizeof(bm32), &bm32);
					while(bm32.bmWidthBytes % 4)
						bm32.bmWidthBytes++;

					// Copy the bitmap into the memory DC
					HBITMAP holdBmp = (HBITMAP)SelectObject(hDC, hBmp);
					BitBlt(hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, hDC, 0, 0, SRCCOPY);

					// For better performances, we will use the ExtCreateRegion() function to create the
					// region. This function take a RGNDATA structure on entry. We will add rectangles by
					// amount of ALLOC_UNIT number in this structure.
					DWORD maxRects = ALLOC_UNIT;
					HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects));
					RGNDATA *pData = (RGNDATA *)GlobalLock(hData);
					pData->rdh.dwSize = sizeof(RGNDATAHEADER);
					pData->rdh.iType = RDH_RECTANGLES;
					pData->rdh.nCount = pData->rdh.nRgnSize = 0;
					SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);

					// Keep on hand highest and lowest values for the "transparent" pixels
					BYTE lr = GetRValue(cTransparentColor);
					BYTE lg = GetGValue(cTransparentColor);
					BYTE lb = GetBValue(cTransparentColor);
					BYTE hr = min(0xff, lr + GetRValue(cTolerance));
					BYTE hg = min(0xff, lg + GetGValue(cTolerance));
					BYTE hb = min(0xff, lb + GetBValue(cTolerance));

					// Scan each bitmap row from bottom to top (the bitmap is inverted vertically)
					BYTE *p32 = (BYTE *)bm32.bmBits + (bm32.bmHeight - 1) * bm32.bmWidthBytes;
					for(int y = 0; y < bm.bmHeight; y++)
					{
						// Scan each bitmap pixel from left to right
						for(int x = 0; x < bm.bmWidth; x++)
						{
							// Search for a continuous range of "non transparent pixels"
							int x0 = x;
							LONG *p = (LONG *)p32 + x;
							while(x < bm.bmWidth)
							{
								BYTE b = GetRValue(*p);
								if(b >= lr && b <= hr)
								{
									b = GetGValue(*p);
									if(b >= lg && b <= hg)
									{
										b = GetBValue(*p);
										if(b >= lb && b <= hb)
											// This pixel is "transparent"
											break;
									}
								}
								p++;
								x++;
							}

							if(x > x0)
							{
								// Add the pixels (x0, y) to (x, y+1) as a new rectangle in the region
								if(pData->rdh.nCount >= maxRects)
								{
									GlobalUnlock(hData);
									maxRects += ALLOC_UNIT;
									hData = GlobalReAlloc(hData, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), GMEM_MOVEABLE);
									pData = (RGNDATA *)GlobalLock(hData);
								}
								RECT *pr = (RECT *)&pData->Buffer;
								SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1);
								if(x0 < pData->rdh.rcBound.left)
									pData->rdh.rcBound.left = x0;
								if(y < pData->rdh.rcBound.top)
									pData->rdh.rcBound.top = y;
								if(x > pData->rdh.rcBound.right)
									pData->rdh.rcBound.right = x;
								if(y+1 > pData->rdh.rcBound.bottom)
									pData->rdh.rcBound.bottom = y+1;
								pData->rdh.nCount++;

								// On Windows98, ExtCreateRegion() may fail if the number of rectangles is too
								// large (ie: > 4000). Therefore, we have to create the region by multiple steps.
								if(pData->rdh.nCount == 2000)
								{
									HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
									if(hRgn)
									{
										CombineRgn(hRgn, hRgn, h, RGN_OR);
										DeleteObject(h);
									}
									else
										hRgn = h;
									pData->rdh.nCount = 0;
									SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
								}
							}
						}

						// Go to next row (remember, the bitmap is inverted vertically)
						p32 -= bm32.bmWidthBytes;
					}

					// Create or extend the region with the remaining rectangles
					HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
					if(hRgn)
					{
						CombineRgn(hRgn, hRgn, h, RGN_OR);
						DeleteObject(h);
					}
					else
						hRgn = h;

					// Clean up
					GlobalUnlock( hData );
					GlobalFree( hData );
					SelectObject( hDC, holdBmp );
					DeleteDC( hDC );
				}

				DeleteObject(SelectObject(hMemDC, holdBmp));
			}

			DeleteDC(hMemDC);
		}	
	}

	return hRgn;
}

/
// InflateRegion - Inflates a region by the x and y values
// specified in nXInflate and nYInflate
// Creates a new region that represents the inflated region
// (retains the contents of the old region)
// Returns NULL if unsuccessfull
/
static HRGN InflateRegion( HRGN hRgn, int nXInflate, int nYInflate )
{
	// Local Variables
	LPRGNDATA lpData;	// The RGNDATA structure
	LPRECT lpRect;		// Pointer to the array of RECT structures
	DWORD BufSize;		// The amount of memory required
	DWORD i;			// General index variable
	HRGN hRgnNew;		// The newly created region

	// Get the number of rectangles in the region
	BufSize = GetRegionData(hRgn, 0, NULL);
	if(BufSize == 0)
		return NULL;

	// Allocate memory for the RGNDATA structure
	lpData = (LPRGNDATA)malloc(BufSize);

	// Set the location of the RECT structures
	lpRect = (LPRECT)(lpData->Buffer);

	// Get the region data
	if(!GetRegionData(hRgn, BufSize, lpData))
	{
		free(lpData);
		return NULL;
	}

	// Expand (or contract) all the rectangles in the data
	for(i=0; i<lpData->rdh.nCount; i++)
		InflateRect(&lpRect[i], nXInflate, nYInflate);

	// Create the new region
	hRgnNew = ExtCreateRegion(NULL, lpData->rdh.nCount, lpData);
	free((void*)lpData);
	return hRgnNew;
}

/
// CSuperProgressCtrl
/

CSuperProgressCtrl::CSuperProgressCtrl()
{
	m_lMin			= 0;							// Minimum range.
	m_lMax			= 100;							// Maximum range.
	m_nStep			= 10;							// Step size.
	m_nPosition		= 0;							// The current position.
	m_Colour1		= RGB(0,0,255);					// Default start colour is blue.
	m_Colour2		= RGB(255,0,0);					// Default end colour is red.
	m_Background	= GetSysColor(COLOR_3DFACE);	// Dialog Background.
	m_hbmArea		= NULL;							// The window area bitmap.
	m_hRegion		= NULL;							// The window region.
	m_nFillStyle	= SP_FILL_HORZGRAD;				// What style is used for filling?
	m_nHeight		= 0;							// The height of the current bitmap.
	m_nWidth		= 0;							// The width of the current bitmap.
}

CSuperProgressCtrl::~CSuperProgressCtrl()
{
	// add this
	DeleteObject( (HBITMAP)m_hbmArea );
	DeleteObject( (HRGN)m_hRegion );
}


BEGIN_MESSAGE_MAP(CSuperProgressCtrl, CWnd)
	//{{AFX_MSG_MAP(CSuperProgressCtrl)
	ON_WM_PAINT()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/
// CSuperProgressCtrl message handlers
/

CString CSuperProgressCtrl::s_Class = _T("");

void CSuperProgressCtrl::RegisterClass()
{
	// Register the window class
	s_Class = AfxRegisterWndClass( CS_CLASSDC, AfxGetApp()->LoadStandardCursor(IDC_ARROW), (HBRUSH)(COLOR_BTNFACE+1), NULL );
}

BOOL CSuperProgressCtrl::Create( CWnd* pParent, int x, int y, HBITMAP hbmArea, UINT nID )
{
	// Local Variables
	BITMAP bm;
	BOOL bRet;
	HRGN hRgn;

	// Get the dimensions of the given bitmap
	if(GetObject((HGDIOBJ)hbmArea, sizeof(BITMAP), (void*)&bm) == 0)
		return FALSE;

	// Create the window
	bRet = CWnd::Create(	s_Class,
//							NULL,
							_T(""),
							WS_VISIBLE | WS_CHILD,
							CRect(x, y, x+bm.bmWidth-1, y+bm.bmHeight-1),
							pParent,
							nID,
							NULL
						);
#if 0
	// Set the various member variables
	m_lMin = 0;									// Default minimum is 0
	m_lMax = 100;								// Default maximum is 100
	m_nPosition = 0;							// Initial position is at 0
	m_nStep = 10;								// Default step is 10
	m_Colour1 = RGB(0,0,255);					// Default start colour is blue
	m_Colour2 = RGB(255,0,0);					// Default end colour is red
	m_Background = GetSysColor(COLOR_3DFACE);	// Dialog Background
	m_nFillStyle = SP_FILL_HORZGRAD;			// Horizontal Gradient
#endif	// 0

	// If the window was created successfully, set the window region
	if( bRet )
	{
		m_hbmArea = hbmArea;
		m_hRegion = BitmapToRegion(hbmArea, RGB(255,255,255), 0x000000);
		hRgn = InflateRegion(m_hRegion, 1, 1);
		::SetWindowRgn( m_hWnd, hRgn, TRUE );

		m_nWidth	= bm.bmWidth;
		m_nHeight	= bm.bmHeight;

		// We don't need to delete the region,
		// Windows does it for us when the
		// window is destroyed
	}

	// Return the status of the window creation
	return bRet;
}

void CSuperProgressCtrl::SetRange(int nMin, int nMax)
{
	// Make sure that max > min
	ASSERT(nMax > nMin);

	// Set the maximum and minimum values
	m_lMin = nMin;
	m_lMax = nMax;

	// Invalidate the window
	::InvalidateRgn(m_hWnd, m_hRegion, FALSE);
}

int CSuperProgressCtrl::SetPos(int nPos)
{
	int oldpos = m_nPosition;
	ASSERT((nPos >= m_lMin) && (nPos <= m_lMax));	// Make sure that min <= pos <= max
	m_nPosition = nPos;								// Set the new position
	if(m_nPosition != oldpos)						// Invalidate the window
		::InvalidateRgn(m_hWnd, m_hRegion, FALSE);
	return oldpos;
}

int CSuperProgressCtrl::OffsetPos(int nOffset)
{
	int oldpos = m_nPosition;

	// Make sure that min <= pos <= max
	ASSERT(((nOffset+m_nPosition) >= m_lMin) && ((nOffset+m_nPosition) <= m_lMax));

	m_nPosition += nOffset;							// Set the new position
	if(m_nPosition != oldpos)						// Invalidate the window
		::InvalidateRgn(m_hWnd, m_hRegion, FALSE);
	return oldpos;
}

int CSuperProgressCtrl::SetStep(int nStep)
{
	int oldpos = m_nStep;
	ASSERT(nStep <= (m_lMax - m_lMin + 1));			// Make sure that step is less than the difference between max and min
	m_nStep = nStep;								// Set the new step value
	return oldpos;
}

int CSuperProgressCtrl::StepIt()
{
	int oldpos = m_nPosition;

	// Only step if the new position is in range
	if(((m_nPosition+m_nStep) >= m_lMin) &&
		((m_nPosition+m_nStep) <= m_lMax))
		m_nPosition += m_nStep;
	else if((m_nPosition+m_nStep) < m_lMin)
		m_nPosition = m_lMin;
	else
		m_nPosition = m_lMax;

	// Invalidate the window if necessary
	if(m_nPosition != oldpos)
		::InvalidateRgn(m_hWnd, m_hRegion, FALSE);

	return oldpos;
}

int CSuperProgressCtrl::SetFillStyle(int nStyle)
{
	int oldstyle = m_nFillStyle;
	ASSERT((nStyle >= 1) && (nStyle <= 4));			// Make sure the new style is valid
	m_nFillStyle = nStyle;							// Set the new fill style
	if(m_nFillStyle != oldstyle)					// Invalidate the window if necessary
		::InvalidateRgn(m_hWnd, m_hRegion, FALSE);
	return oldstyle;								// Return the old style
}

int CSuperProgressCtrl::GetFillStyle() const
{
	return m_nFillStyle;							// Return the current fill style
}

void CSuperProgressCtrl::SetColours(COLORREF Colour1, COLORREF Colour2)
{
	// Invalidate the window if necessary
	if((Colour1 != m_Colour1) || (Colour2 != m_Colour2))
		::InvalidateRgn(m_hWnd, m_hRegion, FALSE);

	// Set the new colours
	m_Colour1 = Colour1;
	m_Colour2 = Colour2;
}

void CSuperProgressCtrl::GetColours(COLORREF* Colour1, COLORREF* Colour2) const
{
	// Return the old colours
	if(Colour1) *Colour1 = m_Colour1;
	if(Colour2) *Colour2 = m_Colour2;
}

COLORREF CSuperProgressCtrl::SetBackColour(COLORREF Colour)
{
	COLORREF oldval = m_Background;
	m_Background = Colour;							// Set the background colour
	return oldval;
}

COLORREF CSuperProgressCtrl::GetBackColour() const
{
	return m_Background;
}

BOOL CSuperProgressCtrl::MessageLoop() const
{
	// Local variables
	MSG msg;
	LONG lIdle;

	// Process all the messages in the message queue
	while(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
	{
		if(!AfxGetApp()->PumpMessage())
		{
			PostQuitMessage(0);
			return FALSE;	// Signal WM_QUIT received
		}
	}

	// let MFC do its idle processing
	lIdle = 0;

	while(AfxGetApp()->OnIdle(lIdle++));

	// Signal to continue processing
	return TRUE;
}

/
// Emboss         - Creates a 3D embossed effect
// Taken directly from an article by Zafir Anjum entitled
// "Emboss text and other shape on your bitmap"
/
//
// Returns                - A new bitmap containing the resulting effect
// hBitmap                - Bitmap that contains the basic text & shapes
// hbmBackGnd             - Contains the color image 
// hPal                   - Handle of palette associated with hbmBackGnd
// bRaised                - True if raised effect is desired. False for sunken effect
// xDest          - x coordinate - used to offset hBitmap
// yDest          - y coordinate - used to offset hBitmap
// clrHightlight  - Color used for the highlight edge
// clrShadow              - Color used for the shadow
//
// Note                   - 1. Neither of the bitmap handles passed in should be selected 
//                          in a device context.
//                          2. The pixel at 0,0 in hBitmap is considered the background color
//
/
static HBITMAP Emboss( HBITMAP hBitmap, HBITMAP hbmBackGnd, HPALETTE hPal, BOOL bRaised, int xDest, int yDest, COLORREF clrHighlight, COLORREF clrShadow )
{
    const DWORD PSDPxax = 0x00B8074A;
    BITMAP   bmInfo ;
    HBITMAP  hbmOld, hbmShadow, hbmHighlight, hbmResult, hbmOldMem ;
    HBRUSH   hbrPat ;
    HDC      hDC, hColorDC, hMonoDC, hMemDC ;

    if( !bRaised )
    {
            // Swap the highlight and shadow color
            COLORREF clrTemp = clrShadow;
            clrShadow = clrHighlight;
            clrHighlight = clrTemp;
    }

    // We create two monochrome bitmaps. One of them will contain the
    // highlighted edge and the other will contain the shadow. These
    // bitmaps are then used to paint the highlight and shadow on the
    // background image.

    hbmResult = NULL ;
    hDC = GetDC( NULL ) ;

    // Create a compatible DCs
    hMemDC		= ::CreateCompatibleDC( hDC );
    hMonoDC		= ::CreateCompatibleDC( hDC );
    hColorDC	= ::CreateCompatibleDC( hDC );

    if( hMemDC == NULL || hMonoDC == NULL || hColorDC == NULL )
    {
            if( hMemDC ) DeleteDC( hMemDC );
            if( hMonoDC ) DeleteDC( hMonoDC );
            if( hColorDC ) DeleteDC( hColorDC );

            return NULL;
    }

    // Select the background image into memory DC so that we can draw it
    hbmOldMem = (HBITMAP)::SelectObject( hMemDC, hbmBackGnd );
    
    // Get dimensions of the background image
    BITMAP bm;
    ::GetObject( hbmBackGnd, sizeof( bm ), &bm );


    // Create the monochrome and compatible color bitmaps 
    GetObject( hBitmap, sizeof( BITMAP ), (LPSTR) &bmInfo ) ;
    hbmShadow		= CreateBitmap( bmInfo.bmWidth, bmInfo.bmHeight, 1, 1, NULL ) ;
    hbmHighlight	= CreateBitmap( bmInfo.bmWidth, bmInfo.bmHeight, 1, 1, NULL ) ;
    hbmResult		= CreateCompatibleBitmap( hDC, bm.bmWidth, bm.bmHeight ) ;

    hbmOld = (HBITMAP)SelectObject( hColorDC, hBitmap ) ;

    // Set background color of bitmap for mono conversion
    // We assume that the pixel in the top left corner has the background color
    SetBkColor( hColorDC, GetPixel( hColorDC, 0, 0 ) ) ;

    // Create the highlight bitmap.
    hbmHighlight = (HBITMAP)SelectObject( hMonoDC, (HGDIOBJ) hbmHighlight ) ;
    PatBlt( hMonoDC, 0, 0, bmInfo.bmWidth, bmInfo.bmHeight, WHITENESS ) ;
    BitBlt( hMonoDC, 0, 0, bmInfo.bmWidth - 1, bmInfo.bmHeight - 1, hColorDC, 1, 1, SRCCOPY ) ;
    BitBlt( hMonoDC, 0, 0, bmInfo.bmWidth, bmInfo.bmHeight, hColorDC, 0, 0, MERGEPAINT ) ;
    hbmHighlight = (HBITMAP)SelectObject( hMonoDC, (HGDIOBJ) hbmHighlight ) ;


    // create the shadow bitmap
    hbmShadow = (HBITMAP)SelectObject( hMonoDC, (HGDIOBJ) hbmShadow ) ;
    PatBlt( hMonoDC, 0, 0, bmInfo.bmWidth, bmInfo.bmHeight, WHITENESS ) ;
    BitBlt( hMonoDC, 1, 1, bmInfo.bmWidth-1, bmInfo.bmHeight-1, hColorDC, 0, 0, SRCCOPY ) ;
    BitBlt( hMonoDC, 0, 0, bmInfo.bmWidth, bmInfo.bmHeight, hColorDC, 0, 0, MERGEPAINT ) ;
    hbmShadow = (HBITMAP)SelectObject( hMonoDC, (HGDIOBJ) hbmShadow ) ;


    // Now let's start working on the final image
    SelectObject( hColorDC, hbmResult ) ;
    // Select and realize the palette if one is supplied
    if( hPal && GetDeviceCaps(hDC, RASTERCAPS) & RC_PALETTE )
    {
		::SelectPalette( hColorDC, hPal, FALSE );
		::RealizePalette(hColorDC);
    }

    // Draw the background image
    BitBlt(hColorDC, 0, 0, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0,SRCCOPY);

    // Restore the old bitmap in the hMemDC
    ::SelectObject( hMemDC, hbmOldMem );


    // Set the background and foreground color for the raster operations
    SetBkColor( hColorDC, RGB(255,255,255) ) ;
    SetTextColor( hColorDC, RGB(0,0,0) ) ;

    // blt the highlight edge
    hbrPat = CreateSolidBrush( clrHighlight ) ;
    hbrPat = (HBRUSH)SelectObject( hColorDC, hbrPat ) ;
    hbmHighlight = (HBITMAP)SelectObject( hMonoDC, (HGDIOBJ) hbmHighlight ) ;
    BitBlt( hColorDC, xDest, yDest, bmInfo.bmWidth, bmInfo.bmHeight,
            hMonoDC, 0, 0, PSDPxax ) ;
    DeleteObject( SelectObject( hColorDC, hbrPat ) ) ;
    hbmHighlight = (HBITMAP)SelectObject( hMonoDC, (HGDIOBJ) hbmHighlight ) ;

    // blt the shadow edge
    hbrPat = CreateSolidBrush( clrShadow ) ;

    hbrPat = (HBRUSH)SelectObject( hColorDC, hbrPat ) ;
    hbmShadow = (HBITMAP)SelectObject( hMonoDC, (HGDIOBJ) hbmShadow ) ;
    BitBlt( hColorDC, xDest, yDest, bmInfo.bmWidth, bmInfo.bmHeight,
            hMonoDC, 0, 0, PSDPxax ) ;
    DeleteObject( SelectObject( hColorDC, hbrPat ) ) ;
    hbmShadow = (HBITMAP)SelectObject( hMonoDC, (HGDIOBJ) hbmShadow ) ;

    // select old bitmap into color DC 
    SelectObject( hColorDC, hbmOld ) ;

    DeleteObject( (HGDIOBJ) hbmShadow ) ;
    DeleteObject( (HGDIOBJ) hbmHighlight ) ;

//	ReleaseDC( NULL, hDC ) ;


	// Clean up.
	DeleteDC( (HDC)hColorDC );
	DeleteDC( (HDC)hMonoDC );
	DeleteDC( (HDC)hMemDC );
	ReleaseDC( NULL,hDC );


    return ( hbmResult ) ;
}

void CSuperProgressCtrl::OnPaint() 
{
	// Note: It is very easy to fill in the shape of the bitmap,
	//       a result of the SetWindowRgn() call in the Create()
	//       function. The only clipping we have to perform is
	//       with a call to SelectClipRgn()

	// Local Variables
	CPaintDC dc(this);	// device context for painting
	CDC memDC;			// memory device context (eliminate flicker)
	HBITMAP hbmBack;	// bitmap for emboss background
	HBITMAP hbmEmboss;	// bitmap for the embossing
	HBITMAP hOldBitmap;	// Save the device context state...
	CRect rect;			// client/region area rectangle
	int nRange;			// The range of the progress control
	BYTE rs, gs, bs;	// Starting red, green and blue values
	BYTE re, ge, be;	// Ending red, green and blue values
	float red, green, blue;	// Current colour components
	float rstep, gstep, bstep;	// Colour step values
	int xPos, yPos;		// Counters for drawing gradients quickly

	// Get the client area
	GetClientRect(rect);
	// Create the memory device contexts
	memDC.CreateCompatibleDC(&dc);
	// Create and select a bitmap to use for the device context
	hbmBack =  CreateCompatibleBitmap(dc.GetSafeHdc(), rect.Width(), rect.Height());
	if(!hbmBack)
		return;
	hOldBitmap = (HBITMAP)SelectObject(memDC.GetSafeHdc(), hbmBack);
	// Colour in the bitmap background
	memDC.FillSolidRect(rect, m_Background);
	SelectClipRgn(memDC.GetSafeHdc(), m_hRegion);

	// Fill the area
	nRange = m_lMax - m_lMin + 1;
	if((m_nFillStyle == SP_FILL_HORZGRAD) ||
		(m_nFillStyle == SP_FILL_VERTGRAD))
	{
		// Get the starting and ending colour components
		rs = GetRValue(m_Colour1); re = GetRValue(m_Colour2);
		gs = GetGValue(m_Colour1); ge = GetGValue(m_Colour2);
		bs = GetBValue(m_Colour1); be = GetBValue(m_Colour2);
	}
	switch( m_nFillStyle )
	{
		case SP_FILL_VERT:
			// Fill in the rectangle
			memDC.FillSolidRect(rect.left, rect.top-1,
				rect.Width(), ((m_nPosition-m_lMin)*(rect.Height()+2)/nRange)+1,
				m_Colour1);
			break;

		case SP_FILL_HORZ:
			// Fill in the rectangle
			memDC.FillSolidRect(rect.left-1, rect.top,
				((m_nPosition-m_lMin)*(rect.Width()+2)/nRange)+1, rect.Height(),
				m_Colour1);
			break;

		case SP_FILL_VERTGRAD:
			// Get the initial colour values
			red = (float)rs;
			green = (float)gs;
			blue = (float)bs;
			// Get the colour step values
			rstep = (float)(re - rs) / rect.Height();
			gstep = (float)(ge - gs) / rect.Height();
			bstep = (float)(be - bs) / rect.Height();
			yPos = rect.top-1;
			while(yPos+1 <= ((m_nPosition-m_lMin)*(rect.Height()+2))/nRange)
			{
				// Fill in the current rectangle
				memDC.FillSolidRect(rect.left, yPos, rect.Width(), 1,
					RGB((int)red, (int)green, (int)blue));
				// Get the next colour to use
				red += rstep; green += gstep; blue += bstep;
				// Get the next rectangle
				yPos++;
			}
			break;

		case SP_FILL_HORZGRAD:
			// Get the initial colour values
			red = (float)rs;
			green = (float)gs;
			blue = (float)bs;
			// Get the colour step values
			rstep = (float)(re - rs) / rect.Width();
			gstep = (float)(ge - gs) / rect.Width();
			bstep = (float)(be - bs) / rect.Width();
			xPos = rect.left-1;
			while(xPos+1 <= ((m_nPosition-m_lMin)*(rect.Width()+2))/nRange)
			{
				// Fill in the current rectangle
				memDC.FillSolidRect(xPos, rect.top, 1, rect.Height(),
					RGB((int)red, (int)green, (int)blue));
				// Get the next colour to use
				red += rstep; green += gstep; blue += bstep;
				// Get the next rectangle
				xPos++;
			}
			break;
	}

	// Emboss the bitmap on the device context
	SelectObject(memDC.GetSafeHdc(), hOldBitmap);
	hbmEmboss = Emboss(m_hbmArea, hbmBack, NULL, FALSE, 0, 0,
					   GetSysColor(COLOR_3DHILIGHT),
					   GetSysColor(COLOR_3DSHADOW));
	SelectObject(memDC.GetSafeHdc(), hbmEmboss);

	// Copy to the screen
	dc.BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);

	// Cleanup
	SelectObject(memDC.GetSafeHdc(), hOldBitmap);
	DeleteObject(hbmBack);
	DeleteObject(hbmEmboss);
}
#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
//



// GradientProgressCtrl.h : header file
//
// Written by matt weagle (matt_weagle@hotmail.com)
// Copyright (c) 1998.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is 
// not sold for profit without the authors written consent, and 
// providing that this notice and the authors name is included. If 
// the source code in  this file is used in any commercial application 
// then a simple email would be nice.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage whatsoever.
//
// Thanks to Chris Maunder (Chris.Maunder@cbr.clw.csiro.au) for the 
// foregoing disclaimer.


#include "MemDC.h"

/
// CGradientProgressCtrl window

class 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_)
// GradientProgressCtrl.cpp : implementation file
//
//
//
// Written by matt weagle (matt_weagle@hotmail.com)
// Copyright (c) 1998.
//
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is 
// not sold for profit without the authors written consent, and 
// providing that this notice and the authors name is included. If 
// the source code in  this file is used in any commercial application 
// then a simple email would be nice.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage whatsoever.
// Consider yourself lucky if it works, unlucky if it doesn't.
//
// Thanks to Chris Maunder (Chris.Maunder@cbr.clw.csiro.au) for the 
// foregoing disclaimer.
// 
// Please use and enjoy. Please let me know of any bugs/mods/improvements 
// that you have found/implemented and I will fix/incorporate them into this
// file. 
//
// Updated 6.6.2000
// -	Changed percent calculation formula with Fabrice GIRARDOT's fix
//		(girardot_fabrice@emc.com)
// -	Updated DrawGradient function to handle boundary case where start
//		color equals end color.  Fix proposed by Rajesh Bobade (rbobade@hotmail.com)
// -	Added handler for CProgressCtrl::SetRange32 which was introduced in VC6
// -	Control no longer clears when the range is complete.  Painted area remains
//		and you must call SetRange or SetRange32 to clear the control.  See 
//		CCTestProgressBarDlg::OnClear() for an example.
// -	Added support for vertical drawing of progress control.
//
//
//

#include "stdafx.h"
#include "GradientProgressCtrl.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CGradientProgressCtrl

CGradientProgressCtrl::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 = FALSE;
}

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(::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));
}

/
/*
	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	

	
	CProMemDC 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;
}

  • 50
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值