You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
480 lines
9.5 KiB
480 lines
9.5 KiB
/*++
|
|
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
Progress.cpp
|
|
|
|
Abstract:
|
|
|
|
Implementation of the old style progress bar class.
|
|
|
|
Notes:
|
|
|
|
ANSI only - must run on Win9x.
|
|
|
|
History:
|
|
|
|
01/30/01 rparsons Created (Thanks to carlco)
|
|
01/10/02 rparsons Revised
|
|
|
|
|
|
--*/
|
|
#include "progress.h"
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor - initialize member variables.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
CProgress::CProgress()
|
|
{
|
|
m_dwMax = 0;
|
|
m_dwMin = 0;
|
|
m_dwPos = 0;
|
|
m_hWndParent = NULL;
|
|
m_hWnd = NULL;
|
|
m_hBackground = NULL;
|
|
m_hComplete = NULL;
|
|
m_hFont = NULL;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destructor - destroy objects and release memory.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
CProgress::~CProgress()
|
|
{
|
|
if (IsWindow(m_hWnd) == TRUE) {
|
|
DestroyWindow(m_hWnd);
|
|
}
|
|
|
|
if (m_hBackground) {
|
|
DeleteObject(m_hBackground);
|
|
}
|
|
|
|
if (m_hComplete) {
|
|
DeleteObject(m_hComplete);
|
|
}
|
|
|
|
if (m_hFont) {
|
|
DeleteObject(m_hFont);
|
|
}
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets up the progress bar class and creates the window.
|
|
|
|
Arguments:
|
|
|
|
hWndParent - Handle to the parent window.
|
|
hInstance - Instance handle.
|
|
x - Initial horizontal position of the window.
|
|
y - Initial vertical position of the window.
|
|
nWidth - Width, in device units, of the window.
|
|
nHeight - Height, in device units, of the window.
|
|
|
|
Return Value:
|
|
|
|
0 on success, -1 on failure.
|
|
|
|
--*/
|
|
int
|
|
CProgress::Create(
|
|
IN HWND hWndParent,
|
|
IN HINSTANCE hInstance,
|
|
IN LPSTR lpClassName,
|
|
IN int x,
|
|
IN int y,
|
|
IN int nWidth,
|
|
IN int nHeight
|
|
)
|
|
{
|
|
WNDCLASS wc;
|
|
ATOM aClass = NULL;
|
|
|
|
//
|
|
// Create brushes and the font.
|
|
//
|
|
m_hBackground = CreateSolidBrush(RGB(255,255,255));
|
|
m_hComplete = CreateSolidBrush(RGB(0,20,244));
|
|
m_hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
|
|
|
|
//
|
|
// Set up the windows class struct and register it.
|
|
//
|
|
ZeroMemory(&wc, sizeof(WNDCLASS));
|
|
|
|
wc.style = CS_VREDRAW | CS_HREDRAW;
|
|
wc.lpfnWndProc = CProgress::WndProc;
|
|
wc.hInstance = hInstance;
|
|
wc.hbrBackground = m_hBackground;
|
|
wc.lpszClassName = lpClassName;
|
|
|
|
aClass = RegisterClass(&wc);
|
|
|
|
if (NULL == aClass) {
|
|
return -1;
|
|
}
|
|
|
|
m_hWnd = CreateWindow(lpClassName,
|
|
NULL,
|
|
WS_CHILD | WS_VISIBLE,
|
|
x,
|
|
y,
|
|
nWidth,
|
|
nHeight,
|
|
hWndParent,
|
|
0,
|
|
hInstance,
|
|
(LPVOID)this);
|
|
|
|
return (m_hWnd ? 0 : -1);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets the current position of the progress bar.
|
|
|
|
Arguments:
|
|
|
|
dwNew - The new value to set.
|
|
|
|
Return Value:
|
|
|
|
The new position.
|
|
|
|
--*/
|
|
DWORD
|
|
CProgress::SetPos(
|
|
IN DWORD dwNewPos
|
|
)
|
|
{
|
|
m_dwPos = dwNewPos;
|
|
this->Refresh();
|
|
|
|
return m_dwPos;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets the maximum range of the progress bar.
|
|
|
|
Arguments:
|
|
|
|
dwMax - The maximum value to set.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
void
|
|
CProgress::SetMax(
|
|
IN DWORD dwMax
|
|
)
|
|
{
|
|
m_dwMax = dwMax;
|
|
|
|
if (m_dwMin > dwMax) {
|
|
m_dwMax = m_dwMin;
|
|
}
|
|
|
|
this->Refresh();
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets the minimum range of the progress bar.
|
|
|
|
Arguments:
|
|
|
|
dwMin - The minimum value to set.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
void
|
|
CProgress::SetMin(
|
|
IN DWORD dwMin
|
|
)
|
|
{
|
|
m_dwMin = dwMin;
|
|
|
|
if (m_dwMin > m_dwMax) {
|
|
m_dwMin = m_dwMax;
|
|
}
|
|
|
|
this->Refresh();
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Runs the message loop for the progress bar.
|
|
|
|
Arguments:
|
|
|
|
hWnd - Owner window handle.
|
|
uMsg - Windows message.
|
|
wParam - Additional message info.
|
|
lParam - Additional message info.
|
|
|
|
Return Value:
|
|
|
|
TRUE if the message was handled, FALSE otherwise.
|
|
|
|
--*/
|
|
LRESULT
|
|
CALLBACK
|
|
CProgress::WndProc(
|
|
IN HWND hWnd,
|
|
IN UINT uMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam
|
|
)
|
|
{
|
|
CProgress *pThis = (CProgress*)GetWindowLong(hWnd, GWL_USERDATA);
|
|
|
|
switch(uMsg) {
|
|
case WM_CREATE:
|
|
{
|
|
LPCREATESTRUCT cs = (LPCREATESTRUCT)lParam;
|
|
pThis = (CProgress*)cs->lpCreateParams;
|
|
SetWindowLong(hWnd, GWL_USERDATA, (LONG)pThis);
|
|
return 0;
|
|
}
|
|
|
|
case WM_PAINT:
|
|
|
|
pThis->OnPaint();
|
|
return 0;
|
|
}
|
|
|
|
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Ensure that are values are within their specified
|
|
ranges.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
inline
|
|
void
|
|
CProgress::CorrectBounds()
|
|
{
|
|
if (m_dwPos < m_dwMin) {
|
|
m_dwPos = m_dwMin;
|
|
}
|
|
|
|
if (m_dwPos > m_dwMax) {
|
|
m_dwPos = m_dwMax;
|
|
}
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Forces a redraw of the progress bar.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
void
|
|
CProgress::Refresh()
|
|
{
|
|
InvalidateRect(m_hWnd, NULL, FALSE);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Does all the work of making the progress bar move and drawing the text.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
void
|
|
CProgress::OnPaint()
|
|
{
|
|
PAINTSTRUCT ps;
|
|
RECT rcClientRect;
|
|
RECT rcComplete;
|
|
RECT rcTheRest;
|
|
RECT rcTextBounds;
|
|
RECT rcTextComplete;
|
|
RECT rcTextTheRest;
|
|
DWORD dwRange = (m_dwMax - m_dwMin);
|
|
char szPercent[5];
|
|
SIZE TextSize;
|
|
HRESULT hr;
|
|
|
|
BeginPaint(m_hWnd, &ps);
|
|
|
|
SetBkMode(ps.hdc, TRANSPARENT);
|
|
|
|
SelectObject(ps.hdc, m_hFont);
|
|
|
|
GetClientRect(m_hWnd, &rcClientRect);
|
|
|
|
InflateRect(&rcClientRect, -2,-2); // this will make the DrawFrame() function look nicer
|
|
|
|
//
|
|
// Get the pixel offset of the completed area.
|
|
//
|
|
float Ratio = (float)m_dwPos / (float)dwRange;
|
|
int nOffset = (int)(Ratio * rcClientRect.right);
|
|
|
|
//
|
|
// Get the RECT for completed area.
|
|
//
|
|
SetRect(&rcComplete, 0, 0, nOffset, rcClientRect.bottom);
|
|
|
|
//
|
|
// Get the RECT for the rest.
|
|
//
|
|
SetRect(&rcTheRest, nOffset, 0, rcClientRect.right, rcClientRect.bottom);
|
|
|
|
//
|
|
// Get the percent, text, and size of the text...
|
|
//
|
|
hr = StringCchPrintf(szPercent,
|
|
sizeof(szPercent),
|
|
"%3d%%",
|
|
(DWORD)(100 * ((float)m_dwPos / (float)dwRange)));
|
|
|
|
if (FAILED(hr)) {
|
|
return;
|
|
}
|
|
|
|
GetTextExtentPoint32(ps.hdc, szPercent, strlen(szPercent), &TextSize);
|
|
|
|
//
|
|
// Figure out where to draw the text.
|
|
//
|
|
rcTextBounds.top = 0;
|
|
rcTextBounds.bottom = rcClientRect.bottom;
|
|
rcTextBounds.left = (rcClientRect.right / 2) - (TextSize.cx / 2);
|
|
rcTextBounds.right = (rcClientRect.right / 2) + (TextSize.cx / 2);
|
|
|
|
CopyRect(&rcTextComplete, &rcTextBounds);
|
|
CopyRect(&rcTextTheRest, &rcTextBounds);
|
|
rcTextComplete.right = rcComplete.right;
|
|
rcTextTheRest.left = rcTheRest.left;
|
|
|
|
FillRect(ps.hdc, &rcComplete, m_hComplete);
|
|
FillRect(ps.hdc, &rcTheRest, m_hBackground);
|
|
|
|
//
|
|
// Draw the completed text.
|
|
//
|
|
SetTextColor(ps.hdc, RGB(255,255,255));
|
|
|
|
HRGN hTextComplete = CreateRectRgn(rcTextComplete.left,
|
|
rcTextComplete.top,
|
|
rcTextComplete.right,
|
|
rcTextComplete.bottom);
|
|
|
|
SelectClipRgn(ps.hdc, hTextComplete);
|
|
DrawText(ps.hdc,
|
|
szPercent,
|
|
strlen(szPercent),
|
|
&rcTextBounds,
|
|
DT_SINGLELINE | DT_VCENTER | DT_CENTER);
|
|
|
|
DeleteObject(hTextComplete);
|
|
|
|
//
|
|
// Draw the completed text.
|
|
//
|
|
SetTextColor(ps.hdc, RGB(0,0,255));
|
|
|
|
HRGN hTextTheRest = CreateRectRgn(rcTextTheRest.left,
|
|
rcTextTheRest.top,
|
|
rcTextTheRest.right,
|
|
rcTextTheRest.bottom);
|
|
|
|
SelectClipRgn(ps.hdc, hTextTheRest);
|
|
DrawText(ps.hdc,
|
|
szPercent,
|
|
strlen(szPercent),
|
|
&rcTextBounds,
|
|
DT_SINGLELINE | DT_VCENTER | DT_CENTER);
|
|
|
|
DeleteObject(hTextTheRest);
|
|
|
|
//
|
|
// And draw a frame around it.
|
|
//
|
|
GetClientRect(m_hWnd, &rcClientRect); //refresh this because we changed it above
|
|
|
|
HRGN hEntireRect = CreateRectRgn(rcClientRect.left,
|
|
rcClientRect.top,
|
|
rcClientRect.right,
|
|
rcClientRect.bottom);
|
|
|
|
SelectClipRgn(ps.hdc, hEntireRect);
|
|
DrawEdge(ps.hdc, &rcClientRect, EDGE_SUNKEN, BF_RECT);
|
|
DeleteObject(hEntireRect);
|
|
|
|
EndPaint(m_hWnd, &ps);
|
|
}
|