clPlot.cpp
上传用户:apnc006
上传日期:2013-01-26
资源大小:178k
文件大小:26k
源码类别:

绘图程序

开发平台:

Visual C++

  1. //*******************************************************************************************************/
  2. //* FileName: clPlot.cpp
  3. //*
  4. //* Contents: Implementation of clPlot, axis, legend, serie and timeaxis
  5. //*
  6. //* NOTE 1: Only a minimum of parameter validation is implemented to save time since this plot is 
  7. //* time critical.
  8. //*
  9. //* NOTE 2: All functionality is not fully implemented.
  10. //*
  11. //* Author: Jan Vidar Berger
  12. //*******************************************************************************************************/
  13. //* 12.feb.98 Jan Vidar Berger Implemented flicker free drawing. Thanks to John Kim for providing 
  14. //* the MemDC and to Keith Rule, the author of CMemDC.
  15. //*******************************************************************************************************/
  16. #include "stdafx.h"
  17. #include "clPlot.h"
  18. #include "MemDC.h"
  19. #include "malloc.h"
  20. #ifdef _DEBUG
  21. #define new DEBUG_NEW
  22. #undef THIS_FILE
  23. static char THIS_FILE[] = __FILE__;
  24. #endif
  25. long clPlot::m_lMaxDataPrSerie; // max allowed data pr. serie.
  26. long clPlot::m_lMaxDataTotal; // max allowed data total.
  27. //*******************************************************************************************************/
  28. //* time axis threshold. contains grid and label intervals to be used within specified
  29. //* seconds pr. pixels thresholds. The array is terminated by a 'bIAmInUse'=FALSE.
  30. //*******************************************************************************************************/
  31. struct{
  32. BOOL bIAmInUse; // indicate valid entry, last=FALSE
  33. long lgridinterval; // grid line interval in seconds
  34. long llabelinterval; // time label interval in seconds
  35. long lmodethreshold; // mode threshold in seconds pr. pixel
  36. }gridsetting[]={
  37. TRUE, 1, 4, 0, // 0: pr. second
  38. FALSE, 1, 1,0, // last entry in table
  39. };
  40. //*******************************************************************************************************/
  41. //* Function: serie::serie
  42. //*******************************************************************************************************/
  43. serie::serie()
  44. {
  45. m_bIAmInUse = FALSE;
  46. m_color = RGB(0,0,0);
  47. m_iLineStyle = PS_SOLID;
  48. m_bRightAxisAlign = FALSE;
  49. m_lNoValues = 0;
  50. m_lbegin = 0;
  51. m_lend = 0;
  52. m_pvalues = NULL;
  53. }
  54. //*******************************************************************************************************/
  55. //* Function: serie::~serie
  56. //*******************************************************************************************************/
  57. serie::~serie()
  58. {
  59. if(m_pvalues !=NULL)
  60. free(m_pvalues);
  61. }
  62. //*******************************************************************************************************/
  63. //* Function: serie::AddPoint
  64. //*
  65. //* Description: AddPoint add new data to the end of a data serie. It will simply append the data,
  66. //* update the list index and get out. 
  67. //*
  68. //* This function will also call realloc or malloc to re-size or create the plot array as
  69. //* needed.
  70. //*
  71. //* The nice thing about circular lists is that they are multi thread enabled as is. You
  72. //* must however implement a syncronization mechanism if more than one thread is supposed
  73. //* to enter data into the plot.
  74. //*
  75. //* Parameters: valuetime Time (x value).
  76. //* y y value
  77. //*
  78. //* Return Value: -none-
  79. //*
  80. //* Author: Jan Vidar Berger
  81. //*******************************************************************************************************/
  82. void serie::AddPoint(CTime &valuetime , double &y)
  83. {
  84. if(m_lNoValues > 0)
  85. m_pvalues = (value*)realloc(m_pvalues, (m_lNoValues+1)*sizeof(value));
  86. else
  87. m_pvalues = (value*)malloc((m_lNoValues+1)*sizeof(value));
  88. m_pvalues[m_lend].ValueTime = valuetime;
  89. m_pvalues[m_lend].dValue = y;
  90. m_lNoValues++;
  91. m_lend++;
  92. if(m_lend >= clPlot::m_lMaxDataPrSerie)
  93. m_lend=0;
  94. if(m_lbegin == m_lend){
  95. m_lbegin++;
  96. if(m_lbegin >= clPlot::m_lMaxDataPrSerie)
  97. m_lbegin=0;
  98. }
  99. }
  100. //*******************************************************************************************************/
  101. //* Function: serie::Reset
  102. //*
  103. //* Description: Reset the serie. Remove data and reset indexes and pointers.
  104. //*
  105. //* Parameters: -none-
  106. //*
  107. //* Return Value: -none-
  108. //*
  109. //* Author: Jan Vidar Berger
  110. //*******************************************************************************************************/
  111. void serie::Reset()
  112. {
  113. m_lNoValues=0;
  114. if(m_pvalues !=NULL)
  115. free(m_pvalues);
  116. m_pvalues = NULL;
  117. m_lbegin = 0;
  118. m_lend = 0;
  119. }
  120. //*******************************************************************************************************/
  121. //*******************************************************************************************************/
  122. clPlot::clPlot()
  123. {
  124. m_ctlBkColor = RGB(255,255,255);
  125. m_plotBkColor = RGB(255,255,255);
  126. m_legendBkColor = RGB(255,255,255);
  127. m_gridColor = RGB(127,127,127);
  128. m_bctlBorder = TRUE;
  129. m_bplotBorder = TRUE;
  130. m_blegendBorder = TRUE;
  131. m_bPrimaryLegend = FALSE;
  132. m_bSecondaryLegend = FALSE;
  133. m_bAxisLY = TRUE;
  134. m_bAxisRY = TRUE;
  135. m_bAxisBX = TRUE;
  136. m_bAutoScrollX = FALSE;
  137. m_bSimMode = FALSE;
  138. m_lMaxDataPrSerie = 10000;
  139. m_lMaxDataTotal = 100000;
  140. m_dNoData = 0.0;
  141. m_dzoom = 1.0;
  142. lArraySize = 1000; // only points with differebt x,y will be put into the array
  143. pLineArray = new CPoint[lArraySize];
  144. SetBXRange(CTime::GetCurrentTime()-CTimeSpan(60),CTime::GetCurrentTime());
  145. m_logFont.lfHeight = -13;
  146. m_logFont.lfWidth = 0;
  147. m_logFont.lfEscapement = 0;
  148. m_logFont.lfOrientation = 0;
  149. m_logFont.lfWeight = 400;
  150. m_logFont.lfItalic = FALSE;
  151. m_logFont.lfUnderline = FALSE;
  152. m_logFont.lfStrikeOut = FALSE;
  153. m_logFont.lfCharSet = ANSI_CHARSET;
  154. m_logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
  155. m_logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  156. m_logFont.lfQuality = PROOF_QUALITY;
  157. m_logFont.lfPitchAndFamily = DEFAULT_PITCH;
  158. strcpy(m_logFont.lfFaceName,"Ariel");
  159. m_zoomFont.lfHeight = -13;
  160. m_zoomFont.lfWidth = 0;
  161. m_zoomFont.lfEscapement = 0;
  162. m_zoomFont.lfOrientation = 0;
  163. m_zoomFont.lfWeight = 400;
  164. m_zoomFont.lfItalic = FALSE;
  165. m_zoomFont.lfUnderline = FALSE;
  166. m_zoomFont.lfStrikeOut = FALSE;
  167. m_zoomFont.lfCharSet = ANSI_CHARSET;
  168. m_zoomFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
  169. m_zoomFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  170. m_zoomFont.lfQuality = PROOF_QUALITY;
  171. m_zoomFont.lfPitchAndFamily = DEFAULT_PITCH;
  172. strcpy(m_zoomFont.lfFaceName,"Ariel");
  173. m_font.CreateFontIndirect(&m_zoomFont);
  174. }
  175. //*******************************************************************************************************/
  176. //*******************************************************************************************************/
  177. clPlot::~clPlot()
  178. {
  179. delete [] pLineArray;
  180. }
  181. //*******************************************************************************************************/
  182. //*******************************************************************************************************/
  183. BEGIN_MESSAGE_MAP(clPlot, CWnd)
  184. //{{AFX_MSG_MAP(clPlot)
  185. ON_WM_PAINT()
  186. //}}AFX_MSG_MAP
  187. END_MESSAGE_MAP()
  188. //*******************************************************************************************************/
  189. //*******************************************************************************************************/
  190. BOOL clPlot::Create(DWORD dwstyle, CRect &rect, CWnd *pParent, UINT id)
  191. {
  192. DWORD style = dwstyle & (~WS_BORDER);
  193. if(dwstyle & WS_BORDER)
  194. m_bctlBorder=TRUE;
  195. else
  196. m_bctlBorder=FALSE;
  197. if(!CWnd::Create(NULL, "", style, rect, pParent, id, NULL))
  198. return FALSE;
  199. m_ctlRect = rect;
  200. pParent->ClientToScreen(m_ctlRect);
  201. ScreenToClient(m_ctlRect);
  202. ComputeRects(TRUE);
  203. return TRUE;
  204. }
  205. //*******************************************************************************************************/
  206. //* Function        : clPlot::ComputeRects
  207. //*
  208. //* Description     : Compute rects used for internal possitioning of different objects. This function is 
  209. //*   called when the plot is created or sized.
  210. //*
  211. //* Return type     : void 
  212. //*
  213. //* Parameter(s)    : bInitialization indicate wherever parameters that can be changed abu the user
  214. //* also should be computed.
  215. //*
  216. //* Author          : Jan Vidar Berger
  217. //*******************************************************************************************************/
  218. void clPlot::ComputeRects(BOOL bInitialization)
  219. {
  220. // adjust the client rect for borders
  221. //GetClientRect(m_ctlRect);
  222. CClientDC dc(this);
  223. int w = 0;
  224. int n=0;
  225. CSize z=dc.GetTextExtent(CString("A"));
  226. // m_TextHeight = z.cy;
  227. m_dzoom = ((double)m_ctlRect.Height()/(double)z.cy) / 25.0;
  228. m_zoomFont.lfWidth = (int)(m_logFont.lfWidth * m_dzoom);
  229. m_zoomFont.lfHeight = (int)(m_logFont.lfHeight * m_dzoom);
  230. m_font.Detach();
  231. m_font.CreateFontIndirect(&m_zoomFont);
  232. CFont *oFont = dc.SelectObject(&m_font);
  233. // SetFont(&m_font);
  234. z=dc.GetTextExtent(CString("A"));
  235. m_TextHeight = z.cy;
  236. if(m_bctlBorder){
  237. m_clientRect.left = m_ctlRect.left+2;
  238. m_clientRect.right = m_ctlRect.right-2;
  239. m_clientRect.top = m_ctlRect.top+2;
  240. m_clientRect.bottom = m_ctlRect.bottom-2;
  241. }else{
  242. m_clientRect = m_ctlRect;
  243. }
  244. if(bInitialization)
  245. {
  246. m_iMtop = m_iMbottom = m_clientRect.Height()/10;
  247. m_iMleft = m_iMright = m_clientRect.Width()/10;
  248. }
  249. // compute plot rect.
  250. m_plotRect.left = m_clientRect.left + m_iMleft;
  251. m_plotRect.right = m_clientRect.right - m_iMright;
  252. m_plotRect.top = m_clientRect.top + m_iMtop;
  253. m_plotRect.bottom = m_clientRect.bottom - m_iMbottom;
  254. // compute default legend possition
  255. if(bInitialization)
  256. {
  257. m_legendRect.left = m_plotRect.left + (m_iMleft/5);
  258. m_legendRect.right = m_plotRect.left + (m_plotRect.Width()/5);
  259. m_legendRect.top = m_plotRect.top - (m_iMtop/2);
  260. m_legendRect.bottom = m_plotRect.top + (m_iMtop);
  261. int w = 0;
  262. int n=0;
  263. for(int x = 0; x< MAXLEGENDS;x++){
  264. if(m_primarylegends[x].m_bIAmInUse){
  265. n++;
  266. z=dc.GetTextExtent(CString(m_primarylegends[x].m_szTitle));
  267. if(z.cx > w )
  268. w=z.cx;
  269. // m_TextHeight = z.cy;
  270. }
  271. }
  272. m_legendRect.right = m_legendRect.left + 40 + w;
  273. m_legendRect.bottom = m_legendRect.top + 10 + (m_TextHeight*n);
  274. }
  275. // compute left axis area
  276. m_axisLYRect.left = m_clientRect.left + (m_iMleft/5);
  277. m_axisLYRect.right = m_plotRect.left;
  278. m_axisLYRect.top = m_plotRect.top;
  279. m_axisLYRect.bottom = m_plotRect.bottom;
  280. // compute right axis area
  281. m_axisRYRect.left =  m_plotRect.left;
  282. m_axisRYRect.right = m_clientRect.right - (m_iMright/5);
  283. m_axisRYRect.top = m_plotRect.top;
  284. m_axisRYRect.bottom = m_plotRect.bottom;
  285. // compute bottom axis area
  286. m_axisBXRect.left = m_plotRect.left;
  287. m_axisBXRect.right = m_plotRect.right;
  288. m_axisBXRect.top = m_plotRect.bottom;
  289. m_axisBXRect.bottom = m_clientRect.bottom - (m_iMbottom/5);
  290. // if(bInitialization)
  291. // {
  292. m_timeaxis.m_dSecondsPrPixel = ((double)(m_timeaxis.m_maxtime.GetTime() - m_timeaxis.m_mintime.GetTime())) / (double)m_plotRect.Width();
  293. m_leftaxis.m_dValuePrPixel   = ((double)(m_leftaxis.maxrange- m_leftaxis.minrange) / (double)m_plotRect.Height());
  294. m_rightaxis.m_dValuePrPixel   = ((double)(m_rightaxis.maxrange- m_rightaxis.minrange) / (double)m_plotRect.Height());
  295. // }
  296. dc.SelectObject(oFont);
  297. }
  298. //*******************************************************************************************************/
  299. //* Function: clPlot::OnPaint
  300. //*
  301. //* Description: This function will create a memory image, call Draw to draw the plot on it, and when
  302. //* copy the image into memory.
  303. //*
  304. //* This is fast and provides flicker free plot update.
  305. //*
  306. //* Author: Jan Vidar Berger
  307. //*******************************************************************************************************/
  308. void clPlot::OnPaint() 
  309. {
  310.         CPaintDC dc(this); // device context for painting
  311.         CMemDC  pdc(&dc);  // non flickering painting
  312.         Draw(&pdc);
  313. // Do not call CWnd::OnPaint() for painting messages
  314. }
  315. BOOL clPlot::OnEraseBkgnd(CDC* pDC) 
  316. {
  317. return FALSE;
  318. }
  319. //*******************************************************************************************************/
  320. //*******************************************************************************************************/
  321. void clPlot::Draw(CDC * dc)
  322. {
  323. CFont *oFont = dc->SelectObject(&m_font);
  324. DrawBasic(dc);
  325. DrawGrid(dc);
  326. DrawPlot(dc);
  327. DrawLegend(dc);
  328. dc->SelectObject(oFont);
  329. }
  330. //*******************************************************************************************************/
  331. //*******************************************************************************************************/
  332. void clPlot::DrawBasic(CDC * dc)
  333. {
  334. CBrush brushctlBkColor(m_ctlBkColor);
  335. dc->FillRect(m_ctlRect,&brushctlBkColor);
  336. if(m_bctlBorder)
  337. {
  338. dc->DrawEdge(m_ctlRect,BDR_SUNKENINNER|BDR_SUNKENOUTER, BF_RECT); 
  339. }
  340. dc->Rectangle(m_plotRect);
  341. DrawLegendShadow(dc);
  342. }
  343. //*******************************************************************************************************/
  344. //*******************************************************************************************************/
  345. void clPlot::DrawPlot(CDC * dc)
  346. {
  347. for(int s=0;s<MAXSERIES;s++)
  348. {
  349. if(m_series[s].m_bIAmInUse)
  350. {
  351. DrawSerie(dc, s);
  352. }
  353. }
  354. }
  355. //*******************************************************************************************************/
  356. //*******************************************************************************************************/
  357. void clPlot::DrawSerie(CDC *dc,int s)
  358. {
  359. BOOL bMore=TRUE;
  360. BOOL bDraw;
  361. CPoint p;
  362. int ly;
  363. // lets get some serie parameters now and save the time of indexing during the loop
  364. long y = m_series[s].m_lbegin;
  365. long m = m_series[s].m_lend;
  366. long a = m_series[s].m_lNoValues;
  367. BOOL bRightAxis = m_series[s].m_bRightAxisAlign;
  368. CPen pen(m_series[s].m_iLineStyle, 1, m_series[s].m_color);
  369. CPen *old = dc->SelectObject(&pen);
  370. while(bMore){
  371. bDraw=FALSE;
  372. bMore=FALSE;
  373. ly=0;
  374. while(y != m && !bDraw){
  375. if(m_series[s].m_pvalues[y].dValue == m_dNoData)
  376. {
  377. bDraw = TRUE;
  378. bMore = TRUE;
  379. }else{
  380. // Scaling. We do scaling inline to save some time
  381. time_t valuetime = m_series[s].m_pvalues[y].ValueTime.GetTime();
  382. p.x = (int)(m_plotRect.left + ((valuetime-m_timeaxis.m_mintime.GetTime())/m_timeaxis.m_dSecondsPrPixel));
  383. if(bRightAxis){
  384. p.y = (int)(m_plotRect.bottom - ((m_series[s].m_pvalues[y].dValue-m_rightaxis.minrange)/m_rightaxis.m_dValuePrPixel));
  385. }else{
  386. p.y = (int)(m_plotRect.bottom - ((m_series[s].m_pvalues[y].dValue-m_leftaxis.minrange)/m_leftaxis.m_dValuePrPixel));
  387. }
  388. if((ly == 0 || p.x != pLineArray[ly].x || p.y != pLineArray[ly].y)
  389. && (p.x >= m_plotRect.left && p.x <= m_plotRect.right))
  390. {
  391. pLineArray[ly].x = p.x;
  392. pLineArray[ly].y = p.y;
  393. ly++;
  394. }
  395. }
  396. y++;
  397. if(y > a) // wrap list index ?
  398. y=0;
  399. }
  400. if(ly > 0){
  401. dc->Polyline(pLineArray, ly);
  402. }
  403. }
  404. dc->SelectObject(old);
  405. }
  406. //*******************************************************************************************************/
  407. //*
  408. //*******************************************************************************************************/
  409. void clPlot::DrawGrid(CDC * dc)
  410. {
  411. DrawXAxisGrid(dc);
  412. DrawYAxisGrid(dc);
  413. }
  414. //*******************************************************************************************************/
  415. //*******************************************************************************************************/
  416. void clPlot::DrawYAxisGrid(CDC * dc)
  417. {
  418. double yGrid = m_leftaxis.minrange;
  419. double delta = 25.0 + (long)(((m_leftaxis.m_dValuePrPixel)))*25;
  420. if((long)delta%50 != 0 && delta > 20.0)
  421. delta +=25;
  422. double d10 = delta / 5.0;
  423. // todo: delta switch
  424. long diff = ((long)yGrid)%((long)delta);
  425. yGrid = yGrid - diff;
  426. CPen *old, pen(PS_SOLID, 1, m_gridColor);
  427. CPen stick(PS_SOLID,0,RGB(0,0,0));
  428. CPen mline(PS_SOLID,0,RGB(192,192,192));
  429. for( long sy = (long)((long)(m_leftaxis.minrange) - diff); sy < m_leftaxis.maxrange; sy+=(long)d10)
  430. {
  431. int off=3;
  432. if((long)sy%(long)delta == 0){
  433. off=5;
  434. }
  435. if(sy > m_leftaxis.minrange){
  436. int y = (int)(m_plotRect.bottom - ((sy-m_leftaxis.minrange)/m_leftaxis.m_dValuePrPixel));
  437. old = dc->SelectObject(&stick); 
  438. dc->MoveTo(CPoint(m_plotRect.left,y));
  439. dc->LineTo(CPoint(m_plotRect.left-off,y));
  440. dc->MoveTo(CPoint(m_plotRect.right,y));
  441. dc->LineTo(CPoint(m_plotRect.right+off,y));
  442. dc->SelectObject(old);
  443. old = dc->SelectObject(&mline);
  444. dc->MoveTo(CPoint(m_plotRect.left+1,y));
  445. dc->LineTo(CPoint(m_plotRect.right-1,y));
  446. dc->SelectObject(old);
  447. }
  448. }
  449. old = dc->SelectObject(&pen);
  450. while(yGrid <= m_leftaxis.maxrange)
  451. {
  452. double yy = m_plotRect.bottom - ((yGrid-m_leftaxis.minrange)/m_leftaxis.m_dValuePrPixel);
  453. int y = (int)yy;
  454. if(yGrid > m_leftaxis.minrange && yGrid<m_leftaxis.maxrange){
  455. dc->MoveTo(CPoint(m_plotRect.left+1,y));
  456. dc->LineTo(CPoint(m_plotRect.right-1,y));
  457. }
  458. char b[100];
  459. sprintf(b, "%.0f", yGrid);
  460. dc->DrawText(b, CRect(m_clientRect.left, y-m_TextHeight/2,m_plotRect.left-5,y+m_TextHeight/2), DT_RIGHT|DT_BOTTOM);
  461. double yr = (m_plotRect.bottom - yy) * m_rightaxis.m_dValuePrPixel + m_rightaxis.minrange;
  462. sprintf(b, "%.0f", yr);
  463. dc->DrawText(b, CRect(m_plotRect.right+5, y-m_TextHeight/2,m_clientRect.right,y+m_TextHeight/2), DT_LEFT|DT_BOTTOM);
  464. yGrid += delta;
  465. }
  466. dc->SelectObject(old);
  467. }
  468. //*******************************************************************************************************/
  469. //*******************************************************************************************************/
  470. void clPlot::DrawXAxisGrid(CDC * dc)
  471. {
  472. long yGrid = m_timeaxis.m_mintime.GetTime();
  473. long delta = (long)(10.0 + (long)(((m_timeaxis.m_dSecondsPrPixel)))*10);
  474. long d10 = (long)(delta / 10.0);
  475. // todo: delta switch
  476. long diff = ((long)yGrid)%((long)delta);
  477. yGrid = yGrid - diff;
  478. CPen *old, pen(PS_SOLID, 1, m_gridColor);
  479. CPen stick(PS_SOLID,0,RGB(0,0,0));
  480. CPen mline(PS_SOLID,0,RGB(192,192,192));
  481. for( long sx = m_timeaxis.m_mintime.GetTime() - diff; sx < m_timeaxis.m_maxtime.GetTime(); sx+=d10)
  482. {
  483. int off=3;
  484. if((long)sx%(long)delta == 0){
  485. off=5;
  486. }
  487. if(sx > m_timeaxis.m_mintime.GetTime()){
  488. int x = (int)(m_plotRect.left + ((sx-m_timeaxis.m_mintime.GetTime())/m_timeaxis.m_dSecondsPrPixel));
  489. // int x = m_plotRect.right - ((sx-m_timeaxis.m_mintime.GetTime())/m_timeaxis.m_lSecondsPrPixel);
  490. old = dc->SelectObject(&stick); 
  491. dc->MoveTo(CPoint(x,m_plotRect.bottom));
  492. dc->LineTo(CPoint(x+off,m_plotRect.bottom));
  493. dc->SelectObject(old);
  494. old = dc->SelectObject(&mline);
  495. dc->MoveTo(CPoint(x,m_plotRect.bottom-1));
  496. dc->LineTo(CPoint(x,m_plotRect.top+1));
  497. dc->SelectObject(old);
  498. }
  499. }
  500. old = dc->SelectObject(&pen);
  501. while(yGrid <= m_timeaxis.m_maxtime.GetTime())
  502. {
  503. int x = (int)(m_plotRect.left + ((yGrid-m_timeaxis.m_mintime.GetTime())/m_timeaxis.m_dSecondsPrPixel));
  504. if(yGrid > m_timeaxis.m_mintime.GetTime() && yGrid<m_timeaxis.m_maxtime.GetTime()){
  505. dc->MoveTo(CPoint(x,m_plotRect.bottom-1));
  506. dc->LineTo(CPoint(x,m_plotRect.top+1));
  507. }
  508. // char b[100];
  509. // sprintf(b, "%.0f", yGrid);
  510. // dc->DrawText(b, CRect(m_clientRect.left, y-m_TextHeight/2,m_plotRect.left-5,y+m_TextHeight/2), DT_RIGHT|DT_BOTTOM);
  511. yGrid += delta;
  512. }
  513. dc->SelectObject(old);
  514. }
  515. //*******************************************************************************************************/
  516. //*******************************************************************************************************/
  517. void clPlot::DrawLegendShadow(CDC * dc)
  518. {
  519. if(m_blegendBorder){
  520. CPen pen(PS_SOLID, 1, RGB(127,127,127));
  521. CPen *oPen = dc->SelectObject(&pen);
  522. CBrush *oBrush , brush(RGB(127,127,127));
  523. oBrush = dc->SelectObject(&brush);
  524. dc->Rectangle(CRect(m_legendRect.left+5,m_legendRect.top+5,m_legendRect.right+5, m_legendRect.bottom+5));
  525. dc->SelectObject(oBrush);
  526. dc->SelectObject(oPen);
  527. }
  528. }
  529. //*******************************************************************************************************/
  530. //*******************************************************************************************************/
  531. void clPlot::DrawLegend(CDC * dc)
  532. {
  533. if(m_blegendBorder){
  534. CPen pen(PS_SOLID, 1, RGB(0,0,0));
  535. CPen *oPen = dc->SelectObject(&pen);
  536. CBrush *oBrush , brush(m_legendBkColor);
  537. oBrush = dc->SelectObject(&brush);
  538. dc->Rectangle(m_legendRect);
  539. dc->SelectObject(oBrush);
  540. dc->SelectObject(oPen);
  541. }
  542. int y = m_legendRect.top + 5;
  543. int dx = m_legendRect.left + (2*m_TextHeight);
  544. int mh = m_TextHeight/2;
  545. for(int x = 0; x< MAXLEGENDS;x++){
  546. if(m_primarylegends[x].m_bIAmInUse){
  547. CRect lRect( dx + 5, y, m_legendRect.right - 5, y + m_TextHeight);
  548. CPen pen(m_primarylegends[x].m_istyle, 1, m_primarylegends[x].m_color);
  549. CPen *oPen = dc->SelectObject(&pen);
  550. dc->MoveTo(CPoint(m_legendRect.left+5, y + mh));
  551. dc->LineTo(CPoint(dx, y+mh));
  552. dc->SelectObject(oPen);
  553. dc->DrawText(m_primarylegends[x].m_szTitle, lRect, DT_LEFT);
  554. y+=m_TextHeight+1;
  555. }
  556. }
  557. }
  558. //*******************************************************************************************************/
  559. //* Function: clPlot::AddPoint
  560. //*******************************************************************************************************/
  561. BOOL clPlot::AddPoint(int serie, CTime &valuetime, double &value)
  562. {
  563. if(m_series[serie].m_lNoValues < m_lMaxDataPrSerie){
  564. m_series[serie].AddPoint(valuetime, value);
  565. if(m_bAutoScrollX && valuetime > m_timeaxis.m_maxtime){
  566. time_t span = m_timeaxis.m_maxtime.GetTime() - m_timeaxis.m_mintime.GetTime();
  567. time_t mintime = valuetime.GetTime() - span;
  568. SetBXRange(CTime(mintime), valuetime);
  569. }
  570. return TRUE;
  571. }
  572. return FALSE;
  573. }
  574. //*******************************************************************************************************/
  575. //*******************************************************************************************************/
  576. void clPlot::SetBXRange(CTime &fromtime, CTime &totime, BOOL bMove)
  577. {
  578. m_timeaxis.m_mintime = fromtime;
  579. m_timeaxis.m_maxtime = totime;
  580. if(!bMove){
  581. m_timeaxis.m_dSecondsPrPixel = ((double)(m_timeaxis.m_maxtime.GetTime() - m_timeaxis.m_mintime.GetTime()+1)) / (double)m_plotRect.Width();
  582. }
  583. }
  584. //*******************************************************************************************************/
  585. //*******************************************************************************************************/
  586. void clPlot::SetLYRange(double &minrange, double &maxrange)
  587. {
  588. }
  589. //*******************************************************************************************************/
  590. //*******************************************************************************************************/
  591. void clPlot::SetRYRange(double &minrange, double &maxrange)
  592. {
  593. }
  594. //*******************************************************************************************************/
  595. //*******************************************************************************************************/
  596. void clPlot::SetBXTitle(const char *title)
  597. {
  598. }
  599. //*******************************************************************************************************/
  600. //*******************************************************************************************************/
  601. void clPlot::SetLYTitle(const char *title)
  602. {
  603. }
  604. //*******************************************************************************************************/
  605. //*******************************************************************************************************/
  606. void clPlot::SetRYTitle(const char *title)
  607. {
  608. }
  609. //*******************************************************************************************************/
  610. //*******************************************************************************************************/
  611. void clPlot::Reset()
  612. {
  613. }
  614. //*******************************************************************************************************/
  615. //*******************************************************************************************************/
  616. void clPlot::SetSerie(int s, int style, COLORREF color, double minrange, double maxrange, const char *szTitle, BOOL Rightalign)
  617. {
  618. m_series[s].m_bIAmInUse = TRUE;
  619. m_series[s].m_color = color;
  620. m_series[s].m_iLineStyle = style;
  621. m_series[s].m_bRightAxisAlign = Rightalign;
  622. }
  623. //*******************************************************************************************************/
  624. //*******************************************************************************************************/
  625. void clPlot::MoveWindow(CRect & Rect)
  626. {
  627. m_ctlRect = Rect;
  628. GetParent()->ClientToScreen(m_ctlRect);
  629. ScreenToClient(m_ctlRect);
  630. ComputeRects(TRUE);
  631. CWnd::MoveWindow(Rect);
  632. }
  633. //*******************************************************************************************************/
  634. //*******************************************************************************************************/
  635. void clPlot::SetLegend(int l, int style, COLORREF color, const char *text)
  636. {
  637. m_primarylegends[l].m_bIAmInUse = TRUE;
  638. m_primarylegends[l].m_color = color;
  639. m_primarylegends[l].m_istyle = style;
  640. m_primarylegends[l].m_szTitle = text;
  641. CClientDC dc(this);
  642. CFont *oFont = dc.SelectObject(&m_font);
  643. int w = 0;
  644. int n=0;
  645. for(int x = 0; x< MAXLEGENDS;x++){
  646. if(m_primarylegends[x].m_bIAmInUse){
  647. n++;
  648. CSize z=dc.GetTextExtent(CString(m_primarylegends[x].m_szTitle));
  649. if(z.cx > w )
  650. w=z.cx;
  651. // m_TextHeight = z.cy;
  652. }
  653. }
  654. m_legendRect.right = m_legendRect.left + 10+(2*m_TextHeight) + w;
  655. m_legendRect.bottom = m_legendRect.top + 10 + (m_TextHeight*n);
  656. dc.SelectObject(oFont);
  657. }