PieChart.h
上传用户:hy_wanghao
上传日期:2007-01-08
资源大小:279k
文件大小:6k
- #if !defined(AFX_PIECHART_H__20010108_9A44_EF9C_1731_0080AD509054__INCLUDED_)
- #define AFX_PIECHART_H__20010108_9A44_EF9C_1731_0080AD509054__INCLUDED_
- // PieChart.h : Pie Chart control
- //
- // Written by Bjarke Viksoe (bjarke@viksoe.dk)
- // Copyright (c) 2001 Bjarke Viksoe.
- //
- // This is a very crude implementation of a pie-chart control.
- // Didn't have time to go through the GDI to find a way to draw a tilted
- // arc so I could make a 3D effect.
- //
- // It subclasses a STATIC control (use MSVC++ Frame control in Rectangle
- // mode).
- //
- // This code may be used in compiled form in any way you desire. This
- // file may be redistributed 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.
- //
- // This file is provided "as is" with no expressed or implied warranty.
- // The author accepts no liability if it causes any damage to you or your
- // computer whatsoever. It's free, so don't hassle me about it.
- //
- // Beware of bugs.
- #pragma once
- #include <math.h>
- #ifndef __ATLWIN_H__
- #error piechart.h requires atlwin.h to be included first
- #endif
- template <class T, class TBase = CWindow, class TWinTraits = CControlWinTraits>
- class ATL_NO_VTABLE CPieChartImpl : public CWindowImpl< T, TBase, TWinTraits >
- {
- public:
- BEGIN_MSG_MAP(CPieChartImpl)
- MESSAGE_HANDLER(WM_CREATE, OnCreate)
- MESSAGE_HANDLER(WM_PAINT, OnPaint)
- MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
- END_MSG_MAP()
- RECT m_rc;
- DWORD m_dwPercent;
- CPieChartImpl()
- {
- ::SetRectEmpty(&m_rc);
- m_dwPercent = 0;
- }
- // Operations
- void SetPercent(DWORD dwPercent)
- {
- ATLASSERT(dwPercent<=100);
- m_dwPercent = dwPercent;
- }
- DWORD GetPercent() const { return m_dwPercent; };
- BOOL SubclassWindow(HWND hWnd)
- {
- ATLASSERT(m_hWnd==NULL);
- ATLASSERT(::IsWindow(hWnd));
- BOOL bRet = CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
- if(bRet) Init();
- return bRet;
- }
- // Message map and handlers
- LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- Init();
- return 0;
- }
- LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- T* pT = static_cast<T*>(this);
- if(wParam != NULL) {
- pT->DoPaint((HDC)wParam);
- }
- else {
- PAINTSTRUCT m_ps;
- HDC hDC = ::BeginPaint(m_hWnd, &m_ps);
- pT->DoPaint(hDC);
- ::EndPaint(m_hWnd, &m_ps);
- }
- return 0;
- }
- // Implementation
- void Init()
- {
- ATLASSERT(::IsWindow(m_hWnd));
- // Check control class
- TCHAR lpszBuffer[8];
- if( ::GetClassName(m_hWnd, lpszBuffer, 8) ) {
- ATLASSERT(::lstrcmpi(lpszBuffer, _T("static"))==0);
- }
- GetClientRect(&m_rc);
- }
- void DoPaint(HDC hdc)
- {
- int dwWidth = (m_rc.right-m_rc.left)/2;
- int dwHeight = (m_rc.bottom-m_rc.top)/2;
- int nX = dwWidth;
- int nY = dwHeight;
- DWORD dwRadius = dwWidth<dwHeight ? dwWidth : dwHeight;
- float xStartAngle = 0.0f;
- float xSweepAngle = (float)m_dwPercent * 3.6f;
-
- HBRUSH hbrushBlue = ::CreateSolidBrush(RGB(0,0,255));
- HBRUSH hbrushRed = ::CreateSolidBrush(RGB(255,0,255));
- HBRUSH hbrushOld = (HBRUSH)::SelectObject(hdc, hbrushBlue);
- ::BeginPath(hdc);
- ::MoveToEx(hdc, nX, nY, (LPPOINT)NULL);
- AngleArc2(hdc, nX, nY, dwRadius, xStartAngle, xSweepAngle);
- ::LineTo(hdc, nX, nY);
- ::EndPath(hdc);
- ::StrokeAndFillPath(hdc);
- ::SelectObject(hdc, hbrushRed);
- ::BeginPath(hdc);
- ::MoveToEx(hdc, nX, nY, (LPPOINT)NULL);
- AngleArc2(hdc, nX, nY, dwRadius, xSweepAngle, 360.0f - xSweepAngle);
- ::EndPath(hdc);
- ::StrokeAndFillPath(hdc);
- ::SelectObject(hdc, hbrushOld);
- ::DeleteObject(hbrushBlue);
- ::DeleteObject(hbrushRed);
- }
- // Crappy Windows... just as I got the control hurdled together it turns
- // out AngleArc() isn't implemented on win95/98. Luckily Bill Gates found
- // it in his heart to offer some replacement code on MSDN...
- BOOL AngleArc2(HDC hdc, int X, int Y, DWORD dwRadius,
- float fStartDegrees, float fSweepDegrees)
- {
- float fStepAngle = 0.03f; // The sweep increment value in radians
- float fStartRadians; // Start angle in radians
- float fEndRadians; // End angle in radians
- float fTwoPi = 2.0f * 3.141592653589793f;
- // Get the starting and ending angle in radians
- if( fSweepDegrees > 0.0f ) {
- fStartRadians = ((fStartDegrees / 360.0f) * fTwoPi);
- fEndRadians = (((fStartDegrees + fSweepDegrees) / 360.0f) * fTwoPi);
- }
- else {
- fStartRadians = (((fStartDegrees + fSweepDegrees) / 360.0f) * fTwoPi);
- fEndRadians = ((fStartDegrees / 360.0f) * fTwoPi);
- }
- // Calculate the starting point for the sweep via
- // polar -> cartesian conversion
- int ix, iy; // Current point on arc
- ix = X + (int)((float)dwRadius * (float)cos(fStartRadians));
- iy = Y - (int)((float)dwRadius * (float)sin(fStartRadians));
- // Draw a line to the starting point
- ::LineTo(hdc, ix, iy);
- // Calculate and draw the sweep
- float fCurrentAngle; // Current angle in radians
- for( fCurrentAngle=fStartRadians; fCurrentAngle<=fEndRadians; fCurrentAngle+=fStepAngle ) {
- // Calculate the current point in the sweep via
- // polar -> cartesian conversion
- ix = X + (int)((float)dwRadius * (float)cos(fCurrentAngle));
- iy = Y - (int)((float)dwRadius * (float)sin(fCurrentAngle));
- // Draw a line segment to current point
- ::LineTo(hdc, ix, iy);
- }
- // Make sure to draw at the very ending point
- ix = X + (int)((float)dwRadius * (float)cos(fEndRadians));
- iy = Y - (int)((float)dwRadius * (float)sin(fEndRadians));
- // Draw a line to the ending point
- ::LineTo(hdc, ix, iy);
- return TRUE;
- }
- };
- class CPieChart : public CPieChartImpl<CPieChart>
- {
- public:
- DECLARE_WND_CLASS(_T("ADF_PieChart"))
- };
- #endif // !defined(AFX_PIECHART_H__20010108_9A44_EF9C_1731_0080AD509054__INCLUDED_)