| [27] | 1 | // ProgressBar.cpp : implementation file |
|---|
| 2 | // |
|---|
| 3 | // Drop-in status bar progress control |
|---|
| 4 | // |
|---|
| 5 | // Written by Chris Maunder (chrismaunder@codeguru.com) |
|---|
| 6 | // Copyright (c) 1998. |
|---|
| 7 | // |
|---|
| 8 | // This code may be used in compiled form in any way you desire. This |
|---|
| 9 | // file may be redistributed unmodified by any means PROVIDING it is |
|---|
| 10 | // not sold for profit without the authors written consent, and |
|---|
| 11 | // providing that this notice and the authors name is included. If |
|---|
| 12 | // the source code in this file is used in any commercial application |
|---|
| 13 | // then an email to me would be nice. |
|---|
| 14 | // |
|---|
| 15 | // This file is provided "as is" with no expressed or implied warranty. |
|---|
| 16 | // The author accepts no liability if it causes any damage in any way, |
|---|
| 17 | // shape or form. |
|---|
| 18 | // |
|---|
| 19 | // Expect bugs. |
|---|
| 20 | // |
|---|
| 21 | // Please use and enjoy. Please let me know of any bugs/mods/improvements |
|---|
| 22 | // that you have found/implemented and I will fix/incorporate them into this |
|---|
| 23 | // file. |
|---|
| 24 | // |
|---|
| 25 | // Version 1.1 Chris Maunder (chrismaunder@codeguru.com) |
|---|
| 26 | // |
|---|
| 27 | // Version 1.2 Michael Martin 07 Aug 1998 mmartin@netspace.net.au |
|---|
| 28 | // Added code to enable progress bar to appear in any pane |
|---|
| 29 | // of the status bar. |
|---|
| 30 | // |
|---|
| 31 | // Chris Maunder 17 Aug 1998 |
|---|
| 32 | // Fixed Pane text restoration, and general cleanup. |
|---|
| 33 | // |
|---|
| 34 | ///////////////////////////////////////////////////////////////////////////// |
|---|
| 35 | |
|---|
| 36 | #include "stdafx.h" |
|---|
| 37 | #include "ProgressBar.h" |
|---|
| 38 | |
|---|
| 39 | #ifdef _DEBUG |
|---|
| 40 | #define new DEBUG_NEW |
|---|
| 41 | #undef THIS_FILE |
|---|
| 42 | static char THIS_FILE[] = __FILE__; |
|---|
| 43 | #endif |
|---|
| 44 | |
|---|
| 45 | IMPLEMENT_DYNCREATE(CProgressBar, CProgressCtrl) |
|---|
| 46 | |
|---|
| 47 | BEGIN_MESSAGE_MAP(CProgressBar, CProgressCtrl) |
|---|
| 48 | //{{AFX_MSG_MAP(CProgressBar) |
|---|
| 49 | ON_WM_ERASEBKGND() |
|---|
| 50 | //}}AFX_MSG_MAP |
|---|
| 51 | END_MESSAGE_MAP() |
|---|
| 52 | |
|---|
| 53 | CProgressBar::CProgressBar() |
|---|
| 54 | { |
|---|
| 55 | m_Rect.SetRect(0,0,0,0); |
|---|
| 56 | } |
|---|
| 57 | |
|---|
| 58 | CProgressBar::CProgressBar(LPCTSTR strMessage, int nSize /*=100*/, |
|---|
| 59 | int MaxValue /*=100*/, BOOL bSmooth /*=FALSE*/, |
|---|
| 60 | int nPane /*=0*/) |
|---|
| 61 | { |
|---|
| 62 | Create(strMessage, nSize, MaxValue, bSmooth, nPane); |
|---|
| 63 | } |
|---|
| 64 | |
|---|
| 65 | CProgressBar::~CProgressBar() |
|---|
| 66 | { |
|---|
| 67 | Clear(); |
|---|
| 68 | } |
|---|
| 69 | |
|---|
| 70 | CStatusBar* CProgressBar::GetStatusBar() |
|---|
| 71 | { |
|---|
| 72 | CWnd *pMainWnd = AfxGetMainWnd(); |
|---|
| 73 | if (!pMainWnd) |
|---|
| 74 | return NULL; |
|---|
| 75 | |
|---|
| 76 | // If main window is a frame window, use normal methods... |
|---|
| 77 | if (pMainWnd->IsKindOf(RUNTIME_CLASS(CFrameWnd))) |
|---|
| 78 | { |
|---|
| 79 | CWnd* pMessageBar = ((CFrameWnd*)pMainWnd)->GetMessageBar(); |
|---|
| 80 | return DYNAMIC_DOWNCAST(CStatusBar, pMessageBar); |
|---|
| 81 | } |
|---|
| 82 | // otherwise traverse children to try and find the status bar... |
|---|
| 83 | else |
|---|
| 84 | return DYNAMIC_DOWNCAST(CStatusBar, |
|---|
| 85 | pMainWnd->GetDescendantWindow(AFX_IDW_STATUS_BAR)); |
|---|
| 86 | } |
|---|
| 87 | |
|---|
| 88 | // Create the CProgressCtrl as a child of the status bar positioned |
|---|
| 89 | // over the first pane, extending "nSize" percentage across pane. |
|---|
| 90 | // Sets the range to be 0 to MaxValue, with a step of 1. |
|---|
| 91 | BOOL CProgressBar::Create(LPCTSTR strMessage, int nSize /*=100*/, |
|---|
| 92 | int MaxValue /*=100*/, BOOL bSmooth /*=FALSE*/, |
|---|
| 93 | int nPane /*=0*/, BOOL bVisible /*=TRUE*/) |
|---|
| 94 | { |
|---|
| 95 | BOOL bSuccess = FALSE; |
|---|
| 96 | |
|---|
| 97 | CStatusBar *pStatusBar = GetStatusBar(); |
|---|
| 98 | if (!pStatusBar) |
|---|
| 99 | return FALSE; |
|---|
| 100 | |
|---|
| 101 | DWORD dwStyle = WS_CHILD; |
|---|
| 102 | |
|---|
| 103 | if (bVisible) |
|---|
| 104 | dwStyle |= WS_VISIBLE; |
|---|
| 105 | |
|---|
| 106 | #ifdef PBS_SMOOTH |
|---|
| 107 | if (bSmooth) |
|---|
| 108 | dwStyle |= PBS_SMOOTH; |
|---|
| 109 | #endif |
|---|
| 110 | |
|---|
| 111 | // Get CRect coordinates for requested status bar pane |
|---|
| 112 | CRect PaneRect; |
|---|
| 113 | pStatusBar->GetItemRect(nPane, &PaneRect); |
|---|
| 114 | |
|---|
| 115 | // Create the progress bar |
|---|
| 116 | bSuccess = CProgressCtrl::Create(dwStyle, PaneRect, pStatusBar, 1); |
|---|
| 117 | ASSERT(bSuccess); |
|---|
| 118 | if (!bSuccess) |
|---|
| 119 | return FALSE; |
|---|
| 120 | |
|---|
| 121 | // Set range and step |
|---|
| 122 | SetRange(0, MaxValue); |
|---|
| 123 | SetStep(1); |
|---|
| 124 | |
|---|
| 125 | m_strMessage = strMessage; |
|---|
| 126 | m_nSize = nSize; |
|---|
| 127 | m_nPane = nPane; |
|---|
| 128 | m_strPrevText = pStatusBar->GetPaneText(m_nPane); |
|---|
| 129 | |
|---|
| 130 | // Resize the control to its desired width |
|---|
| 131 | Resize(); |
|---|
| 132 | |
|---|
| 133 | return TRUE; |
|---|
| 134 | } |
|---|
| 135 | |
|---|
| 136 | void CProgressBar::Clear() |
|---|
| 137 | { |
|---|
| 138 | if (!IsWindow(GetSafeHwnd())) |
|---|
| 139 | return; |
|---|
| 140 | |
|---|
| 141 | // Hide the window. This is necessary so that a cleared |
|---|
| 142 | // window is not redrawn if "Resize" is called |
|---|
| 143 | ModifyStyle(WS_VISIBLE, 0); |
|---|
| 144 | |
|---|
| 145 | CString str; |
|---|
| 146 | if (m_nPane == 0) |
|---|
| 147 | str.LoadString(AFX_IDS_IDLEMESSAGE); // Get the IDLE_MESSAGE |
|---|
| 148 | else |
|---|
| 149 | str = m_strPrevText; // Restore previous text |
|---|
| 150 | |
|---|
| 151 | // Place the IDLE_MESSAGE in the status bar |
|---|
| 152 | CStatusBar *pStatusBar = GetStatusBar(); |
|---|
| 153 | if (pStatusBar) |
|---|
| 154 | { |
|---|
| 155 | pStatusBar->SetPaneText(m_nPane, str); |
|---|
| 156 | pStatusBar->UpdateWindow(); |
|---|
| 157 | } |
|---|
| 158 | } |
|---|
| 159 | |
|---|
| 160 | BOOL CProgressBar::SetText(LPCTSTR strMessage) |
|---|
| 161 | { |
|---|
| 162 | m_strMessage = strMessage; |
|---|
| 163 | return Resize(); |
|---|
| 164 | } |
|---|
| 165 | |
|---|
| 166 | BOOL CProgressBar::SetSize(int nSize) |
|---|
| 167 | { |
|---|
| 168 | m_nSize = nSize; |
|---|
| 169 | return Resize(); |
|---|
| 170 | } |
|---|
| 171 | |
|---|
| 172 | COLORREF CProgressBar::SetBarColour(COLORREF clrBar) |
|---|
| 173 | { |
|---|
| 174 | #ifdef PBM_SETBKCOLOR |
|---|
| 175 | if (!IsWindow(GetSafeHwnd())) |
|---|
| 176 | return CLR_DEFAULT; |
|---|
| 177 | |
|---|
| [44] | 178 | return (COLORREF)SendMessage(PBM_SETBARCOLOR, 0, (LPARAM) clrBar); |
|---|
| [27] | 179 | #else |
|---|
| 180 | UNUSED(clrBar); |
|---|
| 181 | return CLR_DEFAULT; |
|---|
| 182 | #endif |
|---|
| 183 | } |
|---|
| 184 | |
|---|
| 185 | COLORREF CProgressBar::SetBkColour(COLORREF clrBk) |
|---|
| 186 | { |
|---|
| 187 | #ifdef PBM_SETBKCOLOR |
|---|
| 188 | if (!IsWindow(GetSafeHwnd())) |
|---|
| 189 | return CLR_DEFAULT; |
|---|
| 190 | |
|---|
| [57] | 191 | return (COLORREF)SendMessage(PBM_SETBKCOLOR, 0, (LPARAM) clrBk); |
|---|
| [27] | 192 | #else |
|---|
| 193 | UNUSED(clrBk); |
|---|
| 194 | return CLR_DEFAULT; |
|---|
| 195 | #endif |
|---|
| 196 | } |
|---|
| 197 | |
|---|
| 198 | BOOL CProgressBar::SetRange(int nLower, int nUpper, int nStep /* = 1 */) |
|---|
| 199 | { |
|---|
| 200 | if (!IsWindow(GetSafeHwnd())) |
|---|
| 201 | return FALSE; |
|---|
| 202 | |
|---|
| 203 | // To take advantage of the Extended Range Values we use the PBM_SETRANGE32 |
|---|
| 204 | // message intead of calling CProgressCtrl::SetRange directly. If this is |
|---|
| 205 | // being compiled under something less than VC 5.0, the necessary defines |
|---|
| 206 | // may not be available. |
|---|
| 207 | |
|---|
| 208 | #ifdef PBM_SETRANGE32 |
|---|
| 209 | ASSERT(-0x7FFFFFFF <= nLower && nLower <= 0x7FFFFFFF); |
|---|
| 210 | ASSERT(-0x7FFFFFFF <= nUpper && nUpper <= 0x7FFFFFFF); |
|---|
| 211 | SendMessage(PBM_SETRANGE32, (WPARAM) nLower, (LPARAM) nUpper); |
|---|
| 212 | #else |
|---|
| 213 | ASSERT(0 <= nLower && nLower <= 65535); |
|---|
| 214 | ASSERT(0 <= nUpper && nUpper <= 65535); |
|---|
| 215 | CProgressCtrl::SetRange(nLower, nUpper); |
|---|
| 216 | #endif |
|---|
| 217 | |
|---|
| 218 | CProgressCtrl::SetStep(nStep); |
|---|
| 219 | return TRUE; |
|---|
| 220 | } |
|---|
| 221 | |
|---|
| 222 | int CProgressBar::SetPos(int nPos) |
|---|
| 223 | { |
|---|
| 224 | if (!IsWindow(GetSafeHwnd())) |
|---|
| 225 | return 0; |
|---|
| 226 | |
|---|
| 227 | #ifdef PBM_SETRANGE32 |
|---|
| 228 | ASSERT(-0x7FFFFFFF <= nPos && nPos <= 0x7FFFFFFF); |
|---|
| 229 | #else |
|---|
| 230 | ASSERT(0 <= nPos && nPos <= 65535); |
|---|
| 231 | #endif |
|---|
| 232 | |
|---|
| 233 | ModifyStyle(0,WS_VISIBLE); |
|---|
| 234 | return CProgressCtrl::SetPos(nPos); |
|---|
| 235 | } |
|---|
| 236 | |
|---|
| 237 | int CProgressBar::OffsetPos(int nPos) |
|---|
| 238 | { |
|---|
| 239 | if (!IsWindow(GetSafeHwnd())) |
|---|
| 240 | return 0; |
|---|
| 241 | |
|---|
| 242 | ModifyStyle(0,WS_VISIBLE); |
|---|
| 243 | return CProgressCtrl::OffsetPos(nPos); |
|---|
| 244 | } |
|---|
| 245 | |
|---|
| 246 | int CProgressBar::SetStep(int nStep) |
|---|
| 247 | { |
|---|
| 248 | if (!IsWindow(GetSafeHwnd())) |
|---|
| 249 | return 0; |
|---|
| 250 | |
|---|
| 251 | ModifyStyle(0,WS_VISIBLE); |
|---|
| 252 | return CProgressCtrl::SetStep(nStep); |
|---|
| 253 | } |
|---|
| 254 | |
|---|
| 255 | int CProgressBar::StepIt() |
|---|
| 256 | { |
|---|
| 257 | if (!IsWindow(GetSafeHwnd())) |
|---|
| 258 | return 0; |
|---|
| 259 | |
|---|
| 260 | ModifyStyle(0,WS_VISIBLE); |
|---|
| 261 | return CProgressCtrl::StepIt(); |
|---|
| 262 | } |
|---|
| 263 | |
|---|
| 264 | BOOL CProgressBar::Resize() |
|---|
| 265 | { |
|---|
| 266 | if (!IsWindow(GetSafeHwnd())) |
|---|
| 267 | return FALSE; |
|---|
| 268 | |
|---|
| 269 | CStatusBar *pStatusBar = GetStatusBar(); |
|---|
| 270 | if (!pStatusBar) |
|---|
| 271 | return FALSE; |
|---|
| 272 | |
|---|
| 273 | // Redraw the window text |
|---|
| 274 | if (IsWindowVisible()) |
|---|
| 275 | { |
|---|
| 276 | pStatusBar->SetPaneText(m_nPane, m_strMessage); |
|---|
| 277 | pStatusBar->UpdateWindow(); |
|---|
| 278 | } |
|---|
| 279 | |
|---|
| 280 | // Calculate how much space the text takes up |
|---|
| 281 | CClientDC dc(pStatusBar); |
|---|
| 282 | CFont *pOldFont = dc.SelectObject(pStatusBar->GetFont()); |
|---|
| 283 | CSize size = dc.GetTextExtent(m_strMessage); // Length of text |
|---|
| 284 | int margin = dc.GetTextExtent(_T(" ")).cx * 2; // Text margin |
|---|
| 285 | dc.SelectObject(pOldFont); |
|---|
| 286 | |
|---|
| 287 | // Now calculate the rectangle in which we will draw the progress bar |
|---|
| 288 | CRect rc; |
|---|
| 289 | pStatusBar->GetItemRect(m_nPane, rc); |
|---|
| 290 | |
|---|
| 291 | // Position left of progress bar after text and right of progress bar |
|---|
| 292 | // to requested percentage of status bar pane |
|---|
| 293 | if (!m_strMessage.IsEmpty()) |
|---|
| 294 | rc.left += (size.cx + 2*margin); |
|---|
| 295 | rc.right -= (rc.right - rc.left) * (100 - m_nSize) / 100; |
|---|
| 296 | |
|---|
| 297 | if (rc.right < rc.left) rc.right = rc.left; |
|---|
| 298 | |
|---|
| 299 | // Leave a litle vertical margin (10%) between the top and bottom of the bar |
|---|
| 300 | int Height = rc.bottom - rc.top; |
|---|
| 301 | rc.bottom -= Height/10; |
|---|
| 302 | rc.top += Height/10; |
|---|
| 303 | |
|---|
| 304 | // If the window size has changed, resize the window |
|---|
| 305 | if (rc != m_Rect) |
|---|
| 306 | { |
|---|
| 307 | MoveWindow(&rc); |
|---|
| 308 | m_Rect = rc; |
|---|
| 309 | } |
|---|
| 310 | |
|---|
| 311 | return TRUE; |
|---|
| 312 | } |
|---|
| 313 | |
|---|
| 314 | BOOL CProgressBar::OnEraseBkgnd(CDC* pDC) |
|---|
| 315 | { |
|---|
| 316 | Resize(); |
|---|
| 317 | return CProgressCtrl::OnEraseBkgnd(pDC); |
|---|
| 318 | } |
|---|