/*++ 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); }