本文仅供学习交流,严禁用于商业用途,如本文涉及侵权请及时联系本人将于及时删除
目录
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;
}