⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stockgraph.cpp

📁 股软 通达信行情接收接口, 包括美元汇率
💻 CPP
📖 第 1 页 / 共 5 页
字号:
void CStockGraph::DrawNoDataInfo( CDC * pDC )
{
	DECLARE_COLOR_DEFINATION

	CKData	&	kdata	=	m_CurStock.GetKData(m_nCurKType);
	if( 0 == kdata.GetSize() )
	{
		CString	strNoKData = "无历史数据", strTemp;
		strTemp		=	CString(m_CurStock.GetStockInfo().GetStockName()) + "(" + m_CurStock.GetStockInfo().GetStockCode() + ")";
		strTemp		+=	(LPCTSTR)AfxGetKTypeString( m_nCurKType );
		strNoKData	=	strTemp + strNoKData;
		pDC->SetBkColor( clrBK );
		pDC->SetTextColor( clrTitle );
		pDC->TextOut( m_rectAll.left+20, m_rectAll.top+20,  strNoKData );
	}
}

void CStockGraph::DrawDateAxis( CDC * pDC )
{
	CHECK_NODATATODRAW
	DECLARE_COLOR_DEFINATION

	CRect	rect	=	m_rectCenter;
	rect.top	=	m_rectAll.bottom - m_nMarginBottom + 1;
	pDC->FillSolidRect( &rect, clrBK );
	pDC->SetBkColor( clrBK );
	pDC->SetTextColor( clrDJ );

	CKData & kdata	=	m_CurStock.GetKData( m_nCurKType );
	BOOL	bDayOrMin	=	CKData::IsDayOrMin(m_nCurKType);
	int		y	=	m_rectAll.bottom - m_nMarginBottom + 2;
	int	xLast	=	0;
	for( int k=m_nIndexStart; k<=m_nIndexEnd; k++ )
	{
		if( k > 0 && k < kdata.GetSize() )
		{
			CSPTime	sptimeLast, sptime;
			if( sptimeLast.FromStockTime( kdata.ElementAt(k-1).m_date, bDayOrMin )
				&& sptime.FromStockTime( kdata.ElementAt(k).m_date, bDayOrMin ) )
			{
				CString	strText;
				if( (CKData::ktypeDay == m_nCurKType )
					&& (sptimeLast.GetMonth() != sptime.GetMonth()) )
						strText	=	sptime.Format( "%m" );
				else if( (CKData::ktypeWeek == m_nCurKType || CKData::ktypeMonth == m_nCurKType)
					&& (sptimeLast.GetYear() != sptime.GetYear()) )
						strText	=	sptime.Format( "%y" );
				else if( !CKData::IsDayOrMin(m_nCurKType)
					&& (sptimeLast.GetDay() != sptime.GetDay()) )
						strText	=	sptime.Format( "%d" );
				CRect	rectK;
				if( strText.GetLength() > 0 && GetOneKLineRect( k, &rectK, NULL, NULL, NULL ) && xLast < rectK.left )
				{
					pDC->TextOut( rectK.left, y, strText );
					xLast	=	rectK.left + pDC->GetTextExtent(strText).cx;
				}
			}
		}
	}
}

void CStockGraph::DrawKLine(CDC * pDC )
{
	DECLARE_COLOR_DEFINATION

	CKData	& kdata	=	m_CurStock.GetKData(m_nCurKType);

	pDC->FillSolidRect( &m_rectKLine, clrBK );
	pDC->Draw3dRect( &m_rectKLine, clrBorder, clrBorder );

	// Draw Title
	CString	strTitle;
	pDC->SetTextColor( clrTitle );
	pDC->SetBkColor( clrBK );
	strTitle	=	AfxGetKTypeString( m_nCurKType );
	pDC->TextOut( m_rectAll.left+8, m_rectAll.top+2, strTitle );
	strTitle = "K  线";
	pDC->TextOut( m_rectKLine.left+1, m_rectAll.top+2, strTitle );

	double	dMin = 0, dMax = 0;
	if( ! GetKLineMinMaxInfo( m_nIndexStart, m_nIndexEnd, &dMin, &dMax ) )
		return;
	m_dMaxPrice			=	dMax;
	m_dMinPrice			=	dMin;

	// Draw Axis
	DrawAxis( pDC, m_rectKLine, m_nHeightSubtitle, 3, dMin, dMax, TRUE, TRUE, 2 );

	// KLine Attribute Rect
	CRect	rectKLineAttrib = m_rectKLineCenter;
	rectKLineAttrib.top -= m_nHeightSubtitle;

	int k;

	// Draw STT_DJ and STT_CW
	CSPDWordArray	&	anTech	=	AfxGetProfile().GetGraphTechsKLine( );
	for( k=0; k<anTech.GetSize(); k++ )
		if( STT_DJ == anTech[k] || STT_CW == anTech[k] )
			DrawKLineAttribute( pDC, anTech[k], rectKLineAttrib, FALSE, dMin, dMax );

	// Draw K Line
	for(  k=m_nIndexStart; k<=m_nIndexEnd; k++ )
	{
		DrawOneKLine( pDC, k, k, &kdata, dMin, dMax, FALSE );
	}

	// Draw Tech KLine except STT_DJ and STT_CW
	for(  k=0; k<anTech.GetSize(); k++ )
		if( STT_DJ != anTech[k] && STT_CW != anTech[k] )
			DrawKLineAttribute( pDC, anTech[k], rectKLineAttrib, FALSE, dMin, dMax );
	if( anTech.GetSize() > 0 )
		DrawKLineAttribute( pDC, anTech[0], rectKLineAttrib, TRUE, dMin, dMax );

	// Draw Select Line
	DrawSelectionLine( pDC, TRUE );
}

BOOL CStockGraph::GetKLineMinMaxInfo( int nStart, int nEnd, double * pdMin, double * pdMax )
{
	CKData	& kdata	=	m_CurStock.GetKData(m_nCurKType);
	CKLine	kline( &kdata );
	double	dMin = 0, dMax = 0, dMinTemp = 0, dMaxTemp = 0;
	if( nStart < 0 || nEnd < 0 || ! kline.GetMinMaxInfo( nStart, nEnd, &dMin, &dMax ) )
		return FALSE;

	CSPDWordArray	&	anTech	=	AfxGetProfile().GetGraphTechsKLine( );
	for( int k=0; k<anTech.GetSize(); k++ )
	{
		UINT	nTech	=	anTech[k];
		switch( nTech )
		{
		case STT_MA:
			{
				CMA	ma( &kdata ); 
				if( ma.GetMinMaxInfo( nStart, nEnd, &dMinTemp, &dMaxTemp ) )
				{
					if( dMinTemp < dMin )	dMin	=	dMinTemp;
					if( dMaxTemp > dMax )	dMax	=	dMaxTemp;
				}
			}
			break;
		case STT_BBI:
			{
				CBBI	bbi( &kdata ); 
				if( bbi.GetMinMaxInfo( nStart, nEnd, &dMinTemp, &dMaxTemp ) )
				{
					if( dMinTemp < dMin )	dMin	=	dMinTemp;
					if( dMaxTemp > dMax )	dMax	=	dMaxTemp;
				}
			}
			break;
		case STT_BOLL:
			{
				CBOLL	boll( &kdata ); 
				if( boll.GetMinMaxInfo( nStart, nEnd, &dMinTemp, &dMaxTemp ) )
				{
					if( dMinTemp < dMin )	dMin	=	dMinTemp;
					if( dMaxTemp > dMax )	dMax	=	dMaxTemp;
				}
			}
			break;
		case STT_PV:
			{
				CPV	pv( &kdata ); 
				if( pv.GetMinMaxInfo( nStart, nEnd, &dMinTemp, &dMaxTemp ) )
				{
					if( dMinTemp < dMin )	dMin	=	dMinTemp;
					if( dMaxTemp > dMax )	dMax	=	dMaxTemp;
				}
			}
			break;
		case STT_SAR:
			{
				CSAR	sar( &kdata ); 
				if( sar.GetMinMaxInfo( nStart, nEnd, &dMinTemp, &dMaxTemp ) )
				{
					if( dMinTemp < dMin )	dMin	=	dMinTemp;
					if( dMaxTemp > dMax )	dMax	=	dMaxTemp;
				}
			}
			break;
		case STT_DJ:
		case STT_CW:
			break;
		default:;
			ASSERT( FALSE );
		}
	}
	
	if( pdMin )
		*pdMin	=	dMin;
	if( pdMax )
		*pdMax	=	dMax;
	return TRUE;
}

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

	// Check Valid
	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
	CRect	rectK, rcEntity;
	long	xMedium	=	0;
	if( !GetOneKLineRect( nIndexPos, &rectK, &rcEntity.left, &rcEntity.right, &xMedium ) )
		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);

	// Set rcEntity's top and bottom, set yLow, yHigh
	int	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) );
	rcEntity.top	=	min( yOpen, yClose );
	rcEntity.bottom	=	max( yOpen, yClose ) + 1;

	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
		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 );
				}
			}
		}
	}
}

void CStockGraph::DrawBorderMovingLine( CDC * pDC, CPoint point, BOOL bAddOrRemove )
{
	ASSERT( m_pParent && ::IsWindow( m_pParent->GetSafeHwnd() ) );
	if( !m_pParent || !::IsWindow(m_pParent->GetSafeHwnd()) )
		return;

	CClientDC	dc(m_pParent);
	if( NULL == pDC )
		pDC		=	&dc;

	CPen	penLine( PS_SOLID, 1, AfxGetProfile().GetColor( CColorClass::clrBorder ) );
	CPen * pOldPen = pDC->SelectObject( &penLine );
	int nOldDrawMode = pDC->SetROP2( R2_XORPEN );

	pDC->MoveTo( m_rectKLine.left-5, point.y );
	pDC->LineTo( m_rectKLine.right+5, point.y );

	pDC->SetROP2( nOldDrawMode );
	pDC->SelectObject( pOldPen );
}

void CStockGraph::DrawSelectionLine( CDC * pDC, BOOL bAddOrRemove )
{
	ASSERT( m_pParent && ::IsWindow( m_pParent->GetSafeHwnd() ) );
	if( !m_pParent || !::IsWindow(m_pParent->GetSafeHwnd()) )
		return;

	CClientDC	dc(m_pParent);
	if( NULL == pDC )
		pDC		=	&dc;

	CPen	penVLine( PS_SOLID, 1, AfxGetProfile().GetColor( CColorClass::clrLine1 ) );
	CPen * pOldPen = pDC->SelectObject( &penVLine );
	int nOldDrawMode = pDC->SetROP2( R2_XORPEN );

	CRect	rectK;
	long	xMedium = 0;
	if( GetOneKLineRect( m_nIndexCurrent, &rectK, NULL, NULL, &xMedium ) )
	{
		pDC->MoveTo( xMedium, m_rectCenter.bottom );
		pDC->LineTo( xMedium, m_rectKLineCenter.top );
	}

	for( int k=0; k<m_anIndexCurrent.GetSize(); k++ )
	{
		if( ((int)m_anIndexCurrent[k]) == m_nIndexCurrent )
			continue;
		if( GetOneKLineRect( m_anIndexCurrent[k], &rectK, NULL, NULL, &xMedium ) )
		{
			pDC->MoveTo( xMedium, m_rectKLineCenter.bottom );
			pDC->LineTo( xMedium, m_rectKLineCenter.top );
		}
	}

	pDC->SetROP2( nOldDrawMode );
	pDC->SelectObject( pOldPen );
}

void CStockGraph::DrawSelectionRect( CDC * pDC, CPoint ptBegin, CPoint ptEnd, BOOL bAddOrRemove )
{
	ASSERT( m_pParent && ::IsWindow( m_pParent->GetSafeHwnd() ) );
	if( !m_pParent || !::IsWindow(m_pParent->GetSafeHwnd()) )
		return;

	CClientDC	dc(m_pParent);
	if( NULL == pDC )
		pDC		=	&dc;

	CPen	penVLine( PS_SOLID, 1, AfxGetProfile().GetColor( CColorClass::clrLine2 ) );
	CPen * pOldPen = pDC->SelectObject( &penVLine );
	int nOldDrawMode = pDC->SetROP2( R2_XORPEN );

	CRect	rect;
	rect.left	=	min(ptBegin.x,ptEnd.x);
	rect.right	=	max(ptBegin.x,ptEnd.x);
	rect.top	=	min(ptBegin.y,ptEnd.y);
	rect.bottom	=	max(ptBegin.y,ptEnd.y);

	pDC->MoveTo( rect.left, rect.top );
	pDC->LineTo( rect.right, rect.top );
	pDC->LineTo( rect.right, rect.bottom );
	pDC->LineTo( rect.left, rect.bottom );
	pDC->LineTo( rect.left, rect.top );

	pDC->SetROP2( nOldDrawMode );
	pDC->SelectObject( pOldPen );
}

void CStockGraph::DrawKData( )
{
	if( !::IsWindow( m_wndKData.GetSafeHwnd() ) )
	{
		if( !m_wndKData.Create( NULL, "", WS_CHILD, m_rectKData, m_pParent, 0 ) )
		{
			TRACE( "Failed to create m_wndKData!\n" );
			return;
		}
		m_wndKData.SetWindowPos( NULL, m_rectKData.left, m_rectKData.top, m_rectKData.Width(), m_rectKData.Height(),
								SWP_SHOWWINDOW );
	}

	CClientDC	dc(&m_wndKData);
	CRect		rectClient;
	m_wndKData.GetClientRect( &rectClient );

	CKData	&kdata	=	m_CurStock.GetKData(m_nCurKType);
	if( m_nIndexCurrent >= 0 && m_nIndexCurrent < kdata.GetSize() )
	{
		m_wndKData.SetWindowPos( NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW );
		m_wndKData.ValidateRect( &rectClient );
		DrawKData( &dc, rectClient );
		m_wndKData.ValidateRect( &rectClient );
	}
	else
		m_wndKData.SetWindowPos( NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -