PieChartCtrl.cpp
上传用户:tianjwyx
上传日期:2007-01-13
资源大小:813k
文件大小:8k
源码类别:

操作系统开发

开发平台:

Visual C++

  1. // PieChartCtrl.cpp : implementation file
  2. //
  3. // Written by Yuheng Zhao (yuheng@ministars.com)
  4. // Copyright (c) 1998.
  5. //
  6. // This code may be used in compiled form in any way you desire. This
  7. // file may be redistributed unmodified by any means PROVIDING it is 
  8. // not sold for profit without the authors written consent, and 
  9. // providing that this notice and the authors name is included. If 
  10. // the source code in  this file is used in any commercial application 
  11. // then a simple email would be nice.
  12. //
  13. // This file is provided "as is" with no expressed or implied warranty.
  14. // The author accepts no liability if it causes any damage whatsoever.
  15. // It's free - so you get what you pay for.
  16. #include "stdafx.h"
  17. #include "PieChartCtrl.h"
  18. #include <math.h>
  19. #ifdef _DEBUG
  20. #define new DEBUG_NEW
  21. #undef THIS_FILE
  22. static char THIS_FILE[] = __FILE__;
  23. #endif
  24. const double pi = 3.1415926535;
  25. /////////////////////////////////////////////////////////////////////////////
  26. // CPieChartCtrl
  27. CPieChartCtrl::CPieChartCtrl()
  28. {
  29. CPieChartCtrl::RegisterWndClass(AfxGetInstanceHandle());
  30. m_nStartAngle = 0;
  31. m_colorLine = RGB(0,0,0);
  32. m_colorDefault = RGB(0,0,255);
  33. m_rectChart.SetRect(0,0,0,0);
  34. m_bCaptured = FALSE;
  35. m_strTitle = _T("");
  36. m_fontTitle.CreateFont(15, 0,0,0,FW_NORMAL, 0,0,0,
  37. DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS,
  38. DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial");
  39. m_fontInfo.CreateFont(13, 0,0,0,FW_NORMAL, 0,0,0,
  40. DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS,
  41. DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial");
  42. }
  43. CPieChartCtrl::~CPieChartCtrl()
  44. {
  45. Reset();
  46. }
  47. BEGIN_MESSAGE_MAP(CPieChartCtrl, CWnd)
  48. //{{AFX_MSG_MAP(CPieChartCtrl)
  49. ON_WM_PAINT()
  50. ON_WM_LBUTTONUP()
  51. ON_WM_LBUTTONDOWN()
  52. ON_WM_MOUSEMOVE()
  53. ON_WM_SIZE()
  54. //}}AFX_MSG_MAP
  55. END_MESSAGE_MAP()
  56. /////////////////////////////////////////////////////////////////////////////
  57. // CPieChartCtrl message handlers
  58. BOOL CPieChartCtrl::RegisterWndClass(HINSTANCE hInstance)
  59. {
  60. WNDCLASS wc;
  61. wc.lpszClassName = "PIE_CHART_CTRL"; // matches class name in client
  62. wc.hInstance = hInstance;
  63. wc.lpfnWndProc = ::DefWindowProc;
  64. wc.hCursor = ::LoadCursor(NULL, IDC_CROSS);
  65. wc.hIcon = 0;
  66. wc.lpszMenuName = NULL;
  67. wc.hbrBackground = (HBRUSH) ::GetStockObject(LTGRAY_BRUSH);
  68. wc.style = CS_GLOBALCLASS; // To be modified
  69. wc.cbClsExtra = 0;
  70. wc.cbWndExtra = 0;
  71. return (::RegisterClass(&wc) != 0);
  72. }
  73. void CPieChartCtrl::OnPaint() 
  74. {
  75. if (m_rectChart.IsRectEmpty()) // First Time
  76. RecalcRect();
  77. CPaintDC dc(this); // device context for painting
  78. CRect clientRect;
  79. GetClientRect(&clientRect);
  80. CBitmap *pOldMemDCBitmap = NULL;
  81. CDC memDC;
  82. CBitmap bitmap;
  83. memDC.CreateCompatibleDC(&dc);
  84. bitmap.CreateCompatibleBitmap( &dc, clientRect.Width(), clientRect.Height() );
  85. CBitmap *pOldmemDCBitmap = (CBitmap*)memDC.SelectObject(&bitmap);
  86. //memDC.FillSolidRect(clientRect, GetSysColor(COLOR_3DFACE));
  87.     memDC.FillSolidRect(clientRect, RGB(214,223,247));
  88. CPen pen;
  89. pen.CreatePen(PS_SOLID, 1, m_colorLine);
  90. CPen* pOldPen = (CPen*)memDC.SelectStockObject(NULL_PEN);
  91. CBrush brush;
  92. brush.CreateSolidBrush(m_colorDefault);
  93. CBrush* pOldBrush = memDC.SelectObject(&brush);
  94. memDC.Ellipse(m_rectChart);
  95. int nCount = m_chartPieces.GetSize();
  96. CPieChartPiece* pItem;
  97. CPoint pt1, pt2;
  98. int nCurrectAngle = m_nStartAngle;
  99. int nInfo=0;
  100. CountPoint(nCurrectAngle, pt1);
  101. for (int i=0; i<nCount; i++)
  102. {
  103. pItem = m_chartPieces.GetAt(i);
  104. nCurrectAngle += pItem->m_nAngle;
  105. CountPoint(nCurrectAngle, pt2);
  106. memDC.SelectStockObject(NULL_PEN);
  107. memDC.SelectObject(&pItem->m_brushBack);
  108. if (pt2!=pt1)
  109. memDC.Pie(m_rectChart, pt2, pt1);
  110. //Draw line
  111. memDC.SelectObject(&pen);
  112. memDC.MoveTo(pt1);
  113. memDC.LineTo(m_rectChart.CenterPoint());
  114. memDC.LineTo(pt2);
  115. //Draw info
  116. CFont* pOldFont = memDC.SelectObject(&m_fontInfo);
  117. memDC.SetBkMode(TRANSPARENT);
  118. if (!(pItem->m_strInfo).IsEmpty())
  119. {
  120. CSize sz = memDC.GetTextExtent(pItem->m_strInfo);
  121. CRect rcColor(clientRect);
  122. rcColor.left = rcColor.right - sz.cy;
  123. rcColor.bottom = rcColor.top + sz.cy;
  124. rcColor.OffsetRect(0, nInfo*rcColor.Height());//+m_nTitleHeight);
  125. memDC.FillSolidRect(rcColor, pItem->m_colorBack); // i must be less than MAX_COLOR
  126. memDC.DrawEdge(rcColor, EDGE_SUNKEN, BF_RECT);
  127. memDC.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
  128. rcColor.right = rcColor.left - 3;
  129. rcColor.left = clientRect.left;
  130. memDC.DrawText(pItem->m_strInfo, rcColor, DT_RIGHT|DT_VCENTER);
  131. nInfo++;
  132. }
  133. // Draw percent
  134. if (pItem->m_nAngle>25)
  135. {
  136. int n = nCurrectAngle - (pItem->m_nAngle)/2;
  137. CPoint p;
  138. CountPoint(n, p, TRUE);
  139. CString str;
  140. str.Format("%.0f%%", (double)(pItem->m_nAngle)*100.0/360.0);
  141. CSize sz = memDC.GetTextExtent(str);
  142. memDC.SetTextColor(pItem->m_colorText);
  143. memDC.TextOut(p.x-sz.cx/2, p.y-sz.cy/2, str);
  144. }
  145. memDC.SelectObject(pOldFont);
  146. pt1 = pt2;
  147. }
  148. // Draw Line for the out circle
  149. memDC.SelectObject(&pen);
  150. memDC.SelectStockObject(NULL_BRUSH);
  151. memDC.Ellipse(m_rectChart);
  152. //Draw Title
  153. if (!m_strTitle.IsEmpty())
  154. {
  155. CFont* pOldFont = memDC.SelectObject(&m_fontTitle);
  156. memDC.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
  157. memDC.SetBkMode(TRANSPARENT);
  158. memDC.TextOut(1, 1, m_strTitle);
  159. memDC.SelectObject(pOldFont);
  160. }
  161. dc.BitBlt( 0, 0, clientRect.Width(), clientRect.Height(), 
  162.                                        &memDC, 0, 0, SRCCOPY );
  163. memDC.SelectObject(pOldPen);
  164. memDC.SelectObject(&pOldBrush);
  165. memDC.SelectObject(pOldmemDCBitmap);
  166. }
  167. void CPieChartCtrl::OnLButtonUp(UINT, CPoint) 
  168. {
  169. if (m_bCaptured)
  170. {
  171. ::ReleaseCapture();
  172. m_bCaptured = FALSE;
  173. }
  174. }
  175. void CPieChartCtrl::OnLButtonDown(UINT, CPoint point) 
  176. {
  177. SetCapture();
  178. m_bCaptured = TRUE;
  179. m_ptOldPt = point;
  180. }
  181. void CPieChartCtrl::OnMouseMove(UINT, CPoint point) 
  182. {
  183. if (m_bCaptured)
  184. {
  185. int nOffX = point.x - m_ptOldPt.x;
  186. m_nStartAngle += nOffX;
  187. InvalidateRect(m_rectChart, FALSE);
  188. m_ptOldPt = point;
  189. }
  190. }
  191. void CPieChartCtrl::OnSize(UINT nType, int cx, int cy) 
  192. {
  193. CWnd::OnSize(nType, cx, cy);
  194. RecalcRect();
  195. }
  196. void CPieChartCtrl::RecalcRect()
  197. {
  198. CRect rect;
  199. GetClientRect(&rect);
  200. if (!m_strTitle.IsEmpty())
  201. {
  202. CClientDC dc(this);
  203. CFont* pOldFont = dc.SelectObject(&m_fontTitle);
  204. CSize sz = dc.GetTextExtent(m_strTitle);
  205. m_nTitleHeight = sz.cy;
  206. rect.top += sz.cy*2;// Leave  lines.
  207. dc.SelectObject(pOldFont);
  208. }
  209. int nSize = (rect.Width()>rect.Height())?rect.Height():rect.Width();
  210. m_rectChart = CRect(CPoint(rect.left + (rect.Width()-nSize)/2, 
  211. rect.top + (rect.Height()-nSize)), 
  212. CSize(nSize, nSize));
  213. }
  214. BOOL CPieChartCtrl::AddPiece(COLORREF colorBack, COLORREF colorText,
  215.  int nAngle, const CString& str)
  216. {
  217. CPieChartPiece* pItem = new CPieChartPiece;
  218. pItem -> m_colorBack = colorBack;
  219. pItem -> m_colorText = colorText;
  220. pItem -> m_brushBack.CreateSolidBrush(colorBack);
  221. pItem -> m_nAngle = nAngle;
  222. pItem -> m_strInfo = str;
  223. try 
  224. {
  225. m_chartPieces.Add(pItem);
  226. InvalidateRect(NULL, FALSE);
  227. return TRUE;
  228. }
  229. catch (CMemoryException* e)
  230. {
  231. if (pItem !=NULL) 
  232. delete pItem;
  233. e->Delete();
  234. return FALSE;
  235. }
  236. }
  237. // bPercent is TRUE when counting the position for the percent info
  238. void CPieChartCtrl::CountPoint(int nAngle, CPoint & pt, BOOL bPercent)
  239. {
  240. while (nAngle <0)
  241. nAngle += 360;
  242. while (nAngle>359)
  243. nAngle -= 360;
  244. double dAngle = ((double)nAngle)*pi/(double)180;
  245. double r;
  246. r = ((double)m_rectChart.Height())/2.0;
  247. if (bPercent)
  248. r = r*3.0/5.0;
  249. double dOffX = (r*sin(dAngle));
  250. double dOffY = 0.0 - (r*cos(dAngle));
  251. double dX = ((double)(m_rectChart.right+m_rectChart.left))/2.0;
  252. double dY = ((double)(m_rectChart.top+m_rectChart.bottom))/2.0;
  253. pt.x = (int)(dX + dOffX);
  254. pt.y = (int)(dY + dOffY);
  255. }
  256. void CPieChartCtrl::Reset()
  257. {
  258. int nCount = m_chartPieces.GetSize();
  259. for (int i = 0; i < nCount; i++)
  260. delete m_chartPieces.GetAt(i);
  261. m_chartPieces.RemoveAll();
  262. }
  263. void CPieChartCtrl::GetItemColor(int i, COLORREF& color)
  264. {
  265. int nCount = m_chartPieces.GetSize();
  266. if (i>=nCount)
  267. i=nCount-1;
  268. color = (m_chartPieces.GetAt(i))->m_colorBack;
  269. }
  270. void CPieChartCtrl::SetTitle(const CString & str)
  271. {
  272. m_strTitle = str;
  273. RecalcRect();
  274. InvalidateRect(NULL, FALSE);
  275. }