G:\stock\TskingVS2019\src\Client\StkUI\View\HistoryRealTimeView.cpp
思路:
step 1.在主程序Main.cpp启动时创建行情回放工具条(实际为1个窗口程序)
step 2:在src\Client\StkUI\View\HistoryRealTimeView.cpp中添加对实现对播放工具条每个按钮点击事件的函数。
step 3:设计1个定时器对数据每隔3秒刷新,按钮事件控制定时器的刷新间隔
先备份数据,清空原数据。利用定时器中填入原始数据后,调用Invalidate()。视图就会更新。
第一部分 新增加一个工具条资源IDR_REPLAY ToolBar
略
第二部分 在主程序中创建\启用行情回放工具条(实际为1个窗口)
首先,要在主程序中把工具条创建出来
step 1:在MainFrm.cpp中添加对CPlayBackView.h类的引用
/*****custom extend 播放工具条**********/
CToolBar m_wndPlaybackBar;
/************end********************/
step 2:创建行情播放工具条窗口
G:\stock\TskingVS2019\src\Client\StkUI\MainFrm.cpp
/*****custom extend 播放工具条**********/
BOOL CMainFrame::CreatePlaybackBar()
{
if (!m_wndPlaybackBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC, CRect(0, 0, 0, 0), IDW_PERIODBAR)
|| !m_wndPlaybackBar.LoadToolBar(IDR_REPLAY))
{
TRACE0("Failed to create periodbar\n");
return FALSE; // fail to create
}
#if 0
CString strBarTitle;
strBarTitle.LoadString(IDS_TITLE_PERIODBAR);
m_wndPeriodBar.SetWindowText(strBarTitle);
#endif
return TRUE;
}
至此,在程序启动时,行情回放工具条已经准备好了。
第三部分 在历史行情分时图视图程序中添加对按钮事件的处理
首先定义消息
G:\stock\TskingVS2019\src\Client\StkUI\View\HistoryRealTimeView.h
/*************custom extend 工具条 by freema*******/
afx_msg void OnPlaybackBegin();
afx_msg void OnPlaybackEnd();
afx_msg void OnPlaybackForward();
afx_msg void OnPlaybackPause();
afx_msg void OnPlaybackFastfw();
afx_msg void OnPlaybackFastrev();
afx_msg void OnPlaybackStop();
/*************************************************/
然后,将按钮和消息一一对应
G:\stock\TskingVS2019\src\Client\StkUI\View\HistoryRealTimeView.cpp
/*************custom extend 行情回放播放工具条 by freema*******/
ON_COMMAND(ID_PLAYBACK_BEGIN, OnPlaybackBegin)
ON_COMMAND(ID_PLAYBACK_END, OnPlaybackEnd)
ON_COMMAND(ID_PLAYBACK_FORWARD, OnPlaybackForward)
ON_COMMAND(ID_PLAYBACK_PAUSE, OnPlaybackPause)
ON_COMMAND(ID_PLAYBACK_FASTFW, OnPlaybackFastfw)
ON_COMMAND(ID_PLAYBACK_FASTREV, OnPlaybackFastrev)
ON_COMMAND(ID_PLAYBACK_STOP, OnPlaybackStop)
/*****************************************/
最后,在HistoryRealTimeView.cpp中药实现各按钮的点击事件处理。
G:\stock\TskingVS2019\src\Client\StkUI\View\HistoryRealTimeView.cpp
/*************custom extend 工具条 by freema*******/
void CHistoryRealTimeView::OnPlaybackBegin()
{
}
void CHistoryRealTimeView::OnPlaybackEnd()
{
}
void CHistoryRealTimeView::OnPlaybackForward()
{
m_realtime[0].m_nCurrentStartPos2 = 0;
}
void CHistoryRealTimeView::OnPlaybackPause()
{
KillTimer(RTV_TIMER_REFRESHHISTORYREPLY);
}
void CHistoryRealTimeView::OnPlaybackFastfw()
{
KillTimer(RTV_TIMER_REFRESHHISTORYREPLY);
m_timer = m_timer - 500;
if (m_timer <= 0)
m_timer = 10;
SetTimer(RTV_TIMER_REFRESHHISTORYREPLY, m_timer, NULL);
}
void CHistoryRealTimeView::OnPlaybackFastrev()
{
KillTimer(RTV_TIMER_REFRESHHISTORYREPLY);
m_timer = m_timer + 500;
SetTimer(RTV_TIMER_REFRESHHISTORYREPLY, m_timer, NULL);
}
void CHistoryRealTimeView::OnPlaybackStop()
{
}
/*****/
第四部分 为回放视图添加功能
1.在主程中序添加支持键盘精灵
src/Client/StkUI/MainFrm.cpp
@@ -1248,7 +1248,7 @@ BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
|| pView->IsKindOf(RUNTIME_CLASS(CSListView))
|| pView->IsKindOf(RUNTIME_CLASS(CBaseView))
|| pView->IsKindOf(RUNTIME_CLASS(CSelectorView))
|| pView->IsKindOf(RUNTIME_CLASS(CPlayBackView))))
|| pView->IsKindOf(RUNTIME_CLASS(CPlayBackView)))) //add 添加对行情回放视图对键盘精灵的支持 by freeman
{
CRect rect;
GetClientRect(&rect);
@@ -1266,7 +1266,7 @@ BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
|| pView->IsKindOf(RUNTIME_CLASS(CRealTimeView))
|| pView->IsKindOf(RUNTIME_CLASS(CMultiSortView))
|| pView->IsKindOf(RUNTIME_CLASS(CSListView))
|| pView->IsKindOf(RUNTIME_CLASS(CPlayBackView))))
|| pView->IsKindOf(RUNTIME_CLASS(CPlayBackView)))) //add 添加对行情回放视图对键盘精灵的支持 by freeman
pView->SetFocus();
}
}
2.修改窗口里的标题提示文字
G:\stock\TskingVS2019\src\Client\StkUI\resource.h
ID值定义
/* *** extend 提示字符串 by freeman ****/
//行情回放
#define IDS_TITLE_REPLAYREALTIMEVIEW 46000
#define IDS_REPLAYEALTIME_TITLE 46001
//历史行情
#define IDS_TITLE_HISTORYREALTIMEVIEW 46010
#define IDS_HISTORYREALTIME_TITLE 46011
/**************************************/
提示字符串
/************custonm extend 字符串定义 by freeman***********************************/
STRINGTABLE
BEGIN
IDS_TITLE_HISTORYREALTIMEVIEW "历史行情"
IDS_HISTORYREALTIME_TITLE "历史行情"
END
STRINGTABLE
BEGIN
IDS_TITLE_REPLAYREALTIMEVIEW "行情回放"
IDS_REPLAYEALTIME_TITLE "行情回放"
END
/**********************************************************************************/
修改窗口标题提示
G:\stock\TskingVS2019\src\Client\StkUI\View\RePlayRealTimeView.cpp
LRESULT CRePlayRealTimeView::OnGetViewTitle(WPARAM wParam, LPARAM lParam)
{
CString strTitle;
strTitle.LoadString(IDS_TITLE_REPLAYREALTIMEVIEW); //修改窗口标题
lstrcpyn((LPTSTR)lParam, (LPCTSTR)strTitle, wParam);
if ((int)wParam > strTitle.GetLength())
wParam = strTitle.GetLength();
return wParam;
}
修改行情回放分时图标题
G:\stock\TskingVS2019\src\Client\StkUI\View\RePlayRealTime.cpp
//实时行情画分时线:画价格和成交量 by freeman 2019/06/08
void CRePlayRealTime::DrawPriceVolume( CDC * pDC )
{
DECLARE_COLOR_DEFINATION
// Draw Time Axis String
DrawDateAxis( pDC );
// Draw Title
CString strTitle;
pDC->SetTextColor( clrTitle );
pDC->SetBkColor( clrBK );
strTitle.LoadString(IDS_REPLAYEALTIME_TITLE); //修改行情回放分时图标题
if( CRePlayRealTime::modePriceLine != m_nDrawMode )
strTitle = m_CurStock.GetStockCode();
第五部分 实现思路
G:\stock\TskingVS2019\src\Client\StkUI\View\HistoryRealTimeView.cpp
生成1个定时器
int CHistoryRealTimeView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
//行情回放定时器add by freeman
m_timer = 1000;
SetTimer(RTV_TIMER_REFRESHHISTORYREPLY, m_timer, NULL);
return 0;
}
定定时器事件处理函数,
void CHistoryRealTimeView::OnTimer(UINT nIDEvent)
{
//行情回放
if (RTV_TIMER_REFRESHHISTORYREPLY == nIDEvent && m_realtime[0].m_nCurrentStartPos2 >=0)
{
m_realtime[0].OnTimer();
}
//大单交易
if(RTV_TIMER_REFRESHBIGTRADE == nIDEvent)
{
int nDrawMode = m_realtime[0].GetDrawMode();
int nReportWhat = m_realtime[0].GetReportWhat();
if(CHistoryRealTime::modeBigTradeDetail == nDrawMode)
Invalidate();
else if(CHistoryRealTime::modePriceLine == nDrawMode
&& CHistoryRealTime::reportBigTrade == nReportWhat)
m_realtime[0].DrawReportRegion(NULL);
}
//定时向行情服务器发起请求
if(RTV_TIMER_REFRESH == nIDEvent)
{
SendRequestQuote(FALSE);
}
CView::OnTimer(nIDEvent);
}
1.定时器刷新
在定时器中修改数据后,调用Invalidate()后会发送消息,会调用ondraw()函数绘图。
G:\stock\TskingVS2019\src\Client\StkUI\View\HistoryRealTime.cpp
/***********custom extend by freeman*************************/
//用定时器填入股票信息
BOOL CHistoryRealTime::OnTimer()
{
CStockInfo info;
info = m_CurStock.GetStockInfo();
BOOL bInv = FALSE;
//未选择播放时,直接返回,不执行行情播放
if (m_nCurrentStartPos2 == -1)
return TRUE;
if (m_nCurrentStartPos2 < 0)
m_nCurrentStartPos2 = 0;
//播放开始,先备份m_CurStock到m_CurStockBackup,然后将m_CurStock清0,分时线从头开始
if (m_nCurrentStartPos2 == 0)
{
//计算买卖挂单变化
CReport& aReport = m_CurStock.GetReport();
aReport.CalBuySellVolumeChanged();
//把数据作为备份存下来
m_CurStockBackup = m_CurStock;
m_CurStock.GetReport().RemoveAll();
m_CurStock.GetMinute().RemoveAll();
m_CurStock.GetOutline().RemoveAll();
}
//插入分钟线
if (m_nCurrentStartPos2 < m_CurStockBackup.GetReport().GetSize())
{
//将m_CurStock2的成交明细填入 m_CurStock的stockInfo,用于右则显示
//UpdateStockInfoByREPORT(m_CurStock.GetStockInfo(), &m_CurStock2.GetReport()[m_nCurrentStartPos2]);
if (-1 != m_CurStock.GetReport().InsertReportSort(m_CurStockBackup.GetReport()[m_nCurrentStartPos2]))
{
//转换为分钟线插入
MINUTE minute;
if (convert_REPORT_to_MINUTE(&(m_CurStockBackup.GetReport()[m_nCurrentStartPos2]), &minute))
m_CurStock.GetMinute().InsertMinuteSort(minute);
m_nCurrentStartPos = -1;
}
REPORT pReport = m_CurStockBackup.GetReport()[m_nCurrentStartPos2];
info.m_fHigh = m_nCurrentStartPos2;
// 成交买卖价量信息
if (pReport.m_fLast > 1e-4) info.m_fLast = pReport.m_fLast;
info.m_fOpen = pReport.m_fOpen;
info.m_fHigh = pReport.m_fHigh;
info.m_fLow = pReport.m_fLow;
info.m_fClose = pReport.m_fNew;
info.m_fVolume = pReport.m_fVolume;
info.m_fAmount = pReport.m_fAmount;
info.m_fBuyPrice[0] = pReport.m_fBuyPrice[0];
info.m_fBuyPrice[1] = pReport.m_fBuyPrice[1];
info.m_fBuyPrice[2] = pReport.m_fBuyPrice[2];
info.m_fBuyPrice[3] = pReport.m_fBuyPrice[3];
info.m_fBuyPrice[4] = pReport.m_fBuyPrice[4];
info.m_fBuyVolume[0] = pReport.m_fBuyVolume[0];
info.m_fBuyVolume[1] = pReport.m_fBuyVolume[1];
info.m_fBuyVolume[2] = pReport.m_fBuyVolume[2];
info.m_fBuyVolume[3] = pReport.m_fBuyVolume[3];
info.m_fBuyVolume[4] = pReport.m_fBuyVolume[4];
info.m_fSellPrice[0] = pReport.m_fSellPrice[0];
info.m_fSellPrice[1] = pReport.m_fSellPrice[1];
info.m_fSellPrice[2] = pReport.m_fSellPrice[2];
info.m_fSellPrice[3] = pReport.m_fSellPrice[3];
info.m_fSellPrice[4] = pReport.m_fSellPrice[4];
info.m_fSellVolume[0] = pReport.m_fSellVolume[0];
info.m_fSellVolume[1] = pReport.m_fSellVolume[1];
info.m_fSellVolume[2] = pReport.m_fSellVolume[2];
info.m_fSellVolume[3] = pReport.m_fSellVolume[3];
info.m_fSellVolume[4] = pReport.m_fSellVolume[4];
//挂单变化信息复制到 stockinfo变量
memcpy(info.m_fSellVolumeChanged, pReport.m_fSellVolumeChanged, sizeof(info.m_fSellVolumeChanged));
memcpy(info.m_fBuyVolumeChanged, pReport.m_fBuyVolumeChanged, sizeof(info.m_fBuyVolumeChanged));
m_CurStock.SetStockInfo(&info);//当前股票
m_nCurrentStartPos2++;
}
bInv = TRUE;
m_nCurrentStartPos = -1;
//Invalidate的调用会触发对view中OnDraw函数的调用
if (bInv && m_pParent && ::IsWindow(m_pParent->GetSafeHwnd()))
m_pParent->Invalidate();
return TRUE;
}
/************************************/