|
|
/*****************************************************************************
* * 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; HRESULT hr;
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.
//
hr = StringCchPrintf(tsz, cA(tsz), TEXT("%d%%"), iPct); if (FAILED(hr) && (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) { tsz[0] = TEXT('\0'); } for(ctch=0;tsz[ctch];ctch++);
//
// Draw the left-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); }
//
// 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 */
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); }
|