ProgressBar.cpp
上传用户:xp758258
上传日期:2007-01-02
资源大小:40k
文件大小:8k
源码类别:

状态条

开发平台:

Visual C++

  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. #include "stdafx.h"
  36. #include "ProgressBar.h"
  37. #ifdef _DEBUG
  38. #define new DEBUG_NEW
  39. #undef THIS_FILE
  40. static char THIS_FILE[] = __FILE__;
  41. #endif
  42. IMPLEMENT_DYNCREATE(CProgressBar, CProgressCtrl)
  43. BEGIN_MESSAGE_MAP(CProgressBar, CProgressCtrl)
  44. //{{AFX_MSG_MAP(CProgressBar)
  45. ON_WM_ERASEBKGND()
  46. //}}AFX_MSG_MAP
  47. END_MESSAGE_MAP()
  48. CProgressBar::CProgressBar()
  49. {
  50. m_Rect.SetRect(0,0,0,0);
  51. }
  52. CProgressBar::CProgressBar(LPCTSTR strMessage, int nSize /*=100*/, 
  53.    int MaxValue /*=100*/, BOOL bSmooth /*=FALSE*/, 
  54.                            int nPane /*=0*/)
  55. {
  56. Create(strMessage, nSize, MaxValue, bSmooth, nPane);
  57. }
  58. CProgressBar::~CProgressBar()
  59. {
  60. Clear();
  61. }
  62. CStatusBar* CProgressBar::GetStatusBar()
  63. {
  64. CWnd *pMainWnd = AfxGetMainWnd();
  65. if (!pMainWnd)
  66. return NULL;
  67.     // If main window is a frame window, use normal methods...
  68.     if (pMainWnd->IsKindOf(RUNTIME_CLASS(CFrameWnd)))
  69.     {
  70.         CWnd* pMessageBar = ((CFrameWnd*)pMainWnd)->GetMessageBar();
  71.         return DYNAMIC_DOWNCAST(CStatusBar, pMessageBar);
  72.     }
  73.     // otherwise traverse children to try and find the status bar...
  74.     else
  75.     return DYNAMIC_DOWNCAST(CStatusBar, 
  76.                                 pMainWnd->GetDescendantWindow(AFX_IDW_STATUS_BAR));
  77. }
  78. // Create the CProgressCtrl as a child of the status bar positioned
  79. // over the first pane, extending "nSize" percentage across pane.
  80. // Sets the range to be 0 to MaxValue, with a step of 1.
  81. BOOL CProgressBar::Create(LPCTSTR strMessage, int nSize /*=100*/, 
  82.   int MaxValue /*=100*/, BOOL bSmooth /*=FALSE*/, 
  83.                           int nPane /*=0*/)
  84. {
  85. BOOL bSuccess = FALSE;
  86. CStatusBar *pStatusBar = GetStatusBar();
  87. if (!pStatusBar)
  88. return FALSE;
  89. DWORD dwStyle = WS_CHILD|WS_VISIBLE;
  90. #ifdef PBS_SMOOTH  
  91. if (bSmooth)
  92. dwStyle |= PBS_SMOOTH;
  93. #endif
  94. // Get CRect coordinates for requested status bar pane
  95. CRect PaneRect;
  96. pStatusBar->GetItemRect(nPane, &PaneRect);
  97. // Create the progress bar
  98. bSuccess = CProgressCtrl::Create(dwStyle, PaneRect, pStatusBar, 1);
  99. ASSERT(bSuccess);
  100. if (!bSuccess)
  101. return FALSE;
  102. // Set range and step
  103. SetRange(0, MaxValue);
  104. SetStep(1);
  105. m_strMessage  = strMessage;
  106. m_nSize    = nSize;
  107. m_nPane    = nPane;
  108.     m_strPrevText = pStatusBar->GetPaneText(m_nPane); 
  109. // Resize the control to its desired width
  110. Resize();
  111. return TRUE;
  112. }
  113. void CProgressBar::Clear()
  114. {
  115. if (!IsWindow(GetSafeHwnd()))
  116. return;
  117. // Hide the window. This is necessary so that a cleared
  118. // window is not redrawn if "Resize" is called
  119. ModifyStyle(WS_VISIBLE, 0);
  120. CString str;
  121. if (m_nPane == 0)
  122. str.LoadString(AFX_IDS_IDLEMESSAGE);   // Get the IDLE_MESSAGE
  123.       else
  124. str = m_strPrevText;                   // Restore previous text
  125. // Place the IDLE_MESSAGE in the status bar 
  126. CStatusBar *pStatusBar = GetStatusBar();
  127. if (pStatusBar)
  128. {
  129. pStatusBar->SetPaneText(m_nPane, str);
  130. pStatusBar->UpdateWindow();
  131. }
  132. }
  133. BOOL CProgressBar::SetText(LPCTSTR strMessage)
  134. m_strMessage = strMessage; 
  135. return Resize(); 
  136. }
  137. BOOL CProgressBar::SetSize(int nSize)
  138. {
  139. m_nSize = nSize; 
  140. return Resize();
  141. }
  142. COLORREF CProgressBar::SetBarColour(COLORREF clrBar)
  143. {
  144. #ifdef PBM_SETBKCOLOR
  145. if (!IsWindow(GetSafeHwnd()))
  146.           return CLR_DEFAULT;
  147. return SendMessage(PBM_SETBARCOLOR, 0, (LPARAM) clrBar);
  148. #else
  149. UNUSED(clrBar);
  150. return CLR_DEFAULT;
  151. #endif
  152. }
  153. COLORREF CProgressBar::SetBkColour(COLORREF clrBk)
  154. {
  155. #ifdef PBM_SETBKCOLOR
  156. if (!IsWindow(GetSafeHwnd()))
  157. return CLR_DEFAULT;
  158. return SendMessage(PBM_SETBKCOLOR, 0, (LPARAM) clrBk);
  159. #else
  160. UNUSED(clrBk);
  161. return CLR_DEFAULT;
  162. #endif
  163. }
  164. BOOL CProgressBar::SetRange(int nLower, int nUpper, int nStep /* = 1 */)
  165. {  
  166. if (!IsWindow(GetSafeHwnd()))
  167. return FALSE;
  168. // To take advantage of the Extended Range Values we use the PBM_SETRANGE32
  169. // message intead of calling CProgressCtrl::SetRange directly. If this is
  170. // being compiled under something less than VC 5.0, the necessary defines
  171. // may not be available.
  172. #ifdef PBM_SETRANGE32
  173. ASSERT(-0x7FFFFFFF <= nLower && nLower <= 0x7FFFFFFF);
  174. ASSERT(-0x7FFFFFFF <= nUpper && nUpper <= 0x7FFFFFFF);
  175. SendMessage(PBM_SETRANGE32, (WPARAM) nLower, (LPARAM) nUpper);
  176. #else
  177. ASSERT(0 <= nLower && nLower <= 65535);
  178. ASSERT(0 <= nUpper && nUpper <= 65535);
  179. CProgressCtrl::SetRange(nLower, nUpper);
  180. #endif
  181. CProgressCtrl::SetStep(nStep);
  182. return TRUE;
  183. }
  184. int CProgressBar::SetPos(int nPos)    
  185. {
  186. if (!IsWindow(GetSafeHwnd()))
  187. return 0;
  188. #ifdef PBM_SETRANGE32
  189. ASSERT(-0x7FFFFFFF <= nPos && nPos <= 0x7FFFFFFF);
  190. #else
  191. ASSERT(0 <= nPos && nPos <= 65535);
  192. #endif
  193. ModifyStyle(0,WS_VISIBLE);
  194. return CProgressCtrl::SetPos(nPos);
  195. }
  196. int CProgressBar::OffsetPos(int nPos) 
  197. if (!IsWindow(GetSafeHwnd()))
  198. return 0;
  199. ModifyStyle(0,WS_VISIBLE);
  200. return CProgressCtrl::OffsetPos(nPos);
  201. }
  202. int CProgressBar::SetStep(int nStep)
  203. if (!IsWindow(GetSafeHwnd()))
  204. return 0;
  205. ModifyStyle(0,WS_VISIBLE);
  206. return CProgressCtrl::SetStep(nStep);  
  207. }
  208. int CProgressBar::StepIt() 
  209. if (!IsWindow(GetSafeHwnd()))
  210. return 0;
  211. ModifyStyle(0,WS_VISIBLE);
  212. return CProgressCtrl::StepIt();    
  213. }
  214. BOOL CProgressBar::Resize() 
  215. {
  216. if (!IsWindow(GetSafeHwnd()))
  217. return FALSE;
  218. CStatusBar *pStatusBar = GetStatusBar();
  219. if (!pStatusBar)
  220. return FALSE;
  221. // Redraw the window text
  222. if (IsWindowVisible())
  223. {
  224. pStatusBar->SetPaneText(m_nPane, m_strMessage);
  225. pStatusBar->UpdateWindow();
  226. }
  227. // Calculate how much space the text takes up
  228. CClientDC dc(pStatusBar);
  229. CFont *pOldFont = dc.SelectObject(pStatusBar->GetFont());
  230. CSize size = dc.GetTextExtent(m_strMessage); // Length of text
  231. int margin = dc.GetTextExtent(_T(" ")).cx * 2; // Text margin
  232. dc.SelectObject(pOldFont);
  233. // Now calculate the rectangle in which we will draw the progress bar
  234. CRect rc;
  235. pStatusBar->GetItemRect(m_nPane, rc);
  236. // Position left of progress bar after text and right of progress bar
  237. // to requested percentage of status bar pane
  238. if (!m_strMessage.IsEmpty())
  239.     rc.left += (size.cx + 2*margin);
  240. rc.right -= (rc.right - rc.left) * (100 - m_nSize) / 100;
  241. if (rc.right < rc.left) rc.right = rc.left;
  242. // Leave a litle vertical margin (10%) between the top and bottom of the bar
  243. int Height = rc.bottom - rc.top;
  244. rc.bottom -= Height/10;
  245. rc.top   += Height/10;
  246. // If the window size has changed, resize the window
  247. if (rc != m_Rect)
  248. {
  249. MoveWindow(&rc);
  250. m_Rect = rc;
  251. }
  252. return TRUE;
  253. }
  254. BOOL CProgressBar::OnEraseBkgnd(CDC* pDC) 
  255. {
  256. Resize();
  257. return CProgressCtrl::OnEraseBkgnd(pDC);
  258. }