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

操作系统开发

开发平台:

Visual C++

  1. //Graph.cpp - Version 3.0 (Brian Convery, May, 2001)
  2. #include "stdafx.h"
  3. #include "afxtempl.h"
  4. #include "GraphSeries.h"
  5. #include "GraphLegend.h"
  6. #include "math.h"
  7. #include "Graph.h"
  8. #include "GraphDataColor.h"
  9. #include "GraphPieLabel.h" //for pie labels
  10. #ifdef _DEBUG
  11. #define new DEBUG_NEW
  12. #undef THIS_FILE
  13. static char THIS_FILE[] = __FILE__;
  14. #endif
  15. /////////////////////////////////////////////////////////////////////////////
  16. // CGraph
  17. CGraph::CGraph()
  18. {
  19. graphSeries = new CObList();
  20. seriesSize = 0;
  21. minTick = 0;
  22. maxTick = 100;
  23. numTicks = 10;
  24. tickSpace = 10;
  25. graphHasLegend = FALSE;
  26. legendWidth = 0;
  27. legendMaxText= 0;
  28. graphAlignment = VERTICAL_ALIGN;  
  29. graphType = 0;
  30. xAxisAlign = 0;  //horizontal
  31. xAxisLabelLength = 0;
  32. xTickFontSize = 12;
  33. yTickFontSize = 12;
  34. legendFontSize = 12;
  35. depth = 0;
  36. depthRatio = 0.05;
  37. line3DXBase = 0;
  38. line3DYBase = 0;
  39. SetGridLines(FALSE);
  40. graphQuadType = 1;
  41. quadSetManually = FALSE;
  42. }
  43. CGraph::CGraph(int type)
  44. {
  45. graphSeries = new CObList();
  46. colorList = new CObList();
  47. seriesSize = 0;
  48. minTick = 0;
  49. maxTick = 100;
  50. numTicks = 10;
  51. tickSpace = 10;
  52. graphHasLegend = FALSE;
  53. legendWidth = 0;
  54. legendMaxText= 0;
  55. graphAlignment = VERTICAL_ALIGN;  
  56. graphType = type;
  57. xAxisAlign = 0;  //in degrees == horizontal
  58. xAxisLabelLength = 0;
  59. xTickFontSize = 12;
  60. yTickFontSize = 12;
  61. legendFontSize = 12;
  62. depth = 0;
  63. depthRatio = 0.05;
  64. line3DXBase = 0;
  65. line3DYBase = 0;
  66. SetGridLines(FALSE);
  67. graphQuadType = 1;
  68. if(type != BAR_GRAPH)
  69. quadSetManually = TRUE;
  70. else
  71. quadSetManually = FALSE;
  72. }
  73. CGraph::~CGraph()
  74. {
  75. POSITION pos;
  76. CGraphSeries* pSeries;
  77. for( pos = graphSeries->GetHeadPosition(); pos != NULL; )
  78. {
  79. pSeries = (CGraphSeries*) graphSeries->GetNext( pos );
  80. graphSeries->RemoveAt(pos);
  81. delete pSeries;
  82. }
  83. graphSeries->RemoveAll();
  84. delete graphSeries;
  85. CGraphDataColor* dataColor;
  86. for( pos = colorList->GetHeadPosition(); pos != NULL; )
  87. {
  88. dataColor = (CGraphDataColor*) colorList->GetNext( pos );
  89. colorList->RemoveAt(pos);
  90. delete dataColor;
  91. }
  92. colorList->RemoveAll();
  93. delete colorList;
  94. }
  95. BEGIN_MESSAGE_MAP(CGraph, CStatic)
  96. //{{AFX_MSG_MAP(CGraph)
  97. // NOTE - the ClassWizard will add and remove mapping macros here.
  98. //}}AFX_MSG_MAP
  99. END_MESSAGE_MAP()
  100. /////////////////////////////////////////////////////////////////////////////
  101. // CGraph message handlers
  102. void CGraph::SetGraphType(int gType)
  103. {
  104. graphType = gType;
  105. }
  106. void CGraph::SetXAxisAlignment(int alignValue)
  107. {
  108. xAxisAlign = alignValue;
  109. }
  110. int CGraph::GetXAxisAlignment()
  111. {
  112. return xAxisAlign;
  113. }
  114. void CGraph::SetColor(int dataGroup, COLORREF groupColor)
  115. {
  116. CGraphDataColor *dataColor = new CGraphDataColor(dataGroup, groupColor);
  117. colorList->AddTail(dataColor);
  118. }
  119. COLORREF CGraph::GetColor(int dataGroup)
  120. {
  121. POSITION pos;
  122. if((colorList->GetCount() <= dataGroup) || (colorList->GetCount() == 0))
  123. return BLACK;
  124. CGraphDataColor* dataColor;
  125. pos = colorList->GetHeadPosition();
  126. for(int i = 0; i < dataGroup; i++)
  127. colorList->GetNext(pos);
  128. dataColor = (CGraphDataColor*) colorList->GetAt( pos );
  129. return dataColor->GetColor();
  130. }
  131. void CGraph::DrawGraph(CDC* pDC)
  132. {
  133. CString tickLabel;
  134. CWnd* graphWnd = pDC->GetWindow();
  135. CRect graphRect;
  136. graphWnd->GetClientRect(&graphRect);
  137. TEXTMETRIC tm;
  138. //reset graph to be clear background
  139. COLORREF backColor;
  140. pDC->SetBkMode(TRANSPARENT);
  141. backColor = RGB(214,223,247);  //replace with desired background color
  142. CBrush backBrush (backColor);
  143. CBrush* pOldBackBrush;
  144. pOldBackBrush = pDC->SelectObject(&backBrush);
  145. //pDC->Rectangle(0, 0, graphRect.Width(), graphRect.Height());
  146. pDC->SelectObject(pOldBackBrush);
  147. maxHeight = graphRect.Height() - 20;  //for frame window and status bar
  148. maxWidth = graphRect.Width() - 5;  //for frame window
  149. //draw graph title
  150. CFont titleFont;
  151. int tFontSize = 20;
  152. while((graphTitle.GetLength() * (tFontSize / 2)) > maxWidth)
  153. {
  154. tFontSize -= 2;
  155. }
  156. titleFont.CreateFont(tFontSize, 0, 0, 0, 500, FALSE, FALSE, 0,
  157. DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  158. DEFAULT_QUALITY, DEFAULT_PITCH ,"楷体_GB2312");
  159. CFont* pOldFont = (CFont*) pDC->SelectObject(&titleFont);
  160. pDC->GetTextMetrics(&tm);
  161. int charWidth = tm.tmAveCharWidth;
  162. //next line is centered....trust me !!
  163. pDC->TextOut((graphRect.Width() / 2) - ((graphTitle.GetLength() / 2) * charWidth),
  164. 10, graphTitle);
  165. pDC->SelectObject(pOldFont);
  166. if((graphType == PIE_GRAPH) || (graphType == PIE_GRAPH_3D))
  167. {
  168. //since pie does not have axis lines, set to full size minus 5 on each side
  169. //these are needed for legend to plot itself
  170. xAxisWidth = maxWidth - 10;
  171. yAxisHeight = maxHeight - 50;  //10 buffer, 20 for title, and 20 for series label
  172. xApexPoint = 5;
  173. yApexPoint = maxHeight - 5;
  174. }
  175. else
  176. {
  177. //compute label size for axis alignment
  178. CFont sideFont, axisFont;
  179. int tFontSize = 16;
  180. if(maxWidth > maxHeight)
  181. {
  182. while((axisYLabel.GetLength() * (tFontSize / 2)) > maxHeight)
  183. {
  184. tFontSize -= 2;
  185. }
  186. }
  187. else
  188. {
  189. while((axisXLabel.GetLength() * (tFontSize / 2)) > maxWidth)
  190. {
  191. tFontSize -= 2;
  192. }
  193. }
  194. axisFont.CreateFont(tFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  195. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  196. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  197. sideFont.CreateFont(tFontSize, 0, 900, 0, 700, FALSE, FALSE, 0,
  198. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  199. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  200. CFont* pOldFont = (CFont*) pDC->SelectObject(&sideFont);
  201. pDC->GetTextMetrics(&tm);
  202. int charWidth = tm.tmAveCharWidth;
  203. int labelHeight = tm.tmHeight + 10;
  204. if(graphAlignment)
  205. {
  206. if(axisYLabel.GetLength() == 0)
  207. labelHeight = 0;
  208. }
  209. else
  210. {
  211. if(axisXLabel.GetLength() == 0)
  212. labelHeight = 0;
  213. }
  214. pDC->SelectObject(pOldFont);
  215. tickLabel.Format("%d", maxTick);
  216. //determine axis specifications 
  217. if(graphAlignment)
  218. {
  219. if(graphType == SCATTER_GRAPH)
  220. {
  221. xApexPoint = 5 + (xAxisLabelLength * charWidth) + labelHeight; //labelHeight added for y-axis label height
  222. yApexPoint = (maxHeight - 15) - tm.tmHeight;
  223. yAxisHeight = yApexPoint - 40;
  224. xAxisWidth = (maxWidth - 5) - xApexPoint;
  225. }
  226. else
  227. {
  228. xApexPoint = 5 + (tickLabel.GetLength() * (yTickFontSize / 2)) + 45; 
  229. if(!xAxisAlign)  //horizontal
  230. yApexPoint = (maxHeight - 5) - 45; //apex points are the cross section of axis lines
  231. else
  232. yApexPoint = (maxHeight - 5) - (xAxisLabelLength * (xTickFontSize / 2)) - 10;
  233. yAxisHeight = yApexPoint - 40;
  234. xAxisWidth = (maxWidth - 5) - xApexPoint;
  235. }
  236. }
  237. else
  238. {
  239. xApexPoint = 5 + (xAxisLabelLength * charWidth) + labelHeight; //labelHeight added for y-axis label height
  240. yApexPoint = (maxHeight - 15) - tm.tmHeight;
  241. yAxisHeight = yApexPoint - 40;
  242. xAxisWidth = (maxWidth - 5) - xApexPoint;
  243. }
  244. }
  245. //draw legend
  246. if(graphHasLegend)
  247. {
  248. int legendLeft = DrawLegend(pDC);
  249. xAxisWidth = legendLeft - 10 - xApexPoint;
  250. }
  251. if((!quadSetManually) && (graphType == BAR_GRAPH))
  252. {
  253. //computer number of quadrants needed based on data
  254. POSITION pos;
  255. pos = graphSeries->GetHeadPosition();
  256. CGraphSeries* tmpSeries;
  257. int minXValue = 0;
  258. int minYValue = 0;
  259. for(int x = 1; x <= graphSeries->GetCount(); x++)
  260. {
  261. tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
  262. for(int s = 0; s < seriesSize; s++)
  263. {
  264. //to allow scalability (height may be less than tickRange)
  265. int curXValue = tmpSeries->GetXDataValue();
  266. int curYValue = tmpSeries->GetYDataValue();
  267. if(curXValue < minXValue)
  268. minXValue = curXValue;
  269. if(curYValue < minYValue)
  270. minYValue = curYValue;
  271. }
  272. }
  273. graphQuadType = 1;
  274. if((minXValue < 0) && (minYValue < 0))
  275. graphQuadType = 4;
  276. if((minXValue < 0) && (minYValue >= 0))
  277. graphQuadType = 2;
  278. if((minXValue >= 0) && (minYValue < 0))
  279. graphQuadType = 3;
  280. }
  281. if(graphType == BAR_GRAPH)
  282. {
  283. switch(graphQuadType)
  284. {
  285. case 2 :
  286. xApexPoint += xAxisWidth / 2;
  287. break;
  288. case 3 :
  289. yApexPoint -= yAxisHeight / 2;
  290. break;
  291. case 4 :
  292. xApexPoint += xAxisWidth / 2;
  293. yApexPoint -= yAxisHeight / 2;
  294. break;
  295. }
  296. }
  297. if((graphType != 2) && (graphType != 32))  //pie & 3d pie
  298. {
  299. inRedraw = FALSE;
  300. //draw axis lines
  301. DrawAxis(pDC);
  302. }
  303. //draw series data and labels
  304. DrawSeries(pDC);
  305. //lines below are commented for doing redraw.  If you
  306. //want the axis lines on top of the other graph elements
  307. //uncomment this functionality...I may add it back later
  308. //but there were some bugs doing it this way.
  309. //redraw axis lines in case graph elements overwrote the axis lines
  310. // if((graphType != 2) && (graphType != 32) && (graphQuadType > 1))  //pie & 3d pie
  311. // {
  312. // inRedraw = TRUE;
  313. //draw axis lines
  314. // DrawAxis(pDC);
  315. // }
  316. }
  317. void CGraph::DrawAxis(CDC* pDC)
  318. {
  319. TEXTMETRIC tm;
  320. pDC->SetTextColor(BLACK);
  321. CFont sideFont, axisFont, dummyFont;
  322. int charWidth, labelHeight;
  323. double tickScale;
  324. int tickXLocation, tickYLocation;
  325. int seriesSpace;
  326. CFont* pOldFont;
  327. int x, y;
  328. COLORREF axisLineColor;
  329. axisLineColor = BLACK;
  330. CPen axisPen (PS_SOLID, 2, axisLineColor);
  331. dummyFont.CreateFont(12, 0, 0, 0, 700, FALSE, FALSE, 0,
  332. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  333. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  334. pOldFont = (CFont*)pDC->SelectObject(&dummyFont);
  335. switch(graphType)
  336. {
  337. case BAR_GRAPH :
  338. case LINE_GRAPH :
  339. case SCATTER_GRAPH :
  340. case BOX_WHISKER_GRAPH :
  341. // case RADAR_GRAPH :
  342. case STACKED_BAR_GRAPH :
  343. case XY_LINE_GRAPH :
  344. CPen* pOldAxisPen;
  345. pOldAxisPen = pDC->SelectObject(&axisPen);
  346. switch(graphQuadType)
  347. {
  348. case 1 :
  349. //draw y axis
  350. pDC->MoveTo(xApexPoint, yApexPoint);  
  351. pDC->LineTo(xApexPoint, yApexPoint - yAxisHeight);
  352. //draw x axis
  353. pDC->MoveTo(xApexPoint, yApexPoint);  
  354. pDC->LineTo(xApexPoint + xAxisWidth, yApexPoint);
  355. break;
  356. case 2 :
  357. //draw y axis
  358. pDC->MoveTo(xApexPoint, yApexPoint);  
  359. pDC->LineTo(xApexPoint, yApexPoint - yAxisHeight);
  360. //draw x axis
  361. pDC->MoveTo(xApexPoint - (xAxisWidth / 2), yApexPoint);  
  362. pDC->LineTo(xApexPoint + (xAxisWidth / 2), yApexPoint);
  363. break;
  364. case 3 :
  365. //draw y axis
  366. pDC->MoveTo(xApexPoint, yApexPoint + (yAxisHeight / 2));  
  367. pDC->LineTo(xApexPoint, yApexPoint - (yAxisHeight / 2));
  368. //draw x axis
  369. pDC->MoveTo(xApexPoint, yApexPoint);  
  370. pDC->LineTo(xApexPoint + xAxisWidth, yApexPoint);
  371. break;
  372. case 4 :
  373. //draw y axis
  374. pDC->MoveTo(xApexPoint, yApexPoint + (yAxisHeight / 2));  
  375. pDC->LineTo(xApexPoint, yApexPoint - (yAxisHeight / 2));
  376. //draw x axis
  377. pDC->MoveTo(xApexPoint - (xAxisWidth / 2), yApexPoint);  
  378. pDC->LineTo(xApexPoint + (xAxisWidth / 2), yApexPoint);
  379. break;
  380. }
  381. pDC->SelectObject(pOldAxisPen);
  382. int tFontSize;
  383. //draw labels
  384. tFontSize = 16;
  385. if(maxWidth > maxHeight)
  386. {
  387. while((axisYLabel.GetLength() * (tFontSize / 2)) > maxHeight)
  388. {
  389. tFontSize -= 2;
  390. }
  391. }
  392. else
  393. {
  394. while((axisXLabel.GetLength() * (tFontSize / 2)) > maxWidth)
  395. {
  396. tFontSize -= 2;
  397. }
  398. }
  399. axisFont.CreateFont(tFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  400. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  401. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  402. sideFont.CreateFont(tFontSize, 0, 900, 0, 700, FALSE, FALSE, 0,
  403. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  404. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  405. pDC->SelectObject(&sideFont);
  406. pDC->GetTextMetrics(&tm);
  407. charWidth = tm.tmAveCharWidth;
  408. if(graphAlignment)
  409. {
  410. switch(graphQuadType)
  411. {
  412. case 1 :
  413. case 2 :
  414. pDC->TextOut(10, (yApexPoint - (yAxisHeight / 2)) + ((axisYLabel.GetLength() * charWidth) / 2), axisYLabel);
  415. break;
  416. case 3 :
  417. case 4 :
  418. pDC->TextOut(10, yApexPoint + ((axisYLabel.GetLength() * charWidth) / 2), axisYLabel);
  419. break;
  420. }
  421. pDC->SelectObject(&axisFont);
  422. pDC->GetTextMetrics(&tm);
  423. charWidth = tm.tmAveCharWidth;
  424. switch(graphQuadType)
  425. {
  426. case 1 :
  427. pDC->TextOut(xApexPoint + (xAxisWidth / 2) - ((axisXLabel.GetLength() / 2) * charWidth), maxHeight - 5 - 6, axisXLabel);
  428. break;
  429. case 2 :
  430. pDC->TextOut(xApexPoint - ((axisXLabel.GetLength() / 2) * charWidth), maxHeight - 5 - 6, axisXLabel);
  431. break;
  432. case 3 :
  433. pDC->TextOut(xApexPoint + (xAxisWidth / 2) - ((axisXLabel.GetLength() / 2) * charWidth), maxHeight - 5 - 6, axisXLabel);
  434. break;
  435. case 4 :
  436. pDC->TextOut(xApexPoint - ((axisXLabel.GetLength() / 2) * charWidth), maxHeight - 5 - 6, axisXLabel);
  437. break;
  438. }
  439. pDC->SelectObject(pOldFont);
  440. tickScale = 0.00;
  441. tickScale = (yAxisHeight - 10) / numTicks;
  442. //draw y axis ticks
  443. if(!inRedraw)
  444. {
  445. switch(graphQuadType)
  446. {
  447. case 1 :
  448. for(y = 1; y <= numTicks; y++) 
  449. {
  450. tickYLocation = (int)(yApexPoint - (y * tickScale));
  451. //draw tick mark
  452. pDC->MoveTo(xApexPoint - 3, tickYLocation);
  453. pDC->LineTo(xApexPoint + 3, tickYLocation);
  454. if(graphHasGridLines)
  455. {
  456. //draw grid lines
  457. COLORREF gridLineColor;
  458. gridLineColor = DARK_GREY;
  459. CPen gridPen (PS_SOLID, 1, gridLineColor);
  460. CPen* pOldPen;
  461. pOldPen = pDC->SelectObject(&gridPen);
  462. pDC->MoveTo(xApexPoint, tickYLocation);
  463. pDC->LineTo(xApexPoint + xAxisWidth, tickYLocation);
  464. pDC->SelectObject(pOldPen);
  465. }
  466. //draw tick label
  467. CString tickLabel;
  468. tickLabel.Format("%d", minTick + (y * tickSpace));
  469. CFont yFont;
  470. yFont.CreateFont(yTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  471. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  472. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  473. pDC->SelectObject(&yFont);
  474. pDC->TextOut(xApexPoint - 10 - (tickLabel.GetLength() * (yTickFontSize / 2)), tickYLocation - 6, tickLabel);
  475. pDC->SelectObject(pOldFont);
  476. topYTick = tickYLocation;
  477. }
  478. break;
  479. pDC->SelectObject(pOldFont);
  480. case 2 :
  481. if(graphType == SCATTER_GRAPH)
  482. {
  483. double oldTickScale;
  484. int oldNumTicks;
  485. oldNumTicks = numTicks;
  486. oldTickScale = tickScale;
  487. numTicks /= 2;
  488. tickScale *= 2;
  489. for(y = 1; y <= numTicks; y++)  
  490. {
  491. tickYLocation = (int)(yApexPoint - (y * tickScale));
  492. //draw tick mark
  493. pDC->MoveTo(xApexPoint - 3, tickYLocation);
  494. pDC->LineTo(xApexPoint + 3, tickYLocation);
  495. if(graphHasGridLines)
  496. {
  497. //draw grid lines
  498. COLORREF gridLineColor;
  499. gridLineColor = LIGHT_GREY;
  500. CPen gridPen (PS_SOLID, 1, gridLineColor);
  501. CPen* pOldPen;
  502. pOldPen = pDC->SelectObject(&gridPen);
  503. pDC->MoveTo(xApexPoint - (xAxisWidth / 2), tickYLocation);
  504. pDC->LineTo(xApexPoint + (xAxisWidth / 2), tickYLocation);
  505. pDC->SelectObject(pOldPen);
  506. }
  507. //draw tick label
  508. CString tickLabel;
  509. tickLabel.Format("%d", minTick + (y * tickSpace));
  510. CFont yFont;
  511. yFont.CreateFont(yTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  512. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  513. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  514. pDC->SelectObject(&yFont);
  515. pDC->TextOut(xApexPoint - (xAxisWidth / 2) - 10 - (tickLabel.GetLength() * (yTickFontSize / 2)), tickYLocation - 6, tickLabel);
  516. pDC->SelectObject(pOldFont);
  517. topYTick = tickYLocation;
  518. }
  519. //draw the 0
  520. pDC->TextOut(xApexPoint - (xAxisWidth / 2) - 10 - (yTickFontSize / 2), yApexPoint - 6, "0");
  521. //reset numTicks and tickScale back to normal
  522. tickScale = oldTickScale;
  523. numTicks = oldNumTicks;
  524. }
  525. else
  526. {
  527. for(y = 1; y <= numTicks; y++)  
  528. {
  529. tickYLocation = (int)(yApexPoint - (y * tickScale));
  530. //draw tick mark
  531. pDC->MoveTo(xApexPoint - 3, tickYLocation);
  532. pDC->LineTo(xApexPoint + 3, tickYLocation);
  533. if(graphHasGridLines)
  534. {
  535. //draw grid lines
  536. COLORREF gridLineColor;
  537. gridLineColor = DARK_GREY;
  538. CPen gridPen (PS_SOLID, 1, gridLineColor);
  539. CPen* pOldPen;
  540. pOldPen = pDC->SelectObject(&gridPen);
  541. pDC->MoveTo(xApexPoint - (xAxisWidth / 2), tickYLocation);
  542. pDC->LineTo(xApexPoint + (xAxisWidth / 2), tickYLocation);
  543. pDC->SelectObject(pOldPen);
  544. }
  545. //draw tick label
  546. CString tickLabel;
  547. tickLabel.Format("%d", minTick + (y * tickSpace));
  548. CFont yFont;
  549. yFont.CreateFont(yTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  550. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  551. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  552. pDC->SelectObject(&yFont);
  553. pDC->TextOut(xApexPoint - (xAxisWidth / 2) - 10 - (tickLabel.GetLength() * (yTickFontSize / 2)), tickYLocation - 6, tickLabel);
  554. topYTick = tickYLocation;
  555. }
  556. //draw the 0
  557. pDC->TextOut(xApexPoint - (xAxisWidth / 2) - 10 - (yTickFontSize / 2), yApexPoint - 6, "0");
  558. }
  559. pDC->SelectObject(pOldFont);
  560. break;
  561. case 3 :
  562. for(y = 0; y <= numTicks / 2; y++) 
  563. {
  564. tickYLocation = (int)(yApexPoint + 5 - (yAxisHeight / 2) + (y * tickScale));
  565. //draw tick mark
  566. pDC->MoveTo(xApexPoint - 3, tickYLocation);
  567. pDC->LineTo(xApexPoint + 3, tickYLocation);
  568. if(graphHasGridLines)
  569. {
  570. //draw grid lines
  571. COLORREF gridLineColor;
  572. gridLineColor = DARK_GREY;
  573. CPen gridPen (PS_SOLID, 1, gridLineColor);
  574. CPen* pOldPen;
  575. pOldPen = pDC->SelectObject(&gridPen);
  576. pDC->MoveTo(xApexPoint, tickYLocation);
  577. pDC->LineTo(xApexPoint, tickYLocation);
  578. pDC->SelectObject(pOldPen);
  579. }
  580. //draw tick label
  581. CString tickLabel;
  582. tickLabel.Format("%d", maxTick - (y * tickSpace));
  583. CFont yFont;
  584. yFont.CreateFont(yTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  585. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  586. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  587. pDC->SelectObject(&yFont);
  588. pDC->TextOut(xApexPoint - 10 - (tickLabel.GetLength() * (yTickFontSize / 2)), tickYLocation - 6, tickLabel);
  589. topYTick = tickYLocation;
  590. }
  591. //draw the 0
  592. pDC->TextOut(xApexPoint - (xAxisWidth / 2) - 10 - (yTickFontSize / 2), yApexPoint - 6, "0");
  593. for(; y <= numTicks; y++) 
  594. {
  595. tickYLocation = (int)(yApexPoint + 5 - (yAxisHeight / 2) + (y * tickScale));
  596. //draw tick mark
  597. pDC->MoveTo(xApexPoint - 3, tickYLocation);
  598. pDC->LineTo(xApexPoint + 3, tickYLocation);
  599. if(graphHasGridLines)
  600. {
  601. //draw grid lines
  602. COLORREF gridLineColor;
  603. gridLineColor = DARK_GREY;
  604. CPen gridPen (PS_SOLID, 1, gridLineColor);
  605. CPen* pOldPen;
  606. pOldPen = pDC->SelectObject(&gridPen);
  607. pDC->MoveTo(xApexPoint, tickYLocation);
  608. pDC->LineTo(xApexPoint, tickYLocation);
  609. pDC->SelectObject(pOldPen);
  610. }
  611. //draw tick label
  612. CString tickLabel;
  613. tickLabel.Format("%d", minTick + ((numTicks - y) * tickSpace));
  614. pDC->TextOut(xApexPoint - 10 - (tickLabel.GetLength() * (yTickFontSize / 2)), tickYLocation - 6, tickLabel);
  615. topYTick = tickYLocation;
  616. }
  617. pDC->SelectObject(pOldFont);
  618. break;
  619. pDC->SelectObject(pOldFont);
  620. case 4 :
  621. for(y = 1; y <= numTicks / 2; y++) 
  622. {
  623. tickYLocation = (int)(yApexPoint - (y * tickScale));
  624. //draw tick mark
  625. pDC->MoveTo(xApexPoint - 3, tickYLocation);
  626. pDC->LineTo(xApexPoint + 3, tickYLocation);
  627. if(graphHasGridLines)
  628. {
  629. //draw grid lines
  630. COLORREF gridLineColor;
  631. gridLineColor = DARK_GREY;
  632. CPen gridPen (PS_SOLID, 1, gridLineColor);
  633. CPen* pOldPen;
  634. pOldPen = pDC->SelectObject(&gridPen);
  635. pDC->MoveTo(xApexPoint - (xAxisWidth / 2), tickYLocation);
  636. pDC->LineTo(xApexPoint + (xAxisWidth / 2), tickYLocation);
  637. pDC->SelectObject(pOldPen);
  638. }
  639. //draw tick label
  640. CString tickLabel;
  641. tickLabel.Format("%d", minTick + (y * tickSpace));
  642. CFont yFont;
  643. yFont.CreateFont(yTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  644. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  645. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  646. pDC->SelectObject(&yFont);
  647. pDC->TextOut(xApexPoint - (xAxisWidth / 2) - 10 - (tickLabel.GetLength() * (yTickFontSize / 2)), tickYLocation - 6, tickLabel);
  648. topYTick = tickYLocation;
  649. }
  650. //draw the 0
  651. pDC->TextOut(xApexPoint - (xAxisWidth / 2) - 10 - (yTickFontSize / 2), yApexPoint - 6, "0");
  652. for(; y <= numTicks; y++)  
  653. {
  654. tickYLocation = (int)(yApexPoint - (yAxisHeight / 2) + (y * tickScale));
  655. //draw tick mark
  656. pDC->MoveTo(xApexPoint - 3, tickYLocation);
  657. pDC->LineTo(xApexPoint + 3, tickYLocation);
  658. if(graphHasGridLines)
  659. {
  660. //draw grid lines
  661. COLORREF gridLineColor;
  662. gridLineColor = DARK_GREY;
  663. CPen gridPen (PS_SOLID, 1, gridLineColor);
  664. CPen* pOldPen;
  665. pOldPen = pDC->SelectObject(&gridPen);
  666. pDC->MoveTo(xApexPoint - (xAxisWidth / 2), tickYLocation);
  667. pDC->LineTo(xApexPoint + (xAxisWidth / 2), tickYLocation);
  668. pDC->SelectObject(pOldPen);
  669. }
  670. //draw tick label
  671. CString tickLabel;
  672. tickLabel.Format("%d", minTick + ((numTicks - y) * tickSpace));
  673. pDC->TextOut(xApexPoint - (xAxisWidth / 2) - 10 - (tickLabel.GetLength() * (yTickFontSize / 2)), tickYLocation - 6, tickLabel);
  674. topYTick = tickYLocation;
  675. }
  676. pDC->SelectObject(pOldFont);
  677. break;
  678. }
  679. }
  680. //draw X axis tick marks
  681. switch(graphQuadType)
  682. {
  683. case 1 :
  684. if(graphType != SCATTER_GRAPH)
  685. {
  686. POSITION pos;
  687. pos = graphSeries->GetHeadPosition();
  688. CGraphSeries* tmpSeries;
  689. for(int x = 1; x <= graphSeries->GetCount(); x++)
  690. {
  691. tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
  692. seriesSpace = xAxisWidth / graphSeries->GetCount();
  693. tickXLocation = xApexPoint + ((x * seriesSpace) - (seriesSpace / 2));
  694. pDC->MoveTo(tickXLocation,yApexPoint - 3);
  695. pDC->LineTo(tickXLocation,yApexPoint + 3);
  696. //draw tick label
  697. CString tickLabel;
  698. CFont xFont;
  699. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  700. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  701. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  702. pDC->SelectObject(&xFont);
  703. tickLabel = tmpSeries->GetLabel();
  704. if(!xAxisAlign)  //horizontal
  705. pDC->TextOut(tickXLocation - ((tickLabel.GetLength() * 8) / 2), yApexPoint + 8, tickLabel);
  706. else
  707. {
  708. CFont sideFont2;
  709. sideFont2.CreateFont(xTickFontSize, 0, (xAxisAlign * 10), 0, 700, FALSE, FALSE, 0,
  710. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  711. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  712. pDC->SelectObject(&sideFont2);
  713. pDC->GetTextMetrics(&tm);
  714. charWidth = tm.tmAveCharWidth;
  715. if(xAxisAlign < 180)
  716. pDC->TextOut(tickXLocation - 8, yApexPoint + 8 + (xAxisLabelLength * charWidth), tickLabel);
  717. else
  718. pDC->TextOut(tickXLocation + 2, yApexPoint + 8, tickLabel);
  719. pDC->SelectObject(pOldFont);
  720. }
  721. rightXTick = tickXLocation;
  722. }
  723. }
  724. else
  725. {
  726. //scatter graphs will use the same tick marking on both axis lines
  727. seriesSpace = (xAxisWidth - 20) / numTicks;
  728. for(int x = 1; x <= numTicks; x++)  
  729. {
  730. tickXLocation = xApexPoint + (x * seriesSpace);
  731. //draw tick mark
  732. pDC->MoveTo(tickXLocation, yApexPoint - 3);
  733. pDC->LineTo(tickXLocation, yApexPoint + 3);
  734. //draw tick label
  735. CString tickLabel;
  736. CFont xFont;
  737. tickLabel.Format("%d", x * tickSpace);
  738. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  739. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  740. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  741. pDC->SelectObject(&xFont);
  742. pDC->GetTextMetrics(&tm);
  743. charWidth = tm.tmAveCharWidth;
  744. pDC->TextOut(tickXLocation - (tickLabel.GetLength() * charWidth / 2), yApexPoint + 8, tickLabel);
  745. rightXTick = tickXLocation;
  746. pDC->SelectObject(pOldFont);
  747. }
  748. }
  749. break;
  750. case 2 :
  751. if(graphType != SCATTER_GRAPH)
  752. {
  753. POSITION pos;
  754. pos = graphSeries->GetHeadPosition();
  755. CGraphSeries* tmpSeries;
  756. seriesSpace = xAxisWidth / graphSeries->GetCount();
  757. for(x = 1; x <= graphSeries->GetCount() / 2; x++)
  758. {
  759. tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
  760. tickXLocation = xApexPoint - (xAxisWidth / 2) + ((x * seriesSpace) - (seriesSpace / 2));
  761. pDC->MoveTo(tickXLocation,yApexPoint - 3);
  762. pDC->LineTo(tickXLocation,yApexPoint + 3);
  763. if(!inRedraw)
  764. {
  765. //draw tick label
  766. CString tickLabel;
  767. tickLabel = tmpSeries->GetLabel();
  768. if(!xAxisAlign)  //horizontal
  769. {
  770. CFont xFont;
  771. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  772. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  773. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  774. pDC->SelectObject(&xFont);
  775. pDC->TextOut(tickXLocation - ((tickLabel.GetLength() * 8) / 2), yApexPoint + 8, tickLabel);
  776. pDC->SelectObject(pOldFont);
  777. }
  778. else
  779. {
  780. CFont sideFont2;
  781. sideFont2.CreateFont(xTickFontSize, 0, (xAxisAlign * 10), 0, 700, FALSE, FALSE, 0,
  782. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  783. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  784. pDC->SelectObject(&sideFont2);
  785. pDC->GetTextMetrics(&tm);
  786. charWidth = tm.tmAveCharWidth;
  787. if(xAxisAlign < 180)
  788. pDC->TextOut(tickXLocation - 8, yApexPoint + 8 + (xAxisLabelLength * charWidth), tickLabel);
  789. else
  790. pDC->TextOut(tickXLocation + 2, yApexPoint + 8, tickLabel);
  791. pDC->SelectObject(pOldFont);
  792. }
  793. }
  794. rightXTick = tickXLocation;
  795. }
  796. if((graphSeries->GetCount() % 2) > 0)
  797. {
  798. tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
  799. tickXLocation = xApexPoint;
  800. pDC->MoveTo(tickXLocation,yApexPoint - 3);
  801. pDC->LineTo(tickXLocation,yApexPoint + 3);
  802. if(!inRedraw)
  803. {
  804. //draw tick label
  805. CString tickLabel;
  806. tickLabel = tmpSeries->GetLabel();
  807. if(!xAxisAlign)  //horizontal
  808. {
  809. CFont xFont;
  810. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  811. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  812. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  813. pDC->SelectObject(&xFont);
  814. pDC->TextOut(tickXLocation - ((tickLabel.GetLength() * 8) / 2), yApexPoint + 8, tickLabel);
  815. pDC->SelectObject(pOldFont);
  816. }
  817. else
  818. {
  819. CFont sideFont2;
  820. sideFont2.CreateFont(xTickFontSize, 0, (xAxisAlign * 10), 0, 700, FALSE, FALSE, 0,
  821. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  822. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  823. pDC->SelectObject(&sideFont2);
  824. pDC->GetTextMetrics(&tm);
  825. charWidth = tm.tmAveCharWidth;
  826. if(xAxisAlign < 180)
  827. pDC->TextOut(tickXLocation - 8, yApexPoint + 8 + (xAxisLabelLength * charWidth), tickLabel);
  828. else
  829. pDC->TextOut(tickXLocation + 2, yApexPoint + 8, tickLabel);
  830. pDC->SelectObject(pOldFont);
  831. }
  832. }
  833. rightXTick = tickXLocation;
  834. x++;
  835. }
  836. for(; x <= graphSeries->GetCount(); x++)
  837. {
  838. tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
  839. tickXLocation = xApexPoint - (xAxisWidth / 2) + ((x * seriesSpace) - (seriesSpace / 2));
  840. pDC->MoveTo(tickXLocation,yApexPoint - 3);
  841. pDC->LineTo(tickXLocation,yApexPoint + 3);
  842. if(!inRedraw)
  843. {
  844. //draw tick label
  845. CString tickLabel;
  846. tickLabel = tmpSeries->GetLabel();
  847. if(!xAxisAlign)  //horizontal
  848. {
  849. CFont xFont;
  850. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  851. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  852. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  853. pDC->SelectObject(&xFont);
  854. pDC->TextOut(tickXLocation - ((tickLabel.GetLength() * 8) / 2), yApexPoint + 8, tickLabel);
  855. pDC->SelectObject(pOldFont);
  856. }
  857. else
  858. {
  859. CFont sideFont2;
  860. sideFont2.CreateFont(xTickFontSize, 0, (xAxisAlign * 10), 0, 700, FALSE, FALSE, 0,
  861. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  862. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  863. pDC->SelectObject(&sideFont2);
  864. pDC->GetTextMetrics(&tm);
  865. charWidth = tm.tmAveCharWidth;
  866. if(xAxisAlign < 180)
  867. pDC->TextOut(tickXLocation - 8, yApexPoint + 8 + (xAxisLabelLength * charWidth), tickLabel);
  868. else
  869. pDC->TextOut(tickXLocation + 2, yApexPoint + 8, tickLabel);
  870. pDC->SelectObject(pOldFont);
  871. }
  872. }
  873. rightXTick = tickXLocation;
  874. }
  875. }
  876. else
  877. {
  878. //scatter graphs will use the same tick marking on both axis lines
  879. seriesSpace = xAxisWidth / numTicks;
  880. for(x = 0; x <= numTicks / 2; x++)  
  881. {
  882. tickXLocation = xApexPoint + 5 - (xAxisWidth / 2) + (x * seriesSpace);
  883. //draw tick mark
  884. pDC->MoveTo(tickXLocation, yApexPoint - 3);
  885. pDC->LineTo(tickXLocation, yApexPoint + 3);
  886. if(!inRedraw)
  887. {
  888. //draw tick label
  889. CString tickLabel;
  890. tickLabel.Format("%d", minTick + (x * tickSpace));
  891. CFont xFont;
  892. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  893. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  894. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  895. pDC->SelectObject(&xFont);
  896. pDC->GetTextMetrics(&tm);
  897. charWidth = tm.tmAveCharWidth;
  898. pDC->TextOut(tickXLocation - (tickLabel.GetLength() * charWidth / 2), yApexPoint + 8, tickLabel);
  899. }
  900. rightXTick = tickXLocation;
  901. pDC->SelectObject(pOldFont);
  902. }
  903. //draw the 0
  904. tickXLocation = xApexPoint;
  905. if(!inRedraw)
  906. {
  907. //draw tick label
  908. CFont xFont;
  909. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  910. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  911. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  912. pDC->SelectObject(&xFont);
  913. pDC->GetTextMetrics(&tm);
  914. charWidth = tm.tmAveCharWidth;
  915. pDC->TextOut(tickXLocation - (charWidth / 2), yApexPoint + 8, "0");
  916. }
  917. for(; x <= numTicks; x++)  
  918. {
  919. tickXLocation = xApexPoint - (xAxisWidth / 2) + (x * seriesSpace);
  920. //draw tick mark
  921. pDC->MoveTo(tickXLocation, yApexPoint - 3);
  922. pDC->LineTo(tickXLocation, yApexPoint + 3);
  923. if(!inRedraw)
  924. {
  925. //draw tick label
  926. CString tickLabel;
  927. tickLabel.Format("%d", (x / 2) * tickSpace);
  928. CFont xFont;
  929. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  930. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  931. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  932. pDC->SelectObject(&xFont);
  933. pDC->GetTextMetrics(&tm);
  934. charWidth = tm.tmAveCharWidth;
  935. pDC->TextOut(tickXLocation - (tickLabel.GetLength() * charWidth / 2), yApexPoint + 8, tickLabel);
  936. }
  937. rightXTick = tickXLocation;
  938. pDC->SelectObject(pOldFont);
  939. }
  940. }
  941. break;
  942. case 3 :
  943. if(graphType != SCATTER_GRAPH)
  944. {
  945. POSITION pos;
  946. pos = graphSeries->GetHeadPosition();
  947. CGraphSeries* tmpSeries;
  948. for(int x = 1; x <= graphSeries->GetCount(); x++)
  949. {
  950. tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
  951. seriesSpace = xAxisWidth / graphSeries->GetCount();
  952. tickXLocation = xApexPoint + ((x * seriesSpace) - (seriesSpace / 2));
  953. pDC->MoveTo(tickXLocation,yApexPoint - 3);
  954. pDC->LineTo(tickXLocation,yApexPoint + 3);
  955. if(!inRedraw)
  956. {
  957. //draw tick label
  958. CString tickLabel;
  959. tickLabel = tmpSeries->GetLabel();
  960. if(!xAxisAlign)  //horizontal
  961. {
  962. CFont xFont;
  963. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  964. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  965. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  966. pDC->SelectObject(&xFont);
  967. pDC->TextOut(tickXLocation - ((tickLabel.GetLength() * 8) / 2), yApexPoint + (yAxisHeight / 2) + 8, tickLabel);
  968. pDC->SelectObject(pOldFont);
  969. }
  970. else
  971. {
  972. CFont sideFont2;
  973. sideFont2.CreateFont(xTickFontSize, 0, (xAxisAlign * 10), 0, 700, FALSE, FALSE, 0,
  974. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  975. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  976. pDC->SelectObject(&sideFont2);
  977. pDC->GetTextMetrics(&tm);
  978. charWidth = tm.tmAveCharWidth;
  979. if(xAxisAlign < 180)
  980. pDC->TextOut(tickXLocation - 8, yApexPoint + (yAxisHeight / 2) + 8 + (xAxisLabelLength * charWidth), tickLabel);
  981. else
  982. pDC->TextOut(tickXLocation + 2, yApexPoint + (yAxisHeight / 2) + 8, tickLabel);
  983. pDC->SelectObject(pOldFont);
  984. }
  985. }
  986. rightXTick = tickXLocation;
  987. }
  988. }
  989. else
  990. {
  991. //scatter graphs will use the same tick marking on both axis lines
  992. seriesSpace = (xAxisWidth - 20) / numTicks;
  993. for(int x = 1; x <= numTicks; x++)  
  994. {
  995. tickXLocation = xApexPoint + (x * seriesSpace);
  996. //draw tick mark
  997. pDC->MoveTo(tickXLocation, yApexPoint - 3);
  998. pDC->LineTo(tickXLocation, yApexPoint + 3);
  999. if(!inRedraw)
  1000. {
  1001. //draw tick label
  1002. CString tickLabel;
  1003. tickLabel.Format("%d", x * tickSpace);
  1004. CFont xFont;
  1005. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1006. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1007. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1008. pDC->SelectObject(&xFont);
  1009. pDC->GetTextMetrics(&tm);
  1010. charWidth = tm.tmAveCharWidth;
  1011. pDC->TextOut(tickXLocation - (tickLabel.GetLength() * charWidth / 2), yApexPoint + (yAxisHeight / 2) + 8, tickLabel);
  1012. }
  1013. rightXTick = tickXLocation;
  1014. pDC->SelectObject(pOldFont);
  1015. }
  1016. }
  1017. break;
  1018. case 4 :
  1019. if(graphType != SCATTER_GRAPH)
  1020. {
  1021. POSITION pos;
  1022. pos = graphSeries->GetHeadPosition();
  1023. CGraphSeries* tmpSeries;
  1024. seriesSpace = xAxisWidth / graphSeries->GetCount();
  1025. for(x = 1; x <= graphSeries->GetCount() / 2; x++)
  1026. {
  1027. tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
  1028. tickXLocation = xApexPoint - (xAxisWidth / 2) + ((x * seriesSpace) - (seriesSpace / 2));
  1029. pDC->MoveTo(tickXLocation,yApexPoint - 3);
  1030. pDC->LineTo(tickXLocation,yApexPoint + 3);
  1031. if(!inRedraw)
  1032. {
  1033. //draw tick label
  1034. CString tickLabel;
  1035. tickLabel = tmpSeries->GetLabel();
  1036. if(!xAxisAlign)  //horizontal
  1037. {
  1038. CFont xFont;
  1039. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1040. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1041. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1042. pDC->SelectObject(&xFont);
  1043. pDC->TextOut(tickXLocation - ((tickLabel.GetLength() * 8) / 2), yApexPoint + (yAxisHeight / 2) + 8, tickLabel);
  1044. pDC->SelectObject(pOldFont);
  1045. }
  1046. else
  1047. {
  1048. CFont sideFont2;
  1049. sideFont2.CreateFont(xTickFontSize, 0, (xAxisAlign * 10), 0, 700, FALSE, FALSE, 0,
  1050. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1051. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1052. pDC->SelectObject(&sideFont2);
  1053. pDC->GetTextMetrics(&tm);
  1054. charWidth = tm.tmAveCharWidth;
  1055. if(xAxisAlign < 180)
  1056. pDC->TextOut(tickXLocation - 8, yApexPoint + (yAxisHeight / 2) + 8 + (xAxisLabelLength * charWidth), tickLabel);
  1057. else
  1058. pDC->TextOut(tickXLocation + 2, yApexPoint + (yAxisHeight / 2) + 8, tickLabel);
  1059. pDC->SelectObject(pOldFont);
  1060. }
  1061. }
  1062. rightXTick = tickXLocation;
  1063. }
  1064. if((graphSeries->GetCount() % 2) > 0)
  1065. {
  1066. tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
  1067. tickXLocation = xApexPoint;
  1068. pDC->MoveTo(tickXLocation,yApexPoint - 3);
  1069. pDC->LineTo(tickXLocation,yApexPoint + 3);
  1070. if(!inRedraw)
  1071. {
  1072. //draw tick label
  1073. CString tickLabel;
  1074. tickLabel = tmpSeries->GetLabel();
  1075. if(!xAxisAlign)  //horizontal
  1076. {
  1077. CFont xFont;
  1078. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1079. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1080. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1081. pDC->SelectObject(&xFont);
  1082. pDC->TextOut(tickXLocation - ((tickLabel.GetLength() * 8) / 2), yApexPoint + (yAxisHeight / 2) + 8, tickLabel);
  1083. pDC->SelectObject(pOldFont);
  1084. }
  1085. else
  1086. {
  1087. CFont sideFont2;
  1088. sideFont2.CreateFont(xTickFontSize, 0, (xAxisAlign * 10), 0, 700, FALSE, FALSE, 0,
  1089. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1090. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1091. pDC->SelectObject(&sideFont2);
  1092. pDC->GetTextMetrics(&tm);
  1093. charWidth = tm.tmAveCharWidth;
  1094. if(xAxisAlign < 180)
  1095. pDC->TextOut(tickXLocation - 8, yApexPoint + (yAxisHeight / 2) + 8 + (xAxisLabelLength * charWidth), tickLabel);
  1096. else
  1097. pDC->TextOut(tickXLocation + 2, yApexPoint + (yAxisHeight / 2) + 8, tickLabel);
  1098. pDC->SelectObject(pOldFont);
  1099. }
  1100. }
  1101. rightXTick = tickXLocation;
  1102. x++;
  1103. }
  1104. for(; x <= graphSeries->GetCount(); x++)
  1105. {
  1106. tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
  1107. tickXLocation = xApexPoint - (xAxisWidth / 2) + ((x * seriesSpace) - (seriesSpace / 2));
  1108. pDC->MoveTo(tickXLocation,yApexPoint - 3);
  1109. pDC->LineTo(tickXLocation,yApexPoint + 3);
  1110. if(!inRedraw)
  1111. {
  1112. //draw tick label
  1113. CString tickLabel;
  1114. tickLabel = tmpSeries->GetLabel();
  1115. if(!xAxisAlign)  //horizontal
  1116. {
  1117. CFont xFont;
  1118. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1119. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1120. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1121. pDC->SelectObject(&xFont);
  1122. pDC->TextOut(tickXLocation - ((tickLabel.GetLength() * 8) / 2), yApexPoint + (yAxisHeight / 2) + 8, tickLabel);
  1123. pDC->SelectObject(pOldFont);
  1124. }
  1125. else
  1126. {
  1127. CFont sideFont2;
  1128. sideFont2.CreateFont(xTickFontSize, 0, (xAxisAlign * 10), 0, 700, FALSE, FALSE, 0,
  1129. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1130. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1131. pDC->SelectObject(&sideFont2);
  1132. pDC->GetTextMetrics(&tm);
  1133. charWidth = tm.tmAveCharWidth;
  1134. if(xAxisAlign < 180)
  1135. pDC->TextOut(tickXLocation - 8, yApexPoint + (yAxisHeight / 2) + 8 + (xAxisLabelLength * charWidth), tickLabel);
  1136. else
  1137. pDC->TextOut(tickXLocation + 2, yApexPoint + (yAxisHeight / 2) + 8, tickLabel);
  1138. pDC->SelectObject(pOldFont);
  1139. }
  1140. }
  1141. rightXTick = tickXLocation;
  1142. }
  1143. }
  1144. else
  1145. {
  1146. //scatter graphs will use the same tick marking on both axis lines
  1147. seriesSpace = (xAxisWidth - 20) / numTicks;
  1148. for(x = 1; x <= numTicks / 2; x++)  
  1149. {
  1150. tickXLocation = xApexPoint - (xAxisWidth / 2) + (x * seriesSpace);
  1151. //draw tick mark
  1152. pDC->MoveTo(tickXLocation, yApexPoint + (yAxisHeight / 2) - 3);
  1153. pDC->LineTo(tickXLocation, yApexPoint + (yAxisHeight / 2) + 3);
  1154. if(!inRedraw)
  1155. {
  1156. //draw tick label
  1157. CString tickLabel;
  1158. tickLabel.Format("%d", x * tickSpace);
  1159. CFont xFont;
  1160. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1161. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1162. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1163. pDC->SelectObject(&xFont);
  1164. pDC->GetTextMetrics(&tm);
  1165. charWidth = tm.tmAveCharWidth;
  1166. pDC->TextOut(tickXLocation - (tickLabel.GetLength() * charWidth / 2), yApexPoint + 8, tickLabel);
  1167. }
  1168. rightXTick = tickXLocation;
  1169. pDC->SelectObject(pOldFont);
  1170. }
  1171. //draw the 0
  1172. for(; x <= numTicks; x++)  
  1173. {
  1174. tickXLocation = xApexPoint - (xAxisWidth / 2) + (x * seriesSpace);
  1175. //draw tick mark
  1176. pDC->MoveTo(tickXLocation, yApexPoint + (yAxisHeight / 2) - 3);
  1177. pDC->LineTo(tickXLocation, yApexPoint + (yAxisHeight / 2) + 3);
  1178. if(!inRedraw)
  1179. {
  1180. //draw tick label
  1181. CString tickLabel;
  1182. tickLabel.Format("%d", x * tickSpace);
  1183. CFont xFont;
  1184. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1185. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1186. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1187. pDC->SelectObject(&xFont);
  1188. pDC->GetTextMetrics(&tm);
  1189. charWidth = tm.tmAveCharWidth;
  1190. pDC->TextOut(tickXLocation - (tickLabel.GetLength() * charWidth / 2), yApexPoint + 8, tickLabel);
  1191. }
  1192. rightXTick = tickXLocation;
  1193. pDC->SelectObject(pOldFont);
  1194. }
  1195. }
  1196. break;
  1197. }
  1198. }
  1199. else
  1200. {
  1201. //reverse above stuff and treat as horizontal graph
  1202. switch(graphQuadType)
  1203. {
  1204. case 1 :
  1205. pDC->TextOut(10, (yApexPoint - (yAxisHeight / 2)) + (axisYLabel.GetLength() / 2), axisXLabel);
  1206. pDC->SelectObject(&axisFont);
  1207. pDC->GetTextMetrics(&tm);
  1208. charWidth = tm.tmAveCharWidth;
  1209. labelHeight = tm.tmHeight + 10;
  1210. if(axisYLabel.GetLength() == 0)
  1211. labelHeight = 0;
  1212. pDC->TextOut(xApexPoint + (xAxisWidth / 2) - ((axisXLabel.GetLength() / 2) * charWidth), maxHeight - 5 - 6, axisYLabel);
  1213. pDC->SelectObject(pOldFont);
  1214. //to allow scalability (height may be less than tickRange)
  1215. tickScale = 0.00;
  1216. //draw y axis ticks
  1217. if(graphType != SCATTER_GRAPH)
  1218. {
  1219. tickScale = (yAxisHeight - 10) / seriesSize;
  1220. POSITION pos;
  1221. pos = graphSeries->GetHeadPosition();
  1222. CGraphSeries* tmpSeries;
  1223. for(y = 1; y <= graphSeries->GetCount(); y++)  
  1224. {
  1225. tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
  1226. seriesSpace = yAxisHeight / graphSeries->GetCount();
  1227. tickYLocation = yApexPoint - ((y * seriesSpace) - (seriesSpace / 2));
  1228. //draw tick mark
  1229. pDC->MoveTo(xApexPoint - 3, tickYLocation);
  1230. pDC->LineTo(xApexPoint + 3, tickYLocation);
  1231. if(!inRedraw)
  1232. {
  1233. //draw tick label
  1234. CString tickLabel;
  1235. tickLabel = tmpSeries->GetLabel();
  1236. CFont yFont;
  1237. yFont.CreateFont(yTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1238. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1239. DEFAULT_QUALITY, FIXED_PITCH | FF_ROMAN,"Arial");
  1240. pDC->SelectObject(&yFont);
  1241. charWidth = tm.tmAveCharWidth;
  1242. pDC->TextOut(xApexPoint - (xAxisLabelLength * charWidth) - 5, tickYLocation - (tm.tmHeight / 2), tickLabel);
  1243. }
  1244. topYTick = tickYLocation;
  1245. pDC->SelectObject(pOldFont);
  1246. }
  1247. }
  1248. else
  1249. {
  1250. //scatter graphs will use the same tick marking on both axis lines
  1251. for(y = 1; y <= numTicks; y++)  
  1252. {
  1253. tickScale = (yAxisHeight - 10) / numTicks;
  1254. tickYLocation = yApexPoint - (int)(y * tickScale);
  1255. //draw tick mark
  1256. pDC->MoveTo(xApexPoint - 3, tickYLocation);
  1257. pDC->LineTo(xApexPoint + 3, tickYLocation);
  1258. if(!inRedraw)
  1259. {
  1260. //draw tick label
  1261. CString tickLabel;
  1262. tickLabel.Format("%d", y * tickSpace);
  1263. CFont yFont;
  1264. yFont.CreateFont(yTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1265. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1266. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1267. pDC->SelectObject(&yFont);
  1268. pDC->TextOut(xApexPoint - 10 - (tickLabel.GetLength() * (yTickFontSize / 2)), tickYLocation - 6, tickLabel);
  1269. }
  1270. topYTick = tickYLocation;
  1271. pDC->SelectObject(pOldFont);
  1272. }
  1273. }
  1274. //draw X axis tick marks
  1275. tickScale = (xAxisWidth - 10) / numTicks;
  1276. for(x = 1; x <= numTicks; x++)
  1277. {
  1278. tickXLocation = xApexPoint + (int)(x * tickScale);
  1279. pDC->MoveTo(tickXLocation,yApexPoint - 3);
  1280. pDC->LineTo(tickXLocation,yApexPoint + 3);
  1281. if(!inRedraw)
  1282. {
  1283. if(graphHasGridLines)
  1284. {
  1285. //draw grid lines
  1286. COLORREF gridLineColor;
  1287. gridLineColor = DARK_GREY;
  1288. CPen gridPen (PS_SOLID, 1, gridLineColor);
  1289. CPen* pOldPen;
  1290. pOldPen = pDC->SelectObject(&gridPen);
  1291. pDC->MoveTo(tickXLocation, yApexPoint);
  1292. pDC->LineTo(tickXLocation, yApexPoint - yAxisHeight);
  1293. pDC->SelectObject(pOldPen);
  1294. }
  1295. //draw tick label
  1296. CString tickLabel;
  1297. tickLabel.Format("%d", minTick + (x * tickSpace));
  1298. if(!xAxisAlign)  //horizontal
  1299. {
  1300. CFont xFont;
  1301. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1302. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1303. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1304. pDC->SelectObject(&xFont);
  1305. charWidth = tm.tmAveCharWidth;
  1306. pDC->TextOut(tickXLocation - ((tickLabel.GetLength() * charWidth) / 2), yApexPoint + 8, tickLabel);
  1307. pDC->SelectObject(pOldFont);
  1308. }
  1309. else
  1310. {
  1311. CFont sideFont2;
  1312. sideFont2.CreateFont(xTickFontSize, 0, (xAxisAlign * 10), 0, 700, FALSE, FALSE, 0,
  1313. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1314. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1315. pDC->SelectObject(&sideFont2);
  1316. pDC->GetTextMetrics(&tm);
  1317. charWidth = tm.tmAveCharWidth;
  1318. if(xAxisAlign < 180)
  1319. pDC->TextOut(tickXLocation - 8, yApexPoint + 8 + (xAxisLabelLength * charWidth), tickLabel);
  1320. else
  1321. pDC->TextOut(tickXLocation + 2, yApexPoint + 8, tickLabel);
  1322. pDC->SelectObject(pOldFont);
  1323. }
  1324. }
  1325. rightXTick = tickXLocation;
  1326. }
  1327. break;
  1328. case 2 :
  1329. pDC->TextOut(10, (yApexPoint - (yAxisHeight / 2)) + (axisYLabel.GetLength() / 2), axisXLabel);
  1330. pDC->SelectObject(&axisFont);
  1331. pDC->GetTextMetrics(&tm);
  1332. charWidth = tm.tmAveCharWidth;
  1333. labelHeight = tm.tmHeight + 10;
  1334. if(axisYLabel.GetLength() == 0)
  1335. labelHeight = 0;
  1336. pDC->TextOut(xApexPoint - ((axisXLabel.GetLength() / 2) * charWidth), maxHeight - 5 - 6, axisYLabel);
  1337. pDC->SelectObject(pOldFont);
  1338. //to allow scalability (height may be less than tickRange)
  1339. tickScale = 0.00;
  1340. seriesSpace = yAxisHeight / graphSeries->GetCount();
  1341. //draw y axis ticks
  1342. if(graphType != SCATTER_GRAPH)
  1343. {
  1344. tickScale = (yAxisHeight - 10) / seriesSize;
  1345. POSITION pos;
  1346. pos = graphSeries->GetHeadPosition();
  1347. CGraphSeries* tmpSeries;
  1348. for(y = 1; y <= graphSeries->GetCount(); y++)  
  1349. {
  1350. tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
  1351. tickYLocation = yApexPoint - ((y * seriesSpace) - (seriesSpace / 2));
  1352. //draw tick mark
  1353. pDC->MoveTo(xApexPoint - 3, tickYLocation);
  1354. pDC->LineTo(xApexPoint + 3, tickYLocation);
  1355. if(!inRedraw)
  1356. {
  1357. //draw tick label
  1358. CString tickLabel;
  1359. tickLabel = tmpSeries->GetLabel();
  1360. CFont yFont;
  1361. yFont.CreateFont(yTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1362. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1363. DEFAULT_QUALITY, FIXED_PITCH | FF_ROMAN,"Arial");
  1364. pDC->SelectObject(&yFont);
  1365. charWidth = tm.tmAveCharWidth;
  1366. pDC->TextOut(xApexPoint - (xAxisWidth / 2) - (xAxisLabelLength * charWidth) - 5, tickYLocation - (tm.tmHeight / 2), tickLabel);
  1367. }
  1368. topYTick = tickYLocation;
  1369. pDC->SelectObject(pOldFont);
  1370. }
  1371. topYTick = tickYLocation;
  1372. pDC->SelectObject(pOldFont);
  1373. }
  1374. else
  1375. {
  1376. //scatter graphs will use the same tick marking on both axis lines
  1377. int oldNumTicks;
  1378. oldNumTicks = numTicks;
  1379. numTicks /= 2;
  1380. for(y = 0; y <= numTicks; y++)  
  1381. {
  1382. tickScale = (yAxisHeight - 10) / numTicks;
  1383. tickYLocation = yApexPoint - (int)(y * tickScale);
  1384. //draw tick mark
  1385. pDC->MoveTo(xApexPoint - 3, tickYLocation);
  1386. pDC->LineTo(xApexPoint + 3, tickYLocation);
  1387. if(!inRedraw)
  1388. {
  1389. //draw tick label
  1390. CString tickLabel;
  1391. tickLabel.Format("%d", (y * tickSpace));
  1392. CFont yFont;
  1393. yFont.CreateFont(yTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1394. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1395. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1396. pDC->SelectObject(&yFont);
  1397. pDC->TextOut(xApexPoint - (xAxisWidth / 2) - (tickLabel.GetLength() * (yTickFontSize / 2)) - 6, tickYLocation - 6, tickLabel);
  1398. }
  1399. topYTick = tickYLocation;
  1400. pDC->SelectObject(pOldFont);
  1401. }
  1402. numTicks = oldNumTicks;
  1403. }
  1404. //draw X axis tick marks
  1405. tickScale = (xAxisWidth - 10) / numTicks;
  1406. for(x = 0; x <= numTicks / 2; x++)
  1407. {
  1408. tickXLocation = xApexPoint - (xAxisWidth / 2) + (int)(x * tickScale) + 5;
  1409. if(!inRedraw)
  1410. {
  1411. pDC->MoveTo(tickXLocation,yApexPoint - 3);
  1412. pDC->LineTo(tickXLocation,yApexPoint + 3);
  1413. if(graphHasGridLines)
  1414. {
  1415. //draw grid lines
  1416. COLORREF gridLineColor;
  1417. gridLineColor = DARK_GREY;
  1418. CPen gridPen (PS_SOLID, 1, gridLineColor);
  1419. CPen* pOldPen;
  1420. pOldPen = pDC->SelectObject(&gridPen);
  1421. pDC->MoveTo(tickXLocation, yApexPoint - yAxisHeight);
  1422. pDC->LineTo(tickXLocation, yApexPoint);
  1423. pDC->SelectObject(pOldPen);
  1424. }
  1425. //draw tick label
  1426. CString tickLabel;
  1427. tickLabel.Format("%d", minTick + (x * tickSpace));
  1428. if(!xAxisAlign)  //horizontal
  1429. {
  1430. CFont xFont;
  1431. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1432. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1433. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1434. pDC->SelectObject(&xFont);
  1435. charWidth = tm.tmAveCharWidth;
  1436. pDC->TextOut(tickXLocation - ((tickLabel.GetLength() * charWidth) / 2), yApexPoint + 8, tickLabel);
  1437. pDC->SelectObject(pOldFont);
  1438. }
  1439. else
  1440. {
  1441. CFont sideFont2;
  1442. sideFont2.CreateFont(xTickFontSize, 0, (xAxisAlign * 10), 0, 700, FALSE, FALSE, 0,
  1443. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1444. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1445. pDC->SelectObject(&sideFont2);
  1446. pDC->GetTextMetrics(&tm);
  1447. charWidth = tm.tmAveCharWidth;
  1448. if(xAxisAlign < 180)
  1449. pDC->TextOut(tickXLocation - 8, yApexPoint + 8 + (xAxisLabelLength * charWidth), tickLabel);
  1450. else
  1451. pDC->TextOut(tickXLocation + 2, yApexPoint + 8, tickLabel);
  1452. pDC->SelectObject(pOldFont);
  1453. }
  1454. }
  1455. rightXTick = tickXLocation;
  1456. }
  1457. //draw the 0 location
  1458. tickXLocation = xApexPoint - (xAxisWidth / 2) + (int)(x * tickScale);
  1459. if(!inRedraw)
  1460. {
  1461. //draw tick label
  1462. if(!xAxisAlign)  //horizontal
  1463. {
  1464. CFont xFont;
  1465. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1466. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1467. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1468. pDC->SelectObject(&xFont);
  1469. charWidth = tm.tmAveCharWidth;
  1470. pDC->TextOut(tickXLocation - (charWidth / 2), yApexPoint + 8, "0");
  1471. pDC->SelectObject(pOldFont);
  1472. }
  1473. else
  1474. {
  1475. CFont sideFont2;
  1476. sideFont2.CreateFont(xTickFontSize, 0, (xAxisAlign * 10), 0, 700, FALSE, FALSE, 0,
  1477. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1478. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1479. pDC->SelectObject(&sideFont2);
  1480. pDC->GetTextMetrics(&tm);
  1481. charWidth = tm.tmAveCharWidth;
  1482. if(xAxisAlign < 180)
  1483. pDC->TextOut(tickXLocation - 8, yApexPoint + 8 + (xAxisLabelLength * charWidth), "0");
  1484. else
  1485. pDC->TextOut(tickXLocation + 2, yApexPoint + 8, "0");
  1486. pDC->SelectObject(pOldFont);
  1487. }
  1488. }
  1489. for(; x <= numTicks; x++)
  1490. {
  1491. tickXLocation = xApexPoint - (xAxisWidth / 2) + (int)(x * tickScale);
  1492. pDC->MoveTo(tickXLocation,yApexPoint - 3);
  1493. pDC->LineTo(tickXLocation,yApexPoint + 3);
  1494. if(!inRedraw)
  1495. {
  1496. if(graphHasGridLines)
  1497. {
  1498. //draw grid lines
  1499. COLORREF gridLineColor;
  1500. gridLineColor = DARK_GREY;
  1501. CPen gridPen (PS_SOLID, 1, gridLineColor);
  1502. CPen* pOldPen;
  1503. pOldPen = pDC->SelectObject(&gridPen);
  1504. pDC->MoveTo(tickXLocation, yApexPoint - yAxisHeight);
  1505. pDC->LineTo(tickXLocation, yApexPoint);
  1506. pDC->SelectObject(pOldPen);
  1507. }
  1508. //draw tick label
  1509. CString tickLabel;
  1510. tickLabel.Format("%d", minTick + (x * tickSpace));
  1511. if(!xAxisAlign)  //horizontal
  1512. {
  1513. CFont xFont;
  1514. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1515. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1516. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1517. pDC->SelectObject(&xFont);
  1518. charWidth = tm.tmAveCharWidth;
  1519. pDC->TextOut(tickXLocation - ((tickLabel.GetLength() * charWidth) / 2), yApexPoint + 8, tickLabel);
  1520. pDC->SelectObject(pOldFont);
  1521. }
  1522. else
  1523. {
  1524. CFont sideFont2;
  1525. sideFont2.CreateFont(xTickFontSize, 0, (xAxisAlign * 10), 0, 700, FALSE, FALSE, 0,
  1526. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1527. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1528. pDC->SelectObject(&sideFont2);
  1529. pDC->GetTextMetrics(&tm);
  1530. charWidth = tm.tmAveCharWidth;
  1531. if(xAxisAlign < 180)
  1532. pDC->TextOut(tickXLocation - 8, yApexPoint + 8 + (xAxisLabelLength * charWidth), tickLabel);
  1533. else
  1534. pDC->TextOut(tickXLocation + 2, yApexPoint + 8, tickLabel);
  1535. pDC->SelectObject(pOldFont);
  1536. }
  1537. }
  1538. rightXTick = tickXLocation;
  1539. }
  1540. break;
  1541. case 3 :
  1542. pDC->TextOut(10, yApexPoint - (axisYLabel.GetLength() / 2), axisXLabel);
  1543. pDC->SelectObject(&axisFont);
  1544. pDC->GetTextMetrics(&tm);
  1545. charWidth = tm.tmAveCharWidth;
  1546. labelHeight = tm.tmHeight + 10;
  1547. if(axisYLabel.GetLength() == 0)
  1548. labelHeight = 0;
  1549. pDC->TextOut(xApexPoint + (xAxisWidth / 2) - ((axisXLabel.GetLength() / 2) * charWidth), maxHeight - 5 - 6, axisYLabel);
  1550. pDC->SelectObject(pOldFont);
  1551. //to allow scalability (height may be less than tickRange)
  1552. tickScale = 0.00;
  1553. seriesSpace = yAxisHeight / graphSeries->GetCount();
  1554. //draw y axis ticks
  1555. if(graphType != SCATTER_GRAPH)
  1556. {
  1557. tickScale = (yAxisHeight - 10) / seriesSize;
  1558. POSITION pos;
  1559. pos = graphSeries->GetHeadPosition();
  1560. CGraphSeries* tmpSeries;
  1561. for(y = 1; y <= graphSeries->GetCount() / 2; y++)  
  1562. {
  1563. tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
  1564. tickYLocation = yApexPoint - (yAxisHeight / 2) + ((y * seriesSpace) - (seriesSpace / 2));
  1565. //draw tick mark
  1566. pDC->MoveTo(xApexPoint - 3, tickYLocation);
  1567. pDC->LineTo(xApexPoint + 3, tickYLocation);
  1568. if(!inRedraw)
  1569. {
  1570. //draw tick label
  1571. CString tickLabel;
  1572. tickLabel = tmpSeries->GetLabel();
  1573. CFont yFont;
  1574. yFont.CreateFont(yTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1575. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1576. DEFAULT_QUALITY, FIXED_PITCH | FF_ROMAN,"Arial");
  1577. pDC->SelectObject(&yFont);
  1578. charWidth = tm.tmAveCharWidth;
  1579. pDC->TextOut(xApexPoint - 5 - (tickLabel.GetLength() * (yTickFontSize / 2)), tickYLocation - 6, tickLabel);
  1580. }
  1581. topYTick = tickYLocation;
  1582. pDC->SelectObject(pOldFont);
  1583. }
  1584. //draw the 0 location
  1585. tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
  1586. tickYLocation = yApexPoint;
  1587. //draw tick mark
  1588. pDC->MoveTo(xApexPoint - 3, tickYLocation);
  1589. pDC->LineTo(xApexPoint + 3, tickYLocation);
  1590. if(!inRedraw)
  1591. {
  1592. //draw tick label
  1593. CString tickLabel;
  1594. tickLabel = tmpSeries->GetLabel();
  1595. CFont yFont;
  1596. yFont.CreateFont(yTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1597. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1598. DEFAULT_QUALITY, FIXED_PITCH | FF_ROMAN,"Arial");
  1599. pDC->SelectObject(&yFont);
  1600. charWidth = tm.tmAveCharWidth;
  1601. pDC->TextOut(xApexPoint - 5 - (tickLabel.GetLength() * (yTickFontSize / 2)), tickYLocation - 6, tickLabel);
  1602. }
  1603. topYTick = tickYLocation;
  1604. pDC->SelectObject(pOldFont);
  1605. y++;
  1606. for(; y <= graphSeries->GetCount(); y++)  
  1607. {
  1608. tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
  1609. tickYLocation = yApexPoint - (yAxisHeight / 2) + ((y * seriesSpace) - (seriesSpace / 2));
  1610. //draw tick mark
  1611. pDC->MoveTo(xApexPoint - 3, tickYLocation);
  1612. pDC->LineTo(xApexPoint + 3, tickYLocation);
  1613. if(!inRedraw)
  1614. {
  1615. //draw tick label
  1616. CString tickLabel;
  1617. tickLabel = tmpSeries->GetLabel();
  1618. CFont yFont;
  1619. yFont.CreateFont(yTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1620. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1621. DEFAULT_QUALITY, FIXED_PITCH | FF_ROMAN,"Arial");
  1622. pDC->SelectObject(&yFont);
  1623. charWidth = tm.tmAveCharWidth;
  1624. pDC->TextOut(xApexPoint - 5 - (tickLabel.GetLength() * (yTickFontSize / 2)), tickYLocation - 6, tickLabel);
  1625. }
  1626. topYTick = tickYLocation;
  1627. pDC->SelectObject(pOldFont);
  1628. }
  1629. }
  1630. else
  1631. {
  1632. //scatter graphs will use the same tick marking on both axis lines
  1633. for(y = 0; y < numTicks / 2; y++)  
  1634. {
  1635. tickScale = (yAxisHeight - 10) / numTicks;
  1636. tickYLocation = yApexPoint - (yAxisHeight / 2) + (int)(y * tickScale) + 5;
  1637. //draw tick mark
  1638. pDC->MoveTo(xApexPoint - 3, tickYLocation);
  1639. pDC->LineTo(xApexPoint + 3, tickYLocation);
  1640. if(!inRedraw)
  1641. {
  1642. //draw tick label
  1643. CString tickLabel;
  1644. tickLabel.Format("%d", maxTick - (y * tickSpace));
  1645. CFont yFont;
  1646. yFont.CreateFont(yTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1647. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1648. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1649. pDC->SelectObject(&yFont);
  1650. pDC->TextOut(xApexPoint - (tickLabel.GetLength() * (yTickFontSize / 2)) - 8, tickYLocation - 6, tickLabel);
  1651. pDC->SelectObject(pOldFont);
  1652. }
  1653. }
  1654. //draw the 0 location
  1655. tickYLocation = yApexPoint;
  1656. //draw tick mark
  1657. pDC->MoveTo(xApexPoint - 3, tickYLocation);
  1658. pDC->LineTo(xApexPoint + 3, tickYLocation);
  1659. if(!inRedraw)
  1660. {
  1661. //draw tick label
  1662. CFont yFont;
  1663. yFont.CreateFont(yTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1664. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1665. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1666. pDC->SelectObject(&yFont);
  1667. pDC->TextOut(xApexPoint - (yTickFontSize / 2) - 8, tickYLocation - 6, "0");
  1668. pDC->SelectObject(pOldFont);
  1669. }
  1670. y++;
  1671. for(; y <= numTicks; y++)  
  1672. {
  1673. tickScale = (yAxisHeight - 10) / numTicks;
  1674. tickYLocation = yApexPoint - (yAxisHeight / 2) + (int)(y * tickScale) + 5;
  1675. //draw tick mark
  1676. pDC->MoveTo(xApexPoint - 3, tickYLocation);
  1677. pDC->LineTo(xApexPoint + 3, tickYLocation);
  1678. if(!inRedraw)
  1679. {
  1680. //draw tick label
  1681. CString tickLabel;
  1682. tickLabel.Format("%d", maxTick - (y * tickSpace));
  1683. CFont yFont;
  1684. yFont.CreateFont(yTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1685. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1686. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1687. pDC->SelectObject(&yFont);
  1688. pDC->TextOut(xApexPoint - (tickLabel.GetLength() * (yTickFontSize / 2)) - 5, tickYLocation - 6, tickLabel);
  1689. pDC->SelectObject(pOldFont);
  1690. }
  1691. topYTick = tickYLocation;
  1692. }
  1693. }
  1694. //draw X axis tick marks
  1695. int oldNumTicks;
  1696. oldNumTicks = numTicks;
  1697. numTicks /= 2;
  1698. tickScale = (xAxisWidth - 10) / numTicks;
  1699. for(x = 0; x <= numTicks; x++)
  1700. {
  1701. tickXLocation = xApexPoint + (int)(x * tickScale);
  1702. if(!inRedraw)
  1703. {
  1704. pDC->MoveTo(tickXLocation,yApexPoint - 3);
  1705. pDC->LineTo(tickXLocation,yApexPoint + 3);
  1706. if(graphHasGridLines)
  1707. {
  1708. //draw grid lines
  1709. COLORREF gridLineColor;
  1710. gridLineColor = DARK_GREY;
  1711. CPen gridPen (PS_SOLID, 1, gridLineColor);
  1712. CPen* pOldPen;
  1713. pOldPen = pDC->SelectObject(&gridPen);
  1714. pDC->MoveTo(tickXLocation, yApexPoint - (yAxisHeight / 2));
  1715. pDC->LineTo(tickXLocation, yApexPoint + (yAxisHeight / 2));
  1716. pDC->SelectObject(pOldPen);
  1717. }
  1718. //draw tick label
  1719. CString tickLabel;
  1720. tickLabel.Format("%d", (x * tickSpace * 2));
  1721. if(!xAxisAlign)  //horizontal
  1722. {
  1723. CFont xFont;
  1724. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1725. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1726. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1727. pDC->SelectObject(&xFont);
  1728. charWidth = tm.tmAveCharWidth;
  1729. pDC->TextOut(tickXLocation - ((tickLabel.GetLength() * charWidth) / 2), yApexPoint + (yAxisHeight / 2) + 8, tickLabel);
  1730. pDC->SelectObject(pOldFont);
  1731. }
  1732. else
  1733. {
  1734. CFont sideFont2;
  1735. sideFont2.CreateFont(xTickFontSize, 0, (xAxisAlign * 10), 0, 700, FALSE, FALSE, 0,
  1736. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1737. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1738. pDC->SelectObject(&sideFont2);
  1739. pDC->GetTextMetrics(&tm);
  1740. charWidth = tm.tmAveCharWidth;
  1741. if(xAxisAlign < 180)
  1742. pDC->TextOut(tickXLocation - 8, yApexPoint + (yAxisHeight / 2) + 8 + (xAxisLabelLength * charWidth), tickLabel);
  1743. else
  1744. pDC->TextOut(tickXLocation + 2, yApexPoint + (yAxisHeight / 2) + 8, tickLabel);
  1745. pDC->SelectObject(pOldFont);
  1746. }
  1747. }
  1748. }
  1749. numTicks = oldNumTicks;
  1750. rightXTick = tickXLocation;
  1751. break;
  1752. case 4 :
  1753. pDC->TextOut(10, yApexPoint - (axisYLabel.GetLength() / 2), axisXLabel);
  1754. pDC->SelectObject(&axisFont);
  1755. pDC->GetTextMetrics(&tm);
  1756. charWidth = tm.tmAveCharWidth;
  1757. labelHeight = tm.tmHeight + 10;
  1758. if(axisYLabel.GetLength() == 0)
  1759. labelHeight = 0;
  1760. pDC->TextOut(xApexPoint - ((axisXLabel.GetLength() / 2) * charWidth), maxHeight - 5 - 6, axisYLabel);
  1761. pDC->SelectObject(pOldFont);
  1762. //to allow scalability (height may be less than tickRange)
  1763. tickScale = 0.00;
  1764. seriesSpace = yAxisHeight / graphSeries->GetCount();
  1765. //draw y axis ticks
  1766. if(graphType != SCATTER_GRAPH)
  1767. {
  1768. tickScale = (yAxisHeight - 10) / seriesSize;
  1769. POSITION pos;
  1770. pos = graphSeries->GetHeadPosition();
  1771. CGraphSeries* tmpSeries;
  1772. for(y = 1; y <= graphSeries->GetCount() / 2; y++)  
  1773. {
  1774. tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
  1775. tickYLocation = yApexPoint - (yAxisHeight / 2) + ((y * seriesSpace) - (seriesSpace / 2));
  1776. //draw tick mark
  1777. pDC->MoveTo(xApexPoint - 3, tickYLocation);
  1778. pDC->LineTo(xApexPoint + 3, tickYLocation);
  1779. if(!inRedraw)
  1780. {
  1781. //draw tick label
  1782. CString tickLabel;
  1783. tickLabel = tmpSeries->GetLabel();
  1784. CFont yFont;
  1785. yFont.CreateFont(yTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1786. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1787. DEFAULT_QUALITY, FIXED_PITCH | FF_ROMAN,"Arial");
  1788. pDC->SelectObject(&yFont);
  1789. charWidth = tm.tmAveCharWidth;
  1790. pDC->TextOut(xApexPoint - (xAxisWidth / 2) - (xAxisLabelLength * charWidth) - 5, tickYLocation - (tm.tmHeight / 2), tickLabel);
  1791. }
  1792. topYTick = tickYLocation;
  1793. pDC->SelectObject(pOldFont);
  1794. }
  1795. //draw the 0 location
  1796. tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
  1797. tickYLocation = yApexPoint;
  1798. //draw tick mark
  1799. pDC->MoveTo(xApexPoint - 3, tickYLocation);
  1800. pDC->LineTo(xApexPoint + 3, tickYLocation);
  1801. if(!inRedraw)
  1802. {
  1803. //draw tick label
  1804. CString tickLabel;
  1805. tickLabel = tmpSeries->GetLabel();
  1806. CFont yFont;
  1807. yFont.CreateFont(yTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1808. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1809. DEFAULT_QUALITY, FIXED_PITCH | FF_ROMAN,"Arial");
  1810. pDC->SelectObject(&yFont);
  1811. charWidth = tm.tmAveCharWidth;
  1812. pDC->TextOut(xApexPoint - (xAxisWidth / 2) - (xAxisLabelLength * charWidth) - 5, tickYLocation - (tm.tmHeight / 2), tickLabel);
  1813. }
  1814. topYTick = tickYLocation;
  1815. pDC->SelectObject(pOldFont);
  1816. y++;
  1817. for(; y <= graphSeries->GetCount(); y++)  
  1818. {
  1819. tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
  1820. tickYLocation = yApexPoint - (yAxisHeight / 2) + ((y * seriesSpace) - (seriesSpace / 2));
  1821. //draw tick mark
  1822. pDC->MoveTo(xApexPoint - 3, tickYLocation);
  1823. pDC->LineTo(xApexPoint + 3, tickYLocation);
  1824. if(!inRedraw)
  1825. {
  1826. //draw tick label
  1827. CString tickLabel;
  1828. tickLabel = tmpSeries->GetLabel();
  1829. CFont yFont;
  1830. yFont.CreateFont(yTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1831. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1832. DEFAULT_QUALITY, FIXED_PITCH | FF_ROMAN,"Arial");
  1833. pDC->SelectObject(&yFont);
  1834. charWidth = tm.tmAveCharWidth;
  1835. pDC->TextOut(xApexPoint - (xAxisWidth / 2) - (xAxisLabelLength * charWidth) - 5, tickYLocation - (tm.tmHeight / 2), tickLabel);
  1836. }
  1837. topYTick = tickYLocation;
  1838. pDC->SelectObject(pOldFont);
  1839. }
  1840. }
  1841. else
  1842. {
  1843. //scatter graphs will use the same tick marking on both axis lines
  1844. for(y = 1; y <= numTicks; y++)  
  1845. {
  1846. tickScale = (yAxisHeight - 10) / numTicks;
  1847. tickYLocation = yApexPoint - (yAxisHeight / 2) + (int)(y * tickScale);
  1848. //draw tick mark
  1849. pDC->MoveTo(xApexPoint - 3, tickYLocation);
  1850. pDC->LineTo(xApexPoint + 3, tickYLocation);
  1851. if(!inRedraw)
  1852. {
  1853. //draw tick label
  1854. CString tickLabel;
  1855. tickLabel.Format("%d", y * tickSpace);
  1856. CFont yFont;
  1857. yFont.CreateFont(yTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1858. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1859. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1860. pDC->SelectObject(&yFont);
  1861. pDC->TextOut(xApexPoint - (xAxisWidth / 2) - (tickLabel.GetLength() * (yTickFontSize / 2)), tickYLocation - 6, tickLabel);
  1862. }
  1863. topYTick = tickYLocation;
  1864. pDC->SelectObject(pOldFont);
  1865. }
  1866. }
  1867. //draw X axis tick marks
  1868. tickScale = (xAxisWidth - 10) / numTicks;
  1869. for(x = 0; x <= numTicks / 2; x++)
  1870. {
  1871. tickXLocation = xApexPoint - (xAxisWidth / 2) + (int)(x * tickScale) + 5;
  1872. if(!inRedraw)
  1873. {
  1874. pDC->MoveTo(tickXLocation,yApexPoint - 3);
  1875. pDC->LineTo(tickXLocation,yApexPoint + 3);
  1876. if(graphHasGridLines)
  1877. {
  1878. //draw grid lines
  1879. COLORREF gridLineColor;
  1880. gridLineColor = DARK_GREY;
  1881. CPen gridPen (PS_SOLID, 1, gridLineColor);
  1882. CPen* pOldPen;
  1883. pOldPen = pDC->SelectObject(&gridPen);
  1884. pDC->MoveTo(tickXLocation, yApexPoint - (yAxisHeight / 2));
  1885. pDC->LineTo(tickXLocation, yApexPoint + (yAxisHeight / 2));
  1886. pDC->SelectObject(pOldPen);
  1887. }
  1888. //draw tick label
  1889. CString tickLabel;
  1890. tickLabel.Format("%d", minTick + (x * tickSpace));
  1891. if(!xAxisAlign)  //horizontal
  1892. {
  1893. CFont xFont;
  1894. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1895. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1896. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1897. pDC->SelectObject(&xFont);
  1898. charWidth = tm.tmAveCharWidth;
  1899. pDC->TextOut(tickXLocation - ((tickLabel.GetLength() * charWidth) / 2), yApexPoint + (yAxisHeight / 2) + 8, tickLabel);
  1900. pDC->SelectObject(pOldFont);
  1901. }
  1902. else
  1903. {
  1904. CFont sideFont2;
  1905. sideFont2.CreateFont(xTickFontSize, 0, (xAxisAlign * 10), 0, 700, FALSE, FALSE, 0,
  1906. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1907. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1908. pDC->SelectObject(&sideFont2);
  1909. pDC->GetTextMetrics(&tm);
  1910. charWidth = tm.tmAveCharWidth;
  1911. if(xAxisAlign < 180)
  1912. pDC->TextOut(tickXLocation - 8, yApexPoint + (yAxisHeight / 2) + 8 + (xAxisLabelLength * charWidth), tickLabel);
  1913. else
  1914. pDC->TextOut(tickXLocation + 2, yApexPoint + (yAxisHeight / 2) + 8, tickLabel);
  1915. pDC->SelectObject(pOldFont);
  1916. }
  1917. }
  1918. rightXTick = tickXLocation;
  1919. }
  1920. //draw the 0 location
  1921. tickXLocation = xApexPoint - (xAxisWidth / 2) + (int)(x * tickScale);
  1922. if(!inRedraw)
  1923. {
  1924. if(graphHasGridLines)
  1925. {
  1926. //draw grid lines
  1927. COLORREF gridLineColor;
  1928. gridLineColor = DARK_GREY;
  1929. CPen gridPen (PS_SOLID, 1, gridLineColor);
  1930. CPen* pOldPen;
  1931. pOldPen = pDC->SelectObject(&gridPen);
  1932. pDC->MoveTo(tickXLocation, yApexPoint - (yAxisHeight / 2));
  1933. pDC->LineTo(tickXLocation, yApexPoint + (yAxisHeight / 2));
  1934. pDC->SelectObject(pOldPen);
  1935. }
  1936. //draw tick label
  1937. if(!xAxisAlign)  //horizontal
  1938. {
  1939. CFont xFont;
  1940. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1941. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1942. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1943. pDC->SelectObject(&xFont);
  1944. charWidth = tm.tmAveCharWidth;
  1945. pDC->TextOut(tickXLocation - (charWidth / 2), yApexPoint + (yAxisHeight / 2) + 8, "0");
  1946. pDC->SelectObject(pOldFont);
  1947. }
  1948. else
  1949. {
  1950. CFont sideFont2;
  1951. sideFont2.CreateFont(xTickFontSize, 0, (xAxisAlign * 10), 0, 700, FALSE, FALSE, 0,
  1952. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1953. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1954. pDC->SelectObject(&sideFont2);
  1955. pDC->GetTextMetrics(&tm);
  1956. charWidth = tm.tmAveCharWidth;
  1957. if(xAxisAlign < 180)
  1958. pDC->TextOut(tickXLocation - 8, yApexPoint + (yAxisHeight / 2) + 8 + (xAxisLabelLength * charWidth), "0");
  1959. else
  1960. pDC->TextOut(tickXLocation + 2, yApexPoint + (yAxisHeight / 2) + 8, "0");
  1961. pDC->SelectObject(pOldFont);
  1962. }
  1963. }
  1964. x++;
  1965. for(; x <= numTicks; x++)
  1966. {
  1967. tickXLocation = xApexPoint - (xAxisWidth / 2) + (int)(x * tickScale);
  1968. pDC->MoveTo(tickXLocation,yApexPoint - 3);
  1969. pDC->LineTo(tickXLocation,yApexPoint + 3);
  1970. if(!inRedraw)
  1971. {
  1972. if(graphHasGridLines)
  1973. {
  1974. //draw grid lines
  1975. COLORREF gridLineColor;
  1976. gridLineColor = DARK_GREY;
  1977. CPen gridPen (PS_SOLID, 1, gridLineColor);
  1978. CPen* pOldPen;
  1979. pOldPen = pDC->SelectObject(&gridPen);
  1980. pDC->MoveTo(tickXLocation, yApexPoint - (yAxisHeight / 2));
  1981. pDC->LineTo(tickXLocation, yApexPoint + (yAxisHeight / 2));
  1982. pDC->SelectObject(pOldPen);
  1983. }
  1984. //draw tick label
  1985. CString tickLabel;
  1986. tickLabel.Format("%d", (x / 2) * tickSpace);
  1987. if(!xAxisAlign)  //horizontal
  1988. {
  1989. CFont xFont;
  1990. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  1991. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1992. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  1993. pDC->SelectObject(&xFont);
  1994. charWidth = tm.tmAveCharWidth;
  1995. pDC->TextOut(tickXLocation - ((tickLabel.GetLength() * charWidth) / 2), yApexPoint + (yAxisHeight / 2) + 8, tickLabel);
  1996. pDC->SelectObject(pOldFont);
  1997. }
  1998. else
  1999. {
  2000. CFont sideFont2;
  2001. sideFont2.CreateFont(xTickFontSize, 0, (xAxisAlign * 10), 0, 700, FALSE, FALSE, 0,
  2002. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  2003. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  2004. pDC->SelectObject(&sideFont2);
  2005. pDC->GetTextMetrics(&tm);
  2006. charWidth = tm.tmAveCharWidth;
  2007. if(xAxisAlign < 180)
  2008. pDC->TextOut(tickXLocation - 8, yApexPoint + (yAxisHeight / 2) + 8 + (xAxisLabelLength * charWidth), tickLabel);
  2009. else
  2010. pDC->TextOut(tickXLocation + 2, yApexPoint + (yAxisHeight / 2) + 8, tickLabel);
  2011. pDC->SelectObject(pOldFont);
  2012. }
  2013. }
  2014. rightXTick = tickXLocation;
  2015. }
  2016. break;
  2017. }
  2018. }
  2019. break;
  2020. case BAR_GRAPH_3D :
  2021. case LINE_GRAPH_3D :
  2022. case STACKED_BAR_GRAPH_3D :
  2023. depth = (int)(yAxisHeight * depthRatio);
  2024. xApexPoint += depth;
  2025. yApexPoint -= depth;
  2026. xAxisWidth -= depth;
  2027. yAxisHeight -= depth;
  2028. //draw y axis
  2029. pDC->MoveTo(xApexPoint, yApexPoint);  
  2030. pDC->LineTo(xApexPoint, yApexPoint - yAxisHeight);
  2031. //draw x axis
  2032. pDC->MoveTo(xApexPoint, yApexPoint);  
  2033. pDC->LineTo(xApexPoint + xAxisWidth, yApexPoint);
  2034. //adjust graph settings for 3D look
  2035. yApexPoint += depth;
  2036. xApexPoint -= depth;
  2037. //foreground axis
  2038. pDC->MoveTo(xApexPoint, yApexPoint + (int)(depth * .2));  
  2039. pDC->LineTo(xApexPoint, yApexPoint - yAxisHeight);
  2040. pDC->MoveTo(xApexPoint - (int)(depth * .2), yApexPoint);  
  2041. pDC->LineTo(xApexPoint + xAxisWidth, yApexPoint);
  2042. //connecting line at apex
  2043. pDC->MoveTo(xApexPoint, yApexPoint);  
  2044. pDC->LineTo(xApexPoint + depth, yApexPoint - depth);
  2045. //connecting line at height
  2046. pDC->MoveTo(xApexPoint, yApexPoint - yAxisHeight);  
  2047. pDC->LineTo(xApexPoint + depth, yApexPoint - yAxisHeight - depth);
  2048. //connecting line at width
  2049. pDC->MoveTo(xApexPoint + xAxisWidth, yApexPoint);  
  2050. pDC->LineTo(xApexPoint + xAxisWidth + depth, yApexPoint - depth);
  2051. //top and right border lines
  2052. pDC->MoveTo(xApexPoint + depth, yApexPoint - yAxisHeight - depth);
  2053. pDC->LineTo(xApexPoint + xAxisWidth + depth, yApexPoint - yAxisHeight - depth);
  2054. pDC->LineTo(xApexPoint + xAxisWidth + depth, yApexPoint - depth);
  2055. //Tick marks ... and labels too
  2056. //draw labels
  2057. tFontSize = 16;
  2058. if(maxWidth > maxHeight)
  2059. {
  2060. while((axisYLabel.GetLength() * (tFontSize / 2)) > maxHeight)
  2061. {
  2062. tFontSize -= 2;
  2063. }
  2064. }
  2065. else
  2066. {
  2067. while((axisXLabel.GetLength() * (tFontSize / 2)) > maxWidth)
  2068. {
  2069. tFontSize -= 2;
  2070. }
  2071. }
  2072. axisFont.CreateFont(tFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  2073. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  2074. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  2075. sideFont.CreateFont(tFontSize, 0, 900, 0, 700, FALSE, FALSE, 0,
  2076. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  2077. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  2078. pDC->SelectObject(&sideFont);
  2079. pDC->GetTextMetrics(&tm);
  2080. charWidth = tm.tmAveCharWidth;
  2081. if(graphAlignment)
  2082. {
  2083. pDC->TextOut(10, (yApexPoint - (yAxisHeight / 2)) + ((axisYLabel.GetLength() * charWidth) / 2), axisYLabel);
  2084. pDC->SelectObject(&axisFont);
  2085. pDC->GetTextMetrics(&tm);
  2086. charWidth = tm.tmAveCharWidth;
  2087. pDC->TextOut(xApexPoint + (xAxisWidth / 2) - ((axisXLabel.GetLength() / 2) * charWidth), maxHeight - 5 - 6, axisXLabel);
  2088. pDC->SelectObject(pOldFont);
  2089. tickScale = 0.00;
  2090. tickScale = yAxisHeight / numTicks;
  2091. //draw y axis ticks
  2092. for(int y = 1; y <= numTicks; y++)  
  2093. {
  2094. tickYLocation = yApexPoint - (int)(y * tickScale);
  2095. //draw tick mark
  2096. pDC->MoveTo(xApexPoint - (int)(depth * .2), tickYLocation);
  2097. pDC->LineTo(xApexPoint, tickYLocation);
  2098. COLORREF gridLineColor;
  2099. CPen* pOldPen;
  2100. //draw grid lines
  2101. gridLineColor = DARK_GREY;
  2102. CPen gridPen (PS_SOLID, 1, gridLineColor);
  2103. pOldPen = pDC->SelectObject(&gridPen);
  2104. pDC->MoveTo(xApexPoint, tickYLocation);
  2105. pDC->LineTo(xApexPoint + depth, tickYLocation - depth);
  2106. if(graphHasGridLines)
  2107. {
  2108. pDC->LineTo(xApexPoint + xAxisWidth + depth, tickYLocation - depth);
  2109. }
  2110. pDC->SelectObject(pOldPen);
  2111. //draw tick label
  2112. CString tickLabel;
  2113. tickLabel.Format("%d", minTick + (y * tickSpace));
  2114. CFont yFont;
  2115. yFont.CreateFont(yTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  2116. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  2117. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  2118. pDC->SelectObject(&yFont);
  2119. pDC->TextOut(xApexPoint - 10 - (tickLabel.GetLength() * (yTickFontSize / 2)), tickYLocation - 6, tickLabel);
  2120. topYTick = tickYLocation;
  2121. pDC->SelectObject(pOldFont);
  2122. //draw 1/2 tick line (grey)
  2123. int midTickYLocation;
  2124. midTickYLocation = yApexPoint - (int)(y * tickScale * .5) - (int)((y - 1) * tickScale * .5);
  2125. //draw tick mark
  2126. pDC->MoveTo(xApexPoint - (int)(depth * .2), midTickYLocation);
  2127. pDC->LineTo(xApexPoint, midTickYLocation);
  2128. //draw grid lines
  2129. gridLineColor = LIGHT_GREY;
  2130. CPen midGridPen (PS_SOLID, 1, gridLineColor);
  2131. pOldPen = pDC->SelectObject(&midGridPen);
  2132. pDC->MoveTo(xApexPoint, midTickYLocation);
  2133. pDC->LineTo(xApexPoint + depth, midTickYLocation - depth);
  2134. if(graphHasGridLines)
  2135. {
  2136. pDC->LineTo(xApexPoint + xAxisWidth + depth, midTickYLocation - depth);
  2137. }
  2138. pDC->SelectObject(pOldPen);
  2139. }
  2140. //draw X axis tick marks
  2141. POSITION pos;
  2142. pos = graphSeries->GetHeadPosition();
  2143. CGraphSeries* tmpSeries;
  2144. for(int x = 1; x <= graphSeries->GetCount(); x++)
  2145. {
  2146. tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
  2147. seriesSpace = xAxisWidth / graphSeries->GetCount();
  2148. tickXLocation = xApexPoint + ((x * seriesSpace) - (seriesSpace / 2));
  2149. //unlike normal series, we put ticks here
  2150. //on the outsides of the series
  2151. pDC->MoveTo(xApexPoint + (x * seriesSpace),yApexPoint + (int)(depth * .2));
  2152. pDC->LineTo(xApexPoint + (x * seriesSpace),yApexPoint);
  2153. pDC->LineTo(xApexPoint + (x * seriesSpace) + depth,yApexPoint - depth);
  2154. //draw tick label
  2155. CString tickLabel;
  2156. tickLabel = tmpSeries->GetLabel();
  2157. if(!xAxisAlign)  //horizontal
  2158. pDC->TextOut(tickXLocation - ((tickLabel.GetLength() * 8) / 2), yApexPoint + 8, tickLabel);
  2159. else
  2160. {
  2161. CFont sideFont2;
  2162. sideFont2.CreateFont(xTickFontSize, 0, (xAxisAlign * 10), 0, 700, FALSE, FALSE, 0,
  2163. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  2164. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  2165. pDC->SelectObject(&sideFont2);
  2166. pDC->GetTextMetrics(&tm);
  2167. charWidth = tm.tmAveCharWidth;
  2168. if(xAxisAlign < 180)
  2169. pDC->TextOut(tickXLocation - 8, yApexPoint + 8 + (xAxisLabelLength * charWidth), tickLabel);
  2170. else
  2171. pDC->TextOut(tickXLocation + 2, yApexPoint + 8, tickLabel);
  2172. pDC->SelectObject(pOldFont);
  2173. }
  2174. rightXTick = tickXLocation;
  2175. }
  2176. }
  2177. else
  2178. {
  2179. //reverse above stuff and treat as horizontal graph
  2180. pDC->TextOut(10, (yApexPoint - (yAxisHeight / 2)) + (axisYLabel.GetLength() / 2), axisXLabel);
  2181. pDC->SelectObject(&axisFont);
  2182. pDC->GetTextMetrics(&tm);
  2183. charWidth = tm.tmAveCharWidth;
  2184. labelHeight = tm.tmHeight + 10;
  2185. if(axisYLabel.GetLength() == 0)
  2186. labelHeight = 0;
  2187. pDC->TextOut(xApexPoint + (xAxisWidth / 2) - ((axisXLabel.GetLength() / 2) * charWidth), maxHeight - 5 - 6, axisYLabel);
  2188. pDC->SelectObject(pOldFont);
  2189. tickScale = 0.00;
  2190. //draw y axis ticks
  2191. tickScale = (yAxisHeight - 10) / seriesSize;
  2192. POSITION pos;
  2193. pos = graphSeries->GetHeadPosition();
  2194. CGraphSeries* tmpSeries;
  2195. for(int y = 1; y <= graphSeries->GetCount(); y++)  
  2196. {
  2197. tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
  2198. seriesSpace = yAxisHeight / graphSeries->GetCount();
  2199. tickYLocation = yApexPoint - (y * seriesSpace);
  2200. //draw tick mark
  2201. //unlike normal series, we put ticks here on the 
  2202. //outside of the series
  2203. pDC->MoveTo(xApexPoint - (int)(depth * .2), tickYLocation);
  2204. pDC->LineTo(xApexPoint, tickYLocation);
  2205. pDC->LineTo(xApexPoint + depth,yApexPoint - (y * seriesSpace) - depth);
  2206. //draw tick label
  2207. CString tickLabel;
  2208. tickLabel = tmpSeries->GetLabel();
  2209. CFont yFont;
  2210. yFont.CreateFont(yTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  2211. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  2212. DEFAULT_QUALITY, FIXED_PITCH | FF_ROMAN,"Arial");
  2213. pDC->SelectObject(&yFont);
  2214. charWidth = tm.tmAveCharWidth;
  2215. pDC->TextOut(xApexPoint - (xAxisLabelLength * charWidth) - 5, tickYLocation - (tm.tmHeight / 2), tickLabel);
  2216. topYTick = tickYLocation;
  2217. pDC->SelectObject(pOldFont);
  2218. }
  2219. //draw X axis tick marks
  2220. tickScale = (xAxisWidth - 10) / numTicks;
  2221. for(int x = 1; x <= numTicks; x++)
  2222. {
  2223. tickXLocation = xApexPoint + (int)(x * tickScale);
  2224. pDC->MoveTo(tickXLocation,yApexPoint + (int)(depth * .2));
  2225. pDC->LineTo(tickXLocation,yApexPoint);
  2226. COLORREF gridLineColor;
  2227. CPen* pOldPen;
  2228. //draw grid lines
  2229. gridLineColor = DARK_GREY;
  2230. CPen gridPen (PS_SOLID, 1, gridLineColor);
  2231. pOldPen = pDC->SelectObject(&gridPen);
  2232. pDC->MoveTo(tickXLocation, yApexPoint);
  2233. pDC->LineTo(tickXLocation + depth, yApexPoint - depth);
  2234. if(graphHasGridLines)
  2235. {
  2236. pDC->LineTo(tickXLocation + depth, yApexPoint - yAxisHeight - depth);
  2237. }
  2238. pDC->SelectObject(pOldPen);
  2239. //draw tick label
  2240. CString tickLabel;
  2241. tickLabel.Format("%d", minTick + (x * tickSpace));
  2242. if(!xAxisAlign)  //horizontal
  2243. {
  2244. CFont xFont;
  2245. xFont.CreateFont(xTickFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  2246. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  2247. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  2248. pDC->SelectObject(&xFont);
  2249. charWidth = tm.tmAveCharWidth;
  2250. pDC->TextOut(tickXLocation - ((tickLabel.GetLength() * charWidth) / 2), yApexPoint + 8, tickLabel);
  2251. pDC->SelectObject(pOldFont);
  2252. }
  2253. else
  2254. {
  2255. CFont sideFont2;
  2256. sideFont2.CreateFont(xTickFontSize, 0, (xAxisAlign * 10), 0, 700, FALSE, FALSE, 0,
  2257. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  2258. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  2259. pDC->SelectObject(&sideFont2);
  2260. pDC->GetTextMetrics(&tm);
  2261. charWidth = tm.tmAveCharWidth;
  2262. if(xAxisAlign < 180)
  2263. pDC->TextOut(tickXLocation - 8, yApexPoint + 8 + (xAxisLabelLength * charWidth), tickLabel);
  2264. else
  2265. pDC->TextOut(tickXLocation + 2, yApexPoint + 8, tickLabel);
  2266. pDC->SelectObject(pOldFont);
  2267. }
  2268. rightXTick = tickXLocation;
  2269. //draw 1/2 tick line (grey)
  2270. int midTickXLocation;
  2271. midTickXLocation = xApexPoint + (int)(x * tickScale * .5) + (int)((x - 1) * tickScale * .5);
  2272. //draw tick mark
  2273. pDC->MoveTo(midTickXLocation,yApexPoint + (int)(depth * .2));
  2274. pDC->LineTo(midTickXLocation,yApexPoint);
  2275. //draw grid lines
  2276. gridLineColor = LIGHT_GREY;
  2277. CPen midGridPen (PS_SOLID, 1, gridLineColor);
  2278. pDC->SelectObject(&midGridPen);
  2279. pDC->MoveTo(midTickXLocation, yApexPoint);
  2280. pDC->LineTo(midTickXLocation + depth, yApexPoint - depth);
  2281. if(graphHasGridLines)
  2282. {
  2283. pDC->LineTo(midTickXLocation + depth, yApexPoint - yAxisHeight - depth);
  2284. }
  2285. pDC->SelectObject(pOldPen);
  2286. }
  2287. }
  2288. break;
  2289. }
  2290. }
  2291. void CGraph::AddSeries(CGraphSeries* dataSet)
  2292. {
  2293. int numData = 0;
  2294. numData = dataSet->GetDataCount();
  2295. if(numData > seriesSize)
  2296. seriesSize = numData;
  2297. graphSeries->AddTail(dataSet);
  2298. }
  2299. void CGraph::SetXAxisLabel(CString label)
  2300. {
  2301. axisXLabel = label;
  2302. xAxisLabelLength = axisXLabel.GetLength();
  2303. }
  2304. void CGraph::SetYAxisLabel(CString label)
  2305. {
  2306. axisYLabel = label;
  2307. yAxisLabelLength = axisYLabel.GetLength();
  2308. }
  2309. void CGraph::DrawSeries(CDC* pDC)
  2310. {
  2311. switch(graphType)
  2312. {
  2313. case BAR_GRAPH :
  2314.  DrawBarSeries(pDC);
  2315.  break;
  2316. case LINE_GRAPH :
  2317.  DrawLineSeries(pDC);
  2318.  break;
  2319. case PIE_GRAPH :
  2320.  DrawPieSeries(pDC);
  2321.  break;
  2322. case SCATTER_GRAPH :
  2323.  DrawScatterSeries(pDC);
  2324.  break;
  2325. case BOX_WHISKER_GRAPH :
  2326.  DrawBoxWhiskerSeries(pDC);
  2327.  break;
  2328. case STACKED_BAR_GRAPH :
  2329.  DrawStackedBarSeries(pDC);
  2330.  break;
  2331. case XY_LINE_GRAPH :
  2332.  DrawXYLineSeries(pDC);
  2333.  break;
  2334. // case RADAR_GRAPH :
  2335. //  DrawRadarSeries(pDC);
  2336. //  break;
  2337. case BAR_GRAPH_3D :
  2338.  Draw3DBarSeries(pDC);
  2339.  break;
  2340. case LINE_GRAPH_3D :
  2341.  Draw3DLineSeries(pDC);
  2342.  break;
  2343. case STACKED_BAR_GRAPH_3D :
  2344.  Draw3DStackedBarSeries(pDC);
  2345.  break;
  2346. case PIE_GRAPH_3D :
  2347.  Draw3DPieSeries(pDC);
  2348.  break;
  2349. default :
  2350.  AfxMessageBox("No graph type to display");
  2351.  break;
  2352. }
  2353. }
  2354. void CGraph::SetLegend(int datagroup, CString label)
  2355. {
  2356. if(graphType != SCATTER_GRAPH) //scatter graphs don't need legends
  2357. {
  2358. graphLegend.SetLegendText(datagroup, label);
  2359. graphHasLegend = TRUE;
  2360. if(legendMaxText < label.GetLength())
  2361. legendMaxText = label.GetLength();
  2362. }
  2363. }
  2364. int CGraph::DrawLegend(CDC* pDC)
  2365. {
  2366. //determine size of legend
  2367. //12 chars per seriesSize + 6 for spacing (3 top and bottom) 
  2368. //+ 1 set for label title(3+12+6) + rectangle (2 chars) + 3 for final bottom buffer
  2369. int legendHeight = 23 + (seriesSize * 18) + 3;
  2370. int legendL, legendT, legendR, legendB;
  2371. int barL, barT, barR, barB;
  2372. TEXTMETRIC tm;
  2373. legendT = (maxHeight / 2) - (legendHeight / 2);
  2374. legendB = legendT + legendHeight;
  2375. legendR = maxWidth - 5;
  2376. legendL = legendR - ((graphLegend.GetLegendLength() * (int)(legendFontSize * .66)) + 25);
  2377. //allows 50 pixels for display of legend bar 45 + 5 space.
  2378. legendWidth = legendR - legendL;
  2379. pDC->Rectangle(legendL, legendT, legendR, legendB);
  2380. CFont legendTitleFont;
  2381. legendTitleFont.CreateFont(15, 0, 0, 0, 500, FALSE, FALSE, 0,
  2382. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  2383. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  2384. CFont* pOldFont = (CFont*) pDC->SelectObject(&legendTitleFont);
  2385. pDC->GetTextMetrics(&tm);
  2386. int charWidth = tm.tmAveCharWidth;
  2387. pDC->TextOut(legendL + (legendWidth / 2) - (3 * charWidth), 
  2388. legendT + 3, "图例");
  2389. pDC->SelectObject(pOldFont);
  2390. for(int i = 0; i < seriesSize; i++)
  2391. {
  2392. //top "Legend" text will use 12 + 3 top + 6 bottom (21 total)
  2393. //each legend label will need 3 chars on top, so the 24 in the offset
  2394. //each label than uses 12 + 3 below + 3 above next label, so 18
  2395. // in the i * offset.  
  2396. CFont legendFont;
  2397. legendFont.CreateFont(legendFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  2398. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  2399. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  2400. pOldFont = (CFont*) pDC->SelectObject(&legendFont);
  2401. pDC->TextOut(legendL + 5, legendT + 24 + (i * 18) + 1, graphLegend.GetLegendText(i));
  2402. pDC->SelectObject(pOldFont);
  2403. //draw bar
  2404. COLORREF barColor;
  2405. barColor = GetColor(i);
  2406. CBrush brush (barColor);
  2407. CBrush* pOldBrush;
  2408. pOldBrush = pDC->SelectObject(&brush);
  2409. barL = legendL + 5 + (legendMaxText * (legendFontSize / 2)) + 5;
  2410. barT = legendT + 24 + (i * 18) + 1, graphLegend.GetLegendText(i);
  2411. barR = legendR - 5;
  2412. barB = barT + 12;
  2413. pDC->Rectangle(barL, barT, barR, barB);
  2414. pDC->SelectObject(pOldBrush);
  2415. }
  2416. return legendL;
  2417. }
  2418. void CGraph::SetGraphTitle(CString title)
  2419. {
  2420. graphTitle = title;
  2421. }
  2422. void CGraph::SetXTickFontSize(int size)
  2423. {
  2424. xTickFontSize = size;
  2425. }
  2426. void CGraph::SetYTickFontSize(int size)
  2427. {
  2428. yTickFontSize = size;
  2429. }
  2430. void CGraph::SetLegendFontSize(int size)
  2431. {
  2432. legendFontSize = size;
  2433. }
  2434. int CGraph::PrintGraph(CDC* pDC, CPrintInfo* pInfo)
  2435. {
  2436. CString str;
  2437. CFont graphTitleFont, textFont;
  2438. TEXTMETRIC tm;
  2439. CString tickLabel;
  2440. maxHeight = pGraphT - pGraphB; 
  2441. maxWidth = pGraphR - pGraphL; 
  2442.     //titleFont is 24 point, bold
  2443. graphTitleFont.CreateFont(-480, 0, 0, 0, 400, FALSE, FALSE, 0, ANSI_CHARSET,
  2444. OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  2445. DEFAULT_QUALITY, DEFAULT_PITCH || FF_ROMAN,
  2446. "Times New Roman");
  2447. //textFont is 12 point
  2448. textFont.CreateFont(-240, 0, 0, 0, 400, FALSE, FALSE, 0, ANSI_CHARSET,
  2449. OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  2450. DEFAULT_QUALITY, DEFAULT_PITCH || FF_ROMAN,
  2451. "Times New Roman");
  2452. pDC->SetMapMode(MM_TWIPS);
  2453. CFont* pOldFont = (CFont*) pDC->SelectObject(&graphTitleFont);
  2454. pDC->GetTextMetrics(&tm);
  2455. int charWidth = tm.tmAveCharWidth;
  2456. int charHeight = tm.tmHeight;
  2457. //next line is centered....trust me !!
  2458. pDC->TextOut(pGraphL + (maxWidth / 2) - ((graphTitle.GetLength() / 2) * charWidth), pGraphT - 50, graphTitle);
  2459. pDC->SelectObject(pOldFont);
  2460. if((graphType == PIE_GRAPH) || (graphType == PIE_GRAPH_3D))
  2461. {
  2462. xAxisWidth = pGraphR - pGraphL - 200;
  2463. yAxisHeight = maxHeight - 600 - charHeight;
  2464. xApexPoint = pGraphL + 500;
  2465. yApexPoint = pGraphB + 500;
  2466. }
  2467. else
  2468. {
  2469. //compute label size for axis alignment
  2470. CFont sideFont, axisFont;
  2471. int tFontSize;
  2472. tFontSize = 16;
  2473. if(maxWidth > maxHeight)
  2474. {
  2475. while((axisYLabel.GetLength() * (tFontSize / 2)) > maxHeight)
  2476. {
  2477. tFontSize -= 2;
  2478. }
  2479. }
  2480. else
  2481. {
  2482. while((axisXLabel.GetLength() * (tFontSize / 2)) > maxWidth)
  2483. {
  2484. tFontSize -= 2;
  2485. }
  2486. }
  2487. //set tFontSize for printer
  2488. tFontSize *= -20;
  2489. axisFont.CreateFont(tFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
  2490. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  2491. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  2492. sideFont.CreateFont(tFontSize, 0, 900, 0, 700, FALSE, FALSE, 0,
  2493. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  2494. DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
  2495. CFont* pOldFont = (CFont*) pDC->SelectObject(&sideFont);
  2496. pDC->GetTextMetrics(&tm);
  2497. int charWidth = tm.tmAveCharWidth;
  2498. int labelHeight = tm.tmHeight + 50;
  2499. if(graphAlignment)
  2500. {
  2501. if(axisXLabel.GetLength() == 0)
  2502. labelHeight = 0;
  2503. }
  2504. else
  2505. {
  2506. if(axisYLabel.GetLength() == 0)
  2507. labelHeight = 0;
  2508. }
  2509. pDC->SelectObject(pOldFont);
  2510. tickLabel.Format("%d", maxTick);
  2511. //determine axis specifications 
  2512. if(graphAlignment)
  2513. {
  2514. xApexPoint = pGraphL + (tickLabel.GetLength() * charWidth) + labelHeight + 100; 
  2515. if(!xAxisAlign)  //horizontal
  2516. {
  2517. yApexPoint = pGraphB + 50 + (labelHeight * 2);
  2518. }
  2519. else
  2520. {
  2521. yApexPoint = pGraphB + labelHeight + (xAxisLabelLength * labelHeight);
  2522. }
  2523. yAxisHeight = pGraphT - 200 - charHeight/*this is title height*/ - yApexPoint;
  2524. xAxisWidth = (maxWidth - 100) - xApexPoint;
  2525. }
  2526. else
  2527. {
  2528. xApexPoint = pGraphL + (xAxisLabelLength * charWidth) + labelHeight; 
  2529. yApexPoint = pGraphB + 50 + (labelHeight * 2);
  2530. yAxisHeight = pGraphT - 200 - charHeight/*this is title height*/ - yApexPoint;
  2531. xAxisWidth = (maxWidth - 100) - xApexPoint;
  2532. }
  2533. }
  2534. //draw legend
  2535. if(graphHasLegend)
  2536. {
  2537. int legendL = PrintLegend(pDC);
  2538. xAxisWidth = legendL - 200 - xApexPoint;
  2539. }
  2540. if(graphType != 2)  //not pie
  2541. {
  2542. //draw axis lines
  2543. PrintAxis(pDC);
  2544. }
  2545. //draw series data and labels
  2546. PrintSeries(pDC);
  2547. //update pGraphB value to pad some space below the graph
  2548. pGraphB -= 90;
  2549. return pGraphB;
  2550. }
  2551. int CGraph::PrintLegend(CDC *pDC)
  2552. {
  2553. CFont legendLabelFont, legendTitleFont;
  2554. TEXTMETRIC tm;
  2555. int legendL, legendT, legendR, legendB;
  2556. int barL, barT, barR, barB;
  2557. //legendLabelFont is 10 point
  2558. legendLabelFont.CreateFont(-200, 0, 0, 0, 400, FALSE, FALSE, 0, ANSI_CHARSET,
  2559. OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  2560. DEFAULT_QUALITY, DEFAULT_PITCH || FF_ROMAN,
  2561. "Times New Roman");
  2562. //legendTitleFont is 12 point
  2563. legendTitleFont.CreateFont(-240, 0, 0, 0, 400, FALSE, FALSE, 0, ANSI_CHARSET,
  2564. OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  2565. DEFAULT_QUALITY, DEFAULT_PITCH || FF_ROMAN,
  2566. "Times New Roman");
  2567. CFont* pOldFont = (CFont*) pDC->SelectObject(&legendTitleFont);
  2568. pDC->GetTextMetrics(&tm);
  2569. int legendCharWidth = tm.tmAveCharWidth;
  2570. legendT = (((pGraphB - pGraphT) / 2) + pGraphT) + (((seriesSize + 1) / 2) * 240 + 300);
  2571. legendB = (((pGraphB - pGraphT) / 2) + pGraphT) - (((seriesSize + 1) / 2) * 240 + 300);
  2572. legendR = pGraphR - 100;
  2573. legendL = legendR - ((graphLegend.GetLegendLength() * legendCharWidth) + 1000);
  2574. legendWidth = legendR - legendL;
  2575. pDC->Rectangle(legendL, legendT, legendR, legendB);
  2576. pDC->TextOut(legendL + (legendWidth / 2) - 360, 
  2577. legendT - 160, "图例");
  2578. pDC->SelectObject(pOldFont);
  2579. for(int i = 0; i < seriesSize; i++)
  2580. {
  2581. pOldFont = (CFont*) pDC->SelectObject(&legendLabelFont);
  2582. pDC->GetTextMetrics(&tm);
  2583. int charWidth = tm.tmMaxCharWidth;
  2584. int charHeight = tm.tmHeight;
  2585. CString valuStr;
  2586. pDC->TextOut(legendL + 100, legendT - 500 - (i * charHeight), graphLegend.GetLegendText(i));
  2587. pDC->SelectObject(pOldFont);
  2588. //draw bar
  2589. COLORREF barColor;
  2590. barColor = GetColor(i);
  2591. CBrush brush (barColor);
  2592. CBrush* pOldBrush;
  2593. pOldBrush = pDC->SelectObject(&brush);