PieChartCtrl.cpp
资源名称:OSDemo [点击查看]
上传用户:tianjwyx
上传日期:2007-01-13
资源大小:813k
文件大小:8k
源码类别:
操作系统开发
开发平台:
Visual C++
- // PieChartCtrl.cpp : implementation file
- //
- // Written by Yuheng Zhao (yuheng@ministars.com)
- // Copyright (c) 1998.
- //
- // This code may be used in compiled form in any way you desire. This
- // file may be redistributed unmodified by any means PROVIDING it is
- // not sold for profit without the authors written consent, and
- // providing that this notice and the authors name is included. If
- // the source code in this file is used in any commercial application
- // then a simple email would be nice.
- //
- // This file is provided "as is" with no expressed or implied warranty.
- // The author accepts no liability if it causes any damage whatsoever.
- // It's free - so you get what you pay for.
- #include "stdafx.h"
- #include "PieChartCtrl.h"
- #include <math.h>
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- const double pi = 3.1415926535;
- /////////////////////////////////////////////////////////////////////////////
- // CPieChartCtrl
- CPieChartCtrl::CPieChartCtrl()
- {
- CPieChartCtrl::RegisterWndClass(AfxGetInstanceHandle());
- m_nStartAngle = 0;
- m_colorLine = RGB(0,0,0);
- m_colorDefault = RGB(0,0,255);
- m_rectChart.SetRect(0,0,0,0);
- m_bCaptured = FALSE;
- m_strTitle = _T("");
- m_fontTitle.CreateFont(15, 0,0,0,FW_NORMAL, 0,0,0,
- DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS,
- DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial");
- m_fontInfo.CreateFont(13, 0,0,0,FW_NORMAL, 0,0,0,
- DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS,
- DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial");
- }
- CPieChartCtrl::~CPieChartCtrl()
- {
- Reset();
- }
- BEGIN_MESSAGE_MAP(CPieChartCtrl, CWnd)
- //{{AFX_MSG_MAP(CPieChartCtrl)
- ON_WM_PAINT()
- ON_WM_LBUTTONUP()
- ON_WM_LBUTTONDOWN()
- ON_WM_MOUSEMOVE()
- ON_WM_SIZE()
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // CPieChartCtrl message handlers
- BOOL CPieChartCtrl::RegisterWndClass(HINSTANCE hInstance)
- {
- WNDCLASS wc;
- wc.lpszClassName = "PIE_CHART_CTRL"; // matches class name in client
- wc.hInstance = hInstance;
- wc.lpfnWndProc = ::DefWindowProc;
- wc.hCursor = ::LoadCursor(NULL, IDC_CROSS);
- wc.hIcon = 0;
- wc.lpszMenuName = NULL;
- wc.hbrBackground = (HBRUSH) ::GetStockObject(LTGRAY_BRUSH);
- wc.style = CS_GLOBALCLASS; // To be modified
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- return (::RegisterClass(&wc) != 0);
- }
- void CPieChartCtrl::OnPaint()
- {
- if (m_rectChart.IsRectEmpty()) // First Time
- RecalcRect();
- CPaintDC dc(this); // device context for painting
- CRect clientRect;
- GetClientRect(&clientRect);
- CBitmap *pOldMemDCBitmap = NULL;
- CDC memDC;
- CBitmap bitmap;
- memDC.CreateCompatibleDC(&dc);
- bitmap.CreateCompatibleBitmap( &dc, clientRect.Width(), clientRect.Height() );
- CBitmap *pOldmemDCBitmap = (CBitmap*)memDC.SelectObject(&bitmap);
- //memDC.FillSolidRect(clientRect, GetSysColor(COLOR_3DFACE));
- memDC.FillSolidRect(clientRect, RGB(214,223,247));
- CPen pen;
- pen.CreatePen(PS_SOLID, 1, m_colorLine);
- CPen* pOldPen = (CPen*)memDC.SelectStockObject(NULL_PEN);
- CBrush brush;
- brush.CreateSolidBrush(m_colorDefault);
- CBrush* pOldBrush = memDC.SelectObject(&brush);
- memDC.Ellipse(m_rectChart);
- int nCount = m_chartPieces.GetSize();
- CPieChartPiece* pItem;
- CPoint pt1, pt2;
- int nCurrectAngle = m_nStartAngle;
- int nInfo=0;
- CountPoint(nCurrectAngle, pt1);
- for (int i=0; i<nCount; i++)
- {
- pItem = m_chartPieces.GetAt(i);
- nCurrectAngle += pItem->m_nAngle;
- CountPoint(nCurrectAngle, pt2);
- memDC.SelectStockObject(NULL_PEN);
- memDC.SelectObject(&pItem->m_brushBack);
- if (pt2!=pt1)
- memDC.Pie(m_rectChart, pt2, pt1);
- //Draw line
- memDC.SelectObject(&pen);
- memDC.MoveTo(pt1);
- memDC.LineTo(m_rectChart.CenterPoint());
- memDC.LineTo(pt2);
- //Draw info
- CFont* pOldFont = memDC.SelectObject(&m_fontInfo);
- memDC.SetBkMode(TRANSPARENT);
- if (!(pItem->m_strInfo).IsEmpty())
- {
- CSize sz = memDC.GetTextExtent(pItem->m_strInfo);
- CRect rcColor(clientRect);
- rcColor.left = rcColor.right - sz.cy;
- rcColor.bottom = rcColor.top + sz.cy;
- rcColor.OffsetRect(0, nInfo*rcColor.Height());//+m_nTitleHeight);
- memDC.FillSolidRect(rcColor, pItem->m_colorBack); // i must be less than MAX_COLOR
- memDC.DrawEdge(rcColor, EDGE_SUNKEN, BF_RECT);
- memDC.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
- rcColor.right = rcColor.left - 3;
- rcColor.left = clientRect.left;
- memDC.DrawText(pItem->m_strInfo, rcColor, DT_RIGHT|DT_VCENTER);
- nInfo++;
- }
- // Draw percent
- if (pItem->m_nAngle>25)
- {
- int n = nCurrectAngle - (pItem->m_nAngle)/2;
- CPoint p;
- CountPoint(n, p, TRUE);
- CString str;
- str.Format("%.0f%%", (double)(pItem->m_nAngle)*100.0/360.0);
- CSize sz = memDC.GetTextExtent(str);
- memDC.SetTextColor(pItem->m_colorText);
- memDC.TextOut(p.x-sz.cx/2, p.y-sz.cy/2, str);
- }
- memDC.SelectObject(pOldFont);
- pt1 = pt2;
- }
- // Draw Line for the out circle
- memDC.SelectObject(&pen);
- memDC.SelectStockObject(NULL_BRUSH);
- memDC.Ellipse(m_rectChart);
- //Draw Title
- if (!m_strTitle.IsEmpty())
- {
- CFont* pOldFont = memDC.SelectObject(&m_fontTitle);
- memDC.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
- memDC.SetBkMode(TRANSPARENT);
- memDC.TextOut(1, 1, m_strTitle);
- memDC.SelectObject(pOldFont);
- }
- dc.BitBlt( 0, 0, clientRect.Width(), clientRect.Height(),
- &memDC, 0, 0, SRCCOPY );
- memDC.SelectObject(pOldPen);
- memDC.SelectObject(&pOldBrush);
- memDC.SelectObject(pOldmemDCBitmap);
- }
- void CPieChartCtrl::OnLButtonUp(UINT, CPoint)
- {
- if (m_bCaptured)
- {
- ::ReleaseCapture();
- m_bCaptured = FALSE;
- }
- }
- void CPieChartCtrl::OnLButtonDown(UINT, CPoint point)
- {
- SetCapture();
- m_bCaptured = TRUE;
- m_ptOldPt = point;
- }
- void CPieChartCtrl::OnMouseMove(UINT, CPoint point)
- {
- if (m_bCaptured)
- {
- int nOffX = point.x - m_ptOldPt.x;
- m_nStartAngle += nOffX;
- InvalidateRect(m_rectChart, FALSE);
- m_ptOldPt = point;
- }
- }
- void CPieChartCtrl::OnSize(UINT nType, int cx, int cy)
- {
- CWnd::OnSize(nType, cx, cy);
- RecalcRect();
- }
- void CPieChartCtrl::RecalcRect()
- {
- CRect rect;
- GetClientRect(&rect);
- if (!m_strTitle.IsEmpty())
- {
- CClientDC dc(this);
- CFont* pOldFont = dc.SelectObject(&m_fontTitle);
- CSize sz = dc.GetTextExtent(m_strTitle);
- m_nTitleHeight = sz.cy;
- rect.top += sz.cy*2;// Leave lines.
- dc.SelectObject(pOldFont);
- }
- int nSize = (rect.Width()>rect.Height())?rect.Height():rect.Width();
- m_rectChart = CRect(CPoint(rect.left + (rect.Width()-nSize)/2,
- rect.top + (rect.Height()-nSize)),
- CSize(nSize, nSize));
- }
- BOOL CPieChartCtrl::AddPiece(COLORREF colorBack, COLORREF colorText,
- int nAngle, const CString& str)
- {
- CPieChartPiece* pItem = new CPieChartPiece;
- pItem -> m_colorBack = colorBack;
- pItem -> m_colorText = colorText;
- pItem -> m_brushBack.CreateSolidBrush(colorBack);
- pItem -> m_nAngle = nAngle;
- pItem -> m_strInfo = str;
- try
- {
- m_chartPieces.Add(pItem);
- InvalidateRect(NULL, FALSE);
- return TRUE;
- }
- catch (CMemoryException* e)
- {
- if (pItem !=NULL)
- delete pItem;
- e->Delete();
- return FALSE;
- }
- }
- // bPercent is TRUE when counting the position for the percent info
- void CPieChartCtrl::CountPoint(int nAngle, CPoint & pt, BOOL bPercent)
- {
- while (nAngle <0)
- nAngle += 360;
- while (nAngle>359)
- nAngle -= 360;
- double dAngle = ((double)nAngle)*pi/(double)180;
- double r;
- r = ((double)m_rectChart.Height())/2.0;
- if (bPercent)
- r = r*3.0/5.0;
- double dOffX = (r*sin(dAngle));
- double dOffY = 0.0 - (r*cos(dAngle));
- double dX = ((double)(m_rectChart.right+m_rectChart.left))/2.0;
- double dY = ((double)(m_rectChart.top+m_rectChart.bottom))/2.0;
- pt.x = (int)(dX + dOffX);
- pt.y = (int)(dY + dOffY);
- }
- void CPieChartCtrl::Reset()
- {
- int nCount = m_chartPieces.GetSize();
- for (int i = 0; i < nCount; i++)
- delete m_chartPieces.GetAt(i);
- m_chartPieces.RemoveAll();
- }
- void CPieChartCtrl::GetItemColor(int i, COLORREF& color)
- {
- int nCount = m_chartPieces.GetSize();
- if (i>=nCount)
- i=nCount-1;
- color = (m_chartPieces.GetAt(i))->m_colorBack;
- }
- void CPieChartCtrl::SetTitle(const CString & str)
- {
- m_strTitle = str;
- RecalcRect();
- InvalidateRect(NULL, FALSE);
- }