Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
6.2 KiB

  1. // PWSChart.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "PWSChart.h"
  5. #include <pwsdata.hxx>
  6. #ifdef _DEBUG
  7. #define new DEBUG_NEW
  8. #undef THIS_FILE
  9. static char THIS_FILE[] = __FILE__;
  10. #endif
  11. /////////////////////////////////////////////////////////////////////////////
  12. // CPWSChart
  13. CPWSChart::CPWSChart():
  14. m_pData( NULL ),
  15. m_period( PWS_CHART_HOURLY ),
  16. m_dataType( PWS_CHART_SESSIONS )
  17. {
  18. }
  19. CPWSChart::~CPWSChart()
  20. {
  21. }
  22. BEGIN_MESSAGE_MAP(CPWSChart, CStatic)
  23. //{{AFX_MSG_MAP(CPWSChart)
  24. ON_WM_PAINT()
  25. //}}AFX_MSG_MAP
  26. END_MESSAGE_MAP()
  27. //------------------------------------------------------------------
  28. void CPWSChart::DrawChart()
  29. {
  30. CDC* dc = GetDC();
  31. DrawChart( dc );
  32. ReleaseDC( dc );
  33. }
  34. //------------------------------------------------------------------
  35. void CPWSChart::OnPaint()
  36. {
  37. CPaintDC dc(this); // device context for painting
  38. // draw the chart
  39. DrawChart( &dc );
  40. }
  41. #define NUM_ROWS 4
  42. //------------------------------------------------------------------
  43. DWORD CPWSChart::GetDataValue( DWORD i )
  44. {
  45. PPWS_DATA pData = (PPWS_DATA)m_pData;
  46. // get the right thing
  47. switch( m_period )
  48. {
  49. case PWS_CHART_HOURLY:
  50. switch( m_dataType )
  51. {
  52. case PWS_CHART_SESSIONS:
  53. return pData->rgbHourData[i].nTotalSessions;
  54. case PWS_CHART_HITS:
  55. return pData->rgbHourData[i].nHits;
  56. case PWS_CHART_KB:
  57. return pData->rgbHourData[i].nBytesSent;
  58. case PWS_CHART_HITS_PER_USER:
  59. if ( !pData->rgbHourData[i].nTotalSessions )
  60. return 0;
  61. else
  62. return pData->rgbHourData[i].nHits / pData->rgbHourData[i].nTotalSessions;
  63. case PWS_CHART_KB_PER_USER:
  64. if ( !pData->rgbHourData[i].nTotalSessions )
  65. return 0;
  66. else
  67. return pData->rgbHourData[i].nBytesSent / pData->rgbHourData[i].nTotalSessions;
  68. default:
  69. return 0;
  70. };
  71. break;
  72. case PWS_CHART_DAILY:
  73. switch( m_dataType )
  74. {
  75. case PWS_CHART_SESSIONS:
  76. return pData->rgbDayData[i].nTotalSessions;
  77. case PWS_CHART_HITS:
  78. return pData->rgbDayData[i].nHits;
  79. case PWS_CHART_KB:
  80. return pData->rgbDayData[i].nBytesSent;
  81. case PWS_CHART_HITS_PER_USER:
  82. if ( !pData->rgbHourData[i].nTotalSessions )
  83. return 0;
  84. else
  85. return pData->rgbDayData[i].nHits / pData->rgbDayData[i].nTotalSessions;
  86. case PWS_CHART_KB_PER_USER:
  87. if ( !pData->rgbHourData[i].nTotalSessions )
  88. return 0;
  89. else
  90. return pData->rgbDayData[i].nBytesSent / pData->rgbDayData[i].nTotalSessions;
  91. default:
  92. return 0;
  93. };
  94. break;
  95. default:
  96. return 0;
  97. };
  98. return 0;
  99. }
  100. //------------------------------------------------------------------
  101. void CPWSChart::DrawChart( CDC* dc )
  102. {
  103. CRect rectWindow, rectChart;
  104. CDC* dcDraw = dc;
  105. DWORD value;
  106. int cpColWidth;
  107. int cpRowHeight;
  108. int xErr, xLeftover;
  109. CRect rect, rectInterior;
  110. int nNumColumns, i;
  111. if ( !m_pData )
  112. {
  113. return;
  114. }
  115. // cache the current time
  116. GetLocalTime( &m_timeCurrent );
  117. // prepare basic stuff
  118. GetClientRect( &rectWindow );
  119. rectWindow.bottom--;
  120. rectWindow.right--;
  121. rectChart = rectWindow;
  122. rectChart.DeflateRect( 1, 0 );
  123. rectChart.top += 1;
  124. //============= CALCULATIONS
  125. // now we calculate scale factors and the like
  126. // first, the period-based stuff
  127. switch( m_period )
  128. {
  129. case PWS_CHART_HOURLY:
  130. nNumColumns = 24;
  131. break;
  132. case PWS_CHART_DAILY:
  133. nNumColumns = 7;
  134. break;
  135. default:
  136. return;
  137. };
  138. // generic stuff
  139. int cpWindowWidth = rectChart.right - rectChart.left + 1;
  140. cpColWidth = cpWindowWidth / nNumColumns;
  141. xLeftover = cpWindowWidth % nNumColumns;
  142. cpRowHeight = (rectChart.bottom - rectChart.top) / NUM_ROWS;
  143. // figure out the maximum value of the data
  144. m_max = 0;
  145. for ( i = 0; i < nNumColumns; i++ )
  146. {
  147. DWORD data = GetDataValue(i);
  148. if ( data > m_max )
  149. m_max = data;
  150. };
  151. // create a floating point scaling factor for the y value;
  152. float yFactor;
  153. if ( m_max )
  154. yFactor = (float)(rectChart.bottom - rectChart.top ) / m_max;
  155. //============= DRAWING!
  156. // start by blanking out the background of the chart
  157. dcDraw->FillSolidRect( &rectWindow, GetSysColor(COLOR_APPWORKSPACE) );
  158. // prepare the data rect
  159. rect.left = rectChart.left;
  160. rect.right = rect.left + cpColWidth;
  161. rect.bottom = rectChart.bottom;
  162. xErr = 0;
  163. // the bars
  164. if ( m_max )
  165. {
  166. for ( i = 0; i < nNumColumns; i++ )
  167. {
  168. // only draw something if there is a value there
  169. value = GetDataValue(i);
  170. if ( !value )
  171. {
  172. goto increment;
  173. }
  174. // build the rectangle to fill
  175. rect.top = (int)((float)rectWindow.bottom - 1.0 - ((float)GetDataValue(i) * yFactor));
  176. // draw the data bar
  177. dcDraw->Draw3dRect( rect, GetSysColor(COLOR_3DHILIGHT), GetSysColor(COLOR_3DSHADOW) );
  178. // fill in the data bar
  179. rectInterior = rect;
  180. rectInterior.DeflateRect( 1, 1 );
  181. dcDraw->FillSolidRect( rectInterior, GetSysColor(COLOR_3DFACE) );
  182. // increment stuff
  183. increment:
  184. rect.left = rect.right;
  185. // account for the error factor
  186. xErr += xLeftover;
  187. if ( xErr > nNumColumns )
  188. {
  189. rect.right++;
  190. xErr -= nNumColumns;
  191. }
  192. rect.right += cpColWidth;
  193. }
  194. }
  195. }