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

📄 stockgraph.cpp.svn-base

📁 股票软件源码
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
{
	ASSERT( m_nThickness > 0 );
	if( m_nThickness <= 0 || m_rectKLineCenter.Width() <= 0 )
		return FALSE;

	CKData	& kdata	=	m_CurStock.GetKData(m_nCurKType);

	int	nWidth	=	m_rectKLineCenter.Width();
	int	nCount	=	nWidth / m_nThickness;
	if( nCount <= 0 )
		return FALSE;

	if( kdata.GetSize() == 0 )
	{
		m_nIndexCurrent	=	m_nIndexStart	=	m_nIndexEnd	=	-1;
		return FALSE;
	}

	// Check Old Values
	ASSERT( m_nIndexStart <= m_nIndexEnd );
	ASSERT( m_nIndexCurrent < 0 || (m_nIndexCurrent >= m_nIndexStart && m_nIndexCurrent <= m_nIndexEnd) );
	if( m_nIndexCurrent >= 0 && (m_nIndexCurrent < m_nIndexStart || m_nIndexCurrent > m_nIndexEnd) )
		m_nIndexCurrent	=	-1;

	if( -1 == m_nIndexStart || -1 == m_nIndexEnd )
	{
		m_nIndexEnd	=	kdata.GetSize()-1;
	}
	else if( m_nIndexEnd - m_nIndexStart + 1 < nCount )
	{
		// Reset m_nIndexStart and m_nIndexEnd
		int	nExpand	=	nCount-(m_nIndexEnd-m_nIndexStart+1);
		if( m_nIndexCurrent >= 0 && m_nIndexEnd-m_nIndexStart > 0 )
			m_nIndexEnd		+=	(m_nIndexEnd-m_nIndexCurrent)*nExpand / (m_nIndexEnd-m_nIndexStart);
	}
	else if( m_nIndexEnd - m_nIndexStart + 1 > nCount )
	{
		int	nReduce	=	(m_nIndexEnd-m_nIndexStart+1)-nCount;
		if( m_nIndexCurrent >= 0 && m_nIndexEnd-m_nIndexStart > 0 )
			m_nIndexEnd		-=	(m_nIndexEnd-m_nIndexCurrent)*nReduce / (m_nIndexEnd-m_nIndexStart);
	}
	if( m_nIndexEnd >= kdata.GetSize() )
		m_nIndexEnd	=	kdata.GetSize()-1;
	m_nIndexStart	=	m_nIndexEnd - nCount + 1;
	if( m_nIndexStart < 0 )
	{
		m_nIndexEnd		+=	(-m_nIndexStart);
		m_nIndexStart	=	0;
	}
	if( m_nIndexEnd >= kdata.GetSize() )
		m_nIndexEnd	=	kdata.GetSize()-1;

	ASSERT( m_nIndexStart <= m_nIndexEnd );
	ASSERT( m_nIndexCurrent < 0 || (m_nIndexCurrent >= m_nIndexStart && m_nIndexCurrent <= m_nIndexEnd) );
	if( m_nIndexStart > m_nIndexEnd )
		return FALSE;
	if( m_nIndexCurrent >= 0 && (m_nIndexCurrent < m_nIndexStart || m_nIndexCurrent > m_nIndexEnd) )
		m_nIndexCurrent	=	-1;

	return TRUE;
}

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

	CKData	&	kdata	=	m_CurStock.GetKData(m_nCurKType);
	if( 0 == kdata.GetSize() )
	{
		CString	strNoKData, strTemp;
		strNoKData.LoadString( IDS_STOCKGRAPH_NOKDATA );
		strTemp		=	CString(m_CurStock.GetStockInfo().GetStockName()) + "(" + m_CurStock.GetStockInfo().GetStockCode() + ")";
		strTemp		+=	(LPCTSTR)AfxGetKTypeString( m_nCurKType );
		strNoKData	=	strTemp + strNoKData;
		CFont	* pOldFont	=	AfxSelectDCFont( pDC, 14 );
		pDC->SetBkColor( clrBK );
		pDC->SetTextColor( clrTitle );
		pDC->TextOut( m_rectAll.left+20, m_rectAll.top+20,  strNoKData );
		pDC->SelectObject( pOldFont );
	}
}

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;
	CFont	* pOldFont	=	AfxSelectDCFont( pDC, 12 );
	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;
				}
			}
		}
	}
	pDC->SelectObject( pOldFont );
}

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.LoadString( IDS_STOCKGRAPH_KLINE );
	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;

	// Draw STT_DJ and STT_CW
	CSPDWordArray	&	anTech	=	AfxGetProfile().GetGraphTechsKLine( );
	for( int 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( int 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( int 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 ) )
		{

⌨️ 快捷键说明

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