📄 stockgraph.cpp
字号:
// StockGraph.cpp : implementation of the CStockGraph class
//
#include "stdafx.h"
#include "StockGraph.h"
#include <math.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// Some Useful static function
void DrawLine( CDC * pDC, int nWidth, COLORREF clr, int xStart, int yStart, int xEnd, int yEnd )
{
CPen pen( PS_SOLID, nWidth, clr );
CPen *pOldPen = pDC->SelectObject( &pen );
pDC->MoveTo( xStart, yStart );
pDC->LineTo( xEnd, yEnd );
pDC->SelectObject( pOldPen );
}
void DrawDashLine( CDC * pDC, int nWidth, COLORREF clr, int xStart, int yStart, int xEnd, int yEnd )
{
CPen pen( PS_SOLID, nWidth, clr );
CPen *pOldPen = pDC->SelectObject( &pen );
int x = xStart, y = yStart;
while( x < xEnd || y < yEnd )
{
if( x > xEnd ) x = xEnd;
if( y > yEnd ) y = yEnd;
pDC->MoveTo( x, y );
int xNew = x+3;
int yNew = y+3;
if( xNew > xEnd ) xNew = xEnd;
if( yNew > yEnd ) yNew = yEnd;
pDC->LineTo( xNew, yNew );
x = xNew+3;
y = yNew+3;
}
pDC->SelectObject( pOldPen );
}
void DrawDashAxis( CDC * pDC, int nWidth, COLORREF clr, int nCount, int xStart, int yStart, int xEnd, int yEnd )
{
int nHeight = yEnd - yStart;
if( nHeight <= 0 )
return;
if( nCount <= 0 )
return;
for( int k=0; k<nCount; k++ )
DrawDashLine( pDC, nWidth, clr, xStart, yStart+k*nHeight/nCount, xEnd, yStart+k*nHeight/nCount );
}
void DrawAxisNumber(CDC * pDC, COLORREF clr, int nCount,
int xStart, int yStart, int xEnd, int yEnd,
double fMin, double fMax, BOOL bDrawMin, BOOL bDrawMax, int nDotCount )
{
int nHeight = yEnd - yStart;
if( nHeight <= 0 )
return;
if( nCount <= 0 )
return;
ASSERT( nDotCount >= 0 );
CString strFmt;
strFmt.Format( "%%.%df", nDotCount );
pDC->SetTextColor( clr );
CString strText;
CSize sizeText;
for( int k=0; k<=nCount; k++ )
{
if( !bDrawMin && 0 == k )
continue;
if( !bDrawMax && nCount == k )
continue;
double dTemp = fMin+k*(fMax-fMin)/nCount;
if( dTemp < 0 && dTemp > (0-0.6*pow((double)10,0-nDotCount)) )
dTemp = 0;
strText.Format( strFmt, dTemp );
sizeText = pDC->GetTextExtent( strText );
pDC->TextOut( xStart-sizeText.cx-1, yStart+(nCount-k)*nHeight/nCount-7, strText );
}
}
BOOL DrawAxis(CDC * pDC, CRect rect, int nMarginTop, int nAxisLines, double dMin, double dMax, BOOL bDrawMin, BOOL bDrawMax, int nDotCount )
{
DECLARE_COLOR_DEFINATION
if( rect.Height() <= nMarginTop )
return FALSE;
// Draw Axis
pDC->Draw3dRect( &rect, clrBorder, clrBorder );
DrawDashAxis( pDC, 1, clrBorder, nAxisLines,
rect.left, rect.top+nMarginTop, rect.right, rect.bottom );
// Draw Axis Number, Will Extent the rect
pDC->SetBkColor( clrBK );
DrawAxisNumber( pDC, clrText, nAxisLines,
rect.left, rect.top+nMarginTop, rect.right, rect.bottom,
dMin, dMax, bDrawMin, bDrawMax, nDotCount );
return TRUE;
}
BOOL DrawTechTitle(CDC * pDC, int x, int y, LPCTSTR lpszText,
UINT nTextAlign, int nFontSize, COLORREF clrBK, COLORREF clrText )
{
pDC->SetBkColor( clrBK );
pDC->SetTextColor( clrText );
UINT nOldAlign = pDC->SetTextAlign( nTextAlign );
pDC->TextOut( x, y, lpszText );
pDC->SetTextAlign( nOldAlign );
return TRUE;
}
BOOL FixRect( CRect & rect, LPRECT lpRectMax )
{
if( lpRectMax )
{
if( rect.left < lpRectMax->left )
rect.left = lpRectMax->left;
if( rect.top < lpRectMax->top )
rect.top = lpRectMax->top;
if( rect.right > lpRectMax->right )
rect.right = lpRectMax->right;
if( rect.bottom > lpRectMax->bottom )
rect.bottom = lpRectMax->bottom;
return TRUE;
}
return FALSE;
}
BOOL DrawTextWithRect(CDC *pDC, int left, int top, int right, int bottom, LPCTSTR lpszText,
COLORREF clrRect, COLORREF clrText, COLORREF clrBK, LPRECT lpRectMax )
{
CRect rectDraw = CRect( left, top, right, bottom );
if( lpRectMax )
FixRect( rectDraw, lpRectMax );
pDC->Draw3dRect( &rectDraw, clrRect, clrRect );
pDC->SetTextColor( clrText );
pDC->SetBkColor( clrBK );
pDC->DrawText( lpszText, rectDraw, DT_CENTER | DT_VCENTER | DT_SINGLELINE );
return TRUE;
}
BOOL DrawTextWithRect(CDC *pDC, int left, int top, int right, int bottom, UINT nIDString,
COLORREF clrRect, COLORREF clrText, COLORREF clrBK, LPRECT lpRectMax )
{
CString string;
string.LoadString( nIDString );
return DrawTextWithRect( pDC, left, top, right, bottom, string, clrRect, clrText, clrBK, lpRectMax );
}
/////////////////////////////////////////////////////////////////////////////
// CStockGraph
CStockGraph::CStockGraph( )
{
ResetMargins( );
m_pParent = NULL;
m_nThickness = m_nDefaultThickness;
m_dwLatestDate = -1;
m_ptSelectBegin = CPoint(0,0);
m_ptSelectEnd = CPoint(0,0);
m_nReportWhat = CStockGraph::reportParam;
SetKType( );
SetKFormat( AfxGetProfile().GetGraphKFormat() );
SetMaindataType( AfxGetProfile().GetGraphMaindataType() );
#ifdef CLKLAN_ENGLISH_US
SetKLineMode( CStockGraph::klineAmerica );
#else
SetKLineMode( CStockGraph::klineCandle );
#endif
ResetIndex( );
m_rectAll.SetRectEmpty();
m_dMaxPrice = 0;
m_dMinPrice = 0;
m_bCursorBorder = FALSE;
m_nSelectedTechID = STT_INVALID;
}
CStockGraph::~CStockGraph( )
{
ClearCurStock( );
}
void CStockGraph::SetParent( CWnd * pParent )
{
m_pParent = pParent;
}
void CStockGraph::ResetMargins( int nMarginTop, int nMarginBottom,
int nHeightSubtitle, int nWidthSubtitle,
int nWidthParameter, int nDefaultThickness )
{
ASSERT( nMarginTop >= 0 && nMarginBottom >= 0 );
ASSERT( nHeightSubtitle >= 0 && nWidthSubtitle >= 0 );
ASSERT( nWidthParameter >= 0 );
ASSERT( nDefaultThickness > 0 );
m_nMarginTop = nMarginTop;
m_nMarginBottom = nMarginBottom;
m_nHeightSubtitle = nHeightSubtitle + 2;
m_nWidthSubtitle = nWidthSubtitle;
m_nWidthParameter = nWidthParameter;
m_nDefaultThickness = nDefaultThickness;
}
LRESULT CStockGraph::OnStkReceiverData( WPARAM wParam, LPARAM lParam )
{
PCOMMPACKET pCommPacket = (PCOMMPACKET)lParam;
switch( wParam )
{
case CStock::dataReport:
if( pCommPacket && CStock::dataReport == pCommPacket->m_dwDataType )
{
DWORD i;
for( i=0; i<pCommPacket->m_dwCount; i++ )
{
if( m_CurStock.GetStockInfo().IsEqualTo( pCommPacket->m_pReport[i].m_dwMarket, pCommPacket->m_pReport[i].m_szCode ) )
break;
}
if( i != pCommPacket->m_dwCount )
{
// 加入最新一天的K线数据
PrepareStockData( TRUE );
if( m_pParent && ::IsWindow(m_pParent->GetSafeHwnd()) )
m_pParent->Invalidate();
}
}
break;
case CStock::dataK:
if( pCommPacket && CStock::dataK == pCommPacket->m_dwDataType )
{
DWORD i;
for( i=0; i<pCommPacket->m_dwCount; i++ )
{
if( m_CurStock.GetStockInfo().IsEqualTo( pCommPacket->m_pKdata[i].m_dwMarket, pCommPacket->m_pKdata[i].m_szCode ) )
break;
}
if( i != pCommPacket->m_dwCount )
{
// 加入最新一天的K线数据
PrepareStockData( TRUE );
if( m_pParent && ::IsWindow(m_pParent->GetSafeHwnd()) )
m_pParent->Invalidate();
}
}
break;
case CStock::dataMinute:
// WILLCHECK
if( !CKData::IsDayOrMin(m_nCurKType) && pCommPacket && CStock::dataMinute == pCommPacket->m_dwDataType )
{
int nOldSize = m_CurStock.GetMinute().GetSize();
DWORD i;
for(i=0; i<pCommPacket->m_dwCount; i++)
{
if( m_CurStock.GetStockInfo().IsEqualTo( pCommPacket->m_pMinute[i].m_dwMarket, pCommPacket->m_pMinute[i].m_szCode ) )
break;
}
if( i != pCommPacket->m_dwCount )
{
// 加入最新的分钟K线数据
PrepareStockData( TRUE );
if( m_pParent && ::IsWindow(m_pParent->GetSafeHwnd()) )
m_pParent->Invalidate();
}
}
break;
}
return 0L;
}
int CStockGraph::GetKType( )
{
return m_nCurKType;
}
void CStockGraph::SetKType( int ktype )
{
m_nCurKType = ktype;
PrepareStockData( );
}
int CStockGraph::GetKFormat( )
{
return m_nCurKFormat;
}
void CStockGraph::SetKFormat( int kformat )
{
m_nCurKFormat = kformat;
AfxGetProfile().SetGraphKFormat( kformat );
PrepareStockData( );
}
int CStockGraph::GetMaindataType( )
{
return m_nCurMaindataType;
}
void CStockGraph::SetMaindataType( int maindatatype )
{
m_nCurMaindataType = maindatatype;
AfxGetProfile().SetGraphMaindataType( maindatatype );
PrepareStockData( );
}
int CStockGraph::GetKLineMode( )
{
return m_nCurKLineMode;
}
void CStockGraph::SetKLineMode( int klineMode )
{
m_nCurKLineMode = klineMode;
}
CRect & CStockGraph::GetKDataRect( )
{
return m_rectKData;
}
void CStockGraph::ResetIndexCurrent( int nIndexCurrent )
{
m_nIndexCurrent = nIndexCurrent;
m_anIndexCurrent.RemoveAll();
}
void CStockGraph::ResetIndex( int nIndexStart, int nIndexEnd, int nIndexCurrent )
{
m_nIndexStart = nIndexStart;
m_nIndexEnd = nIndexEnd;
m_nIndexCurrent = nIndexCurrent;
m_anIndexCurrent.RemoveAll();
}
void CStockGraph::ResetClient( CRect rectAll )
{
if( rectAll.IsRectEmpty() )
return;
m_rectAll = rectAll;
if( m_rectAll.IsRectEmpty() )
return;
// The Left Side m_rectKData
m_rectKData.top = m_rectAll.top + m_nMarginTop+m_nMarginTop;
m_rectKData.left = m_rectAll.left+1;
m_rectKData.bottom = m_rectKData.top + 313;
m_rectKData.right = m_rectKData.left + 82;
// The Right Side m_rectReport
m_rectReport.top = m_rectAll.top + m_nMarginTop+7;
m_rectReport.left = m_rectAll.right - 174;
m_rectReport.bottom = m_rectAll.bottom - m_nMarginBottom;
m_rectReport.right = m_rectAll.right;
// The Center m_rectKLine
CSPDWordArray & anTech = AfxGetProfile().GetGraphTechsShow();
int nTechCount = anTech.GetSize();
int nUnit = (int)( (m_rectAll.Height()-m_nMarginTop-m_nMarginBottom) / (nTechCount+1.8) );
m_rectKLine.top = m_rectAll.top + m_nMarginTop;
m_rectKLine.left = m_rectKData.right+1;
m_rectKLine.bottom = m_rectKLine.top + m_rectAll.Height() - m_nMarginTop - m_nMarginBottom - nUnit*nTechCount;
m_rectKLine.right = m_rectAll.right-m_rectReport.Width()-1;
// The m_rectKLineCenter
m_rectKLineCenter = m_rectKLine;
m_rectKLineCenter.InflateRect( -2, -m_nHeightSubtitle, -2, -2 );
// The m_arcTech
m_arcTech.RemoveAll();
int nLastBottom = m_rectKLine.bottom;
for( int k=0; k<anTech.GetSize(); k++ )
{
CRect rectTech;
rectTech.top = nLastBottom;
rectTech.left = m_rectKLine.left;
rectTech.bottom = rectTech.top + nUnit;
rectTech.right = m_rectKLine.right;
nLastBottom = rectTech.bottom;
m_arcTech.Add( rectTech );
}
// The m_rectCenter
m_rectCenter = m_rectKLine;
m_rectCenter.bottom = m_rectAll.bottom;
}
void CStockGraph::ClearTechniqueCache( )
{
m_techparam.Clear();
for( int i=0; i<m_aptrTechUser.GetSize(); i++ )
{
CTechUser * pTechUser = (CTechUser *)m_aptrTechUser.GetAt(i);
if( pTechUser )
delete pTechUser;
}
m_aptrTechUser.RemoveAll();
}
void CStockGraph::ClearCurStock( )
{
ClearTechniqueCache( );
m_CurStock.Clear();
m_CurStockDown.Clear();
}
BOOL CStockGraph::SetCurStock( const char * szCode )
{
if( NULL == szCode || strlen(szCode) <= 0 )
{
ASSERT( FALSE );
return FALSE;
}
CStockInfo info;
if( !AfxGetStockContainer().GetStockInfo( szCode, &info ) )
{
ASSERT( FALSE );
return FALSE;
}
return SetCurStock( info );
}
BOOL CStockGraph::SetCurStock( CStockInfo & info )
{
if( m_CurStock.GetStockInfo().IsEqualTo( info.GetMarket(), info.GetStockCode() ) )
{
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -