204 lines
6.2 KiB
C++
204 lines
6.2 KiB
C++
//
|
|
// GradientProgressCtrl.cpp : implementation file
|
|
//
|
|
|
|
#include "afxcmn.h"
|
|
#include "Gradient.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;
|
|
|
|
// Default is vertical, because the only clients are the Test page and
|
|
// the calibration wizard, and hitting the test page is Far more common.
|
|
m_nDirection = VERTICAL;
|
|
|
|
// Initial colors
|
|
// m_clrStart = COLORREF(RGB(255, 0,0));
|
|
// m_clrEnd = COLORREF(RGB(255,128,192));
|
|
m_clrStart = COLORREF(RGB(255,0,0));
|
|
m_clrEnd = COLORREF(RGB(0,0,255));
|
|
m_clrBkGround = GetSysColor(COLOR_WINDOW);
|
|
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
|
|
|
|
void CGradientProgressCtrl::OnPaint()
|
|
{
|
|
PAINTSTRUCT ps;
|
|
::BeginPaint(this->m_hWnd, &ps);
|
|
|
|
CDC *pDC=GetDC();
|
|
HDC hDC = pDC->m_hDC;
|
|
|
|
if ((m_nLower < 0) || (m_nUpper < 0))
|
|
m_nCurrentPosition -= m_nLower;
|
|
|
|
// Figure out what part should be visible so we can stop the gradient when needed
|
|
RECT rectClient;
|
|
::GetClientRect(this->m_hWnd, &rectClient);
|
|
|
|
float nTmp = ((float)m_nCurrentPosition/(float)abs(m_nLower - m_nUpper));
|
|
|
|
// Draw the gradient
|
|
DrawGradient(hDC, rectClient, (short)(nTmp * ((m_nDirection == VERTICAL) ? rectClient.bottom : rectClient.right)));
|
|
|
|
// Show percent indicator if needed
|
|
if (m_bShowPercent)
|
|
{
|
|
TCHAR tszBuff[5];
|
|
wsprintf(tszBuff, TEXT("%d%%"), (short)(100*nTmp));
|
|
|
|
::SetTextColor(hDC, m_clrText);
|
|
::SetBkMode(hDC, TRANSPARENT);
|
|
::DrawText(hDC, tszBuff, lstrlen(tszBuff), &rectClient, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
|
|
}
|
|
|
|
ReleaseDC(pDC);
|
|
|
|
::EndPaint(this->m_hWnd, &ps);
|
|
// Do not call CProgressCtrl::OnPaint() for painting messages
|
|
}
|
|
|
|
|
|
/*************************************************************************/
|
|
// Need to keep track of where the indicator thinks it is.
|
|
/*************************************************************************/
|
|
void CGradientProgressCtrl:: SetRange(long nLower, long nUpper)
|
|
{
|
|
m_nCurrentPosition = m_nLower = nLower;
|
|
m_nUpper = nUpper;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
// Where most of the actual work is done. The general version would fill the entire rectangle with
|
|
// a gradient, but we want to truncate the drawing to reflect the actual progress control position.
|
|
/*************************************************************************/
|
|
void CGradientProgressCtrl::DrawGradient(const HDC hDC, const RECT &rectClient, const short &nMaxWidth)
|
|
{
|
|
// 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.
|
|
|
|
// Get the color differences
|
|
short r = (GetRValue(m_clrEnd) - GetRValue(m_clrStart));
|
|
short g = (GetGValue(m_clrEnd) - GetGValue(m_clrStart));
|
|
short b = (GetBValue(m_clrEnd) - GetBValue(m_clrStart));
|
|
|
|
|
|
// Make the number of steps equal to the greatest distance
|
|
short 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)
|
|
float fStep = ((m_nDirection == VERTICAL) ? (float)rectClient.bottom : (float)rectClient.right) / (float)nSteps;
|
|
|
|
// Calculate the step size for each color
|
|
float rStep = r/(float)nSteps;
|
|
float gStep = g/(float)nSteps;
|
|
float bStep = b/(float)nSteps;
|
|
|
|
// Reset the colors to the starting position
|
|
r = GetRValue(m_clrStart);
|
|
g = GetGValue(m_clrStart);
|
|
b = GetBValue(m_clrStart);
|
|
|
|
RECT rectFill; // Rectangle for filling band
|
|
|
|
// Start filling bands
|
|
for (short iOnBand = 0; iOnBand < nSteps; iOnBand++)
|
|
{
|
|
|
|
if (m_nDirection == VERTICAL)
|
|
{
|
|
// This provides the "velvet" look...
|
|
::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
|
|
|
|
/* Use this if we want the gradient to go up/down
|
|
::SetRect(&rectFill,
|
|
0, // Upper left Y
|
|
(int)(iOnBand * fStep), // Upper left X
|
|
rectClient.bottom+1, // Lower right Y
|
|
(int)((iOnBand+1) * fStep)); // Lower right X
|
|
*/
|
|
}
|
|
else
|
|
{
|
|
// Use this if we want the gradient to go left/right
|
|
::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
|
|
}
|
|
|
|
// Home-brew'd FillSolidRect... Much more effecient!
|
|
::SetBkColor(hDC, RGB(r+rStep*iOnBand, g + gStep*iOnBand, b + bStep *iOnBand));
|
|
::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rectFill, NULL, 0, NULL);
|
|
|
|
if (m_nDirection == VERTICAL)
|
|
{
|
|
// Grey Rect
|
|
::SetRect(&rectFill, 0, 0, rectClient.right, nMaxWidth);
|
|
::SetBkColor(hDC, m_clrBkGround);
|
|
::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rectFill, NULL, 0, NULL);
|
|
}
|
|
else
|
|
{
|
|
// 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);
|
|
::SetBkColor(hDC, m_clrBkGround);
|
|
::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rectFill, NULL, 0, NULL);
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*************************************************************************/
|
|
// All drawing is done in the OnPaint function
|
|
/*************************************************************************/
|
|
BOOL CGradientProgressCtrl::OnEraseBkgnd(CDC *pDC)
|
|
{
|
|
// TODO: Add your message handler code here and/or call default
|
|
return TRUE;
|
|
}
|