English | 简体中文 | 繁體中文
一流镖客16bk.com

书写民间股市传奇...

DrawOneKLine如何画单根K线

admin2021-03-30 19:30:23220

//函数实现画单根K线的功能,坐标为普通坐标,而非对数坐标

void CStockGraph::DrawOneKLine(CDC * pDC, int nIndexPos, int nIndexKD, CKData * pKData, double dMin, double dMax, BOOL bGreyed ){DECLARE_COLOR_DEFINATION

// Check Valid

//判断当前位置的序列号是否有效,指的是显示窗口,在当前的m_nIndexStart 和 m_nIndexEnd之间ASSERT( pDC && nIndexPos >= m_nIndexStart && nIndexPos <= m_nIndexEnd && nIndexPos >= 0 );if( !(pDC && nIndexPos >= m_nIndexStart && nIndexPos <= m_nIndexEnd && nIndexPos >= 0) ) return;

//判断当前位置的序列号是否有效,序列号是否是小于零或大于当前序列的长度if( !pKData || nIndexKD < 0 || nIndexKD >= pKData->GetSize() ) return;if( dMax-dMin < 1e-4 ) return;

// Get Region

//关于GetOneKLineRect请参看下面关于这个函数的分析

//这里需要注意的一个问题就是rectK, rcEntity,是有不同的含义的,rectK是指显示的K线矩形区域,实际的画K线的区域是rcEntity,指的是画K线实体的区域CRect rectK, rcEntity;long xMedium = 0;if( !GetOneKLineRect( nIndexPos, &rectK, &rcEntity.left, &rcEntity.right, &xMedium ) )//参数xMedium 为K线实体的中间位置,对应画K线的图形 return;

int xStart = rectK.left;int xEnd = rectK.right;ASSERT( xEnd <= m_rectKLineCenter.right );if( xEnd > m_rectKLineCenter.right ) return;

KDATA kd = pKData->ElementAt(nIndexKD);

//根据当前最低价格/最高价格/收盘价格/开盘价格的计算出K线实体在当前显示区域中坐标.(等比例的计算)

// Set rcEntity's top and bottom, set yLow, yHighint yLow = int( m_rectKLineCenter.bottom - m_rectKLineCenter.Height() * (kd.m_fLow - dMin) / (dMax-dMin) );int yHigh = int( m_rectKLineCenter.bottom - m_rectKLineCenter.Height() * (kd.m_fHigh - dMin) / (dMax-dMin) );int yOpen = int( m_rectKLineCenter.bottom - m_rectKLineCenter.Height() * (kd.m_fOpen - dMin) / (dMax-dMin) );int yClose = int( m_rectKLineCenter.bottom - m_rectKLineCenter.Height() * (kd.m_fClose - dMin) / (dMax-dMin) );

//计算出实体区域的上下坐标,左右坐标已经根据序列位置计算出来了,到这个地方,已经计算出了要画K线的试题区域的具体坐标了.

rcEntity.top = min( yOpen, yClose );rcEntity.bottom = max( yOpen, yClose ) + 1;

//上面已经计算出了要画的K线的坐标了,下面就开始画K线了

if( CStockGraph::klineCandle == m_nCurKLineMode ){ // Draw Entity

//画实体区域了 COLORREF clr = clrRise; if( kd.m_fClose < kd.m_fOpen ) clr = clrFallEntity; if( kd.m_date > m_dwLatestDate ) clr = clrNewKLine; if( bGreyed ) clr = clrDJ; pDC->SetBkColor( clrBK ); if( kd.m_fClose < kd.m_fOpen ) pDC->FillSolidRect( &rcEntity, clr ); else pDC->Draw3dRect( &rcEntity, clr, clr ); // Draw Line

//画K线上的最高和最低价格的线 CPen pen( PS_SOLID, 1, clr ); CPen *pOldPen = pDC->SelectObject( &pen ); pDC->MoveTo( xMedium, yHigh ); pDC->LineTo( xMedium, rcEntity.top ); pDC->MoveTo( xMedium, rcEntity.bottom ); pDC->LineTo( xMedium, yLow );

pDC->SelectObject( pOldPen );}else if( CStockGraph::klineAmerica == m_nCurKLineMode ){ // Draw Entity COLORREF clr = clrRise; if( kd.m_date > m_dwLatestDate ) clr = clrNewKLine; if( bGreyed ) clr = clrDJ; pDC->SetBkColor( clrBK ); // Draw Line CPen pen( PS_SOLID, 1, clr ); CPen *pOldPen = pDC->SelectObject( &pen ); pDC->MoveTo( xStart, yHigh ); pDC->LineTo( xStart, yLow ); pDC->MoveTo( xStart, yClose ); pDC->LineTo( xEnd, yClose );

pDC->SelectObject( pOldPen );}else if( CStockGraph::klineTower == m_nCurKLineMode ){ // Draw Entity COLORREF clr = clrRise; if( kd.m_fClose < kd.m_fOpen ) clr = clrFallEntity; if( kd.m_date > m_dwLatestDate ) clr = clrNewKLine; if( bGreyed ) clr = clrDJ; pDC->SetBkColor( clrBK ); if( kd.m_fClose < kd.m_fOpen ) pDC->FillSolidRect( &rcEntity, clr ); else pDC->Draw3dRect( &rcEntity, clr, clr );

if( nIndexKD > 0 ) { KDATA kdLast = pKData->ElementAt(nIndexKD-1); int yOpenLast = int( m_rectKLineCenter.bottom - m_rectKLineCenter.Height() * (kdLast.m_fOpen - dMin) / (dMax-dMin) ); int yCloseLast = int( m_rectKLineCenter.bottom - m_rectKLineCenter.Height() * (kdLast.m_fClose - dMin) / (dMax-dMin) ); if( kdLast.m_fClose > kdLast.m_fOpen && kd.m_fClose < kd.m_fOpen ) { rcEntity.bottom = min(yOpenLast,rcEntity.bottom); if( rcEntity.bottom > rcEntity.top ) { pDC->FillSolidRect( &rcEntity, clrBK ); clr = clrRise; if( kd.m_date > m_dwLatestDate ) clr = clrNewKLine; if( bGreyed ) clr = clrDJ; pDC->Draw3dRect( &rcEntity, clr, clr ); } } else if( kdLast.m_fClose < kdLast.m_fOpen && kd.m_fClose > kd.m_fOpen ) { rcEntity.top = max(yOpenLast,rcEntity.top); if( rcEntity.bottom > rcEntity.top ) { clr = clrFallEntity; if( kd.m_date > m_dwLatestDate ) clr = clrNewKLine; if( bGreyed ) clr = clrDJ; pDC->FillSolidRect( &rcEntity, clr ); } } }}}

//函数GetOneKLineRect的分析,得到当前序列位置处要画K线的区域

BOOL CStockGraph::GetOneKLineRect( int nIndex, LPRECT lpRect, long *pxEntityLeft, long *pxEntityRight, long *pxMedium ){

//判断当前的序列位置是在当前显示的窗口区域中if( nIndex == -1 || nIndex < m_nIndexStart || nIndex > m_nIndexEnd ) return FALSE;

//初始化画K线的位置的矩形区域

CRect rectK = m_rectCenter;

//计算出K线位置的左右宽度的坐标,上下的坐标没有给出,只是初始化为m_rectCenter中的参数

//左边的起誓位置为,从K线显示区域的左边开始m_rectKLineCenter.left,加上已经显示了nIndex-m_nIndexStart点的距离就是当前序列处的坐标rectK.left = m_rectKLineCenter.left + (nIndex-m_nIndexStart) * m_nThickness;

//右边的坐标最简单,就是左边左边加上宽度就可以了.rectK.right = rectK.left + m_nThickness;

if( rectK.Width() <= 0 || rectK.Height() <= 0 ) return FALSE;

//传出参数lpRect if( lpRect ) *lpRect = rectK;

int xStart = rectK.left;

CRect rcEntity;

//根据当前的K线的宽度计算出序列的右边的坐标点,并传出参数switch( m_nThickness ){case 1:case 2: rcEntity.left = xStart; rcEntity.right = xStart + 1; break;case 4:case 5: rcEntity.left = xStart; rcEntity.right = xStart + 3; break;case 6:case 7: rcEntity.left = xStart; rcEntity.right = xStart + 5; break;case 9:case 10: rcEntity.left = xStart; rcEntity.right = xStart + 7; break;case 13:case 15: rcEntity.left = xStart; rcEntity.right = xStart + 11; break;default: ASSERT( FALSE ); rcEntity.left = xStart; rcEntity.right = xStart + 3; return FALSE;}if( pxEntityLeft ) *pxEntityLeft = rcEntity.left;if( pxEntityRight ) *pxEntityRight = rcEntity.right;if( pxMedium ) *pxMedium = rcEntity.left + rcEntity.Width() / 2;

return TRUE;}

其他股票