?? realtime.cpp
字號:
// RealTime.cpp : implementation of the CRealTime class
//
#include "stdafx.h"
#include "RealTime.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define TOOLBARHIGHT 20
BOOL bShowReport = FALSE;
#define RT_DETERMINE_COLOR(x,y) ((x)-(y)>1e-4?clrRise:((x)-(y)<1e-4?clrFall:clrPlane))
void DrawPriceAxisNumber(CDC * pDC, COLORREF clr, int nCount,
int xStart, int yStart, int xEnd, int yEnd,
double dLastClose, double fMin, double fMax, 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++ )
{
double dCur = fMin+k*(fMax-fMin)/nCount;
if( dCur < 0 && dCur > (0-0.6*pow((double)10,0-nDotCount)) )
dCur = 0;
strText.Format( strFmt, dCur );
sizeText = pDC->GetTextExtent( strText );
pDC->TextOut( xStart-sizeText.cx-1, yStart+(nCount-k)*nHeight/nCount-7, strText );
}
}
BOOL DrawPriceVolumeAxis( CDC * pDC, CRect rectPrice, CRect rectVolume,
int nGapYAxis, double dLastClose, double * pdMin, double * pdMax, double dMaxVolume, int nDotCount )
{
DECLARE_COLOR_DEFINATION
ASSERT( pdMin && pdMax );
if( NULL == pdMin || NULL == pdMax )
return FALSE;
if( rectPrice.Height() <= 0 || rectPrice.Width() <= 0 )
return FALSE;
if( rectVolume.Height() <= 0 || rectVolume.Width() <= 0 )
return FALSE;
ASSERT( rectPrice.left == rectVolume.left && rectPrice.right == rectVolume.right );
ASSERT( nDotCount >= 0 );
if( nGapYAxis <= 0 || nDotCount < 0 )
return FALSE;
if( dLastClose < 1e-4 )
dLastClose = (*pdMin+*pdMax)/2;
// 重新修正 *pdMin, *pdMax
int nPriceLines = 2*((rectPrice.Height()/2)/nGapYAxis);
int nVolumeLines = 2*((rectVolume.Height()/2)/nGapYAxis);
double dABS = max(fabs(*pdMax-dLastClose),fabs(*pdMin-dLastClose));
double dPrecision = pow((double)10,0-nDotCount);
if( dABS < dPrecision*nPriceLines )
dABS = dPrecision*nPriceLines;
else if( dABS < 2*dPrecision*nPriceLines )
dABS = 2*dPrecision*nPriceLines;
else if( dABS < 3*dPrecision*nPriceLines )
dABS = 3*dPrecision*nPriceLines;
*pdMin = dLastClose-dABS;
*pdMax = dLastClose+dABS;
// Draw Border
pDC->Draw3dRect( &rectPrice, clrBorder, clrBorder );
pDC->Draw3dRect( &rectVolume, clrBorder, clrBorder );
int k=0;
// Draw Lines
for( k=0; k<nPriceLines; k++ )
DrawLine( pDC, 1, clrBorder, rectPrice.left, rectPrice.top+k*rectPrice.Height()/nPriceLines, rectPrice.right, rectPrice.top+k*rectPrice.Height()/nPriceLines );
DrawLine( pDC, 2, clrBorder, rectPrice.left, rectPrice.top+rectPrice.Height()/2, rectPrice.right, rectPrice.top+rectPrice.Height()/2 );
for( k=0; k<nVolumeLines; k++ )
DrawLine( pDC, 1, clrBorder, rectVolume.left, rectVolume.top+k*rectVolume.Height()/nVolumeLines, rectVolume.right, rectVolume.top+k*rectVolume.Height()/nVolumeLines );
// Draw Columns
for( k=1; k<=8; k++ )
{
if( k % 2 )
DrawDashLine( pDC, 1, clrBorder, rectPrice.left+k*rectPrice.Width()/8, rectPrice.top, rectPrice.left+k*rectPrice.Width()/8, rectVolume.bottom );
else
DrawLine( pDC, 1, clrBorder, rectPrice.left+k*rectPrice.Width()/8, rectPrice.top, rectPrice.left+k*rectPrice.Width()/8, rectVolume.bottom );
}
// Draw Price Axis Number, Will Extent the rect
CFont * pOldFont = AfxSelectDCFont( pDC, 12 );
pDC->SetBkColor( clrBK );
CSize sizeText;
CString strFmt, strText;
strFmt.Format( "%%.%df", nDotCount );
double dMinAxis = dLastClose-dABS;
double dMaxAxis = dLastClose+dABS;
for( k=0; k<=nPriceLines && nPriceLines>0; k++ )
{
double dCur = dMinAxis+k*(dMaxAxis-dMinAxis)/nPriceLines;
COLORREF clr = clrPlane;
if( dCur-dLastClose > 1e-4)
clr = clrRise;
if( dCur-dLastClose < -1e-4 )
clr = clrFall;
if( dCur < 0 && dCur > (-0.51*pow((double)10,0-nDotCount)) )
dCur = 0;
strText.Format( strFmt, dCur );
sizeText = pDC->GetTextExtent( strText );
pDC->SetTextColor( clr );
pDC->TextOut( rectPrice.left-sizeText.cx-1, rectPrice.top+(nPriceLines-k)*rectPrice.Height()/nPriceLines-7, strText );
double dCurPercent = 0.00;
if( dLastClose > 1e-4 )
dCurPercent = 100*fabs(dCur-dLastClose)/dLastClose;
strText.Format( "%.2f%%", dCurPercent );
pDC->TextOut( rectPrice.right+3, rectPrice.top+(nPriceLines-k)*rectPrice.Height()/nPriceLines-7, strText );
}
// Draw Volume Axis Number
DrawAxisNumber( pDC, clrPlane, nVolumeLines, rectVolume.left, rectVolume.top, rectVolume.right, rectVolume.bottom,
0, dMaxVolume/100/*成交量手數*/, FALSE, FALSE, 0 );
pDC->SelectObject( pOldFont );
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CRealTime
#define RT_RDTITLE_HEIGHT 24
#define RT_RDELEMENT_HEIGHT 16
#define RT_RDCOLUMN_WIDTH 220
CRealTime::CRealTime( )
{
m_pParent = NULL;
m_nDrawMode = CRealTime::modePriceLine;
m_nReportWhat = CRealTime::reportQuote;
m_nTechLine = CRealTime::techNone;
m_nIndexCurrent = -1;
m_nCurrentStartPos = -1;
m_nCurrentPageCount = -1;
m_nCurrentSelectPos = -1;
m_dMaxPrice = 0;
m_dMinPrice = 0;
ResetMargins( );
ResetIndexCurrent( );
}
CRealTime::~CRealTime( )
{
ClearCurStock();
}
void CRealTime::SetParent( CWnd * pParent )
{
m_pParent = pParent;
}
void CRealTime::ResetMargins( int nMarginTop, int nMarginLeft,
int nMarginCenter, int nMarginBottom,
int nGapYAxis, int nWidthReport )
{
ASSERT( nMarginTop >= 0 && nMarginLeft >= 0 );
ASSERT( nMarginCenter >= 0 && nMarginBottom >= 0 );
ASSERT( nGapYAxis > 0 );
ASSERT( nWidthReport >= 0 );
m_nMarginTop = nMarginTop;
m_nMarginLeft = nMarginLeft;
m_nMarginCenter = nMarginCenter;
m_nMarginBottom = nMarginBottom;
m_nGapYAxis = nGapYAxis;
m_nWidthReport = nWidthReport;
if( m_nGapYAxis <= 0 )
m_nGapYAxis = 18;
}
void CRealTime::ClearCurStock( )
{
m_CurStock.Clear();
}
BOOL CRealTime::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 CRealTime::SetCurStock( CStockInfo & info )
{
if( m_CurStock.GetStockInfo().IsEqualTo( info.GetMarket(), info.GetStockCode() ) )
{
return TRUE;
}
ResetIndexCurrent( );
ClearCurStock();
m_CurStock.SetStockInfo( &info );
return TRUE;
}
BOOL CRealTime::PrepareStockData( )
{
m_CurStock.GetReport().RemoveAll();
m_CurStock.GetMinute().RemoveAll();
m_CurStock.GetOutline().RemoveAll();
// 讀取本地文件
m_CurStock.SetDatabase( &AfxGetDB() );
// 取得最新行情
m_CurStock.PrepareData( CStock::dataReport, CKData::ktypeDay, TRUE );
m_CurStock.PrepareData( CStock::dataMinute, CKData::ktypeDay, TRUE );
m_CurStock.PrepareData( CStock::dataOutline, CKData::ktypeDay, TRUE );
AfxGetStkReceiver().GetReport( m_CurStock.GetStockInfo(), m_CurStock.GetReport() );
int nLen = m_CurStock.GetReport().GetSize();
if( nLen > 0 )
UpdateStockInfoByREPORT( m_CurStock.GetStockInfo(), &(m_CurStock.GetReport().ElementAt(nLen-1)) );
return TRUE;
}
void CRealTime::SetDrawMode( int nDrawMode, int nTechLine, int nReportWhat )
{
m_nDrawMode = nDrawMode;
m_nTechLine = nTechLine;
m_nReportWhat = nReportWhat;
m_nCurrentStartPos = -1;
m_nCurrentPageCount = -1;
m_nCurrentSelectPos = -1;
}
int CRealTime::GetDrawMode( )
{
return m_nDrawMode;
}
int CRealTime::GetDrawTechLine( )
{
return m_nTechLine;
}
int CRealTime::GetReportWhat( )
{
return m_nReportWhat;
}
LRESULT CRealTime::OnStkReceiverData( WPARAM wParam, LPARAM lParam )
{
PCOMMPACKET pCommPacket = (PCOMMPACKET)lParam;
switch( wParam )
{
case CStock::dataReport:
if( pCommPacket && CStock::dataReport == pCommPacket->m_dwDataType )
{
BOOL bInv = FALSE;
for(DWORD i=0; i<pCommPacket->m_dwCount; i++)
{
if( m_CurStock.GetStockInfo().IsEqualTo( pCommPacket->m_pReport[i].m_dwMarket, pCommPacket->m_pReport[i].m_szCode ) )
{
UpdateStockInfoByREPORT( m_CurStock.GetStockInfo(), &(pCommPacket->m_pReport[i]) );
if( -1 != m_CurStock.GetReport().InsertReportSort( pCommPacket->m_pReport[i] ) )
{
MINUTE minute;
if( convert_REPORT_to_MINUTE( &(pCommPacket->m_pReport[i]), &minute ) )
m_CurStock.GetMinute().InsertMinuteSort( minute );
m_nCurrentStartPos = -1;
bInv = TRUE;
}
}
}
if( bInv && m_pParent && ::IsWindow(m_pParent->GetSafeHwnd()) )
m_pParent->Invalidate();
}
break;
case CStock::dataMinute:
if( pCommPacket && CStock::dataMinute == pCommPacket->m_dwDataType )
{
int nOldSize = m_CurStock.GetMinute().GetSize();
for(DWORD i=0; i<pCommPacket->m_dwCount; i++)
{
if( m_CurStock.GetStockInfo().IsEqualTo( pCommPacket->m_pMinute[i].m_dwMarket, pCommPacket->m_pMinute[i].m_szCode ) )
m_CurStock.GetMinute().InsertMinuteSort( pCommPacket->m_pMinute[i] );
}
if( nOldSize != m_CurStock.GetMinute().GetSize() && m_pParent && ::IsWindow(m_pParent->GetSafeHwnd()) )
{
m_nCurrentStartPos = -1;
m_pParent->Invalidate();
}
}
break;
}
return 0L;
}
void CRealTime::Redraw( CDC * pDC, CRect rectAll )
{
ASSERT( m_pParent && ::IsWindow( m_pParent->GetSafeHwnd() ) );
if( !m_pParent || !::IsWindow(m_pParent->GetSafeHwnd()) )
return;
CClientDC dc(m_pParent);
if( NULL == pDC )
pDC = &dc;
ResetClient( rectAll );
pDC->FillSolidRect( &rectAll, AfxGetProfile().GetColor(CColorClass::clrGraphBK) );
if( CRealTime::modePriceLine == m_nDrawMode )
{
DrawPriceVolume( pDC );
DrawLBDK( pDC );
DrawMMLD( pDC );
DrawReportRegion( pDC );
DrawSelectionLine( pDC, TRUE );
OnIndexCurrentChanged( );
}
else if( CRealTime::modeReportDetail == m_nDrawMode )
{
DrawReportDetail( pDC );
}
else if( CRealTime::modeMinuteDetail == m_nDrawMode )
{
DrawMinuteDetail( pDC );
}
else if( CRealTime::modeBigTradeDetail == m_nDrawMode )
{
DrawBigTradeDetail( pDC );
}
}
void CRealTime::DrawReportRegion( CDC * pDC )
{
ASSERT( m_pParent && ::IsWindow( m_pParent->GetSafeHwnd() ) );
if( !m_pParent || !::IsWindow(m_pParent->GetSafeHwnd()) )
return;
CClientDC dc(m_pParent);
if( NULL == pDC )
pDC = &dc;
if( CRealTime::modePriceLine == m_nDrawMode )
{
switch( m_nReportWhat )
{
case CRealTime::reportQuote: DrawReportQuote( pDC ); break;
case CRealTime::reportPrice: DrawReportPrice( pDC ); break;
case CRealTime::reportMinute: DrawReportMinute( pDC ); break;
case CRealTime::reportBuySellEx: DrawReportBuySellEx( pDC ); break;
case CRealTime::reportValue: DrawReportValue( pDC ); break;
case CRealTime::reportDistribute: DrawReportDistribute( pDC ); break;
case CRealTime::reportBigTrade: DrawReportBigTrade( pDC ); break;
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
// 以下為分時價格線使用 modePriceLine
void CRealTime::MoveLeft( BOOL bShiftPressed )
{
if( CRealTime::modePriceLine != m_nDrawMode )
return;
Move( -1, bShiftPressed, FALSE );
}
void CRealTime::MoveRight( BOOL bShiftPressed )
{
if( CRealTime::modePriceLine != m_nDrawMode )
return;
Move( 1, bShiftPressed, FALSE );
}
void CRealTime::MoveUp( BOOL bShiftPressed )
{
if( CRealTime::modePriceLine == m_nDrawMode )
{
int nTotalSize = 0;
if( CRealTime::reportQuote == m_nReportWhat )
nTotalSize = m_CurStock.GetReport().GetSize();
// else if( CRealTime::reportPrice == m_nReportWhat )
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -