295 lines
7.3 KiB
C
295 lines
7.3 KiB
C
/*****************************************************************************
|
|
*
|
|
* Progress.c
|
|
*
|
|
* Copyright (c) 1996 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* Abstract:
|
|
*
|
|
* Our private progress control (because commctrl might be damanged)
|
|
*
|
|
* Contents:
|
|
*
|
|
* Progress_Init
|
|
*
|
|
*****************************************************************************/
|
|
#include "sigverif.h"
|
|
|
|
/***************************************************************************
|
|
*
|
|
* GWL_* for Progress goo.
|
|
*
|
|
***************************************************************************/
|
|
|
|
#define GWL_CUR GWLP_USERDATA
|
|
|
|
/***************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func int | Progress_GetRectPos |
|
|
*
|
|
* Compute the position within the drawing rectangle that
|
|
* corresponds to the current position.
|
|
*
|
|
* This is basically a MulDiv, except that we don't let the
|
|
* bar get all the way to 100% unless it really means it.
|
|
*
|
|
*
|
|
***************************************************************************/
|
|
|
|
int Progress_GetRectPos(int cx, int iCur, int iMax)
|
|
{
|
|
int iRc;
|
|
|
|
if (iCur != iMax) {
|
|
iRc = MulDiv(cx, iCur, iMax);
|
|
} else {
|
|
iRc = cx;
|
|
}
|
|
|
|
return iRc;
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func LRESULT | Progress_OnPaint |
|
|
*
|
|
* Draw the first part in the highlight colors.
|
|
*
|
|
* Draw the second part in the 3dface colors.
|
|
*
|
|
***************************************************************************/
|
|
|
|
void Progress_OnPaint(HWND hwnd)
|
|
{
|
|
HDC hdc;
|
|
PAINTSTRUCT ps;
|
|
|
|
hdc = BeginPaint(hwnd, &ps);
|
|
if (hdc) {
|
|
UINT taPrev;
|
|
RECT rc;
|
|
int cx;
|
|
COLORREF clrTextPrev, clrBackPrev;
|
|
int iCur, iMax, iPct;
|
|
int ctch;
|
|
HFONT hfPrev;
|
|
TCHAR tsz[256];
|
|
SIZE size;
|
|
|
|
/*
|
|
* Set up the DC generically.
|
|
*/
|
|
taPrev = SetTextAlign(hdc, TA_CENTER | TA_TOP);
|
|
hfPrev = SelectFont(hdc, GetWindowFont(GetParent(hwnd)));
|
|
|
|
/*
|
|
* Set up the colors for the left-hand side.
|
|
*/
|
|
clrTextPrev = SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
|
|
clrBackPrev = SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
|
|
|
|
/*
|
|
* Now do some math.
|
|
*/
|
|
GetClientRect(hwnd, &rc);
|
|
|
|
cx = rc.right;
|
|
|
|
iCur = LOWORD(GetWindowLong(hwnd, GWL_CUR));
|
|
iMax = HIWORD(GetWindowLong(hwnd, GWL_CUR));
|
|
|
|
if (iMax == 0)
|
|
{
|
|
iMax = 1; /* Avoid divide by zero */
|
|
}
|
|
|
|
if (iCur > 0)
|
|
{
|
|
iPct = (iCur * 100) / iMax;
|
|
if (iPct < 1)
|
|
iPct = 1;
|
|
} else iPct = 0;
|
|
|
|
rc.right = Progress_GetRectPos(cx, iCur, iMax);
|
|
|
|
// Update the percentage text in the progress bar.
|
|
wsprintf(tsz, TEXT("%d%%"), iPct);
|
|
for(ctch=0;tsz[ctch];ctch++);
|
|
|
|
/*
|
|
* Draw the left-hand side.
|
|
*/
|
|
//ctch = GetWindowText(hwnd, tsz, cA(tsz));
|
|
if (!GetTextExtentPoint32(hdc, tsz, ctch, &size))
|
|
{
|
|
ExtTextOut( hdc, cx/2, 1,
|
|
ETO_CLIPPED | ETO_OPAQUE,
|
|
&rc, tsz, ctch, 0);
|
|
} else {
|
|
ExtTextOut( hdc, cx/2, (rc.bottom - rc.top - size.cy + 1) / 2,
|
|
ETO_CLIPPED | ETO_OPAQUE,
|
|
&rc, tsz, ctch, 0);
|
|
}
|
|
|
|
/*
|
|
* Now set up for the right-hand side.
|
|
*/
|
|
SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
|
|
SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
|
|
|
|
rc.left = rc.right;
|
|
rc.right = cx;
|
|
|
|
/*
|
|
* Draw the right-hand side.
|
|
*/
|
|
if (!GetTextExtentPoint32(hdc, tsz, ctch, &size))
|
|
{
|
|
ExtTextOut( hdc, cx/2, 1,
|
|
ETO_CLIPPED | ETO_OPAQUE,
|
|
&rc, tsz, ctch, 0);
|
|
} else {
|
|
ExtTextOut( hdc, cx/2, (rc.bottom - rc.top - size.cy + 1) / 2,
|
|
ETO_CLIPPED | ETO_OPAQUE,
|
|
&rc, tsz, ctch, 0);
|
|
}
|
|
|
|
SetBkColor(hdc, clrBackPrev);
|
|
SetTextColor(hdc, clrTextPrev);
|
|
SelectFont(hdc, hfPrev);
|
|
SetTextAlign(hdc, taPrev);
|
|
|
|
EndPaint(hwnd, &ps);
|
|
}
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func LRESULT | Progress_OnSetPos |
|
|
*
|
|
* Update the state and invalidate the section that is affected.
|
|
*
|
|
***************************************************************************/
|
|
|
|
void Progress_OnSetPos(HWND hwnd, WPARAM wp)
|
|
{
|
|
int iCur, iMax;
|
|
RECT rc;
|
|
LONG lState = GetWindowLong(hwnd, GWL_CUR);
|
|
|
|
|
|
GetClientRect(hwnd, &rc);
|
|
|
|
iCur = LOWORD(GetWindowLong(hwnd, GWL_CUR));
|
|
iMax = HIWORD(GetWindowLong(hwnd, GWL_CUR));
|
|
|
|
if (iMax == 0) {
|
|
iMax = 1; /* Avoid divide by zero */
|
|
}
|
|
|
|
rc.left = Progress_GetRectPos(rc.right, iCur, iMax);
|
|
rc.right = Progress_GetRectPos(rc.right, (int)wp, iMax);
|
|
|
|
InvalidateRect(hwnd, 0, 0);
|
|
|
|
SetWindowLong(hwnd, GWL_CUR, MAKELONG(wp,HIWORD(lState)));
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func LRESULT | Progress_WndProc |
|
|
*
|
|
* There really isn't much to do.
|
|
*
|
|
* The string is our window text (which Windows manages for us).
|
|
*
|
|
* The progress bar itself is kept in the high/low words of
|
|
* our GWL_USERDATA.
|
|
*
|
|
* HIWORD(GetWindowLong(GWL_USERDATA)) = maximum
|
|
* LOWORD(GetWindowLong(GWL_USERDATA)) = current value
|
|
*
|
|
***************************************************************************/
|
|
|
|
LRESULT CALLBACK
|
|
Progress_WndProc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp)
|
|
{
|
|
switch (wm) {
|
|
|
|
case WM_PAINT:
|
|
Progress_OnPaint(hwnd);
|
|
return 0;
|
|
|
|
/*
|
|
* When the range resets, invalidate so we repaint.
|
|
*
|
|
* wp = new current pos
|
|
* lp = new range
|
|
*/
|
|
case PBM_SETRANGE:
|
|
lp = HIWORD(lp);
|
|
SetWindowLong(hwnd, GWL_CUR, MAKELONG(wp, lp));
|
|
/* FALLTHROUGH */
|
|
|
|
/*
|
|
* When our text changes, invalidate so we repaint.
|
|
*/
|
|
//case WM_SETTEXT:
|
|
//InvalidateRect(hwnd, 0, 0);
|
|
//break;
|
|
|
|
case PBM_SETPOS:
|
|
Progress_OnSetPos(hwnd, wp);
|
|
break;
|
|
|
|
case PBM_DELTAPOS:
|
|
lp = LOWORD(GetWindowLong(hwnd, GWL_CUR));
|
|
Progress_OnSetPos(hwnd, wp + lp);
|
|
break;
|
|
|
|
case WM_ERASEBKGND:
|
|
return 0;
|
|
}
|
|
|
|
return DefWindowProc(hwnd, wm, wp, lp);
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func void | Progress_InitRegisterClass |
|
|
*
|
|
* Register our window classes.
|
|
*
|
|
***************************************************************************/
|
|
|
|
void Progress_InitRegisterClass(void)
|
|
{
|
|
WNDCLASS wc;
|
|
|
|
/*
|
|
* Progress control.
|
|
*/
|
|
wc.style = 0;
|
|
wc.lpfnWndProc = Progress_WndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = cbX(DWORD);
|
|
wc.hInstance = g_App.hInstance;
|
|
wc.hIcon = 0;
|
|
wc.hCursor = LoadCursor(0, IDC_ARROW);
|
|
wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
|
|
wc.lpszMenuName = 0;
|
|
wc.lpszClassName = TEXT("progress");
|
|
|
|
RegisterClass(&wc);
|
|
}
|