windows-nt/Source/XPSP1/NT/sdktools/bvtsigvf/progress.c
2020-09-26 16:20:57 +08:00

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