GradientProgressCtrl.cpp
上传用户:oadesign
上传日期:2013-12-25
资源大小:265k
文件大小:13k
源码类别:

进程与线程

开发平台:

Visual C++

  1. #include "stdafx.h"
  2. #include "GradientProgressCtrl.h"
  3. #ifdef _DEBUG
  4. #define new DEBUG_NEW
  5. #undef THIS_FILE
  6. static char THIS_FILE[] = __FILE__;
  7. #endif
  8. /*
  9. Modified by 谢红伟 2000.12
  10. 功能:渐变色进度条显示效果
  11. */
  12. /////////////////////////////////////////////////////////////////////////////
  13. // CGradientProgressCtrl
  14. CGradientProgressCtrl::CGradientProgressCtrl()
  15. {
  16. // Defaults assigned by CProgressCtrl()
  17. m_nLower = 0;
  18. m_nUpper = 100;
  19. m_nCurrentPosition = 0;
  20. m_nStep = 10;
  21. // Initial colors
  22. m_clrStart = COLORREF(RGB(128, 0,128));
  23. m_clrEnd =  COLORREF(RGB(0,128,0));
  24. //改变渐变色进度条背景色
  25. m_clrBkGround = ::GetSysColor(COLOR_3DFACE);
  26. m_clrText = COLORREF(RGB(0, 255, 255));
  27. // Initial show percent
  28. m_bShowPercent = TRUE;
  29. }
  30. CGradientProgressCtrl::~CGradientProgressCtrl()
  31. {
  32. }
  33. BEGIN_MESSAGE_MAP(CGradientProgressCtrl, CProgressCtrl)
  34. //{{AFX_MSG_MAP(CGradientProgressCtrl)
  35. ON_WM_PAINT()
  36. ON_WM_ERASEBKGND()
  37. //}}AFX_MSG_MAP
  38. END_MESSAGE_MAP()
  39. /////////////////////////////////////////////////////////////////////////////
  40. // CGradientProgressCtrl message handlers
  41. /////////////////////////////////////////////////////////////////////////////
  42. /* 
  43. OnPaint
  44. The main drawing routine.  Consists of two parts
  45. (1) Call the DrawGradient routine to draw the visible part of the progress gradient
  46. (2) If needed, show the percentage text
  47.  */
  48. /////////////////////////////////////////////////////////////////////////////
  49. void CGradientProgressCtrl::OnPaint() 
  50. {
  51. CPaintDC dc(this); // device context for painting
  52. // TODO: Add your message handler code here
  53. CRect rectClient;
  54. GetClientRect(&rectClient);
  55. // If the current positionis  invalid then we should fade into the  background
  56. if (m_nCurrentPosition <= m_nLower || m_nCurrentPosition > m_nUpper)
  57. {
  58. CRect rect;
  59. GetClientRect(rect);
  60. CBrush brush;
  61. //重画时渐变色进度条设为自定义颜色
  62. brush.CreateSolidBrush(m_clrBkGround);//::GetSysColor(COLOR_3DFACE));
  63. dc.FillRect(&rect, &brush);
  64. VERIFY(brush.DeleteObject());
  65. return;
  66. }
  67. // The actions to take depend on whether or not we are a vertical control
  68. DWORD dwStyles = GetStyle();
  69. BOOL bVertical = (BOOL)(dwStyles & PBS_VERTICAL);
  70. // Figure out what part should be visible so we can stop the gradient when needed
  71. float maxWidth;
  72. if (bVertical)
  73. maxWidth = ((float)m_nCurrentPosition/(float)m_nUpper * (float)rectClient.bottom);
  74. else
  75. maxWidth = ((float)m_nCurrentPosition/(float)m_nUpper * (float)rectClient.right);
  76. // Draw the gradient
  77. DrawGradient(&dc, rectClient, (int)maxWidth, bVertical);
  78. // Show percent indicator if needed
  79. if (m_bShowPercent)
  80. {
  81. CString strPercent;
  82. float fp = 100.0f; 
  83. fp *= (float)(m_nCurrentPosition-m_nLower); 
  84. fp /= (float)(m_nUpper-m_nLower); 
  85. strPercent.Format(_T("%3.0f %%"), fp);
  86. dc.SetTextColor(m_clrText);
  87. dc.SetBkMode(TRANSPARENT);
  88. dc.DrawText(strPercent, &rectClient, DT_VCENTER |  DT_CENTER | DT_SINGLELINE);
  89. }
  90. // Do not call CProgressCtrl::OnPaint() for painting messages
  91. }
  92. /////////////////////////////////////////////////////////////////////////////
  93. /*
  94. SetRange
  95. Overridden base class member to remember where the indicator thinks 
  96. it is and the boundary range of the control.
  97. Params
  98. nLower lower bound
  99. nUpper uppoer bound
  100. */
  101. /////////////////////////////////////////////////////////////////////////////
  102. void CGradientProgressCtrl:: SetRange(int nLower, int nUpper)
  103. {
  104. m_nLower = nLower;
  105. m_nUpper = nUpper;
  106. m_nCurrentPosition = nLower;
  107. CProgressCtrl::SetRange(nLower, nUpper);
  108. }
  109. /////////////////////////////////////////////////////////////////////////////
  110. /*
  111. SetRange32
  112. Overridden base class member to remember where the indicator thinks 
  113. it is and the boundary range of the control.
  114. Params
  115. nLower lower bound
  116. nUpper uppoer bound
  117. */
  118. /////////////////////////////////////////////////////////////////////////////
  119. void CGradientProgressCtrl:: SetRange32( int nLower, int nUpper )
  120. {
  121. if ( nLower == nUpper ) return;
  122. m_nLower = nLower;
  123. m_nUpper = nUpper;
  124. m_nCurrentPosition = nLower;
  125. CProgressCtrl::SetRange(nLower, nUpper);
  126. }
  127. /////////////////////////////////////////////////////////////////////////////
  128. /*
  129. SetPos
  130. Overridden base class member to retain where the current progress indicator
  131. is located.
  132. Params
  133. nPos Current position in range
  134. */
  135. /////////////////////////////////////////////////////////////////////////////
  136. int CGradientProgressCtrl:: SetPos(int nPos)
  137. {
  138. m_nCurrentPosition = nPos;
  139. return (CProgressCtrl::SetPos(nPos));
  140. }
  141. /////////////////////////////////////////////////////////////////////////////
  142. /*
  143. SetStep
  144. Overridden base class member to retain the step interval used when 
  145. filling the progress control
  146. Params
  147. nStep step interval for filling progress control
  148. */
  149. /////////////////////////////////////////////////////////////////////////////
  150. int CGradientProgressCtrl:: SetStep(int nStep)
  151. {
  152. m_nStep = nStep;
  153. return (CProgressCtrl::SetStep(nStep));
  154. }
  155. /////////////////////////////////////////////////////////////////////////////
  156. /*
  157. StepIt
  158. Overridden base class member to increment the control according to the
  159. current position and the step interval
  160. Params
  161. nStep step interval for filling progress control
  162. */
  163. /////////////////////////////////////////////////////////////////////////////
  164. int CGradientProgressCtrl:: StepIt(void)
  165. {
  166. m_nCurrentPosition += m_nStep;
  167. return (CProgressCtrl::StepIt());
  168. }
  169. /////////////////////////////////////////////////////////////////////////////
  170. /*
  171. DrawGradient
  172. Called from OnPaint, it does most of the work of filling in the client 
  173. rectangle with the appropriate colors.  The normal routine would fill
  174. the entire client rectangle, but we truncate the drawing to reflect
  175. the current position in the progress control
  176. Params
  177. pDC pointer to CPaintDC for rendering
  178. rectClient client rectangle where we should draw
  179. nMaxWidth where we should stop drawing the gradient
  180. */
  181. /////////////////////////////////////////////////////////////////////////////
  182. void CGradientProgressCtrl::DrawGradient(CPaintDC *pDC, const RECT &rectClient, const int &nMaxWidth, const BOOL &bVertical)
  183. {
  184. RECT rectFill;    // Rectangle for filling band
  185. float fStep;              // How wide is each band?
  186. CBrush brush; // Brush to fill in the bar
  187. CMemDC1 memDC(pDC);
  188. // First find out the largest color distance between the start and end colors.  This distance
  189. // will determine how many steps we use to carve up the client region and the size of each
  190. // gradient rect.
  191. int r, g, b; // First distance, then starting value
  192. float rStep, gStep, bStep; // Step size for each color
  193. BOOL  bSameColor = FALSE; // Handle case if start color == end color
  194. // Get the color differences
  195. r = (GetRValue(m_clrEnd) - GetRValue(m_clrStart));
  196. g = (GetGValue(m_clrEnd) - GetGValue(m_clrStart));
  197. b =  (GetBValue(m_clrEnd) - GetBValue(m_clrStart));
  198. // Check to see if colors are same
  199. if((r == 0) && (g == 0) && (b == 0))
  200. {
  201. bSameColor = TRUE;
  202. //Added the three lines below to fix the drawing 
  203. //problem which used to occur when both the start 
  204. //and end colors are same.
  205. r = GetRValue(m_clrStart);
  206. g = GetGValue(m_clrStart);
  207. b = GetBValue(m_clrStart);
  208. }
  209. int nSteps;
  210. //Select max. possible value for nSteps if the colors are equal
  211. if(bSameColor && m_clrStart == 0)
  212. nSteps = 255;
  213. else  // Make the number of steps equal to the greatest distance
  214. nSteps = max(abs(r), max(abs(g), abs(b)));
  215. // Determine how large each band should be in order to cover the
  216. // client with nSteps bands (one for every color intensity level)
  217. if (bVertical)
  218. fStep = (float)rectClient.bottom / (float)nSteps;
  219. else
  220. fStep = (float)rectClient.right / (float)nSteps;
  221. // Calculate the step size for each color
  222. rStep = r/(float)nSteps;
  223. gStep = g/(float)nSteps;
  224. bStep = b/(float)nSteps;
  225. // Reset the colors to the starting position
  226. r = GetRValue(m_clrStart);
  227. g = GetGValue(m_clrStart);
  228. b = GetBValue(m_clrStart);
  229. // Start filling bands
  230. for (int iOnBand = 0; iOnBand < nSteps; iOnBand++) 
  231. {
  232. // Fill the vertical control
  233. if (bVertical)
  234. {
  235. ::SetRect(&rectFill,
  236. 0, // Upper left X
  237. (int)(iOnBand * fStep), // Upper left Y
  238. rectClient.right+1, // Lower right X
  239. (int)((iOnBand+1) * fStep));// Lower right Y
  240. // CDC::FillSolidRect is faster, but it does not handle 8-bit color depth
  241. if ( brush.CreateSolidBrush(RGB(r+rStep*iOnBand, g + gStep*iOnBand, b + bStep *iOnBand)) )
  242. {
  243. memDC.FillRect(&rectFill,&brush);
  244. VERIFY(brush.DeleteObject());
  245. }
  246. // If we are past the maximum for the current position we need to get out of the loop.
  247. // Before we leave, we repaint the remainder of the client area with the background color.
  248. if (rectFill.bottom > nMaxWidth)
  249. {
  250. ::SetRect(&rectFill, 0, rectFill.bottom, rectClient.right, rectClient.bottom);
  251. if ( brush.CreateSolidBrush(m_clrBkGround) )
  252. {
  253. memDC.FillRect(&rectFill, &brush);
  254. VERIFY(brush.DeleteObject());
  255. }
  256. return;
  257. }
  258. }
  259. else // Fill the horizontal control
  260. {
  261. ::SetRect(&rectFill,
  262. (int)(iOnBand * fStep),     // Upper left X
  263.  0, // Upper left Y
  264. (int)((iOnBand+1) * fStep), // Lower right X
  265. rectClient.bottom+1); // Lower right Y
  266. // CDC::FillSolidRect is faster, but it does not handle 8-bit color depth
  267. if ( brush.CreateSolidBrush(RGB(r+rStep*iOnBand, g + gStep*iOnBand, b + bStep *iOnBand)) )
  268. {
  269. memDC.FillRect(&rectFill,&brush);
  270. VERIFY(brush.DeleteObject());
  271. }
  272. // If we are past the maximum for the current position we need to get out of the loop.
  273. // Before we leave, we repaint the remainder of the client area with the background color.
  274. if (rectFill.right > nMaxWidth)
  275. {
  276. ::SetRect(&rectFill, rectFill.right, 0, rectClient.right, rectClient.bottom);
  277. if ( brush.CreateSolidBrush(m_clrBkGround) )
  278. {
  279. memDC.FillRect(&rectFill, &brush);
  280. VERIFY(brush.DeleteObject());
  281. }
  282. return;
  283. }
  284. }
  285. }
  286. }
  287. /////////////////////////////////////////////////////////////////////////////
  288. /*
  289. OnEraseBkgnd
  290. Overridden CWnd function so that all drawing is done in the OnPaint call.
  291. We return TRUE so that CWnd doesn't try to erase our background.
  292. Params
  293. pDC pointer to CDC for rendering
  294. */
  295. /////////////////////////////////////////////////////////////////////////////
  296. BOOL CGradientProgressCtrl::OnEraseBkgnd(CDC* pDC) 
  297. {
  298. // TODO: Add your message handler code here and/or call default
  299. return TRUE;
  300. }
  301. BOOL CGradientProgressCtrl::Create(CStatusBar *parent, UINT id, DWORD style)
  302. {
  303. CRect r;
  304. setup(parent, id, r);
  305. return CProgressCtrl::Create(style | WS_CHILD, r, parent, id);
  306. }
  307. /****************************************************************************
  308. *                            CStatusControl::setup
  309. * Inputs:
  310. * CStatusBar * parent: Parent window (status bar)
  311. * UINT id: ID of pane
  312. * CRect & r: Place to put rectangle
  313. * Result: BOOL
  314. *       TRUE if successful
  315. * FALSE if the area is off-window
  316. * Effect: 
  317. *       Computes the rectangle for the pane, given the status bar and id
  318. ****************************************************************************/
  319. BOOL CGradientProgressCtrl::setup(CStatusBar *parent, UINT id, CRect &r)
  320. {
  321. int i = parent->CommandToIndex(id);
  322. parent->GetItemRect(i, &r);
  323. parent->SetPaneText(i, "");
  324. // If the pane was not visible, GetItemRect has returned a
  325. // (0, 0, 0, 0) rectangle. Attempting to create the control
  326. // using this rectangle creates it, possibly of zero size,
  327. // at the left of the status bar. We correct this by
  328. // forcing it to be off the visible right end of the status
  329. // bar. If the programmer properly handles the parent frame's
  330. // OnSize method, when the control becomes visible it will
  331. // move to the correct location.
  332. if(r.IsRectEmpty())
  333. { /* offscreen */
  334. CRect r1;
  335. parent->GetWindowRect(&r1); // get parent width
  336. r.left = r1.right + 1;
  337. r.top =  r1.top;
  338. r.right = r1.right + 2;
  339. r.bottom = r1.bottom;
  340. return FALSE;
  341. } /* offscreen */
  342. return TRUE;
  343. }
  344. void CGradientProgressCtrl::Reposition()
  345. {
  346. if ( m_hWnd == NULL)
  347. return;
  348. UINT id = ::GetWindowLong(m_hWnd, GWL_ID);
  349. CRect r;
  350. // Note that because the control ID is the same as the
  351. // pane ID, this actually works well enough that
  352. // no special variable is required to obtain the
  353. // pane index.
  354. CStatusBar * parent = (CStatusBar *)GetParent();
  355. int i = parent->CommandToIndex(id);
  356. parent->GetItemRect(i, &r);
  357. SetWindowPos(&wndTop, r.left, r.top, r.Width(), r.Height(), 0);
  358. }