StockGraph.cpp
上传用户:zhanglf88
上传日期:2013-11-19
资源大小:6036k
文件大小:80k
源码类别:

金融证券系统

开发平台:

Visual C++

  1. // StockGraph.cpp : implementation of the CStockGraph class
  2. //
  3. #include "stdafx.h"
  4. #include "StockGraph.h"
  5. #include "../Dialog/EditKDATADlg.h"
  6. #include <math.h>
  7. #ifdef _DEBUG
  8. #define new DEBUG_NEW
  9. #undef THIS_FILE
  10. static char THIS_FILE[] = __FILE__;
  11. #endif
  12. /////////////////////////////////////////////////////////////////////////////
  13. // Some Useful static function
  14. void DrawLine( CDC * pDC, int nWidth, COLORREF clr, int xStart, int yStart, int xEnd, int yEnd )
  15. {
  16. CPen pen( PS_SOLID, nWidth, clr );
  17. CPen *pOldPen = pDC->SelectObject( &pen );
  18. pDC->MoveTo( xStart, yStart );
  19. pDC->LineTo( xEnd, yEnd );
  20. pDC->SelectObject( pOldPen );
  21. }
  22. void DrawDashLine( CDC * pDC, int nWidth, COLORREF clr, int xStart, int yStart, int xEnd, int yEnd )
  23. {
  24. CPen pen( PS_SOLID, nWidth, clr );
  25. CPen *pOldPen = pDC->SelectObject( &pen );
  26. int x = xStart, y = yStart;
  27. while( x < xEnd || y < yEnd )
  28. {
  29. if( x > xEnd ) x = xEnd;
  30. if( y > yEnd ) y = yEnd;
  31. pDC->MoveTo( x, y );
  32. int xNew = x+3;
  33. int yNew = y+3;
  34. if( xNew > xEnd ) xNew = xEnd;
  35. if( yNew > yEnd ) yNew = yEnd;
  36. pDC->LineTo( xNew, yNew );
  37. x = xNew+3;
  38. y = yNew+3;
  39. }
  40. pDC->SelectObject( pOldPen );
  41. }
  42. void DrawDashAxis( CDC * pDC, int nWidth, COLORREF clr, int nCount, int xStart, int yStart, int xEnd, int yEnd )
  43. {
  44. int nHeight = yEnd - yStart;
  45. if( nHeight <= 0 )
  46. return;
  47. if( nCount <= 0 )
  48. return;
  49. for( int k=0; k<nCount; k++ )
  50. DrawDashLine( pDC, nWidth, clr, xStart, yStart+k*nHeight/nCount, xEnd, yStart+k*nHeight/nCount );
  51. }
  52. void DrawAxisNumber(CDC * pDC, COLORREF clr, int nCount,
  53. int xStart, int yStart, int xEnd, int yEnd,
  54. double fMin, double fMax, BOOL bDrawMin, BOOL bDrawMax, int nDotCount )
  55. {
  56. int nHeight = yEnd - yStart;
  57. if( nHeight <= 0 )
  58. return;
  59. if( nCount <= 0 )
  60. return;
  61. ASSERT( nDotCount >= 0 );
  62. CString strFmt;
  63. strFmt.Format( "%%.%df", nDotCount );
  64. pDC->SetTextColor( clr );
  65. CString strText;
  66. CSize sizeText;
  67. for( int k=0; k<=nCount; k++ )
  68. {
  69. if( !bDrawMin && 0 == k )
  70. continue;
  71. if( !bDrawMax && nCount == k )
  72. continue;
  73. double dTemp = fMin+k*(fMax-fMin)/nCount;
  74. if( dTemp < 0 && dTemp > (0-0.6*pow(10,0-nDotCount)) )
  75. dTemp = 0;
  76. strText.Format( strFmt, dTemp );
  77. sizeText = pDC->GetTextExtent( strText );
  78. pDC->TextOut( xStart-sizeText.cx-1, yStart+(nCount-k)*nHeight/nCount-7, strText );
  79. }
  80. }
  81. BOOL DrawAxis(CDC * pDC, CRect rect, int nMarginTop, int nAxisLines, double dMin, double dMax, BOOL bDrawMin, BOOL bDrawMax, int nDotCount )
  82. {
  83. DECLARE_COLOR_DEFINATION
  84. if( rect.Height() <= nMarginTop )
  85. return FALSE;
  86. // Draw Axis
  87. pDC->Draw3dRect( &rect, clrBorder, clrBorder );
  88. DrawDashAxis( pDC, 1, clrBorder, nAxisLines,
  89. rect.left, rect.top+nMarginTop, rect.right, rect.bottom );
  90. // Draw Axis Number, Will Extent the rect
  91. CFont * pOldFont = AfxSelectDCFont( pDC, 12 );
  92. pDC->SetBkColor( clrBK );
  93. DrawAxisNumber( pDC, clrText, nAxisLines,
  94. rect.left, rect.top+nMarginTop, rect.right, rect.bottom,
  95. dMin, dMax, bDrawMin, bDrawMax, nDotCount );
  96. pDC->SelectObject( pOldFont );
  97. return TRUE;
  98. }
  99. BOOL DrawTechTitle(CDC * pDC, int x, int y, LPCTSTR lpszText,
  100.    UINT nTextAlign, int nFontSize, COLORREF clrBK, COLORREF clrText )
  101. {
  102. CFont * pOldFont = AfxSelectDCFont( pDC, nFontSize );
  103. pDC->SetBkColor( clrBK );
  104. pDC->SetTextColor( clrText );
  105. UINT nOldAlign = pDC->SetTextAlign( nTextAlign );
  106. pDC->TextOut( x, y, lpszText );
  107. pDC->SetTextAlign( nOldAlign );
  108. pDC->SelectObject( pOldFont );
  109. return TRUE;
  110. }
  111. BOOL FixRect( CRect & rect, LPRECT lpRectMax )
  112. {
  113. if( lpRectMax )
  114. {
  115. if( rect.left < lpRectMax->left )
  116. rect.left = lpRectMax->left;
  117. if( rect.top < lpRectMax->top )
  118. rect.top = lpRectMax->top;
  119. if( rect.right > lpRectMax->right )
  120. rect.right = lpRectMax->right;
  121. if( rect.bottom > lpRectMax->bottom )
  122. rect.bottom = lpRectMax->bottom;
  123. return TRUE;
  124. }
  125. return FALSE;
  126. }
  127. BOOL DrawTextWithRect(CDC *pDC, int left, int top, int right, int bottom, LPCTSTR lpszText,
  128.   COLORREF clrRect, COLORREF clrText, COLORREF clrBK, LPRECT lpRectMax )
  129. {
  130. CRect rectDraw = CRect( left, top, right, bottom );
  131. if( lpRectMax )
  132. FixRect( rectDraw, lpRectMax );
  133. pDC->Draw3dRect( &rectDraw, clrRect, clrRect );
  134. pDC->SetTextColor( clrText );
  135. pDC->SetBkColor( clrBK );
  136. pDC->DrawText( lpszText, rectDraw, DT_CENTER | DT_VCENTER | DT_SINGLELINE );
  137. return TRUE;
  138. }
  139. BOOL DrawTextWithRect(CDC *pDC, int left, int top, int right, int bottom, UINT nIDString,
  140.   COLORREF clrRect, COLORREF clrText, COLORREF clrBK, LPRECT lpRectMax )
  141. {
  142. CString string;
  143. string.LoadString( nIDString );
  144. return DrawTextWithRect( pDC, left, top, right, bottom, string, clrRect, clrText, clrBK, lpRectMax );
  145. }
  146. /////////////////////////////////////////////////////////////////////////////
  147. // CStockGraph
  148. CStockGraph::CStockGraph( )
  149. {
  150. ResetMargins( );
  151. m_pParent = NULL;
  152. m_nThickness = m_nDefaultThickness;
  153. m_dwLatestDate = -1;
  154. m_ptSelectBegin = CPoint(0,0);
  155. m_ptSelectEnd = CPoint(0,0);
  156. m_nReportWhat = CStockGraph::reportParam;
  157. SetKType( );
  158. SetKFormat( AfxGetProfile().GetGraphKFormat() );
  159. SetMaindataType( AfxGetProfile().GetGraphMaindataType() );
  160. #ifdef CLKLAN_ENGLISH_US
  161. SetKLineMode( CStockGraph::klineAmerica );
  162. #else
  163. SetKLineMode( CStockGraph::klineCandle );
  164. #endif
  165. ResetIndex( );
  166. m_rectAll.SetRectEmpty();
  167. m_dMaxPrice = 0;
  168. m_dMinPrice = 0;
  169. m_bCursorBorder = FALSE;
  170. m_nSelectedTechID = STT_INVALID;
  171. }
  172. CStockGraph::~CStockGraph( )
  173. {
  174. ClearCurStock( );
  175. }
  176. void CStockGraph::SetParent( CWnd * pParent )
  177. {
  178. m_pParent = pParent;
  179. }
  180. void CStockGraph::ResetMargins( int nMarginTop, int nMarginBottom,
  181. int nHeightSubtitle, int nWidthSubtitle,
  182. int nWidthParameter, int nDefaultThickness )
  183. {
  184. ASSERT( nMarginTop >= 0 && nMarginBottom >= 0 );
  185. ASSERT( nHeightSubtitle >= 0 && nWidthSubtitle >= 0 );
  186. ASSERT( nWidthParameter >= 0 );
  187. ASSERT( nDefaultThickness > 0 );
  188. m_nMarginTop = nMarginTop;
  189. m_nMarginBottom = nMarginBottom;
  190. m_nHeightSubtitle = nHeightSubtitle + 2;
  191. m_nWidthSubtitle = nWidthSubtitle;
  192. m_nWidthParameter = nWidthParameter;
  193. m_nDefaultThickness = nDefaultThickness;
  194. }
  195. LRESULT CStockGraph::OnStkReceiverData( WPARAM wParam, LPARAM lParam )
  196. {
  197. PCOMMPACKET pCommPacket = (PCOMMPACKET)lParam;
  198. switch( wParam )
  199. {
  200. case CStock::dataReport:
  201. if( pCommPacket && CStock::dataReport == pCommPacket->m_dwDataType )
  202. {
  203. for( DWORD i=0; i<pCommPacket->m_dwCount; i++ )
  204. {
  205. if( m_CurStock.GetStockInfo().IsEqualTo( pCommPacket->m_pReport[i].m_dwMarket, pCommPacket->m_pReport[i].m_szCode ) )
  206. break;
  207. }
  208. if( i != pCommPacket->m_dwCount )
  209. {
  210. // 加入最新一天的K线数据
  211. PrepareStockData( TRUE );
  212. if( m_pParent && ::IsWindow(m_pParent->GetSafeHwnd()) )
  213. m_pParent->Invalidate();
  214. }
  215. }
  216. break;
  217. case CStock::dataK:
  218. if( pCommPacket && CStock::dataK == pCommPacket->m_dwDataType )
  219. {
  220. for( DWORD i=0; i<pCommPacket->m_dwCount; i++ )
  221. {
  222. if( m_CurStock.GetStockInfo().IsEqualTo( pCommPacket->m_pKdata[i].m_dwMarket, pCommPacket->m_pKdata[i].m_szCode ) )
  223. break;
  224. }
  225. if( i != pCommPacket->m_dwCount )
  226. {
  227. // 加入最新一天的K线数据
  228. PrepareStockData( TRUE );
  229. if( m_pParent && ::IsWindow(m_pParent->GetSafeHwnd()) )
  230. m_pParent->Invalidate();
  231. }
  232. }
  233. break;
  234. case CStock::dataMinute:
  235. // WILLCHECK
  236. if( !CKData::IsDayOrMin(m_nCurKType) && pCommPacket && CStock::dataMinute == pCommPacket->m_dwDataType )
  237. {
  238. int nOldSize = m_CurStock.GetMinute().GetSize();
  239. for(DWORD i=0; i<pCommPacket->m_dwCount; i++)
  240. {
  241. if( m_CurStock.GetStockInfo().IsEqualTo( pCommPacket->m_pMinute[i].m_dwMarket, pCommPacket->m_pMinute[i].m_szCode ) )
  242. break;
  243. }
  244. if( i != pCommPacket->m_dwCount )
  245. {
  246. // 加入最新的分钟K线数据
  247. PrepareStockData( TRUE );
  248. if( m_pParent && ::IsWindow(m_pParent->GetSafeHwnd()) )
  249. m_pParent->Invalidate();
  250. }
  251. }
  252. break;
  253. }
  254. return 0L;
  255. }
  256. int CStockGraph::GetKType( )
  257. {
  258. return m_nCurKType;
  259. }
  260. void CStockGraph::SetKType( int ktype )
  261. {
  262. m_nCurKType = ktype;
  263. PrepareStockData( );
  264. }
  265. int CStockGraph::GetKFormat( )
  266. {
  267. return m_nCurKFormat;
  268. }
  269. void CStockGraph::SetKFormat( int kformat )
  270. {
  271. m_nCurKFormat = kformat;
  272. AfxGetProfile().SetGraphKFormat( kformat );
  273. PrepareStockData( );
  274. }
  275. int CStockGraph::GetMaindataType( )
  276. {
  277. return m_nCurMaindataType;
  278. }
  279. void CStockGraph::SetMaindataType( int maindatatype )
  280. {
  281. m_nCurMaindataType = maindatatype;
  282. AfxGetProfile().SetGraphMaindataType( maindatatype );
  283. PrepareStockData( );
  284. }
  285. int CStockGraph::GetKLineMode( )
  286. {
  287. return m_nCurKLineMode;
  288. }
  289. void CStockGraph::SetKLineMode( int klineMode )
  290. {
  291. m_nCurKLineMode = klineMode;
  292. }
  293. CRect & CStockGraph::GetKDataRect( )
  294. {
  295. return m_rectKData;
  296. }
  297. void CStockGraph::ResetIndexCurrent( int nIndexCurrent )
  298. {
  299. m_nIndexCurrent = nIndexCurrent;
  300. m_anIndexCurrent.RemoveAll();
  301. }
  302. void CStockGraph::ResetIndex( int nIndexStart, int nIndexEnd, int nIndexCurrent )
  303. {
  304. m_nIndexStart = nIndexStart;
  305. m_nIndexEnd = nIndexEnd;
  306. m_nIndexCurrent = nIndexCurrent;
  307. m_anIndexCurrent.RemoveAll();
  308. }
  309. void CStockGraph::ResetClient( CRect rectAll )
  310. {
  311. if( rectAll.IsRectEmpty() )
  312. return;
  313. m_rectAll = rectAll;
  314. if( m_rectAll.IsRectEmpty() )
  315. return;
  316. // The Left Side m_rectKData
  317. m_rectKData.top = m_rectAll.top + m_nMarginTop+m_nMarginTop;
  318. m_rectKData.left = m_rectAll.left+1;
  319. m_rectKData.bottom = m_rectKData.top + 313;
  320. m_rectKData.right = m_rectKData.left + 82;
  321. // The Right Side m_rectReport
  322. m_rectReport.top = m_rectAll.top + m_nMarginTop+7;
  323. m_rectReport.left = m_rectAll.right - 174;
  324. m_rectReport.bottom = m_rectAll.bottom - m_nMarginBottom;
  325. m_rectReport.right = m_rectAll.right;
  326. // The Center m_rectKLine
  327. CSPDWordArray & anTech = AfxGetProfile().GetGraphTechsShow();
  328. int nTechCount = anTech.GetSize();
  329. int nUnit = (int)( (m_rectAll.Height()-m_nMarginTop-m_nMarginBottom) / (nTechCount+1.8) );
  330. m_rectKLine.top = m_rectAll.top + m_nMarginTop;
  331. m_rectKLine.left = m_rectKData.right+1;
  332. m_rectKLine.bottom = m_rectKLine.top + m_rectAll.Height() - m_nMarginTop - m_nMarginBottom - nUnit*nTechCount;
  333. m_rectKLine.right = m_rectAll.right-m_rectReport.Width()-1;
  334. // The m_rectKLineCenter
  335. m_rectKLineCenter = m_rectKLine;
  336. m_rectKLineCenter.InflateRect( -2, -m_nHeightSubtitle, -2, -2 );
  337. // The m_arcTech
  338. m_arcTech.RemoveAll();
  339. int nLastBottom = m_rectKLine.bottom;
  340. for( int k=0; k<anTech.GetSize(); k++ )
  341. {
  342. CRect rectTech;
  343. rectTech.top = nLastBottom;
  344. rectTech.left = m_rectKLine.left;
  345. rectTech.bottom = rectTech.top + nUnit;
  346. rectTech.right = m_rectKLine.right;
  347. nLastBottom = rectTech.bottom;
  348. m_arcTech.Add( rectTech );
  349. }
  350. // The m_rectCenter
  351. m_rectCenter = m_rectKLine;
  352. m_rectCenter.bottom = m_rectAll.bottom;
  353. }
  354. void CStockGraph::ClearTechniqueCache( )
  355. {
  356. m_techparam.Clear();
  357. for( int i=0; i<m_aptrTechUser.GetSize(); i++ )
  358. {
  359. CTechUser * pTechUser = (CTechUser *)m_aptrTechUser.GetAt(i);
  360. if( pTechUser )
  361. delete pTechUser;
  362. }
  363. m_aptrTechUser.RemoveAll();
  364. }
  365. void CStockGraph::ClearCurStock( )
  366. {
  367. ClearTechniqueCache( );
  368. m_CurStock.Clear();
  369. m_CurStockDown.Clear();
  370. }
  371. BOOL CStockGraph::SetCurStock( const char * szCode )
  372. {
  373. if( NULL == szCode || strlen(szCode) <= 0 )
  374. {
  375. ASSERT( FALSE );
  376. return FALSE;
  377. }
  378. CStockInfo info;
  379. if( !AfxGetStockContainer().GetStockInfo( szCode, &info ) )
  380. {
  381. ASSERT( FALSE );
  382. return FALSE;
  383. }
  384. return SetCurStock( info );
  385. }
  386. BOOL CStockGraph::SetCurStock( CStockInfo & info )
  387. {
  388. if( m_CurStock.GetStockInfo().IsEqualTo( info.GetMarket(), info.GetStockCode() ) )
  389. {
  390. return TRUE;
  391. }
  392. ResetIndex( );
  393. ClearCurStock( );
  394. m_CurStock.SetStockInfo( &info );
  395. m_CurStock.SetDatabase( &AfxGetDB() );
  396. m_CurStockDown.SetStockInfo( &info );
  397. m_CurStockDown.SetDatabase( &AfxGetDB() );
  398. m_dwLatestDate = -1;
  399. return TRUE;
  400. }
  401. void CStockGraph::SetReportWhat( int nReportWhat )
  402. {
  403. m_nReportWhat = nReportWhat;
  404. }
  405. BOOL CStockGraph::PrepareStockData( BOOL bReload )
  406. {
  407. if( !m_CurStock.GetStockInfo().IsValidStock() )
  408. return FALSE;
  409. CStockInfo info;
  410. if( AfxGetStockContainer().GetStockInfo( m_CurStock.GetStockCode(), &info )
  411. && m_CurStock.GetStockInfo().IsEqualTo( info.GetMarket(), info.GetStockCode() ) )
  412. {
  413. m_CurStock.SetStockInfo( &info );
  414. m_CurStockDown.SetStockInfo( &info );
  415. }
  416. int nOldSize = m_CurStock.GetKData(m_nCurKType).GetSize();
  417. // Prepare Data
  418. AfxPrepareStockData( &AfxGetDB(), m_CurStock, m_nCurKType, m_nCurKFormat, m_nCurMaindataType, FALSE, bReload );
  419. AfxPrepareStockData( &AfxGetDB(), m_CurStockDown, m_nCurKType, CKData::formatXDRdown, m_nCurMaindataType, FALSE, bReload );
  420. if( m_CurStock.GetKData(m_nCurKType).GetSize() != nOldSize )
  421. ResetIndex( );
  422. AfxGetStkReceiver().RequestKData( &m_CurStock, m_nCurKType );
  423. m_techparam.Clear( );
  424. m_techparam.SetKData( &(m_CurStockDown.GetKData(m_nCurKType)) );
  425. m_techparam.volume.SetKData( &(m_CurStock.GetKData(m_nCurKType)) );
  426. m_techparam.ma.SetKData( &(m_CurStock.GetKData(m_nCurKType)) );
  427. m_techparam.bbi.SetKData( &(m_CurStock.GetKData(m_nCurKType)) );
  428. m_techparam.boll.SetKData( &(m_CurStock.GetKData(m_nCurKType)) );
  429. m_techparam.pv.SetKData( &(m_CurStock.GetKData(m_nCurKType)) );
  430. m_techparam.sar.SetKData( &(m_CurStock.GetKData(m_nCurKType)) );
  431. m_techparam.dj.SetKData( &(m_CurStock.GetKData(m_nCurKType)) );
  432. m_techparam.mike.SetKData( &(m_CurStock.GetKData(m_nCurKType)) );
  433. return TRUE;
  434. }
  435. void CStockGraph::Redraw( CDC * pDC, CRect rectAll )
  436. {
  437. ASSERT( m_pParent && ::IsWindow( m_pParent->GetSafeHwnd() ) );
  438. if( m_rectAll != rectAll )
  439. ResetClient( rectAll );
  440. DrawStock( pDC );
  441. }
  442. void CStockGraph::DrawReportRegion( CDC * pDC )
  443. {
  444. ASSERT( m_pParent && ::IsWindow( m_pParent->GetSafeHwnd() ) );
  445. if( !m_pParent || !::IsWindow(m_pParent->GetSafeHwnd()) )
  446. return;
  447. CClientDC dc(m_pParent);
  448. if( NULL == pDC )
  449. pDC = &dc;
  450. switch( m_nReportWhat )
  451. {
  452. case CStockGraph::reportParam: DrawReportParam( pDC ); break;
  453. case CStockGraph::reportCost: DrawReportCost( pDC ); break;
  454. case CStockGraph::reportFlame: DrawReportFlame( pDC ); break;
  455. case CStockGraph::reportActivity: DrawReportActivity( pDC ); break;
  456. }
  457. }
  458. int CStockGraph::GetNextThickness( int nCurrentThickness, BOOL bAsc )
  459. {
  460. if( bAsc )
  461. {
  462. switch( nCurrentThickness )
  463. {
  464. case 1: return 2;
  465. case 2: return 4;
  466. case 4: return 5;
  467. case 5: return 6;
  468. case 6: return 7;
  469. case 7: return 9;
  470. case 9: return 10;
  471. case 10: return 13;
  472. case 13: return 15;
  473. case 15: return 15;
  474. default:
  475. ASSERT( FALSE );
  476. return m_nDefaultThickness;
  477. }
  478. }
  479. else
  480. {
  481. switch( nCurrentThickness )
  482. {
  483. case 1: return 1;
  484. case 2: return 1;
  485. case 4: return 2;
  486. case 5: return 4;
  487. case 6: return 5;
  488. case 7: return 6;
  489. case 9: return 7;
  490. case 10: return 9;
  491. case 13: return 10;
  492. case 15: return 13;
  493. default:
  494. ASSERT( FALSE );
  495. return m_nDefaultThickness;
  496. }
  497. }
  498. }
  499. void CStockGraph::ExpandUp( BOOL bShiftPressed )
  500. {
  501. if( m_nIndexCurrent >= 0 )
  502. {
  503. CKData &kdata = m_CurStock.GetKData( m_nCurKType );
  504. if( m_nIndexCurrent < kdata.GetSize() )
  505. {
  506. if( -1 != m_dwLatestDate && kdata.ElementAt(m_nIndexCurrent).m_date > m_dwLatestDate )
  507. {
  508. KDATA & kd = kdata.ElementAt(m_nIndexCurrent);
  509. if( bShiftPressed )
  510. {
  511. float fIncrease = 100000;
  512. fIncrease = ( kd.m_fVolume/10 > fIncrease ? kd.m_fVolume/10 : fIncrease );
  513. kd.m_fVolume += fIncrease;
  514. kd.m_fAmount = ( kd.m_fVolume*(kd.m_fOpen+kd.m_fClose)/2 );
  515. }
  516. else
  517. {
  518. float fIncrease = (float)0.001;
  519. fIncrease = (float)( kd.m_fClose/500 > fIncrease ? kd.m_fClose/500 : fIncrease );
  520. kd.m_fClose += fIncrease;
  521. kd.m_fOpen += fIncrease;
  522. kd.m_fHigh += fIncrease;
  523. kd.m_fLow += fIncrease;
  524. }
  525. DrawStock( NULL );
  526. return;
  527. }
  528. }
  529. }
  530. int nOld = m_nThickness;
  531. m_nThickness = GetNextThickness( m_nThickness, TRUE );
  532. if( nOld != m_nThickness )
  533. DrawStock( NULL );
  534. }
  535. void CStockGraph::ExpandDown( BOOL bShiftPressed )
  536. {
  537. if( m_nIndexCurrent >= 0 )
  538. {
  539. CKData &kdata = m_CurStock.GetKData( m_nCurKType );
  540. if( m_nIndexCurrent < kdata.GetSize() )
  541. {
  542. if( -1 != m_dwLatestDate && kdata.ElementAt(m_nIndexCurrent).m_date > m_dwLatestDate )
  543. {
  544. KDATA & kd = kdata.ElementAt(m_nIndexCurrent);
  545. if( bShiftPressed )
  546. {
  547. float fDecline = 100000;
  548. fDecline = ( kd.m_fVolume/10 > fDecline ? kd.m_fVolume/10 : fDecline );
  549. if( kd.m_fVolume > fDecline )
  550. kd.m_fVolume -= fDecline;
  551. kd.m_fAmount = (float)( kd.m_fVolume*(kd.m_fOpen+kd.m_fClose)/2 );
  552. }
  553. else
  554. {
  555. float fDecline = (float)0.001;
  556. fDecline = (float)( kd.m_fClose/500 > fDecline ? kd.m_fClose/500 : fDecline );
  557. if( kd.m_fLow > fDecline )
  558. {
  559. kd.m_fClose -= fDecline;
  560. kd.m_fOpen -= fDecline;
  561. kd.m_fHigh -= fDecline;
  562. kd.m_fLow -= fDecline;
  563. }
  564. }
  565. DrawStock( NULL );
  566. return;
  567. }
  568. }
  569. }
  570. int nOld = m_nThickness;
  571. m_nThickness = GetNextThickness( m_nThickness, FALSE );
  572. if( nOld != m_nThickness )
  573. DrawStock( NULL );
  574. }
  575. void CStockGraph::MoveLeft( BOOL bShiftPressed )
  576. {
  577. Move( -1, bShiftPressed, FALSE );
  578. }
  579. void CStockGraph::MoveRight( BOOL bShiftPressed )
  580. {
  581. if( m_nIndexCurrent >= 0 && bShiftPressed )
  582. {
  583. CKData &kdata = m_CurStock.GetKData( m_nCurKType );
  584. if( m_nIndexCurrent+1 >= kdata.GetSize() )
  585. {
  586. // Add New KDATA to test predicate
  587. if( 0 == kdata.GetSize() )
  588. m_dwLatestDate = 0;
  589. else if( -1 == m_dwLatestDate )
  590. m_dwLatestDate = kdata.ElementAt(kdata.GetSize()-1).m_date;
  591. KDATA kd;
  592. memset( &kd, 0, sizeof(kd) );
  593. if( kdata.GetSize() > 0 )
  594. kd = kdata.ElementAt(kdata.GetSize()-1);
  595. else
  596. kd.m_fClose = 1;
  597. kd.m_fOpen = kd.m_fHigh = kd.m_fLow = kd.m_fClose;
  598. kd.m_date = CSPTime::GetStockTimeNext( kd.m_date, m_nCurKType );
  599. kdata.Add( kd );
  600. m_CurStockDown.GetKData( m_nCurKType ).Add( kd );
  601. bShiftPressed = FALSE;
  602. }
  603. }
  604. Move( 1, bShiftPressed, FALSE );
  605. }
  606. void CStockGraph::PageLeft( BOOL bShiftPressed )
  607. {
  608. int nMove = -(m_nIndexEnd-m_nIndexStart-5);
  609. if( nMove >= 0 )
  610. nMove = -1;
  611. Move( nMove, bShiftPressed, FALSE );
  612. }
  613. void CStockGraph::PageRight( BOOL bShiftPressed )
  614. {
  615. int nMove = (m_nIndexEnd-m_nIndexStart-5);
  616. if( nMove <= 0 )
  617. nMove = 1;
  618. Move( nMove, bShiftPressed, FALSE );
  619. }
  620. void CStockGraph::MoveHome( BOOL bShiftPressed )
  621. {
  622. if( m_nIndexCurrent >= 0 )
  623. {
  624. // Move Current Selection
  625. int nPos = m_nIndexStart;
  626. MoveTo( nPos, bShiftPressed, FALSE );
  627. }
  628. else
  629. {
  630. // Show Prev Technique Line
  631. UINT nTechUserCount = CTechUser::GetTechUserCount();
  632. UINT nTechMax = STT_MAX;
  633. if( nTechUserCount > 0 )
  634. nTechMax = STT_USER_MIN + nTechUserCount - 1;
  635. CSPDWordArray & auShow = AfxGetProfile().GetGraphTechsShow();
  636. int nOldSize = auShow.GetSize();
  637. if( auShow.GetSize() > 0 )
  638. {
  639. UINT nNext = auShow.ElementAt(auShow.GetSize()-1);
  640. nNext --;
  641. if( nNext < STT_TREND_MIN || nNext > nTechMax )
  642. nNext = nTechMax;
  643. if( nNext > STT_MAX && nNext < STT_USER_MIN )
  644. nNext = STT_MAX;
  645. AfxGetProfile().ShowGraphViewTech( nNext );
  646. }
  647. else
  648. {
  649. auShow.Add( nTechMax );
  650. }
  651. if( auShow.GetSize() == nOldSize )
  652. InvalidateCenter( );
  653. else if( m_pParent && ::IsWindow(m_pParent->GetSafeHwnd()) )
  654. {
  655. ResetClient( m_rectAll );
  656. m_pParent->Invalidate();
  657. }
  658. }
  659. }
  660. void CStockGraph::MoveEnd( BOOL bShiftPressed )
  661. {
  662. if( m_nIndexCurrent >= 0 )
  663. {
  664. // Move Current Selection
  665. CKData & kdata = m_CurStock.GetKData( m_nCurKType );
  666. int nPos = ( m_nIndexEnd < 0 ? kdata.GetSize()-1 : m_nIndexEnd );
  667. MoveTo( nPos, bShiftPressed, FALSE );
  668. }
  669. else
  670. {
  671. // Show Next Technique Line
  672. UINT nTechUserCount = CTechUser::GetTechUserCount();
  673. UINT nTechMax = STT_MAX;
  674. if( nTechUserCount > 0 )
  675. nTechMax = STT_USER_MIN + nTechUserCount - 1;
  676. CSPDWordArray & auShow = AfxGetProfile().GetGraphTechsShow();
  677. int nOldSize = auShow.GetSize();
  678. if( auShow.GetSize() > 0 )
  679. {
  680. UINT nNext = auShow.ElementAt(auShow.GetSize()-1);
  681. nNext ++;
  682. if( nNext < STT_TREND_MIN || nNext > nTechMax )
  683. nNext = STT_TREND_MIN;
  684. if( nNext > STT_MAX && nNext < STT_USER_MIN )
  685. nNext = STT_USER_MIN;
  686. AfxGetProfile().ShowGraphViewTech( nNext );
  687. }
  688. else
  689. {
  690. auShow.Add( STT_TREND_MIN );
  691. }
  692. if( auShow.GetSize() == nOldSize )
  693. InvalidateCenter( );
  694. else if( m_pParent && ::IsWindow(m_pParent->GetSafeHwnd()) )
  695. {
  696. ResetClient( m_rectAll );
  697. m_pParent->Invalidate();
  698. }
  699. }
  700. }
  701. void CStockGraph::OnInsert( )
  702. {
  703. CKData &kdata = m_CurStock.GetKData( m_nCurKType );
  704. KDATA kd;
  705. memset( &kd, 0, sizeof(kd) );
  706. if( kdata.GetSize() > 0 )
  707. kd = kdata.ElementAt(kdata.GetSize()-1);
  708. else
  709. kd.m_fClose = 1;
  710. kd.m_fOpen = kd.m_fHigh = kd.m_fLow = kd.m_fClose;
  711. kd.m_date = CSPTime::GetStockTimeNext( kd.m_date, m_nCurKType );
  712. CEditKDATADlg dlg( m_pParent );
  713. dlg.SetKDATA( kd, m_nCurKType );
  714. if( IDOK == dlg.DoModal( ) )
  715. {
  716. kd = dlg.GetKDATA( );
  717. kdata.Add( kd );
  718. m_CurStockDown.GetKData( m_nCurKType ).Add( kd );
  719. m_nIndexCurrent = kdata.GetSize()-1;
  720. if( -1 == m_dwLatestDate )
  721. {
  722. if( kdata.GetSize() <= 1 )
  723. m_dwLatestDate = 0;
  724. else
  725. m_dwLatestDate = kdata.ElementAt(kdata.GetSize()-2).m_date;
  726. }
  727. MoveTo( m_nIndexCurrent, FALSE, FALSE );
  728. }
  729. if( m_pParent && ::IsWindow( m_pParent->GetSafeHwnd() ) )
  730. m_pParent->SetFocus( );
  731. }
  732. void CStockGraph::OnLButtonDown( UINT nFlags, CPoint point, BOOL bShiftPressed, BOOL bCtrlPressed )
  733. {
  734. // Border Move
  735. if( m_bCursorBorder )
  736. {
  737. SetCapture(m_pParent->GetSafeHwnd());
  738. // Draw Border Moving Line
  739. DrawBorderMovingLine( NULL, point, TRUE );
  740. m_ptLastMovingLine = point;
  741. return;
  742. }
  743. // KLine Index
  744. int nIndexClick = GetIndexClick( point );
  745. MoveTo( nIndexClick, bShiftPressed, bCtrlPressed );
  746. // Selection Rect
  747. if( -1 != nIndexClick && m_rectKLineCenter.PtInRect(point) )
  748. {
  749. SetCapture(m_pParent->GetSafeHwnd());
  750. m_ptSelectBegin = point;
  751. m_ptSelectEnd = point;
  752. DrawSelectionRect( NULL, m_ptSelectBegin, m_ptSelectEnd, TRUE );
  753. }
  754. // Selected TechID
  755. SelectTechID( point );
  756. }
  757. void CStockGraph::OnLButtonUp( UINT nFlags, CPoint point, BOOL bShiftPressed, BOOL bCtrlPressed )
  758. {
  759. if( m_bCursorBorder && GetCapture() == m_pParent->GetSafeHwnd() )
  760. {
  761. ReleaseCapture( );
  762. // Remove Border Moving Line
  763. DrawBorderMovingLine( NULL, point, FALSE );
  764. // Reset Border
  765. if( 0 == m_nPosSelectBorder )
  766. {
  767. m_rectKLine.bottom = point.y;
  768. m_rectKLineCenter = m_rectKLine;
  769. m_rectKLineCenter.InflateRect( -2, -m_nHeightSubtitle, -2, -2 );
  770. if( m_arcTech.GetSize() > 0 )
  771. m_arcTech.ElementAt(0).top = point.y;
  772. }
  773. else if( m_nPosSelectBorder > 0 )
  774. {
  775. if( m_nPosSelectBorder < m_arcTech.GetSize() )
  776. {
  777. m_arcTech.ElementAt(m_nPosSelectBorder-1).bottom = point.y;
  778. m_arcTech.ElementAt(m_nPosSelectBorder).top = point.y;
  779. }
  780. }
  781. m_bCursorBorder = FALSE;
  782. DrawStock( NULL );
  783. return;
  784. }
  785. if( GetCapture() == m_pParent->GetSafeHwnd() )
  786. {
  787. ReleaseCapture( );
  788. DrawSelectionRect( NULL, m_ptSelectBegin, m_ptSelectEnd, FALSE );
  789. int nClickBegin = GetIndexClick( m_ptSelectBegin );
  790. int nClickEnd = GetIndexClick( m_ptSelectEnd );
  791. if( -1 == nClickBegin )
  792. {
  793. if( m_ptSelectBegin.x < m_rectCenter.left ) nClickBegin = m_nIndexStart;
  794. if( m_ptSelectBegin.x > m_rectCenter.right ) nClickBegin = m_nIndexEnd;
  795. }
  796. if( -1 == nClickEnd )
  797. {
  798. if( m_ptSelectEnd.x < m_rectCenter.left ) nClickEnd = m_nIndexStart;
  799. if( m_ptSelectEnd.x > m_rectCenter.right ) nClickEnd = m_nIndexEnd;
  800. }
  801. if( -1 != nClickBegin && -1 != nClickEnd )
  802. {
  803. if( nClickBegin < nClickEnd ) // 放大
  804. {
  805. int nLeft = min(nClickBegin,nClickEnd);
  806. int nRight = max(nClickBegin,nClickEnd);
  807. if( 15*(nRight-nLeft+1) < m_rectCenter.Width() )
  808. {
  809. nLeft -= (m_rectCenter.Width() - 15*(nRight-nLeft+1))/30 + 1;
  810. nRight += (m_rectCenter.Width() - 15*(nRight-nLeft+1))/30 + 1;
  811. }
  812. int nOldLen = m_nIndexEnd - m_nIndexStart;
  813. int nOldThick = m_nThickness;
  814. ResetIndex( nLeft, nRight, m_nIndexCurrent );
  815. int nNewLen = m_nIndexEnd - m_nIndexStart;
  816. while( nOldLen * nOldThick > nNewLen * m_nThickness )
  817. {
  818. int nTemp = m_nThickness;
  819. m_nThickness = GetNextThickness( m_nThickness, TRUE );
  820. if( nTemp == m_nThickness )
  821. break;
  822. }
  823. }
  824. else if( nClickBegin > nClickEnd ) // 缩小
  825. {
  826. m_nThickness = GetNextThickness( m_nThickness, FALSE );
  827. m_nThickness = GetNextThickness( m_nThickness, FALSE );
  828. m_nThickness = GetNextThickness( m_nThickness, FALSE );
  829. }
  830. DrawStock( NULL );
  831. }
  832. }
  833. }
  834. void CStockGraph::OnMouseMove( UINT nFlags, CPoint point )
  835. {
  836. // Size Border
  837. if( m_bCursorBorder && GetCapture() == m_pParent->GetSafeHwnd() )
  838. {
  839. DrawBorderMovingLine( NULL, m_ptLastMovingLine, TRUE );
  840. DrawBorderMovingLine( NULL, point, TRUE );
  841. m_ptLastMovingLine = point;
  842. return;
  843. }
  844. int nPosSelectBorder = -1;
  845. if( m_rectCenter.PtInRect(point) )
  846. {
  847. CRect rect = m_rectKLine;
  848. for( int i=0; i<m_arcTech.GetSize(); i++ )
  849. {
  850. rect.top = rect.bottom-5;
  851. rect.bottom = rect.bottom+5;
  852. if( rect.PtInRect(point) )
  853. nPosSelectBorder = i;
  854. rect = m_arcTech[i];
  855. }
  856. }
  857. if( -1 != nPosSelectBorder )
  858. {
  859. ::SetCursor( AfxGetApp()->LoadCursor(AFX_IDC_VSPLITBAR) );
  860. m_bCursorBorder = TRUE;
  861. m_nPosSelectBorder = nPosSelectBorder;
  862. }
  863. if( -1 == nPosSelectBorder && m_bCursorBorder && GetCapture() != m_pParent->GetSafeHwnd() )
  864. {
  865. ::SetCursor( AfxGetApp()->LoadCursor(IDC_ARROW) );
  866. m_bCursorBorder = FALSE;
  867. }
  868. if( m_bCursorBorder )
  869. return;
  870. // Selection Rect
  871. if( GetCapture() == m_pParent->GetSafeHwnd() )
  872. {
  873. DrawSelectionRect( NULL, m_ptSelectBegin, m_ptSelectEnd, FALSE );
  874. m_ptSelectEnd = point;
  875. if( m_ptSelectEnd.x <= m_rectKLineCenter.left )
  876. m_ptSelectEnd.x = m_rectKLineCenter.left+1;
  877. if( m_ptSelectEnd.x >= m_rectKLineCenter.right )
  878. m_ptSelectEnd.x = m_rectKLineCenter.right-1;
  879. if( m_ptSelectEnd.y <= m_rectKLineCenter.top )
  880. m_ptSelectEnd.y = m_rectKLineCenter.top+1;
  881. if( m_ptSelectEnd.y >= m_rectKLineCenter.bottom )
  882. m_ptSelectEnd.y = m_rectKLineCenter.bottom-1;
  883. DrawSelectionRect( NULL, m_ptSelectBegin, m_ptSelectEnd, TRUE );
  884. }
  885. }
  886. void CStockGraph::OnLButtonDblClk( UINT nFlags, CPoint point, BOOL bShiftPressed, BOOL bCtrlPressed )
  887. {
  888. OnLButtonDown( nFlags, point, bShiftPressed, bCtrlPressed );
  889. AdjustSelectedTech();
  890. OnReturn( bShiftPressed, bCtrlPressed );
  891. }
  892. void CStockGraph::OnRButtonDown( UINT nFlags, CPoint point, BOOL bShiftPressed, BOOL bCtrlPressed )
  893. {
  894. SelectTechID( point );
  895. }
  896. void CStockGraph::OnReturn( BOOL bShiftPressed, BOOL bCtrlPressed )
  897. {
  898. if( m_nIndexCurrent >= 0 )
  899. {
  900. CKData &kdata = m_CurStock.GetKData( m_nCurKType );
  901. if( m_nIndexCurrent < kdata.GetSize() )
  902. {
  903. if( -1 != m_dwLatestDate && kdata.ElementAt(m_nIndexCurrent).m_date > m_dwLatestDate )
  904. {
  905. KDATA & kd = kdata.ElementAt(m_nIndexCurrent);
  906. CEditKDATADlg dlg( m_pParent );
  907. dlg.SetKDATA( kd, m_nCurKType );
  908. if( IDOK == dlg.DoModal( ) )
  909. {
  910. kd = dlg.GetKDATA( );
  911. if( m_nIndexCurrent < m_CurStockDown.GetKData( m_nCurKType ).GetSize() )
  912. m_CurStockDown.GetKData( m_nCurKType ).SetAt(m_nIndexCurrent,kd);
  913. DrawStock( NULL );
  914. }
  915. if( m_pParent && ::IsWindow( m_pParent->GetSafeHwnd() ) )
  916. m_pParent->SetFocus( );
  917. }
  918. }
  919. }
  920. }
  921. UINT CStockGraph::GetSelectedTech( )
  922. {
  923. return m_nSelectedTechID;
  924. }
  925. void CStockGraph::HideSelectedTech()
  926. {
  927. AfxGetProfile().ToggleGraphViewTech( m_nSelectedTechID );
  928. if( m_pParent && ::IsWindow(m_pParent->GetSafeHwnd()) )
  929. {
  930. ResetClient( m_rectAll );
  931. m_pParent->Invalidate();
  932. }
  933. }
  934. void CStockGraph::AdjustSelectedTech()
  935. {
  936. if( STT_INVALID != m_nSelectedTechID )
  937. {
  938. CSetParamDlg dlg;
  939. dlg.SetFirstSelected( m_nSelectedTechID );
  940. dlg.DoModal();
  941. CGraphView * pGraphView = AfxGetGraphView();
  942. if( pGraphView )
  943. pGraphView->OnTechParametersChange( );
  944. AfxGetStaticDoc()->UpdateAllViews( NULL, UPDATE_HINT_GRAPHVIEW, NULL );
  945. }
  946. }
  947. void CStockGraph::MoveTo( int nIndex, BOOL bShiftPressed, BOOL bCtrlPressed )
  948. {
  949. DrawSelectionLine( NULL, FALSE );
  950. // To Change m_anIndexCurrent
  951. if( bShiftPressed && nIndex >= 0 )
  952. {
  953. if( m_nIndexCurrent < 0 )
  954. {
  955. AddIndexCurrent( nIndex );
  956. }
  957. else if( m_nIndexCurrent <= nIndex )
  958. {
  959. for( int nSel=m_nIndexCurrent; nSel<=nIndex; nSel++ )
  960. {
  961. AddIndexCurrent( nSel );
  962. }
  963. }
  964. else
  965. {
  966. for( int nSel=nIndex; nSel<=m_nIndexCurrent; nSel++ )
  967. {
  968. AddIndexCurrent( nSel );
  969. }
  970. }
  971. }
  972. else if( bCtrlPressed && nIndex >= 0 )
  973. {
  974. AddIndexCurrent( nIndex );
  975. }
  976. else
  977. {
  978. m_anIndexCurrent.RemoveAll();
  979. }
  980. BOOL bNeedDrawAll = FALSE;
  981. if( -1 != nIndex && nIndex < m_nIndexStart )
  982. {
  983. m_nIndexEnd -= (m_nIndexStart-nIndex);
  984. m_nIndexStart = nIndex;
  985. m_nIndexCurrent = nIndex;
  986. bNeedDrawAll = TRUE;
  987. }
  988. if( -1 != nIndex && nIndex > m_nIndexEnd )
  989. {
  990. m_nIndexStart += (nIndex-m_nIndexEnd);
  991. m_nIndexEnd = nIndex;
  992. m_nIndexCurrent = nIndex;
  993. bNeedDrawAll = TRUE;
  994. }
  995. if( m_nIndexCurrent != nIndex )
  996. {
  997. int nOld = m_nIndexCurrent;
  998. m_nIndexCurrent = nIndex;
  999. OnIndexCurrentChanged( );
  1000. }
  1001. if( bNeedDrawAll )
  1002. DrawStock( NULL );
  1003. else
  1004. DrawSelectionLine( NULL, TRUE );
  1005. }
  1006. void CStockGraph::OnIndexCurrentChanged( )
  1007. {
  1008. if( m_pParent && ::IsWindow(m_pParent->GetSafeHwnd()) )
  1009. {
  1010. CClientDC dc(m_pParent);
  1011. CRect rectKLineAttrib = m_rectKLineCenter;
  1012. rectKLineAttrib.top -= m_nHeightSubtitle;
  1013. CSPDWordArray & anTech = AfxGetProfile().GetGraphTechsKLine();
  1014. if( anTech.GetSize() > 0 )
  1015. DrawKLineAttribute( &dc, anTech[0], rectKLineAttrib, TRUE, 0, 0 );
  1016. CSPDWordArray & anShow = AfxGetProfile().GetGraphTechsShow( );
  1017. for( int k=0; k<m_arcTech.GetSize(); k++ )
  1018. {
  1019. CRect rect = m_arcTech.ElementAt(k);
  1020. if( k < anShow.GetSize() && anShow[k] == STT_MIKE )
  1021. {
  1022. DrawTechLine( &dc, anShow[k], rect, FALSE );
  1023. DrawTechLine( &dc, anShow[k], rect, TRUE );
  1024. }
  1025. else if( k < anShow.GetSize() )
  1026. {
  1027. DrawTechLine( &dc, anShow[k], rect, TRUE );
  1028. }
  1029. }
  1030. DrawReportRegion( &dc );
  1031. DrawKData( );
  1032. }
  1033. }
  1034. void CStockGraph::Move( int nMove, BOOL bShiftPressed, BOOL bCtrlPressed )
  1035. {
  1036. int nIndexCurrent = m_nIndexCurrent;
  1037. if( nIndexCurrent < 0 )
  1038. {
  1039. if( nMove < 0 )
  1040. nIndexCurrent = m_nIndexEnd;
  1041. else if( nMove > 0 )
  1042. nIndexCurrent = m_nIndexStart;
  1043. }
  1044. else
  1045. {
  1046. nIndexCurrent += nMove;
  1047. }
  1048. CKData &kdata = m_CurStock.GetKData( m_nCurKType );
  1049. if( nIndexCurrent < 0 )
  1050. nIndexCurrent = 0;
  1051. if( nIndexCurrent >= kdata.GetSize() )
  1052. nIndexCurrent = kdata.GetSize()-1;
  1053. MoveTo( nIndexCurrent, bShiftPressed, bCtrlPressed );
  1054. }
  1055. int CStockGraph::GetIndexClick( CPoint point )
  1056. {
  1057. int nIndexClick = -1;
  1058. if( m_rectCenter.PtInRect( point ) )
  1059. {
  1060. for( int nIndex=m_nIndexStart; nIndex<=m_nIndexEnd; nIndex ++ )
  1061. {
  1062. CRect rectK;
  1063. if( GetOneKLineRect( nIndex, &rectK, NULL, NULL, NULL ) && rectK.PtInRect(point) )
  1064. {
  1065. nIndexClick = nIndex;
  1066. break;
  1067. }
  1068. }
  1069. }
  1070. return nIndexClick;
  1071. }
  1072. void CStockGraph::SelectTechID( CPoint point )
  1073. {
  1074. m_nSelectedTechID = STT_INVALID;
  1075. int nTechClick = -1;
  1076. for( int k=0; k<m_arcTech.GetSize(); k++ )
  1077. {
  1078. if( m_arcTech.ElementAt(k).PtInRect( point ) )
  1079. {
  1080. nTechClick = k;
  1081. break;
  1082. }
  1083. }
  1084. CSPDWordArray & anTech = AfxGetProfile().GetGraphTechsShow();
  1085. if( nTechClick >= 0 && nTechClick < m_arcTech.GetSize() && nTechClick < anTech.GetSize() )
  1086. {
  1087. m_nSelectedTechID = anTech.ElementAt(nTechClick);
  1088. }
  1089. }
  1090. BOOL CStockGraph::AddIndexCurrent( int nIndex )
  1091. {
  1092. for( int k=0; k<m_anIndexCurrent.GetSize(); k++ )
  1093. {
  1094. if( (UINT)nIndex == m_anIndexCurrent[k] )
  1095. return FALSE;
  1096. }
  1097. m_anIndexCurrent.Add( nIndex );
  1098. return TRUE;
  1099. }
  1100. void CStockGraph::InvalidateCenter( )
  1101. {
  1102. if( !m_pParent || !::IsWindow(m_pParent->GetSafeHwnd()) )
  1103. return;
  1104. CClientDC dc(m_pParent);
  1105. DrawDateAxis( &dc );
  1106. DrawTechLine( &dc );
  1107. DrawKLine( &dc );
  1108. }
  1109. BOOL CStockGraph::GetOneKLineRect( int nIndex, LPRECT lpRect, long *pxEntityLeft, long *pxEntityRight, long *pxMedium )
  1110. {
  1111. if( nIndex == -1 || nIndex < m_nIndexStart || nIndex > m_nIndexEnd )
  1112. return FALSE;
  1113. CRect rectK = m_rectCenter;
  1114. rectK.left = m_rectKLineCenter.left + (nIndex-m_nIndexStart) * m_nThickness;
  1115. rectK.right = rectK.left + m_nThickness;
  1116. if( rectK.Width() <= 0 || rectK.Height() <= 0 )
  1117. return FALSE;
  1118. if( lpRect )
  1119. *lpRect = rectK;
  1120. int xStart = rectK.left;
  1121. CRect rcEntity;
  1122. switch( m_nThickness )
  1123. {
  1124. case 1:
  1125. case 2:
  1126. rcEntity.left = xStart;
  1127. rcEntity.right = xStart + 1;
  1128. break;
  1129. case 4:
  1130. case 5:
  1131. rcEntity.left = xStart;
  1132. rcEntity.right = xStart + 3;
  1133. break;
  1134. case 6:
  1135. case 7:
  1136. rcEntity.left = xStart;
  1137. rcEntity.right = xStart + 5;
  1138. break;
  1139. case 9:
  1140. case 10:
  1141. rcEntity.left = xStart;
  1142. rcEntity.right = xStart + 7;
  1143. break;
  1144. case 13:
  1145. case 15:
  1146. rcEntity.left = xStart;
  1147. rcEntity.right = xStart + 11;
  1148. break;
  1149. default:
  1150. ASSERT( FALSE );
  1151. rcEntity.left = xStart;
  1152. rcEntity.right = xStart + 3;
  1153. return FALSE;
  1154. }
  1155. if( pxEntityLeft )
  1156. *pxEntityLeft = rcEntity.left;
  1157. if( pxEntityRight )
  1158. *pxEntityRight = rcEntity.right;
  1159. if( pxMedium )
  1160. *pxMedium = rcEntity.left + rcEntity.Width() / 2;
  1161. return TRUE;
  1162. }
  1163. void CStockGraph::DrawStock( CDC * pDC )
  1164. {
  1165. ASSERT( m_pParent && ::IsWindow( m_pParent->GetSafeHwnd() ) );
  1166. if( !m_pParent || !::IsWindow(m_pParent->GetSafeHwnd()) )
  1167. return;
  1168. CClientDC dc(m_pParent);
  1169. if( NULL == pDC )
  1170. pDC = &dc;
  1171. if( !m_CurStock.GetStockInfo().IsValidStock() )
  1172. return;
  1173. CKData & kdata = m_CurStock.GetKData(m_nCurKType);
  1174. if( kdata.GetSize() == 0 )
  1175. {
  1176. DrawNoDataInfo( pDC );
  1177. }
  1178. else if( PrepareDrawKLine( ) ) // Reset m_nIndexStart, m_nIndexEnd, m_nIndexCurrent
  1179. {
  1180. DrawDateAxis( pDC );
  1181. DrawTechLine( pDC );
  1182. DrawKLine( pDC );
  1183. DrawKData( );
  1184. }
  1185. DrawReportRegion( pDC );
  1186. }
  1187. BOOL CStockGraph::PrepareDrawKLine( )
  1188. {
  1189. ASSERT( m_nThickness > 0 );
  1190. if( m_nThickness <= 0 || m_rectKLineCenter.Width() <= 0 )
  1191. return FALSE;
  1192. CKData & kdata = m_CurStock.GetKData(m_nCurKType);
  1193. int nWidth = m_rectKLineCenter.Width();
  1194. int nCount = nWidth / m_nThickness;
  1195. if( nCount <= 0 )
  1196. return FALSE;
  1197. if( kdata.GetSize() == 0 )
  1198. {
  1199. m_nIndexCurrent = m_nIndexStart = m_nIndexEnd = -1;
  1200. return FALSE;
  1201. }
  1202. // Check Old Values
  1203. ASSERT( m_nIndexStart <= m_nIndexEnd );
  1204. ASSERT( m_nIndexCurrent < 0 || (m_nIndexCurrent >= m_nIndexStart && m_nIndexCurrent <= m_nIndexEnd) );
  1205. if( m_nIndexCurrent >= 0 && (m_nIndexCurrent < m_nIndexStart || m_nIndexCurrent > m_nIndexEnd) )
  1206. m_nIndexCurrent = -1;
  1207. if( -1 == m_nIndexStart || -1 == m_nIndexEnd )
  1208. {
  1209. m_nIndexEnd = kdata.GetSize()-1;
  1210. }
  1211. else if( m_nIndexEnd - m_nIndexStart + 1 < nCount )
  1212. {
  1213. // Reset m_nIndexStart and m_nIndexEnd
  1214. int nExpand = nCount-(m_nIndexEnd-m_nIndexStart+1);
  1215. if( m_nIndexCurrent >= 0 && m_nIndexEnd-m_nIndexStart > 0 )
  1216. m_nIndexEnd += (m_nIndexEnd-m_nIndexCurrent)*nExpand / (m_nIndexEnd-m_nIndexStart);
  1217. }
  1218. else if( m_nIndexEnd - m_nIndexStart + 1 > nCount )
  1219. {
  1220. int nReduce = (m_nIndexEnd-m_nIndexStart+1)-nCount;
  1221. if( m_nIndexCurrent >= 0 && m_nIndexEnd-m_nIndexStart > 0 )
  1222. m_nIndexEnd -= (m_nIndexEnd-m_nIndexCurrent)*nReduce / (m_nIndexEnd-m_nIndexStart);
  1223. }
  1224. if( m_nIndexEnd >= kdata.GetSize() )
  1225. m_nIndexEnd = kdata.GetSize()-1;
  1226. m_nIndexStart = m_nIndexEnd - nCount + 1;
  1227. if( m_nIndexStart < 0 )
  1228. {
  1229. m_nIndexEnd += (-m_nIndexStart);
  1230. m_nIndexStart = 0;
  1231. }
  1232. if( m_nIndexEnd >= kdata.GetSize() )
  1233. m_nIndexEnd = kdata.GetSize()-1;
  1234. ASSERT( m_nIndexStart <= m_nIndexEnd );
  1235. ASSERT( m_nIndexCurrent < 0 || (m_nIndexCurrent >= m_nIndexStart && m_nIndexCurrent <= m_nIndexEnd) );
  1236. if( m_nIndexStart > m_nIndexEnd )
  1237. return FALSE;
  1238. if( m_nIndexCurrent >= 0 && (m_nIndexCurrent < m_nIndexStart || m_nIndexCurrent > m_nIndexEnd) )
  1239. m_nIndexCurrent = -1;
  1240. return TRUE;
  1241. }
  1242. void CStockGraph::DrawNoDataInfo( CDC * pDC )
  1243. {
  1244. DECLARE_COLOR_DEFINATION
  1245. CKData & kdata = m_CurStock.GetKData(m_nCurKType);
  1246. if( 0 == kdata.GetSize() )
  1247. {
  1248. CString strNoKData, strTemp;
  1249. strNoKData.LoadString( IDS_STOCKGRAPH_NOKDATA );
  1250. strTemp = CString(m_CurStock.GetStockInfo().GetStockName()) + "(" + m_CurStock.GetStockInfo().GetStockCode() + ")";
  1251. strTemp += (LPCTSTR)AfxGetKTypeString( m_nCurKType );
  1252. strNoKData = strTemp + strNoKData;
  1253. CFont * pOldFont = AfxSelectDCFont( pDC, 14 );
  1254. pDC->SetBkColor( clrBK );
  1255. pDC->SetTextColor( clrTitle );
  1256. pDC->TextOut( m_rectAll.left+20, m_rectAll.top+20,  strNoKData );
  1257. pDC->SelectObject( pOldFont );
  1258. }
  1259. }
  1260. void CStockGraph::DrawDateAxis( CDC * pDC )
  1261. {
  1262. CHECK_NODATATODRAW
  1263. DECLARE_COLOR_DEFINATION
  1264. CRect rect = m_rectCenter;
  1265. rect.top = m_rectAll.bottom - m_nMarginBottom + 1;
  1266. pDC->FillSolidRect( &rect, clrBK );
  1267. pDC->SetBkColor( clrBK );
  1268. pDC->SetTextColor( clrDJ );
  1269. CKData & kdata = m_CurStock.GetKData( m_nCurKType );
  1270. BOOL bDayOrMin = CKData::IsDayOrMin(m_nCurKType);
  1271. int y = m_rectAll.bottom - m_nMarginBottom + 2;
  1272. CFont * pOldFont = AfxSelectDCFont( pDC, 12 );
  1273. int xLast = 0;
  1274. for( int k=m_nIndexStart; k<=m_nIndexEnd; k++ )
  1275. {
  1276. if( k > 0 && k < kdata.GetSize() )
  1277. {
  1278. CSPTime sptimeLast, sptime;
  1279. if( sptimeLast.FromStockTime( kdata.ElementAt(k-1).m_date, bDayOrMin )
  1280. && sptime.FromStockTime( kdata.ElementAt(k).m_date, bDayOrMin ) )
  1281. {
  1282. CString strText;
  1283. if( (CKData::ktypeDay == m_nCurKType )
  1284. && (sptimeLast.GetMonth() != sptime.GetMonth()) )
  1285. strText = sptime.Format( "%m" );
  1286. else if( (CKData::ktypeWeek == m_nCurKType || CKData::ktypeMonth == m_nCurKType)
  1287. && (sptimeLast.GetYear() != sptime.GetYear()) )
  1288. strText = sptime.Format( "%y" );
  1289. else if( !CKData::IsDayOrMin(m_nCurKType)
  1290. && (sptimeLast.GetDay() != sptime.GetDay()) )
  1291. strText = sptime.Format( "%d" );
  1292. CRect rectK;
  1293. if( strText.GetLength() > 0 && GetOneKLineRect( k, &rectK, NULL, NULL, NULL ) && xLast < rectK.left )
  1294. {
  1295. pDC->TextOut( rectK.left, y, strText );
  1296. xLast = rectK.left + pDC->GetTextExtent(strText).cx;
  1297. }
  1298. }
  1299. }
  1300. }
  1301. pDC->SelectObject( pOldFont );
  1302. }
  1303. void CStockGraph::DrawKLine(CDC * pDC )
  1304. {
  1305. DECLARE_COLOR_DEFINATION
  1306. CKData & kdata = m_CurStock.GetKData(m_nCurKType);
  1307. pDC->FillSolidRect( &m_rectKLine, clrBK );
  1308. pDC->Draw3dRect( &m_rectKLine, clrBorder, clrBorder );
  1309. // Draw Title
  1310. CString strTitle;
  1311. pDC->SetTextColor( clrTitle );
  1312. pDC->SetBkColor( clrBK );
  1313. strTitle = AfxGetKTypeString( m_nCurKType );
  1314. pDC->TextOut( m_rectAll.left+8, m_rectAll.top+2, strTitle );
  1315. strTitle.LoadString( IDS_STOCKGRAPH_KLINE );
  1316. pDC->TextOut( m_rectKLine.left+1, m_rectAll.top+2, strTitle );
  1317. double dMin = 0, dMax = 0;
  1318. if( ! GetKLineMinMaxInfo( m_nIndexStart, m_nIndexEnd, &dMin, &dMax ) )
  1319. return;
  1320. m_dMaxPrice = dMax;
  1321. m_dMinPrice = dMin;
  1322. // Draw Axis
  1323. DrawAxis( pDC, m_rectKLine, m_nHeightSubtitle, 3, dMin, dMax, TRUE, TRUE, 2 );
  1324. // KLine Attribute Rect
  1325. CRect rectKLineAttrib = m_rectKLineCenter;
  1326. rectKLineAttrib.top -= m_nHeightSubtitle;
  1327. // Draw STT_DJ and STT_CW
  1328. CSPDWordArray & anTech = AfxGetProfile().GetGraphTechsKLine( );
  1329. for( int k=0; k<anTech.GetSize(); k++ )
  1330. if( STT_DJ == anTech[k] || STT_CW == anTech[k] )
  1331. DrawKLineAttribute( pDC, anTech[k], rectKLineAttrib, FALSE, dMin, dMax );
  1332. // Draw K Line
  1333. for( k=m_nIndexStart; k<=m_nIndexEnd; k++ )
  1334. {
  1335. DrawOneKLine( pDC, k, k, &kdata, dMin, dMax, FALSE );
  1336. }
  1337. // Draw Tech KLine except STT_DJ and STT_CW
  1338. for( k=0; k<anTech.GetSize(); k++ )
  1339. if( STT_DJ != anTech[k] && STT_CW != anTech[k] )
  1340. DrawKLineAttribute( pDC, anTech[k], rectKLineAttrib, FALSE, dMin, dMax );
  1341. if( anTech.GetSize() > 0 )
  1342. DrawKLineAttribute( pDC, anTech[0], rectKLineAttrib, TRUE, dMin, dMax );
  1343. // Draw Select Line
  1344. DrawSelectionLine( pDC, TRUE );
  1345. }
  1346. BOOL CStockGraph::GetKLineMinMaxInfo( int nStart, int nEnd, double * pdMin, double * pdMax )
  1347. {
  1348. CKData & kdata = m_CurStock.GetKData(m_nCurKType);
  1349. CKLine kline( &kdata );
  1350. double dMin = 0, dMax = 0, dMinTemp = 0, dMaxTemp = 0;
  1351. if( nStart < 0 || nEnd < 0 || ! kline.GetMinMaxInfo( nStart, nEnd, &dMin, &dMax ) )
  1352. return FALSE;
  1353. CSPDWordArray & anTech = AfxGetProfile().GetGraphTechsKLine( );
  1354. for( int k=0; k<anTech.GetSize(); k++ )
  1355. {
  1356. UINT nTech = anTech[k];
  1357. switch( nTech )
  1358. {
  1359. case STT_MA:
  1360. {
  1361. CMA ma( &kdata ); 
  1362. if( ma.GetMinMaxInfo( nStart, nEnd, &dMinTemp, &dMaxTemp ) )
  1363. {
  1364. if( dMinTemp < dMin ) dMin = dMinTemp;
  1365. if( dMaxTemp > dMax ) dMax = dMaxTemp;
  1366. }
  1367. }
  1368. break;
  1369. case STT_BBI:
  1370. {
  1371. CBBI bbi( &kdata ); 
  1372. if( bbi.GetMinMaxInfo( nStart, nEnd, &dMinTemp, &dMaxTemp ) )
  1373. {
  1374. if( dMinTemp < dMin ) dMin = dMinTemp;
  1375. if( dMaxTemp > dMax ) dMax = dMaxTemp;
  1376. }
  1377. }
  1378. break;
  1379. case STT_BOLL:
  1380. {
  1381. CBOLL boll( &kdata ); 
  1382. if( boll.GetMinMaxInfo( nStart, nEnd, &dMinTemp, &dMaxTemp ) )
  1383. {
  1384. if( dMinTemp < dMin ) dMin = dMinTemp;
  1385. if( dMaxTemp > dMax ) dMax = dMaxTemp;
  1386. }
  1387. }
  1388. break;
  1389. case STT_PV:
  1390. {
  1391. CPV pv( &kdata ); 
  1392. if( pv.GetMinMaxInfo( nStart, nEnd, &dMinTemp, &dMaxTemp ) )
  1393. {
  1394. if( dMinTemp < dMin ) dMin = dMinTemp;
  1395. if( dMaxTemp > dMax ) dMax = dMaxTemp;
  1396. }
  1397. }
  1398. break;
  1399. case STT_SAR:
  1400. {
  1401. CSAR sar( &kdata ); 
  1402. if( sar.GetMinMaxInfo( nStart, nEnd, &dMinTemp, &dMaxTemp ) )
  1403. {
  1404. if( dMinTemp < dMin ) dMin = dMinTemp;
  1405. if( dMaxTemp > dMax ) dMax = dMaxTemp;
  1406. }
  1407. }
  1408. break;
  1409. case STT_DJ:
  1410. case STT_CW:
  1411. break;
  1412. default:;
  1413. ASSERT( FALSE );
  1414. }
  1415. }
  1416. if( pdMin )
  1417. *pdMin = dMin;
  1418. if( pdMax )
  1419. *pdMax = dMax;
  1420. return TRUE;
  1421. }
  1422. void CStockGraph::DrawOneKLine(CDC * pDC, int nIndexPos, int nIndexKD, CKData * pKData, double dMin, double dMax, BOOL bGreyed )
  1423. {
  1424. DECLARE_COLOR_DEFINATION
  1425. // Check Valid
  1426. ASSERT( pDC && nIndexPos >= m_nIndexStart && nIndexPos <= m_nIndexEnd && nIndexPos >= 0 );
  1427. if( !(pDC && nIndexPos >= m_nIndexStart && nIndexPos <= m_nIndexEnd && nIndexPos >= 0) )
  1428. return;
  1429. if( !pKData || nIndexKD < 0 || nIndexKD >= pKData->GetSize() )
  1430. return;
  1431. if( dMax-dMin < 1e-4 )
  1432. return;
  1433. // Get Region
  1434. CRect rectK, rcEntity;
  1435. long xMedium = 0;
  1436. if( !GetOneKLineRect( nIndexPos, &rectK, &rcEntity.left, &rcEntity.right, &xMedium ) )
  1437. return;
  1438. int xStart = rectK.left;
  1439. int xEnd = rectK.right;
  1440. ASSERT( xEnd <= m_rectKLineCenter.right );
  1441. if( xEnd > m_rectKLineCenter.right )
  1442. return;
  1443. KDATA kd = pKData->ElementAt(nIndexKD);
  1444. // Set rcEntity's top and bottom, set yLow, yHigh
  1445. int yLow = int( m_rectKLineCenter.bottom - m_rectKLineCenter.Height() * (kd.m_fLow - dMin) / (dMax-dMin) );
  1446. int yHigh = int( m_rectKLineCenter.bottom - m_rectKLineCenter.Height() * (kd.m_fHigh - dMin) / (dMax-dMin) );
  1447. int yOpen = int( m_rectKLineCenter.bottom - m_rectKLineCenter.Height() * (kd.m_fOpen - dMin) / (dMax-dMin) );
  1448. int yClose = int( m_rectKLineCenter.bottom - m_rectKLineCenter.Height() * (kd.m_fClose - dMin) / (dMax-dMin) );
  1449. rcEntity.top = min( yOpen, yClose );
  1450. rcEntity.bottom = max( yOpen, yClose ) + 1;
  1451. if( CStockGraph::klineCandle == m_nCurKLineMode )
  1452. {
  1453. // Draw Entity
  1454. COLORREF clr = clrRise;
  1455. if( kd.m_fClose < kd.m_fOpen )
  1456. clr = clrFallEntity;
  1457. if( kd.m_date > m_dwLatestDate )
  1458. clr = clrNewKLine;
  1459. if( bGreyed )
  1460. clr = clrDJ;
  1461. pDC->SetBkColor( clrBK );
  1462. if( kd.m_fClose < kd.m_fOpen )
  1463. pDC->FillSolidRect( &rcEntity, clr );
  1464. else
  1465. pDC->Draw3dRect( &rcEntity, clr, clr );
  1466. // Draw Line
  1467. CPen pen( PS_SOLID, 1, clr );
  1468. CPen *pOldPen = pDC->SelectObject( &pen );
  1469. pDC->MoveTo( xMedium, yHigh );
  1470. pDC->LineTo( xMedium, rcEntity.top );
  1471. pDC->MoveTo( xMedium, rcEntity.bottom );
  1472. pDC->LineTo( xMedium, yLow );
  1473. pDC->SelectObject( pOldPen );
  1474. }
  1475. else if( CStockGraph::klineAmerica == m_nCurKLineMode )
  1476. {
  1477. // Draw Entity
  1478. COLORREF clr = clrRise;
  1479. if( kd.m_date > m_dwLatestDate )
  1480. clr = clrNewKLine;
  1481. if( bGreyed )
  1482. clr = clrDJ;
  1483. pDC->SetBkColor( clrBK );
  1484. // Draw Line
  1485. CPen pen( PS_SOLID, 1, clr );
  1486. CPen *pOldPen = pDC->SelectObject( &pen );
  1487. pDC->MoveTo( xStart, yHigh );
  1488. pDC->LineTo( xStart, yLow );
  1489. pDC->MoveTo( xStart, yClose );
  1490. pDC->LineTo( xEnd, yClose );
  1491. pDC->SelectObject( pOldPen );
  1492. }
  1493. else if( CStockGraph::klineTower == m_nCurKLineMode )
  1494. {
  1495. /*
  1496. 在起步股價和當日收盤價之間畫線,股價上漲時,畫紅色空心實體,股價下跌時,畫綠色實心實體。
  1497. 若前一交易日是上漲紅線,而次日下跌,股價未跌破前一天紅線低點的那一部分跌幅仍畫紅線,跌破部分畫綠線。
  1498. 若前一交易日為下跌綠線,而次日上漲,股價未漲過前一天綠線低點的那一部分漲幅仍畫綠色實體,漲過部分才畫紅線。
  1499. */
  1500. // Draw Entity
  1501. COLORREF clr = clrRise;
  1502. if( kd.m_fClose < kd.m_fOpen )
  1503. clr = clrFallEntity;
  1504. if( kd.m_date > m_dwLatestDate )
  1505. clr = clrNewKLine;
  1506. if( bGreyed )
  1507. clr = clrDJ;
  1508. pDC->SetBkColor( clrBK );
  1509. if( kd.m_fClose < kd.m_fOpen )
  1510. pDC->FillSolidRect( &rcEntity, clr );
  1511. else
  1512. pDC->Draw3dRect( &rcEntity, clr, clr );
  1513. if( nIndexKD > 0 )
  1514. {
  1515. KDATA kdLast = pKData->ElementAt(nIndexKD-1);
  1516. int yOpenLast = int( m_rectKLineCenter.bottom - m_rectKLineCenter.Height() * (kdLast.m_fOpen - dMin) / (dMax-dMin) );
  1517. int yCloseLast = int( m_rectKLineCenter.bottom - m_rectKLineCenter.Height() * (kdLast.m_fClose - dMin) / (dMax-dMin) );
  1518. if( kdLast.m_fClose > kdLast.m_fOpen && kd.m_fClose < kd.m_fOpen )
  1519. {
  1520. rcEntity.bottom = min(yOpenLast,rcEntity.bottom);
  1521. if( rcEntity.bottom > rcEntity.top )
  1522. {
  1523. pDC->FillSolidRect( &rcEntity, clrBK );
  1524. clr = clrRise;
  1525. if( kd.m_date > m_dwLatestDate )
  1526. clr = clrNewKLine;
  1527. if( bGreyed )
  1528. clr = clrDJ;
  1529. pDC->Draw3dRect( &rcEntity, clr, clr );
  1530. }
  1531. }
  1532. else if( kdLast.m_fClose < kdLast.m_fOpen && kd.m_fClose > kd.m_fOpen )
  1533. {
  1534. rcEntity.top = max(yOpenLast,rcEntity.top);
  1535. if( rcEntity.bottom > rcEntity.top )
  1536. {
  1537. clr = clrFallEntity;
  1538. if( kd.m_date > m_dwLatestDate )
  1539. clr = clrNewKLine;
  1540. if( bGreyed )
  1541. clr = clrDJ;
  1542. pDC->FillSolidRect( &rcEntity, clr );
  1543. }
  1544. }
  1545. }
  1546. }
  1547. }
  1548. void CStockGraph::DrawBorderMovingLine( CDC * pDC, CPoint point, BOOL bAddOrRemove )
  1549. {
  1550. ASSERT( m_pParent && ::IsWindow( m_pParent->GetSafeHwnd() ) );
  1551. if( !m_pParent || !::IsWindow(m_pParent->GetSafeHwnd()) )
  1552. return;
  1553. CClientDC dc(m_pParent);
  1554. if( NULL == pDC )
  1555. pDC = &dc;
  1556. CPen penLine( PS_SOLID, 1, AfxGetProfile().GetColor( CColorClass::clrBorder ) );
  1557. CPen * pOldPen = pDC->SelectObject( &penLine );
  1558. int nOldDrawMode = pDC->SetROP2( R2_XORPEN );
  1559. pDC->MoveTo( m_rectKLine.left-5, point.y );
  1560. pDC->LineTo( m_rectKLine.right+5, point.y );
  1561. pDC->SetROP2( nOldDrawMode );
  1562. pDC->SelectObject( pOldPen );
  1563. }
  1564. void CStockGraph::DrawSelectionLine( CDC * pDC, BOOL bAddOrRemove )
  1565. {
  1566. ASSERT( m_pParent && ::IsWindow( m_pParent->GetSafeHwnd() ) );
  1567. if( !m_pParent || !::IsWindow(m_pParent->GetSafeHwnd()) )
  1568. return;
  1569. CClientDC dc(m_pParent);
  1570. if( NULL == pDC )
  1571. pDC = &dc;
  1572. CPen penVLine( PS_SOLID, 1, AfxGetProfile().GetColor( CColorClass::clrLine1 ) );
  1573. CPen * pOldPen = pDC->SelectObject( &penVLine );
  1574. int nOldDrawMode = pDC->SetROP2( R2_XORPEN );
  1575. CRect rectK;
  1576. long xMedium = 0;
  1577. if( GetOneKLineRect( m_nIndexCurrent, &rectK, NULL, NULL, &xMedium ) )
  1578. {
  1579. pDC->MoveTo( xMedium, m_rectCenter.bottom );
  1580. pDC->LineTo( xMedium, m_rectKLineCenter.top );
  1581. }
  1582. for( int k=0; k<m_anIndexCurrent.GetSize(); k++ )
  1583. {
  1584. if( ((int)m_anIndexCurrent[k]) == m_nIndexCurrent )
  1585. continue;
  1586. if( GetOneKLineRect( m_anIndexCurrent[k], &rectK, NULL, NULL, &xMedium ) )
  1587. {
  1588. pDC->MoveTo( xMedium, m_rectKLineCenter.bottom );
  1589. pDC->LineTo( xMedium, m_rectKLineCenter.top );
  1590. }
  1591. }
  1592. pDC->SetROP2( nOldDrawMode );
  1593. pDC->SelectObject( pOldPen );
  1594. }
  1595. void CStockGraph::DrawSelectionRect( CDC * pDC, CPoint ptBegin, CPoint ptEnd, BOOL bAddOrRemove )
  1596. {
  1597. ASSERT( m_pParent && ::IsWindow( m_pParent->GetSafeHwnd() ) );
  1598. if( !m_pParent || !::IsWindow(m_pParent->GetSafeHwnd()) )
  1599. return;
  1600. CClientDC dc(m_pParent);
  1601. if( NULL == pDC )
  1602. pDC = &dc;
  1603. CPen penVLine( PS_SOLID, 1, AfxGetProfile().GetColor( CColorClass::clrLine2 ) );
  1604. CPen * pOldPen = pDC->SelectObject( &penVLine );
  1605. int nOldDrawMode = pDC->SetROP2( R2_XORPEN );
  1606. CRect rect;
  1607. rect.left = min(ptBegin.x,ptEnd.x);
  1608. rect.right = max(ptBegin.x,ptEnd.x);
  1609. rect.top = min(ptBegin.y,ptEnd.y);
  1610. rect.bottom = max(ptBegin.y,ptEnd.y);
  1611. pDC->MoveTo( rect.left, rect.top );
  1612. pDC->LineTo( rect.right, rect.top );
  1613. pDC->LineTo( rect.right, rect.bottom );
  1614. pDC->LineTo( rect.left, rect.bottom );
  1615. pDC->LineTo( rect.left, rect.top );
  1616. pDC->SetROP2( nOldDrawMode );
  1617. pDC->SelectObject( pOldPen );
  1618. }
  1619. void CStockGraph::DrawKData( )
  1620. {
  1621. if( !::IsWindow( m_wndKData.GetSafeHwnd() ) )
  1622. {
  1623. if( !m_wndKData.Create( NULL, "", WS_CHILD, m_rectKData, m_pParent, 0 ) )
  1624. {
  1625. TRACE( "Failed to create m_wndKData!n" );
  1626. return;
  1627. }
  1628. m_wndKData.SetWindowPos( NULL, m_rectKData.left, m_rectKData.top, m_rectKData.Width(), m_rectKData.Height(),
  1629. SWP_SHOWWINDOW );
  1630. }
  1631. CClientDC dc(&m_wndKData);
  1632. CRect rectClient;
  1633. m_wndKData.GetClientRect( &rectClient );
  1634. CKData &kdata = m_CurStock.GetKData(m_nCurKType);
  1635. if( m_nIndexCurrent >= 0 && m_nIndexCurrent < kdata.GetSize() )
  1636. {
  1637. m_wndKData.SetWindowPos( NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW );
  1638. m_wndKData.ValidateRect( &rectClient );
  1639. DrawKData( &dc, rectClient );
  1640. m_wndKData.ValidateRect( &rectClient );
  1641. }
  1642. else
  1643. m_wndKData.SetWindowPos( NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW );
  1644. }
  1645. void CStockGraph::DrawKData( CDC * pDC, CRect rect )
  1646. {
  1647. CHECK_NODATATODRAW
  1648. DECLARE_COLOR_DEFINATION
  1649. CStockInfo & info = m_CurStock.GetStockInfo();
  1650. CKData &kdata = m_CurStock.GetKData( m_nCurKType );
  1651. CKData &kdataDown = m_CurStockDown.GetKData( m_nCurKType );
  1652. // Prepare kd and fLastClose
  1653. KDATA kd;
  1654. memset( &kd, 0, sizeof(kd) );
  1655. float fLastClose = 0;
  1656. double dAmount = 0, dVolume = 0, dPriceAverage = 0, dRatioChangeHand = 0, dVolumeDown = 0;
  1657. if( m_anIndexCurrent.GetSize() > 0 
  1658. && (int)m_anIndexCurrent[0] < kdata.GetSize() && (int)m_anIndexCurrent[m_anIndexCurrent.GetSize()-1] < kdata.GetSize() )
  1659. {
  1660. int nStart = m_anIndexCurrent[0];
  1661. int nEnd = m_anIndexCurrent[m_anIndexCurrent.GetSize()-1];
  1662. kd.m_date = kdata.ElementAt(nStart).m_date;
  1663. kd.m_fOpen = kdata.ElementAt(nStart).m_fOpen;
  1664. kd.m_fLow = kdata.ElementAt(nStart).m_fLow;
  1665. kd.m_fClose = kdata.ElementAt(nEnd).m_fClose;
  1666. for( int k=0; k<m_anIndexCurrent.GetSize() && (int)m_anIndexCurrent[k]<kdata.GetSize(); k++ )
  1667. {
  1668. KDATA & kdTemp = kdata.ElementAt(m_anIndexCurrent[k]);
  1669. if( (int)m_anIndexCurrent[k] < nStart )
  1670. {
  1671. kd.m_fOpen = kdTemp.m_fOpen;
  1672. kd.m_date = kdTemp.m_date;
  1673. nStart = m_anIndexCurrent[k];
  1674. }
  1675. if( (int)m_anIndexCurrent[k] > nEnd )
  1676. {
  1677. kd.m_fClose= kdTemp.m_fClose;
  1678. nEnd = m_anIndexCurrent[k];
  1679. }
  1680. if( kd.m_fHigh < kdTemp.m_fHigh )
  1681. kd.m_fHigh = kdTemp.m_fHigh;
  1682. if( kd.m_fLow > kdTemp.m_fLow )
  1683. kd.m_fLow = kdTemp.m_fLow;
  1684. dAmount += kdTemp.m_fAmount;
  1685. dVolume += kdTemp.m_fVolume;
  1686. if( (int)m_anIndexCurrent[k] < kdataDown.GetSize() )
  1687. dVolumeDown += kdataDown.ElementAt(m_anIndexCurrent[k]).m_fVolume;
  1688. }
  1689. fLastClose = kd.m_fOpen;
  1690. if( nStart - 1 >= 0 )
  1691. fLastClose = kdata.ElementAt(nStart-1).m_fClose;
  1692. }
  1693. else if( m_nIndexCurrent >= 0 && m_nIndexCurrent < kdata.GetSize() )
  1694. {
  1695. kd = kdata.ElementAt(m_nIndexCurrent);
  1696. dAmount = kd.m_fAmount;
  1697. dVolume = kd.m_fVolume;
  1698. if( m_nIndexCurrent < kdataDown.GetSize() )
  1699. dVolumeDown += kdataDown.ElementAt(m_nIndexCurrent).m_fVolume;
  1700. fLastClose = kd.m_fOpen;
  1701. if( m_nIndexCurrent - 1 >= 0 )
  1702. fLastClose = kdata.ElementAt(m_nIndexCurrent-1).m_fClose;
  1703. }
  1704. else
  1705. return;
  1706. if( dVolume >= 1 )
  1707. dPriceAverage = dAmount / dVolume;
  1708. m_CurStockDown.GetStockInfo().GetRatioChangeHand( &dRatioChangeHand, dVolumeDown );
  1709. // 相对换手率
  1710. double dMainChangeHand = CHSL::GetMainChangeHand( m_CurStockDown.GetStockInfo().GetMarket(), kdataDown, m_nIndexCurrent );
  1711. double dRelativeChangeHand = 1.0;
  1712. if( dMainChangeHand > 1e-6 )
  1713. dRelativeChangeHand = dRatioChangeHand / dMainChangeHand;
  1714. // Fill Background
  1715. pDC->FillSolidRect( &rect, clrBK );
  1716. pDC->Draw3dRect( &rect, clrBorder, clrBorder );
  1717. pDC->SetBkColor( clrBK );
  1718. CString strTemp;
  1719. CFont * pOldFont = AfxSelectDCFont( pDC, 14 );
  1720. int x = rect.left + 1;
  1721. int y = rect.top;
  1722. pDC->SetTextColor( clrText );
  1723. strTemp.LoadString( IDS_STOCKGRAPH_TIME );
  1724. pDC->TextOut( x, y+2,   strTemp );
  1725. strTemp.LoadString( IDS_STOCKGRAPH_OPEN );
  1726. pDC->TextOut( x, y+37,  strTemp );
  1727. strTemp.LoadString( IDS_STOCKGRAPH_HIGH );
  1728. pDC->TextOut( x, y+71,  strTemp );
  1729. strTemp.LoadString( IDS_STOCKGRAPH_LOW );
  1730. pDC->TextOut( x, y+105, strTemp );
  1731. strTemp.LoadString( IDS_STOCKGRAPH_CLOSE );
  1732. pDC->TextOut( x, y+139, strTemp );
  1733. strTemp.LoadString( IDS_STOCKGRAPH_VOLUME );
  1734. pDC->TextOut( x, y+173, strTemp );
  1735. strTemp.LoadString( IDS_STOCKGRAPH_AMOUNT );
  1736. pDC->TextOut( x, y+207, strTemp );
  1737. strTemp.LoadString( IDS_STOCKGRAPH_PRICEAVERAGE );
  1738. pDC->TextOut( x, y+241, strTemp );
  1739. strTemp.LoadString( IDS_STOCKGRAPH_RELATIVECHANGEHAND );
  1740. pDC->TextOut( x, y+275, strTemp );
  1741. x = rect.right - 3;
  1742. UINT nOldAlign = pDC->SetTextAlign( TA_RIGHT | TA_TOP );
  1743. CSPTime sptime;
  1744. if( CKData::IsDayOrMin( m_nCurKType ) )
  1745. {
  1746. sptime.FromStockTimeDay( kd.m_date );
  1747. strTemp = sptime.Format( "%y-%m-%d" );
  1748. }
  1749. else
  1750. {
  1751. sptime.FromStockTimeMin( kd.m_date );
  1752. strTemp = sptime.Format( "%m%d%H%M" );
  1753. }
  1754. pDC->SetTextColor( clrPlane );
  1755. pDC->TextOut( x, y+18, strTemp );
  1756. // 价格小数位数格式串
  1757. CString strPriceFmt;
  1758. strPriceFmt.Format( "%%.%df", info.DigitBit() );
  1759. strTemp.Format( strPriceFmt, kd.m_fOpen );
  1760. pDC->SetTextColor( kd.m_fOpen > fLastClose ? clrRise : (kd.m_fOpen<fLastClose?clrFall:clrPlane) );
  1761. pDC->TextOut( x, y+53, strTemp );
  1762. strTemp.Format( strPriceFmt, kd.m_fHigh );
  1763. pDC->SetTextColor( kd.m_fHigh > fLastClose ? clrRise : (kd.m_fHigh<fLastClose?clrFall:clrPlane) );
  1764. pDC->TextOut( x, y+87, strTemp );
  1765. strTemp.Format( strPriceFmt, kd.m_fLow );
  1766. pDC->SetTextColor( kd.m_fLow > fLastClose ? clrRise : (kd.m_fLow<fLastClose?clrFall:clrPlane) );
  1767. pDC->TextOut( x, y+121, strTemp );
  1768. strTemp.Format( strPriceFmt, kd.m_fClose );
  1769. pDC->SetTextColor( kd.m_fClose > fLastClose ? clrRise : (kd.m_fClose<fLastClose?clrFall:clrPlane) );
  1770. pDC->TextOut( x, y+155, strTemp );
  1771. strTemp.Format( "%.0f", dVolume/100 );
  1772. pDC->SetTextColor( clrTitle );
  1773. pDC->TextOut( x, y+189, strTemp );
  1774. strTemp.Format( "%.0f", dAmount/1000 );
  1775. pDC->SetTextColor( clrTitle );
  1776. pDC->TextOut( x, y+223, strTemp );
  1777. strTemp.Format( strPriceFmt, dPriceAverage );
  1778. pDC->SetTextColor( clrTitle );
  1779. pDC->TextOut( x, y+257, strTemp );
  1780. strTemp.Format( "%.2f", dRelativeChangeHand );
  1781. pDC->SetTextColor( clrTitle );
  1782. pDC->TextOut( x, y+291, strTemp );
  1783. pDC->SetTextAlign( nOldAlign );
  1784. pDC->SelectObject( pOldFont );
  1785. }
  1786. void CStockGraph::DrawTechLine(CDC * pDC )
  1787. {
  1788. CSPDWordArray & anShow = AfxGetProfile().GetGraphTechsShow( );
  1789. for( int k=0; k<m_arcTech.GetSize(); k++ )
  1790. {
  1791. CRect rect = m_arcTech.ElementAt(k);
  1792. if( k < anShow.GetSize() )
  1793. {
  1794. DrawTechLine( pDC, anShow[k], rect, FALSE );
  1795. DrawTechLine( pDC, anShow[k], rect, TRUE );
  1796. }
  1797. }
  1798. }
  1799. void CStockGraph::DrawKLineAttribute(CDC * pDC, UINT nTech, CRect rect, BOOL bDrawTitle, double dMin, double dMax )
  1800. {
  1801. switch( nTech )
  1802. {
  1803. case STT_MA: DrawTechMA( pDC, rect, bDrawTitle, dMin, dMax ); break;
  1804. case STT_BBI: DrawTechBBI( pDC, rect, bDrawTitle, dMin, dMax ); break;
  1805. case STT_BOLL: DrawTechBOLL( pDC, rect, bDrawTitle, dMin, dMax ); break;
  1806. case STT_PV: DrawTechPV( pDC, rect, bDrawTitle, dMin, dMax ); break;
  1807. case STT_SAR: DrawTechSAR( pDC, rect, bDrawTitle, dMin, dMax ); break;
  1808. case STT_DJ: DrawTechDJ( pDC, rect, bDrawTitle, dMin, dMax ); break;
  1809. case STT_CW: DrawTechCW( pDC, rect, bDrawTitle, dMin, dMax ); break;
  1810. default:;
  1811. ASSERT( FALSE );
  1812. }
  1813. }
  1814. void CStockGraph::DrawTechLine(CDC * pDC, UINT nTech, CRect rect, BOOL bDrawTitle )
  1815. {
  1816. DECLARE_COLOR_DEFINATION
  1817. if( !bDrawTitle )
  1818. {
  1819. pDC->FillSolidRect( &rect, clrBK );
  1820. pDC->FillSolidRect( CRect(m_rectAll.left,rect.top,rect.left-1,rect.bottom), clrBK );
  1821. pDC->Draw3dRect( &rect, clrBorder, clrBorder );
  1822. }
  1823. switch( nTech )
  1824. {
  1825. case STT_MACD: DrawTechMACD( pDC, rect, bDrawTitle ); break;
  1826. case STT_MIKE: DrawTechMIKE( pDC, rect, bDrawTitle ); break;
  1827. case STT_PSY: DrawTechPSY( pDC, rect, bDrawTitle ); break;
  1828. case STT_VOLUME: DrawTechVOLUME( pDC, rect, bDrawTitle ); break;
  1829. case STT_NVI: DrawTechNVI( pDC, rect, bDrawTitle ); break;
  1830. case STT_PVI: DrawTechPVI( pDC, rect, bDrawTitle ); break;
  1831. case STT_VR: DrawTechVR( pDC, rect, bDrawTitle ); break;
  1832. case STT_VROC: DrawTechVROC( pDC, rect, bDrawTitle ); break;
  1833. case STT_OBV: DrawTechOBV( pDC, rect, bDrawTitle ); break;
  1834. case STT_MOBV: DrawTechMOBV( pDC, rect, bDrawTitle ); break;
  1835. case STT_MFI: DrawTechMFI( pDC, rect, bDrawTitle ); break;
  1836. case STT_VMACD: DrawTechVMACD( pDC, rect, bDrawTitle ); break;
  1837. case STT_WVAD: DrawTechWVAD( pDC, rect, bDrawTitle ); break;
  1838. case STT_EMV: DrawTechEMV( pDC, rect, bDrawTitle ); break;
  1839. case STT_VRSI: DrawTechVRSI( pDC, rect, bDrawTitle ); break;
  1840. case STT_NVRSI: DrawTechNVRSI( pDC, rect, bDrawTitle ); break;
  1841. case STT_AD: DrawTechAD( pDC, rect, bDrawTitle ); break;
  1842. case STT_CI: DrawTechCI( pDC, rect, bDrawTitle ); break;
  1843. case STT_KDJ: DrawTechKDJ( pDC, rect, bDrawTitle ); break;
  1844. case STT_R: DrawTechR( pDC, rect, bDrawTitle ); break;
  1845. case STT_RSI: DrawTechRSI( pDC, rect, bDrawTitle ); break;
  1846. case STT_BIAS: DrawTechBIAS( pDC, rect, bDrawTitle ); break;
  1847. case STT_MTM: DrawTechMTM( pDC, rect, bDrawTitle ); break;
  1848. case STT_DMI: DrawTechDMI( pDC, rect, bDrawTitle ); break;
  1849. case STT_ROC: DrawTechROC( pDC, rect, bDrawTitle ); break;
  1850. case STT_CCI: DrawTechCCI( pDC, rect, bDrawTitle ); break;
  1851. case STT_CV: DrawTechCV( pDC, rect, bDrawTitle ); break;
  1852. case STT_ARBR: DrawTechARBR( pDC, rect, bDrawTitle ); break;
  1853. case STT_CR: DrawTechCR( pDC, rect, bDrawTitle ); break;
  1854. case STT_OSC: DrawTechOSC( pDC, rect, bDrawTitle ); break;
  1855. case STT_UOS: DrawTechUOS( pDC, rect, bDrawTitle ); break;
  1856. case STT_MAOSC: DrawTechMAOSC( pDC, rect, bDrawTitle ); break;
  1857. case STT_36BIAS: DrawTech3_6BIAS( pDC, rect, bDrawTitle ); break;
  1858. case STT_DPO: DrawTechDPO( pDC, rect, bDrawTitle ); break;
  1859. case STT_KST: DrawTechKST( pDC, rect, bDrawTitle ); break;
  1860. case STT_REI: DrawTechREI( pDC, rect, bDrawTitle ); break;
  1861. case STT_DMKI: DrawTechDMKI( pDC, rect, bDrawTitle ); break;
  1862. case STT_PCNT: DrawTechPCNT( pDC, rect, bDrawTitle ); break;
  1863. case STT_HLC: DrawTechHLC( pDC, rect, bDrawTitle ); break;
  1864. case STT_CDP: DrawTechCDP( pDC, rect, bDrawTitle ); break;
  1865. case STT_ASI: DrawTechASI( pDC, rect, bDrawTitle ); break;
  1866. case STT_ATR: DrawTechATR( pDC, rect, bDrawTitle ); break;
  1867. case STT_CYO: DrawTechCYO( pDC, rect, bDrawTitle ); break;
  1868. case STT_DCYO: DrawTechDCYO( pDC, rect, bDrawTitle ); break;
  1869. case STT_HSL: DrawTechHSL( pDC, rect, bDrawTitle ); break;
  1870. case STT_DPER: DrawTechDPER( pDC, rect, bDrawTitle ); break;
  1871. default:
  1872. {
  1873. UINT nTechUserCount = CTechUser::GetTechUserCount();
  1874. if( nTech >= STT_USER_MIN && nTech <= STT_USER_MIN+nTechUserCount-1 )
  1875. DrawTechUser( nTech, pDC, rect, bDrawTitle );
  1876. else
  1877. ASSERT( FALSE );
  1878. }
  1879. }
  1880. }
  1881. void CStockGraph::DrawReportParam( CDC * pDC )
  1882. {
  1883. DECLARE_COLOR_DEFINATION
  1884. // Prepare Data
  1885. /* Old Version
  1886. m_CurStock.PrepareData( CStock::dataK, CKData::ktypeDay );
  1887. m_CurStock.PrepareData( CStock::dataDR );
  1888. m_CurStock.PrepareData( CStock::dataK, m_nCurKType );
  1889. CStockInfo & info = m_CurStock.GetStockInfo();
  1890. CKData & kday = m_CurStock.GetKDataDay();
  1891. CKData & kdata = m_CurStock.GetKData(m_nCurKType);
  1892. CKData & kdayMain = AfxGetStockMain().GetKDataDay();
  1893. kday.SetDRData( m_CurStock.GetDRData() );
  1894. if( kday.GetCurFormat() < CKData::formatMin
  1895. || kday.GetCurFormat() > CKData::formatMax )
  1896. return ;
  1897. kday.FullFillKData( kdayMain, FALSE );
  1898. if( CKData::formatXDRup != kday.GetCurFormat() && CKData::formatXDRdown != kday.GetCurFormat() )
  1899. kday.ChangeCurFormat( CKData::formatXDRdown, AfxGetProfile().GetAutoResumeDRBegin(), AfxGetProfile().GetAutoResumeDRLimit() );
  1900. */
  1901. CStockInfo & info = m_CurStock.GetStockInfo();
  1902. CKData & kday = m_CurStockDown.GetKDataDay();
  1903. CKData & kdata = m_CurStockDown.GetKData(m_nCurKType);
  1904. CKData & kdayMain = AfxGetStockMain().GetKDataDay();
  1905. double dValue = 0.;
  1906. DWORD dateCurrent = kdata.GetDate(m_nIndexCurrent);
  1907. DWORD dateDayCurrent = kdata.GetDateDay( m_nIndexCurrent );
  1908. int nIndexDay = kday.GetIndexByDate( dateDayCurrent );
  1909. int nIndexDayMain = kdayMain.GetIndexByDate( dateDayCurrent );
  1910. // Draw Rect
  1911. pDC->FillSolidRect( &m_rectReport, clrBK );
  1912. pDC->Draw3dRect( &m_rectReport, clrBorder, clrBorder );
  1913. pDC->SetBkColor( clrBK );
  1914. // Select Name And Code Font
  1915. CString strTemp, strFont, strTempFmt, strDay;
  1916. strDay.LoadString( IDS_STOCKGRAPH_DAY );
  1917. CFont * pOldFont = AfxSelectDCFont( pDC, 18 );
  1918. // Draw Name And Code
  1919. pDC->SetTextColor( clrTitle );
  1920. pDC->TextOut( m_rectReport.left+1, m_rectAll.top+3, m_CurStock.GetStockInfo().GetStockName() );
  1921. pDC->SetTextColor( clrText );
  1922. pDC->TextOut( m_rectReport.left+96, m_rectAll.top+3, m_CurStock.GetStockInfo().GetStockCode() );
  1923. // Select Param Font
  1924. AfxSelectDCFont( pDC, 14 );
  1925. // Draw Param Names
  1926. int x = m_rectReport.left + 6;
  1927. int y = m_rectReport.top;
  1928. pDC->SetTextColor( clrText );
  1929. strTemp.LoadString( IDS_STOCKGRAPH_TIME2 );
  1930. pDC->TextOut( x, y+5,   strTemp );
  1931. #ifdef CLKLAN_ENGLISH_US
  1932. strTempFmt.Format( "(%d)", AfxGetProfile().GetYieldAverageDays() );
  1933. #else
  1934. strTempFmt.Format( "-%d%s-", AfxGetProfile().GetYieldAverageDays(), strDay );
  1935. #endif
  1936. strTemp.LoadString( IDS_STOCKGRAPH_YIELDAVERAGE );
  1937. pDC->TextOut( x, y+30,  strTemp+strTempFmt );
  1938. strTemp.LoadString( IDS_STOCKGRAPH_YIELDSTDDEV );
  1939. pDC->TextOut( x, y+55,  strTemp+strTempFmt );
  1940. strTemp.LoadString( IDS_STOCKGRAPH_BEITE );
  1941. pDC->TextOut( x, y+80,  strTemp+strTempFmt );
  1942. strTemp.LoadString( IDS_STOCKGRAPH_XIAPU );
  1943. pDC->TextOut( x, y+105, strTemp+strTempFmt );
  1944. DrawLine( pDC, 1, clrBorder, m_rectReport.left, y+126, m_rectReport.right, y+126 );
  1945. strTempFmt.LoadString( IDS_STOCKGRAPH_CHANGEHAND );
  1946. strTemp.Format( "%s-%d", strTempFmt, 1 );
  1947. pDC->TextOut( x, y+130, strTemp );
  1948. strTemp.Format( "%s-%d", strTempFmt, 5 );
  1949. pDC->TextOut( x, y+155, strTemp );
  1950. strTemp.Format( "%s-%d", strTempFmt, 10 );
  1951. pDC->TextOut( x, y+180, strTemp );
  1952. strTemp.Format( "%s-%d", strTempFmt, 20 );
  1953. pDC->TextOut( x, y+205, strTemp );
  1954. DrawLine( pDC, 1, clrBorder, m_rectReport.left, y+226, m_rectReport.right, y+226 );
  1955. strTempFmt.LoadString( IDS_STOCKGRAPH_RATIOVOLUME );
  1956. strTemp.Format( "%s-%d", strTempFmt, 5 );
  1957. pDC->TextOut( x, y+230, strTemp );
  1958. strTemp.Format( "%s-%d", strTempFmt, 10 );
  1959. pDC->TextOut( x, y+255, strTemp );
  1960. strTemp.Format( "%s-%d", strTempFmt, 20 );
  1961. pDC->TextOut( x, y+280, strTemp );
  1962. DrawLine( pDC, 1, clrBorder, m_rectReport.left, y+301, m_rectReport.right, y+301 );
  1963. strTempFmt.LoadString( IDS_STOCKGRAPH_RS );
  1964. strTemp.Format( "%s-%d", strTempFmt, 5 );
  1965. pDC->TextOut( x, y+305, strTemp );
  1966. strTemp.Format( "%s-%d", strTempFmt, 10 );
  1967. pDC->TextOut( x, y+330, strTemp );
  1968. strTemp.Format( "%s-%d", strTempFmt, 20 );
  1969. pDC->TextOut( x, y+355, strTemp );
  1970. DrawLine( pDC, 1, clrBorder, m_rectReport.left, y+376, m_rectReport.right, y+376 );
  1971. strTemp.LoadString( IDS_STOCKGRAPH_SHARETOTAL );
  1972. pDC->TextOut( x, y+380, strTemp );
  1973. strTemp.LoadString( IDS_STOCKGRAPH_SHARECURRENCY );
  1974. pDC->TextOut( x, y+405, strTemp );
  1975. strTemp.LoadString( IDS_STOCKGRAPH_NETASSETPS );
  1976. pDC->TextOut( x, y+430, strTemp );
  1977. strTemp.LoadString( IDS_STOCKGRAPH_EPS );
  1978. pDC->TextOut( x, y+455, strTemp );
  1979. strTemp.LoadString( IDS_STOCKGRAPH_PE );
  1980. pDC->TextOut( x, y+480, strTemp );
  1981. // Draw Param Values
  1982. // Time
  1983. UINT nOldAlign = pDC->SetTextAlign( TA_RIGHT | TA_TOP );
  1984. pDC->SetTextColor( clrPlane );
  1985. x = m_rectReport.right - 5;
  1986. CSPTime sptime;
  1987. if( CKData::IsDayOrMin( m_nCurKType ) )
  1988. {
  1989. sptime.FromStockTimeDay( dateCurrent );
  1990. strTemp = sptime.Format( "%Y-%m-%d" );
  1991. }
  1992. else
  1993. {
  1994. sptime.FromStockTimeMin( dateCurrent );
  1995. strTemp = sptime.Format( "%Y-%m-%d %H:%M" );
  1996. }
  1997. pDC->TextOut( x, y+5, strTemp );
  1998. // Change Hand
  1999. strTemp = "-   ";
  2000. if( info.GetRatioChangeHand( kdata, &dValue, dateCurrent, 1) )
  2001. strTemp.Format( "%.2f%%", dValue );
  2002. pDC->TextOut( x, y+130, strTemp );
  2003. strTemp = "-   ";
  2004. if( info.GetRatioChangeHand( kdata, &dValue, dateCurrent, 5) )
  2005. strTemp.Format( "%.2f%%", dValue );
  2006. pDC->TextOut( x, y+155, strTemp );
  2007. strTemp = "-   ";
  2008. if( info.GetRatioChangeHand( kdata, &dValue, dateCurrent, 10) )
  2009. strTemp.Format( "%.2f%%", dValue );
  2010. pDC->TextOut( x, y+180, strTemp );
  2011. strTemp = "-   ";
  2012. if( info.GetRatioChangeHand( kdata, &dValue, dateCurrent, 20) )
  2013. strTemp.Format( "%.2f%%", dValue );
  2014. pDC->TextOut( x, y+205, strTemp );
  2015. // Ratio Volume
  2016. strTemp = "-   ";
  2017. if( kdata.GetRatioVolume(&dValue, dateCurrent, 5) )
  2018. strTemp.Format( "%.2f", dValue );
  2019. pDC->SetTextColor( dValue >= 1.005 ? clrRise : (dValue<0.995?clrFall:clrPlane) );
  2020. pDC->TextOut( x, y+230, strTemp );
  2021. strTemp = "-   ";
  2022. if( kdata.GetRatioVolume(&dValue, dateCurrent, 10) )
  2023. strTemp.Format( "%.2f", dValue );
  2024. pDC->SetTextColor( dValue >= 1.005 ? clrRise : (dValue<0.995?clrFall:clrPlane) );
  2025. pDC->TextOut( x, y+255, strTemp );
  2026. strTemp = "-   ";
  2027. if( kdata.GetRatioVolume(&dValue, dateCurrent, 20) )
  2028. strTemp.Format( "%.2f", dValue );
  2029. pDC->SetTextColor( dValue >= 1.005 ? clrRise : (dValue<0.995?clrFall:clrPlane) );
  2030. pDC->TextOut( x, y+280, strTemp );
  2031. // RS
  2032. strTemp = "-   ";
  2033. if( kdata.GetRS(&dValue, dateCurrent, 5) )
  2034. strTemp.Format( "%.2f%%", dValue );
  2035. pDC->SetTextColor( dValue >= 1.005 ? clrRise : (dValue<0.995?clrFall:clrPlane) );
  2036. pDC->TextOut( x, y+305, strTemp );
  2037. strTemp = "-   ";
  2038. if( kdata.GetRS(&dValue, dateCurrent, 10) )
  2039. strTemp.Format( "%.2f%%", dValue );
  2040. pDC->SetTextColor( dValue >= 1.005 ? clrRise : (dValue<0.995?clrFall:clrPlane) );
  2041. pDC->TextOut( x, y+330, strTemp );
  2042. strTemp = "-   ";
  2043. if( kdata.GetRS(&dValue, dateCurrent, 20) )
  2044. strTemp.Format( "%.2f%%", dValue );
  2045. pDC->SetTextColor( dValue >= 1.005 ? clrRise : (dValue<0.995?clrFall:clrPlane) );
  2046. pDC->TextOut( x, y+355, strTemp );
  2047. // Base Info
  2048. pDC->SetTextColor( clrPlane );
  2049. strTemp = "-   ";
  2050. if( info.m_fShare_count_total > 1e-4 )
  2051. strTemp.Format( "%.0f", info.m_fShare_count_total*0.0001 );
  2052. pDC->TextOut( x, y+380, strTemp );
  2053. strTemp = "-   ";
  2054. if( info.GetShareCurrency( &dValue ) )
  2055. strTemp.Format( "%.0f", dValue*0.0001 );
  2056. pDC->TextOut( x, y+405, strTemp );
  2057. strTemp = "-   ";
  2058. if( fabs(info.m_fNetasset_ps) > 1e-4 )
  2059. strTemp.Format( "%.2f", info.m_fNetasset_ps );
  2060. pDC->TextOut( x, y+430, strTemp );
  2061. strTemp = "-   ";
  2062. if( fabs(info.m_fEps) > 1e-4 )
  2063. strTemp.Format( "%.2f(%d)", info.m_fEps, info.m_reporttype );
  2064. pDC->TextOut( x, y+455, strTemp );
  2065. strTemp = "-   ";
  2066. if( info.GetPE(&dValue) )
  2067. strTemp.Format( "%.1f", dValue );
  2068. pDC->TextOut( x, y+480, strTemp );
  2069. // Yield
  2070. double market_dayyield_average = 0.0, market_dayyield_d = 0.0;
  2071. BOOL bmarket_yield_ok = TRUE;
  2072. if( !CalculateYieldDay( kdayMain, &market_dayyield_average, &market_dayyield_d, AfxGetProfile().GetYieldAverageDays(), nIndexDayMain ) )
  2073. bmarket_yield_ok = FALSE;
  2074. double yield_average = 0., yield_d = 0., beite = 0., xiapu = 0. ;
  2075. if( CalculateYieldDay( kday, &yield_average, &yield_d, AfxGetProfile().GetYieldAverageDays(), nIndexDay ) )
  2076. {
  2077. yield_average = ( 100. * (pow(1+yield_average,STKLIB_DAYS_INONEYEAR)-1) );
  2078. yield_d = ( 100. * sqrt((double)STKLIB_DAYS_INONEYEAR) * yield_d );
  2079. if( fabs(yield_d) > 0.01 )
  2080. {
  2081. xiapu = 100. * yield_average / yield_d;
  2082. strTemp.Format( "%.2f%%", xiapu );
  2083. pDC->TextOut( x, y+105, strTemp );
  2084. }
  2085. strTemp.Format( "%.2f%%", yield_average );
  2086. pDC->TextOut( x, y+30, strTemp );
  2087. strTemp.Format( "%.2f%%", yield_d );
  2088. pDC->TextOut( x, y+55, strTemp );
  2089. }
  2090. if( bmarket_yield_ok && CalculateBeiteDay( kday, kdayMain, market_dayyield_average, market_dayyield_d, &beite, AfxGetProfile().GetYieldAverageDays(), nIndexDay ) )
  2091. {
  2092. beite = beite;
  2093. strTemp.Format( "%.2f", beite );
  2094. pDC->TextOut( x, y+80, strTemp );
  2095. }
  2096. pDC->SetTextAlign( nOldAlign );
  2097. pDC->SelectObject( pOldFont );
  2098. // kday.ChangeCurFormat( m_nCurKFormat, AfxGetProfile().GetAutoResumeDRBegin(), AfxGetProfile().GetAutoResumeDRLimit() );
  2099. }
  2100. void CStockGraph::DrawReportCost( CDC * pDC )
  2101. {
  2102. DECLARE_COLOR_DEFINATION
  2103. // Draw Rect
  2104. pDC->FillSolidRect( &m_rectReport, clrBK );
  2105. pDC->Draw3dRect( &m_rectReport, clrBorder, clrBorder );
  2106. pDC->SetBkColor( clrBK );
  2107. // Select Name And Code Font
  2108. CString strTemp, strFont, strTempFmt, strDay;
  2109. strDay.LoadString( IDS_STOCKGRAPH_DAY );
  2110. CFont * pOldFont = AfxSelectDCFont( pDC, 18 );
  2111. UINT nOldAlign = pDC->SetTextAlign( TA_LEFT | TA_TOP );
  2112. // Draw Name And Code
  2113. pDC->SetTextColor( clrTitle );
  2114. pDC->TextOut( m_rectReport.left+1, m_rectAll.top+3, m_CurStock.GetStockInfo().GetStockName() );
  2115. pDC->SetTextColor( clrText );
  2116. pDC->TextOut( m_rectReport.left+96, m_rectAll.top+3, m_CurStock.GetStockInfo().GetStockCode() );
  2117. // 成本分布图
  2118. CKData & kdata = m_CurStock.GetKData(m_nCurKType);
  2119. double dStep = (m_dMaxPrice-m_dMinPrice)*0.003;
  2120. CSPDWordArray adwPrice, adwVolume;
  2121. double dMinVolume = 0, dMaxVolume = 0, dTotalVolume = 0, dVolPercent = 0;
  2122. CCW cw(&kdata);
  2123. cw.m_dChangeHand = 1.5;
  2124. int nEnd = m_nIndexCurrent;
  2125. if( -1 == nEnd )
  2126. nEnd = kdata.GetSize()-1;
  2127. if( !cw.CalculatePastCW(nEnd, 0, m_CurStock.GetStockInfo(), dStep, adwPrice, adwVolume, &dMinVolume, &dMaxVolume, &dTotalVolume, &dVolPercent )
  2128. || dMinVolume < 0 || dMaxVolume < 1e-4 || dTotalVolume < 1e-4 )
  2129. return;
  2130. COLORREF clrGain = RGB(255,128,0), clrBad = RGB(160,160,255);
  2131. CPen penGain( PS_SOLID, 1, clrGain );
  2132. CPen penBad( PS_SOLID, 1, clrBad );
  2133. CPen * pOldPen = pDC->SelectObject( &penGain );
  2134. double dPriceSel = 0;
  2135. if( nEnd >= 0 && nEnd < kdata.GetSize() )
  2136. dPriceSel = kdata.ElementAt(nEnd).m_fClose;
  2137. double dVolume = 0, dPrice = 0;
  2138. double dVolFactor = -1;
  2139. for( int k=0; k<adwPrice.GetSize() && k<adwVolume.GetSize(); k++ )
  2140. {
  2141. if( dVolFactor < 0 )
  2142. dVolFactor = 40.0/dTotalVolume;
  2143. dPrice = double(adwPrice[k]) * 0.001;
  2144. dVolume = adwVolume[k];
  2145. if( dPrice > dPriceSel )
  2146. pDC->SelectObject( &penBad );
  2147. int yPrice = int( m_rectKLineCenter.bottom - m_rectKLineCenter.Height() * (dPrice - m_dMinPrice) / (m_dMaxPrice-m_dMinPrice) );
  2148. int xVolume = int( m_rectReport.left + (m_rectReport.Width()*dVolume*dVolFactor) );
  2149. if( yPrice > m_rectReport.top+1 && yPrice < m_rectReport.bottom-2 )
  2150. {
  2151. pDC->MoveTo( m_rectReport.left + 1, yPrice );
  2152. pDC->LineTo( xVolume, yPrice );
  2153. }
  2154. }
  2155. // Select Param Font
  2156. AfxSelectDCFont( pDC, 12 );
  2157. pDC->SetBkColor( clrBK );
  2158. pDC->SetTextColor( clrText );
  2159. int x = m_rectReport.left+2;
  2160. int y = m_rectReport.bottom-100;
  2161. // Date
  2162. CString strDate;
  2163. if( nEnd >= 0 && nEnd < kdata.GetSize() )
  2164. strDate = ::AfxGetTimeString( kdata.ElementAt(nEnd).m_time, "%Y-%m-%d", TRUE );
  2165. pDC->TextOut( x+10, y, strDate );
  2166. // 获利比例: 
  2167. double dGainPercent = 0;
  2168. CCW::StatGainPercent( &dGainPercent, adwPrice, adwVolume, dPriceSel );
  2169. strTemp.LoadString( IDS_STOCKGRAPH_GAINPERCENT );
  2170. pDC->TextOut( x, y+20, strTemp );
  2171. strTemp.Format( "%.1f%%", dGainPercent*100 );
  2172. pDC->TextOut( x+100, y+20, strTemp );
  2173. CRect rectGain( x+60, y+20, x+160, y+32 );
  2174. pDC->Draw3dRect( rectGain, clrBad, clrBad );
  2175. rectGain.right = rectGain.left + rectGain.Width() * dGainPercent;
  2176. pDC->Draw3dRect( rectGain, clrGain, clrGain );
  2177. pDC->SetBkColor( clrBK );
  2178. // 平均成本: %.3f元
  2179. double dCostAve = 0;
  2180. CCW::StatCostAverage( &dCostAve, adwPrice, adwVolume );
  2181. strTempFmt.LoadString( IDS_STOCKGRAPH_COSTAVE );
  2182. strTemp.Format( strTempFmt, dCostAve );
  2183. pDC->TextOut( x, y+36, strTemp );
  2184. // 90%成本%.2f-%.2f,集中度%.1f%%
  2185. double dLow = 0, dHigh = 0, dMassPrice = 0;
  2186. CCW::StatMass( &dLow, &dHigh, &dMassPrice, adwPrice, adwVolume, 0.9 );
  2187. strTempFmt.LoadString( IDS_STOCKGRAPH_MASSFMT90 );
  2188. strTemp.Format( strTempFmt, dLow, dHigh, dMassPrice*100 );
  2189. pDC->TextOut( x, y+52, strTemp );
  2190. // 70%成本%.2f-%.2f,集中度%.1f%%
  2191. dLow = 0, dHigh = 0, dMassPrice = 0;
  2192. CCW::StatMass( &dLow, &dHigh, &dMassPrice, adwPrice, adwVolume, 0.7 );
  2193. strTempFmt.LoadString( IDS_STOCKGRAPH_MASSFMT70 );
  2194. strTemp.Format( strTempFmt, dLow, dHigh, dMassPrice*100 );
  2195. pDC->TextOut( x, y+68, strTemp );
  2196. pDC->SelectObject( pOldPen );
  2197. pDC->SetTextAlign( nOldAlign );
  2198. pDC->SelectObject( pOldFont );
  2199. }
  2200. void CStockGraph::DrawReportFlame( CDC * pDC )
  2201. {
  2202. DECLARE_COLOR_DEFINATION
  2203. // Draw Rect
  2204. pDC->FillSolidRect( &m_rectReport, clrBK );
  2205. pDC->Draw3dRect( &m_rectReport, clrBorder, clrBorder );
  2206. pDC->SetBkColor( clrBK );
  2207. // Select Name And Code Font
  2208. CString strTemp, strFont, strTempFmt, strDay;
  2209. strDay.LoadString( IDS_STOCKGRAPH_DAY );
  2210. CFont * pOldFont = AfxSelectDCFont( pDC, 18 );
  2211. UINT nOldAlign = pDC->SetTextAlign( TA_LEFT | TA_TOP );
  2212. // Draw Name And Code
  2213. pDC->SetTextColor( clrTitle );
  2214. pDC->TextOut( m_rectReport.left+1, m_rectAll.top+3, m_CurStock.GetStockInfo().GetStockName() );
  2215. pDC->SetTextColor( clrText );
  2216. pDC->TextOut( m_rectReport.left+96, m_rectAll.top+3, m_CurStock.GetStockInfo().GetStockCode() );
  2217. // 火焰山
  2218. CKData & kdata = m_CurStock.GetKData(m_nCurKType);
  2219. int nEnd = m_nIndexCurrent;
  2220. if( -1 == nEnd )
  2221. nEnd = kdata.GetSize()-1;
  2222. int nBot = 5;
  2223. CRect rectDescript( m_rectReport.left+30, m_rectReport.bottom-nBot-100, m_rectReport.left+170, m_rectReport.bottom-nBot-84);
  2224. DrawReportCW( pDC, FALSE, nEnd, 5, 1.5, RGB(255,0,0), rectDescript );
  2225. rectDescript = CRect( m_rectReport.left+30, m_rectReport.bottom-nBot-84, m_rectReport.left+170, m_rectReport.bottom-nBot-68);
  2226. DrawReportCW( pDC, FALSE, nEnd, 10, 1.5, RGB(255,0,128), rectDescript );
  2227. rectDescript = CRect( m_rectReport.left+30, m_rectReport.bottom-nBot-68, m_rectReport.left+170, m_rectReport.bottom-nBot-52);
  2228. DrawReportCW( pDC, FALSE, nEnd, 20, 1.5, RGB(255,128,0), rectDescript );
  2229. rectDescript = CRect( m_rectReport.left+30, m_rectReport.bottom-nBot-52, m_rectReport.left+170, m_rectReport.bottom-nBot-36);
  2230. DrawReportCW( pDC, FALSE, nEnd, 30, 1.5, RGB(255,128,128), rectDescript );
  2231. rectDescript = CRect( m_rectReport.left+30, m_rectReport.bottom-nBot-36, m_rectReport.left+170, m_rectReport.bottom-nBot-20);
  2232. DrawReportCW( pDC, FALSE, nEnd, 60, 1.5, RGB(255,255,0), rectDescript );
  2233. // Select Param Font
  2234. AfxSelectDCFont( pDC, 12 );
  2235. // Date
  2236. pDC->SetBkColor( clrBK );
  2237. pDC->SetTextColor( clrText );
  2238. CString strDate;
  2239. if( nEnd >= 0 && nEnd < kdata.GetSize() )
  2240. strDate = ::AfxGetTimeString( kdata.ElementAt(nEnd).m_time, "%Y-%m-%d", TRUE );
  2241. pDC->TextOut( m_rectReport.left+20, m_rectReport.bottom-20, strDate );
  2242. pDC->SetTextAlign( nOldAlign );
  2243. pDC->SelectObject( pOldFont );
  2244. }
  2245. void CStockGraph::DrawReportActivity( CDC * pDC )
  2246. {
  2247. DECLARE_COLOR_DEFINATION
  2248. // Draw Rect
  2249. pDC->FillSolidRect( &m_rectReport, clrBK );
  2250. pDC->Draw3dRect( &m_rectReport, clrBorder, clrBorder );
  2251. pDC->SetBkColor( clrBK );
  2252. // Select Name And Code Font
  2253. CString strTemp, strFont, strTempFmt, strDay;
  2254. strDay.LoadString( IDS_STOCKGRAPH_DAY );
  2255. CFont * pOldFont = AfxSelectDCFont( pDC, 18 );
  2256. UINT nOldAlign = pDC->SetTextAlign( TA_LEFT | TA_TOP );
  2257. // Draw Name And Code
  2258. pDC->SetTextColor( clrTitle );
  2259. pDC->TextOut( m_rectReport.left+1, m_rectAll.top+3, m_CurStock.GetStockInfo().GetStockName() );
  2260. pDC->SetTextColor( clrText );
  2261. pDC->TextOut( m_rectReport.left+96, m_rectAll.top+3, m_CurStock.GetStockInfo().GetStockCode() );
  2262. // 活跃度
  2263. CKData & kdata = m_CurStock.GetKData(m_nCurKType);
  2264. int nEnd = m_nIndexCurrent;
  2265. if( -1 == nEnd )
  2266. nEnd = kdata.GetSize()-1;
  2267. int nBot = 5;
  2268. CRect rectDescript( m_rectReport.left+30, m_rectReport.bottom-nBot-36, m_rectReport.left+170, m_rectReport.bottom-nBot-20);
  2269. DrawReportCW( pDC, TRUE, nEnd, 60, 1, RGB(0,40,160), rectDescript );
  2270. rectDescript = CRect( m_rectReport.left+30, m_rectReport.bottom-nBot-52, m_rectReport.left+170, m_rectReport.bottom-nBot-36);
  2271. DrawReportCW( pDC, TRUE, nEnd, 30, 1, RGB(80,80,255), rectDescript );
  2272. rectDescript = CRect( m_rectReport.left+30, m_rectReport.bottom-nBot-68, m_rectReport.left+170, m_rectReport.bottom-nBot-52);
  2273. DrawReportCW( pDC, TRUE, nEnd, 20, 1, RGB(120,80,255), rectDescript );
  2274. rectDescript = CRect( m_rectReport.left+30, m_rectReport.bottom-nBot-84, m_rectReport.left+170, m_rectReport.bottom-nBot-68);
  2275. DrawReportCW( pDC, TRUE, nEnd, 10, 1, RGB(120,120,255), rectDescript );
  2276. rectDescript = CRect( m_rectReport.left+30, m_rectReport.bottom-nBot-100, m_rectReport.left+170, m_rectReport.bottom-nBot-84);
  2277. DrawReportCW( pDC, TRUE, nEnd, 5, 1, RGB(160,160,255), rectDescript );
  2278. // Select Param Font
  2279. AfxSelectDCFont( pDC, 12 );
  2280. // Date
  2281. pDC->SetBkColor( clrBK );
  2282. pDC->SetTextColor( clrText );
  2283. CString strDate;
  2284. if( nEnd >= 0 && nEnd < kdata.GetSize() )
  2285. strDate = ::AfxGetTimeString( kdata.ElementAt(nEnd).m_time, "%Y-%m-%d", TRUE );
  2286. pDC->TextOut( m_rectReport.left+20, m_rectReport.bottom-20, strDate );
  2287. pDC->SetTextAlign( nOldAlign );
  2288. pDC->SelectObject( pOldFont );
  2289. }
  2290. void CStockGraph::DrawReportCW( CDC * pDC, BOOL bRecent, int nEnd, int nDays, double dChangeHand, COLORREF clr, CRect rectDescript )
  2291. {
  2292. double dVolFactor = -1;
  2293. CKData & kdata = m_CurStock.GetKData(m_nCurKType);
  2294. double dStep = (m_dMaxPrice-m_dMinPrice)*0.003;
  2295. CSPDWordArray adwPrice, adwVolume;
  2296. double dMinVolume = 0, dMaxVolume = 0, dTotalVolume = 0, dVolPercent = 0;
  2297. CCW cw(&kdata);
  2298. cw.m_dChangeHand = dChangeHand;
  2299. int yPriceLast = -1;
  2300. BOOL bOK = FALSE;
  2301. if( bRecent )
  2302. bOK = cw.CalculateRecentCW(nEnd, nDays, m_CurStock.GetStockInfo(), dStep, adwPrice, adwVolume, &dMinVolume, &dMaxVolume, &dTotalVolume, &dVolPercent );
  2303. else
  2304. bOK = cw.CalculatePastCW(nEnd, nDays, m_CurStock.GetStockInfo(), dStep, adwPrice, adwVolume, &dMinVolume, &dMaxVolume, &dTotalVolume, &dVolPercent );
  2305. CPen pen( PS_SOLID, 1, clr );
  2306. CPen * pOldPen = pDC->SelectObject( &pen );
  2307. if( bOK && dMinVolume >= 0 && dMaxVolume > 1e-4 && dTotalVolume > 1e-4
  2308. && m_dMaxPrice-m_dMinPrice > 1e-4 && m_dMinPrice > 1e-4 )
  2309. {
  2310. if( dVolFactor < 0 )
  2311. dVolFactor = bRecent ? 15.0/dTotalVolume : 40.0/dTotalVolume;
  2312. CArray <POINT, POINT &> apt;
  2313. apt.SetSize( 0, m_rectKLineCenter.Height() );
  2314. double dVolume = 0, dPrice = 0;
  2315. for( int k=0; k<adwPrice.GetSize() && k<adwVolume.GetSize(); k++ )
  2316. {
  2317. dPrice = double(adwPrice[k]) * 0.001;
  2318. dVolume = adwVolume[k];
  2319. int yPrice = int( m_rectKLineCenter.bottom - m_rectKLineCenter.Height() * (dPrice - m_dMinPrice) / (m_dMaxPrice-m_dMinPrice) );
  2320. int xVolume = int( m_rectReport.left + (m_rectReport.Width()*dVolume*dVolFactor) );
  2321. if( yPrice > m_rectReport.top+1 && yPrice < m_rectReport.bottom-2 )
  2322. {
  2323. if( -1 == yPriceLast )
  2324. yPriceLast = yPrice+1;
  2325. for( int y=yPriceLast-1; y>=yPrice; y-- )
  2326. {
  2327. pDC->MoveTo( m_rectReport.left+2, y );
  2328. pDC->LineTo( xVolume, y );
  2329. }
  2330. yPriceLast = yPrice;
  2331. apt.Add( CPoint(xVolume, yPrice) );
  2332. }
  2333. }
  2334. if( apt.GetSize() > 0 )
  2335. {
  2336. CPen penEdge( PS_SOLID, 1, RGB(255,255,255) );
  2337. pDC->SelectObject( &penEdge );
  2338. pDC->MoveTo( apt[0] );
  2339. pDC->PolylineTo( apt.GetData(), apt.GetSize() );
  2340. }
  2341. }
  2342. // rectDescript
  2343. pDC->Draw3dRect( rectDescript, clr, clr );
  2344. pDC->FillSolidRect( rectDescript, clr );
  2345. CString sText, sTextFmt;
  2346. if( bRecent )
  2347. sTextFmt.LoadString( IDS_STOCKGRAPH_RECENTCWDISFMT );
  2348. else
  2349. sTextFmt.LoadString( IDS_STOCKGRAPH_PASTCWDISFMT );
  2350. sText.Format( sTextFmt, nDays, dVolPercent*100 );
  2351. CFont * pOldFont = AfxSelectDCFont( pDC, 12 );
  2352. pDC->SetTextColor( RGB(255,255,255) );
  2353. pDC->SetBkColor( clr );
  2354. pDC->TextOut( rectDescript.left+5, rectDescript.top+2, sText );
  2355. pDC->SelectObject( pOldPen );
  2356. pDC->SelectObject( pOldFont );
  2357. }