PieChart.h
上传用户:hy_wanghao
上传日期:2007-01-08
资源大小:279k
文件大小:6k
源码类别:

Shell编程

开发平台:

Visual C++

  1. #if !defined(AFX_PIECHART_H__20010108_9A44_EF9C_1731_0080AD509054__INCLUDED_)
  2. #define AFX_PIECHART_H__20010108_9A44_EF9C_1731_0080AD509054__INCLUDED_
  3. // PieChart.h : Pie Chart control
  4. //
  5. // Written by Bjarke Viksoe (bjarke@viksoe.dk)
  6. // Copyright (c) 2001 Bjarke Viksoe.
  7. //
  8. // This is a very crude implementation of a pie-chart control.
  9. // Didn't have time to go through the GDI to find a way to draw a tilted 
  10. // arc so I could make a 3D effect.
  11. //
  12. // It subclasses a STATIC control (use MSVC++ Frame control in Rectangle
  13. // mode).
  14. //
  15. // This code may be used in compiled form in any way you desire. This
  16. // file may be redistributed by any means PROVIDING it is 
  17. // not sold for profit without the authors written consent, and 
  18. // providing that this notice and the authors name is included. 
  19. //
  20. // This file is provided "as is" with no expressed or implied warranty.
  21. // The author accepts no liability if it causes any damage to you or your
  22. // computer whatsoever. It's free, so don't hassle me about it.
  23. //
  24. // Beware of bugs.
  25. #pragma once
  26. #include <math.h>
  27. #ifndef __ATLWIN_H__
  28.   #error piechart.h requires atlwin.h to be included first
  29. #endif
  30. template <class T, class TBase = CWindow, class TWinTraits = CControlWinTraits>
  31. class ATL_NO_VTABLE CPieChartImpl : public CWindowImpl< T, TBase, TWinTraits >
  32. {
  33. public:
  34. BEGIN_MSG_MAP(CPieChartImpl)
  35.    MESSAGE_HANDLER(WM_CREATE, OnCreate)
  36.    MESSAGE_HANDLER(WM_PAINT, OnPaint)
  37.    MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
  38. END_MSG_MAP()
  39.    RECT m_rc;
  40.    DWORD m_dwPercent;
  41.    CPieChartImpl()
  42.    {
  43.       ::SetRectEmpty(&m_rc);
  44.       m_dwPercent = 0;
  45.    }
  46.    // Operations
  47.    void SetPercent(DWORD dwPercent) 
  48.    { 
  49.       ATLASSERT(dwPercent<=100);
  50.       m_dwPercent = dwPercent; 
  51.    }
  52.    DWORD GetPercent() const { return m_dwPercent; };
  53.    BOOL SubclassWindow(HWND hWnd)
  54.    {
  55.       ATLASSERT(m_hWnd==NULL);
  56.       ATLASSERT(::IsWindow(hWnd));
  57.       BOOL bRet = CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
  58.       if(bRet) Init();
  59.       return bRet;
  60.    }
  61.    // Message map and handlers
  62.    LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  63.    {
  64.       Init();
  65.       return 0;
  66.    }
  67.    LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  68.    {
  69.       T* pT = static_cast<T*>(this);
  70.       if(wParam != NULL) {
  71.          pT->DoPaint((HDC)wParam);
  72.       }
  73.       else {
  74.          PAINTSTRUCT m_ps;
  75.          HDC hDC = ::BeginPaint(m_hWnd, &m_ps);
  76.          pT->DoPaint(hDC);
  77.          ::EndPaint(m_hWnd, &m_ps);
  78.       }
  79.       return 0;
  80.    }
  81.    // Implementation
  82.    void Init()
  83.    {
  84.       ATLASSERT(::IsWindow(m_hWnd));
  85.       // Check control class
  86.       TCHAR lpszBuffer[8];
  87.       if( ::GetClassName(m_hWnd, lpszBuffer, 8) ) {
  88.          ATLASSERT(::lstrcmpi(lpszBuffer, _T("static"))==0);
  89.       }
  90.       GetClientRect(&m_rc);
  91.    }
  92.    void DoPaint(HDC hdc)
  93.    {
  94.       int dwWidth = (m_rc.right-m_rc.left)/2;
  95.       int dwHeight = (m_rc.bottom-m_rc.top)/2;
  96.       int nX = dwWidth;
  97.       int nY = dwHeight;
  98.       DWORD dwRadius = dwWidth<dwHeight ? dwWidth : dwHeight;
  99.       float xStartAngle = 0.0f;
  100.       float xSweepAngle = (float)m_dwPercent * 3.6f;
  101.       
  102.       HBRUSH hbrushBlue = ::CreateSolidBrush(RGB(0,0,255)); 
  103.       HBRUSH hbrushRed = ::CreateSolidBrush(RGB(255,0,255)); 
  104.       HBRUSH hbrushOld = (HBRUSH)::SelectObject(hdc, hbrushBlue); 
  105.       ::BeginPath(hdc);
  106.       ::MoveToEx(hdc, nX, nY, (LPPOINT)NULL); 
  107.       AngleArc2(hdc, nX, nY, dwRadius, xStartAngle, xSweepAngle); 
  108.       ::LineTo(hdc, nX, nY); 
  109.       ::EndPath(hdc); 
  110.       ::StrokeAndFillPath(hdc); 
  111.       ::SelectObject(hdc, hbrushRed); 
  112.       ::BeginPath(hdc);
  113.       ::MoveToEx(hdc, nX, nY, (LPPOINT)NULL); 
  114.       AngleArc2(hdc, nX, nY, dwRadius, xSweepAngle, 360.0f - xSweepAngle); 
  115.       ::EndPath(hdc); 
  116.       ::StrokeAndFillPath(hdc); 
  117.       ::SelectObject(hdc, hbrushOld);
  118.       ::DeleteObject(hbrushBlue);
  119.       ::DeleteObject(hbrushRed);
  120.    }
  121.    // Crappy Windows... just as I got the control hurdled together it turns
  122.    // out AngleArc() isn't implemented on win95/98. Luckily Bill Gates found
  123.    // it in his heart to offer some replacement code on MSDN...
  124.    BOOL AngleArc2(HDC hdc, int X, int Y, DWORD dwRadius,
  125.                   float fStartDegrees, float fSweepDegrees)
  126.    {
  127.       float fStepAngle = 0.03f;  // The sweep increment value in radians
  128.       float fStartRadians;       // Start angle in radians
  129.       float fEndRadians;         // End angle in radians
  130.       float fTwoPi = 2.0f * 3.141592653589793f;
  131.       // Get the starting and ending angle in radians
  132.       if( fSweepDegrees > 0.0f ) {
  133.         fStartRadians = ((fStartDegrees / 360.0f) * fTwoPi);
  134.         fEndRadians = (((fStartDegrees + fSweepDegrees) / 360.0f) * fTwoPi);
  135.       } 
  136.       else {
  137.         fStartRadians = (((fStartDegrees + fSweepDegrees)  / 360.0f) * fTwoPi);
  138.         fEndRadians =  ((fStartDegrees / 360.0f) * fTwoPi);
  139.       }
  140.       // Calculate the starting point for the sweep via
  141.       // polar -> cartesian conversion
  142.       int ix, iy;                // Current point on arc
  143.       ix = X + (int)((float)dwRadius * (float)cos(fStartRadians));
  144.       iy = Y - (int)((float)dwRadius * (float)sin(fStartRadians));
  145.       // Draw a line to the starting point
  146.       ::LineTo(hdc, ix, iy);
  147.       // Calculate and draw the sweep
  148.       float fCurrentAngle;       // Current angle in radians
  149.       for( fCurrentAngle=fStartRadians; fCurrentAngle<=fEndRadians; fCurrentAngle+=fStepAngle ) {
  150.          // Calculate the current point in the sweep via
  151.          // polar -> cartesian conversion 
  152.          ix = X + (int)((float)dwRadius * (float)cos(fCurrentAngle));
  153.          iy = Y - (int)((float)dwRadius * (float)sin(fCurrentAngle));
  154.          // Draw a line segment to current point
  155.          ::LineTo(hdc, ix, iy);
  156.       }
  157.       // Make sure to draw at the very ending point
  158.       ix = X + (int)((float)dwRadius * (float)cos(fEndRadians));
  159.       iy = Y - (int)((float)dwRadius * (float)sin(fEndRadians));
  160.       // Draw a line to the ending point
  161.       ::LineTo(hdc, ix, iy);
  162.       return TRUE;
  163.    } 
  164. };
  165. class CPieChart : public CPieChartImpl<CPieChart>
  166. {
  167. public:
  168.    DECLARE_WND_CLASS(_T("ADF_PieChart"))
  169. };
  170. #endif // !defined(AFX_PIECHART_H__20010108_9A44_EF9C_1731_0080AD509054__INCLUDED_)