摘要:
1.分时图由RealTimeView.cpp和RealTime.cpp两个类完成。其中:
RealTimeView.cpp负责对画框、画右下角标签。捕获键盘事件后调用CRealTime类中的函数进行处理。
RealTime.cpp负责对数据进行处理,处理完成后,对CRealTimeView传过来的参数PDC进行画图,然后反过来调用显示实时行情。
2.分为多股同列和单个股票两种情形。
3.函数功能索引
├── src // 源码目录
│ ├── CRealTime::DrawReportRegion(CDC* pDC) // 组件
│ │ ├── CRealTime::DrawReportRegion(CDC* pDC) // 右下角标签画图
│ │ │ ├── DrawReportQuote(pDC); //笔
│ │ │ ├── DrawReportPrice(pDC); //价
│ │ │ ├── computeTime.vue // 倒计时组件
│ │ │ ├── loading.vue // 页面初始化加载数据的动画组件
│ │ │ ├── mixin.js // 组件混合(包括:指令-下拉加载更多,处理图片地址)
│ │ │ ├── ratingStar.vue // 评论的五颗星组件
│ │ │ └── shoplist.vue // msite和shop页面的餐馆列表公共组件
│ │ ├── footer
│ │ │ └── footGuide.vue // 底部公共组件
│ │ └── header
│ │ └── head.vue // 头部公共组件
│ ├── config // 基本配置
│ │ ├── env.js // 环境切换配置
│ │ ├── fetch.js // 获取数据
│ │ ├── mUtils.js // 常用的js方法
│ │ └── rem.js // px转换rem
│ ├── images // 公共图片
│ ├── page
│ │ ├── balance
│ │ │ ├── balance.vue // 余额页
│ │ │ └── children
│ │ │ └── detail.vue // 余额说明
│ │ ├── benefit
│ │ │ ├── benefit.vue // 红包页
│ │ │ └── children
│ │ │ ├── commend.vue // 推荐有奖
│ │ │ ├── coupon.vue // 代金券说明
│ │ │ ├── exchange.vue // 兑换红包
│ │ │ ├── hbDescription.vue // 红包说明
│ │ │ └── hbHistory.vue // 历史红包
│ │ ├── city
│ │ │ └── city.vue // 当前城市页
│ │ ├── confirmOrder
│ │ │ ├── children
│ │ │ │ ├── children
│ │ │ │ │ ├── addAddress.vue // 添加地址页
│ │ │ │ │ └── children
│ │ │ │ │ └── searchAddress.vue // 搜索地址页
│ │ │ │ ├── chooseAddress.vue // 选择地址页
│ │ │ │ ├── invoice.vue // 选择发票页
│ │ │ │ ├── payment.vue // 付款页
│ │ │ │ ├── remark.vue // 订单备注页
│ │ │ │ └── userValidation.vue // 用户验证页
│ │ │ └── confirmOrder.vue // 确认订单页
│ │ ├── download
│ │ │ └── download.vue // 下载App
│ │ ├── find
│ │ │ └── find.vue // 发现页
│ │ ├── food
│ │ │ └── food.vue // 食品筛选排序页
│ │ ├── forget
│ │ │ └── forget.vue // 忘记密码,修改密码页
│ │ ├── home
│ │ │ └── home.vue // 首页
│ │ ├── login
│ │ │ └── login.vue // 登录注册页
│ │ ├── msite
│ │ │ └── msite.vue // 商铺列表页
│ │ ├── order
│ │ │ ├── children
│ │ │ │ └── orderDetail.vue // 订单详情页
│ │ │ └── order.vue // 订单列表页
│ │ ├── points
│ │ │ ├── children
│ │ │ │ └── detail.vue // 积分说明
│ │ │ └── points.vue // 积分页
│ │ ├── profile
│ │ │ ├── children
│ │ │ │ ├── children
│ │ │ │ │ ├── address.vue // 地址
│ │ │ │ │ └── children
│ │ │ │ │ ├── add.vue // 新增地址
│ │ │ │ │ └── children
│ │ │ │ │ └── addDetail.vue // 搜索地址
│ │ │ │ ├── info.vue // 帐户信息
│ │ │ │ └── setusername.vue // 重置用户名
│ │ │ └── profile.vue // 个人中心
│ │ ├── search
│ │ │ └── search.vue // 搜索页
│ │ ├── service
│ │ │ ├── children
│ │ │ │ └── questionDetail.vue // 问题详情
│ │ │ └── service.vue // 服务中心
│ │ ├── shop
│ │ │ ├── children
│ │ │ │ ├── children
│ │ │ │ │ └── shopSafe.vue // 商铺认证信息页
│ │ │ │ ├── foodDetail.vue // 商铺信息页
│ │ │ │ └── shopDetail.vue // 单个商铺信息页
│ │ │ └── shop.vue // 商铺筛选页
│ │ └── vipcard
│ │ ├── children
│ │ │ ├── invoiceRecord.vue // 购买记录
│ │ │ ├── useCart.vue // 使用卡号购买
│ │ │ └── vipDescription.vue // 会员说明
│ │ └── vipcard.vue // 会员卡办理页
│ ├── plugins // 引用的插件
│ ├── router
│ │ └── router.js // 路由配置
│ ├── service // 数据交互统一调配
│ │ ├── getData.js // 获取数据的统一调配文件,对接口进行统一管理
│ │ └── tempdata // 开发阶段的临时数据
│ ├── store // vuex的状态管理
│ │ ├── action.js // 配置actions
│ │ ├── getters.js // 配置getters
│ │ ├── index.js // 引用vuex,创建store
│ │ ├── modules // store模块
│ │ ├── mutation-types.js // 定义常量muations名
│ │ └── mutations.js // 配置mutations
│ └── style
│ ├── common.scss // 公共样式文件
│ ├── mixin.scss // 样式配置文件
│ └── swiper.min.css
│ ├── App.vue // 页面入口文件
│ ├── main.js // 程序入口文件,加载各种公共组件
├── favicon.ico // 图标
├── index.html
右下角标签画图:void CRealTime::DrawReportRegion( CDC * pDC )
顶部窗口提示信息:oid CRealTime::OnIndexCurrentChanged( )
画右上角五档信息:int CRealTime::DrawBuySell( CDC * pDC, int xStart, int yStart, int nWidth )
4.数据调用链:硬盘数据---KDATA---CKData---CStock---CStockGraph---CGraphView。
右上角行情窗口显示流程:
1.切换到激活窗口,执行 OnUpdate()函数。
2.在 OnUpdate()函数中,调用AfxGetProfile().GetCurrentStock(&info)获取股票代码信息,股票信息从不同的容器中获取。
BOOL CStProfile::GetCurrentStock( CStockInfo * pInfo )
{
if( m_bCurStockFromSList )
return AfxGetSListStockContainer().GetCurrentStock( pInfo );
else
return AfxGetStockContainer().GetCurrentStock( pInfo );
}
用m_realtime[0].PrepareStockData();
m_realtime[0].PrepareStockData()做了下面的事情:
step 2.1.从本地加载分笔数据、分时数据、外部数据3项,2.向通视驱动发起分笔请求。
2.1.1 从本地加载分笔数据
.m_CurStock.PrepareData( CStock::dataReport, CKData::ktypeDay, TRUE );//从本地获取股票分笔成交明细,用于右下角显示成交明细交易记录。
2.1.2 向通视驱动发起分笔数据请求,用于右上角显示在行情子窗口
AfxGetStkReceiver().GetReport( m_CurStock.GetStockInfo(), m_CurStock.GetReport() );
void CRealTimeView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
.....
CStockInfo info;
if(AfxGetProfile().GetCurrentStock(&info))
{
m_realtime[0].SetCurStock(info);//当前股票
m_realtime[0].PrepareStockData();
}
......
}
G:\stock\TskingVS2019\src\Client\StkLib\Src\Profile.cpp
BOOL CStProfile::GetCurrentStock( CStockInfo * pInfo )
{
if( m_bCurStockFromSList )
return AfxGetSListStockContainer().GetCurrentStock( pInfo );
else
return AfxGetStockContainer().GetCurrentStock( pInfo );
}
G:\stock\TskingVS2019\src\Client\StkLib\Src\Container.cpp
BOOL CStockContainer::GetCurrentStock( CStockInfo * pInfo )
{
CSPMutex::Scoped l(m_mutex);
SP_ASSERT( pInfo );
if( m_nCurrentStock >= 0 && m_nCurrentStock < GetSize() )
{
CStockInfo & info = ElementAt(m_nCurrentStock);
if( pInfo )
* pInfo = info;
return TRUE;
}
else if( m_strCurrentStockCode.GetLength() > 0 )
{
CStockInfo info;
info.SetStockCode( CStock::marketUnknown, m_strCurrentStockCode );
if( pInfo )
*pInfo = info;
return TRUE;
}
return FALSE;
}
step 2.2 数据准备好了,更新stockINfo里面的行情信息
UpdateStockInfoByREPORT( m_CurStock.GetStockInfo(), &(m_CurStock.GetReport().ElementAt(nLen-1)) );//更新股票信息类里面的成交明细,用于在右上角显示行情信息
第一部分 视图的结构和数据初始化
step 1. 初始化视图结构
当视图切换到GraphView时,首先调用ONCREATE()对view进行初始化,主要是准备窗口右下角的标签项(笔、分等子窗口)、注册窗口句柄。
1.1通过AfxGetStkReceiver().AddRcvDataWnd(GetSafeHwnd());向stkreciever注册了窗口句柄。用来接收主动推送的行情。
1.2 定义了两个定时器,都是向行情服务器发出请求。
大单定时器
行情刷新定时器
int CRealTimeView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
CFont font;
if (!font.CreateStockObject(DEFAULT_GUI_FONT))
font.CreateStockObject(ANSI_VAR_FONT);
SetFont(&font);
CTSKTabManagerItem* pItem;
CString strName;
//成交记录下面的笔、价、分等
strName.LoadString(IDS_REALTIMETAB_QUOTE);//笔
pItem = new CTSKTabManagerItem();
pItem->SetCaption(strName);
AddItem(RT_REPORTTAB_QUOTE, pItem);
strName.LoadString(IDS_REALTIMETAB_PRICE);
pItem = new CTSKTabManagerItem();
pItem->SetCaption(strName);
AddItem(RT_REPORTTAB_PRICE, pItem);
strName.LoadString(IDS_REALTIMETAB_MINUTE);
pItem = new CTSKTabManagerItem();
pItem->SetCaption(strName);
AddItem(RT_REPORTTAB_MINUTE, pItem);
strName.LoadString(IDS_REALTIMETAB_BUYSELLEX);
pItem = new CTSKTabManagerItem();
pItem->SetCaption(strName);
AddItem(RT_REPORTTAB_BUYSELLEX, pItem);
strName.LoadString(IDS_REALTIMETAB_VALUE);
pItem = new CTSKTabManagerItem();
pItem->SetCaption(strName);
AddItem(RT_REPORTTAB_VALUE, pItem);
strName.LoadString(IDS_REALTIMETAB_DISTRIBUTE);
pItem = new CTSKTabManagerItem();
pItem->SetCaption(strName);
AddItem(RT_REPORTTAB_DISTRIBUTE, pItem);
strName.LoadString(IDS_REALTIMETAB_BIGTRADE);
pItem = new CTSKTabManagerItem();
pItem->SetCaption(strName);
AddItem(RT_REPORTTAB_BIGTRADE, pItem);
SetSelectedItem(GetItem(0));
// m_realtime
for(int i = 0; i < RTV_MAX_MULTICOUNT; i++)
m_realtime[i].SetParent(this);
// 实时行情刷新
AfxGetStkReceiver().AddRcvDataWnd(GetSafeHwnd());
// 大单成交刷新频率,改为3秒
SetTimer(RTV_TIMER_REFRESHBIGTRADE, 3000, NULL);
SetTimer(RTV_TIMER_REFRESH, 3000, NULL);
return 0;
}
step 2:初始化视图数据
系统调用OnInitialUpDate()初始化,OnInitialUpDate()调用OnUpdate()初始化数据。
在OnUpdate()函数中,执行了以下动作:
2.1 从本地加载分笔、分笔、外部数据。
2.2 向通视驱动请求分笔数据
//第一次初始化
void CRealTimeView::OnInitialUpdate()
{
CView::OnInitialUpdate();
// TODO: Add your specialized code here and/or call the base class
OnUpdate(NULL, UPDATE_HINT_REALTIMEVIEW, NULL);
}
void CRealTimeView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
// TODO: Add your specialized code here and/or call the base class
if(UPDATE_HINT_REALTIMEVIEW != lHint)
return;
if(!IsWindowVisible())
return;
SetFocus();
ASSERT(RTV_MAX_MULTICOUNT > 0);
CStockInfo info;
if(AfxGetProfile().GetCurrentStock(&info))
{
m_realtime[0].SetCurStock(info);//当前股票
m_realtime[0].PrepareStockData();
}
else
{
m_realtime[0].SetCurStock(STKLIB_CODE_MAIN);
m_realtime[0].PrepareStockData(); //1.从本地加载分笔数据、分时数据、外部数据3项,2.向通视驱动发起分笔请求。
AfxGetProfile().SetCurrentStock(STKLIB_CODE_MAIN, FALSE);
}
if(CRealTime::modeReportDetail == m_realtime[0].GetDrawMode())
AfxGetStkReceiver().RequestStockData(CStock::dataDetail, &info, 1, 0, 0);
else
AfxGetStkReceiver().RequestStockData(CStock::dataMinute, &info, 1, 0, 0);
// 多股同列
for(int i=1; i < m_nMultiStockCount && i < RTV_MAX_MULTICOUNT; i++)
{
if(AfxGetProfile().GetNextStock(&info))
{
m_realtime[i].SetCurStock(info);
m_realtime[i].PrepareStockData();
if(CRealTime::modeReportDetail == m_realtime[0].GetDrawMode())
AfxGetStkReceiver().RequestStockData(CStock::dataDetail, &info, 1, 0, 0);
else
AfxGetStkReceiver().RequestStockData(CStock::dataMinute, &info, 1, 0, 0);
}
}
for(int i=1; i < m_nMultiStockCount && i < RTV_MAX_MULTICOUNT; i++)
AfxGetProfile().GetPrevStock(&info);
Invalidate();
/*if(1 == m_nMultiStockCount && CRealTime::modePriceLine == m_realtime[0].GetDrawMode())
m_wndReportTab.SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
else
m_wndReportTab.SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW);*/
CMainFrame * pFrame = AfxGetMainFrame();
if(pFrame)
pFrame->m_SearchBox.SetCurrentWindowText();//应该是键盘精灵
//向行情服务器发起分笔数据请求,bForced=true表示非开盘时间也发起刷新请求
SendRequestQuote(TRUE);
}
step 3:在激活窗口时,会调用OnUpdate()函数
//激活窗口事件
void CRealTimeView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView)
{
// TODO: Add your specialized code here and/or call the base class
if(bActivate)
OnUpdate(NULL, UPDATE_HINT_REALTIMEVIEW, NULL);
CView::OnActivateView(bActivate, pActivateView, pDeactiveView);
}
在OnUpdate()函数中,会调用m_realtime[0].PrepareStockData()加载本地数据,
//第一次初始化
void CRealTimeView::OnInitialUpdate()
{
CView::OnInitialUpdate();
// TODO: Add your specialized code here and/or call the base class
OnUpdate(NULL, UPDATE_HINT_REALTIMEVIEW, NULL);
}
void CRealTimeView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
// TODO: Add your specialized code here and/or call the base class
if(UPDATE_HINT_REALTIMEVIEW != lHint)
return;
if(!IsWindowVisible())
return;
SetFocus();
ASSERT(RTV_MAX_MULTICOUNT > 0);
CStockInfo info;
if(AfxGetProfile().GetCurrentStock(&info))
{
m_realtime[0].SetCurStock(info);//当前股票
m_realtime[0].PrepareStockData();
}
else
{
m_realtime[0].SetCurStock(STKLIB_CODE_MAIN);
m_realtime[0].PrepareStockData(); //1.从本地加载分笔数据、分时数据、外部数据3项,2.向通视驱动发起分笔请求。
AfxGetProfile().SetCurrentStock(STKLIB_CODE_MAIN, FALSE);
}
if(CRealTime::modeReportDetail == m_realtime[0].GetDrawMode())
AfxGetStkReceiver().RequestStockData(CStock::dataDetail, &info, 1, 0, 0);
else
AfxGetStkReceiver().RequestStockData(CStock::dataMinute, &info, 1, 0, 0);
// 多股同列
for(int i=1; i < m_nMultiStockCount && i < RTV_MAX_MULTICOUNT; i++)
{
if(AfxGetProfile().GetNextStock(&info))
{
m_realtime[i].SetCurStock(info);
m_realtime[i].PrepareStockData();
if(CRealTime::modeReportDetail == m_realtime[0].GetDrawMode())
AfxGetStkReceiver().RequestStockData(CStock::dataDetail, &info, 1, 0, 0);
else
AfxGetStkReceiver().RequestStockData(CStock::dataMinute, &info, 1, 0, 0);
}
}
for(int i=1; i < m_nMultiStockCount && i < RTV_MAX_MULTICOUNT; i++)
AfxGetProfile().GetPrevStock(&info);
Invalidate();
/*if(1 == m_nMultiStockCount && CRealTime::modePriceLine == m_realtime[0].GetDrawMode())
m_wndReportTab.SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
else
m_wndReportTab.SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW);*/
CMainFrame * pFrame = AfxGetMainFrame();
if(pFrame)
pFrame->m_SearchBox.SetCurrentWindowText();//应该是键盘精灵
//向行情服务器发起分笔数据请求,bForced=true表示非开盘时间也发起刷新请求
SendRequestQuote(TRUE);
}
读取了分笔、分时数据、外部数据三项。最后,取分笔数据的最后笔,填入stockINfo的行情显示部分。
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;
}
1.3 向行情服务器请求分笔数据
向行情服务器发起分笔数据请求
在Updata()的最后一句,用void CRealTimeView::SendRequestQuote(BOOL bForced)
//向行情服务器发起分笔数据请求,bForced=true表示非开盘时间也发起刷新请求
void CRealTimeView::SendRequestQuote(BOOL bForced)
{
BOOL bInTrade = CSPTime::InTradeTime(CSPTime::GetCurrentTime().GetTime(),900);
CView * pView = AfxGetStaticDoc()->GetActiveView();
if(bForced || (bInTrade && pView == this))
{
for(int i = 0; i < m_nMultiStockCount && i < RTV_MAX_MULTICOUNT; i++)
{
CStock & stock = m_realtime[i].GetCurStock();
CStockInfo & info = stock.GetStockInfo();
if(info.IsValidStock())
AfxGetStkReceiver().RequestStockData(CStock::dataReport, &info, 1, 0, 0);
}
}
}
调用AfxGetStkReceiver().RequestStockData(),它又是调用的int nRet = gNetTSDLL.RequestStockData(nDataTypeTS, pStocks, nSize, nKType, nDataCount);
int CStkReceiver::RequestStockData(int nDataType/*CStock::DataType*/, CStockInfo * pStockInfo, int nSize, int nKType, int nDataCount) //向行情服务器发起分笔数据请求
{
int nDataTypeTS = DataType_to_TSDataType(nDataType);
if (nSize < 0)
return 0;
STOCK_STRUCTEx * pStocks = new STOCK_STRUCTEx[nSize+1];
memset(pStocks, 0, sizeof(STOCK_STRUCTEx)*(nSize+1));
for(int i=0; i<nSize; i++)
{
pStocks[i].m_type = (BYTE)pStockInfo[i].GetType();
strncpy(pStocks[i].m_code, pStockInfo[i].GetStockCode(), sizeof(pStocks[i].m_code));
}
int nRet = gNetTSDLL.RequestStockData(nDataTypeTS, pStocks, nSize, nKType, nDataCount);//调用 gNetTSDLL.RequestStockData()
delete [] pStocks;
return nRet;
}
NetTs调用CTWSocket::GetInstance().RequestStockData( nDataType, pStocks, nSize, nKType, nDataCount )
int WINAPI RequestStockData( int nDataType, TW_STOCK * pStocks, int nSize, int nKType, int nDataCount )
{
return CTWSocket::GetInstance().RequestStockData( nDataType, pStocks, nSize, nKType, nDataCount );
}
根据请求的数据类型发送请求
int CTWSocket::RequestStockData(int nDataType, TW_STOCK* pStocks, int nSize, int nKType, int nDataCount)
{
//判断是否正在接收数据,
if (m_bIsReceiving && time(NULL) - m_timeReceiveLast > 60) //离上一次接收数据的时间要超过60秒
m_bIsReceiving = FALSE;
//如果正在接收数据,则推入队列,立即返回。
if (m_bIsReceiving)
{
CTWCommand cmd(nDataType, pStocks, nSize, nKType, nDataCount);
PushCommand(cmd);
return nSize;
}
//OnNewCommand的作用是先推入再弹出
int nRet = 0;
switch (nDataType)
{
case RCV_REPORT:
if (OnNewCommand(nDataType, pStocks, 0))
nRet = RequestReport(pStocks, nSize);
break;
case FILE_HISTORY_EX:
if (OnNewCommand(nDataType, pStocks, 300))
nRet = RequestHistory(pStocks, nSize, nKType, nDataCount);
break;
case FILE_MINUTE_EX:
if (OnNewCommand(nDataType, pStocks, 60))
nRet = RequestMinute(pStocks, nSize);
break;
case FILE_POWER_EX:
if (OnNewCommand(nDataType, pStocks, 300))
nRet = RequestPower(pStocks, nSize);
break;
case FILE_MULTISORT_EX:
if (OnNewCommand(nDataType, pStocks, 0))
nRet = RequestMultisort(pStocks, nSize);
break;
case FILE_DETAIL_EX:
if(OnNewCommand(nDataType, pStocks, 60))
nRet = RequestDetail(pStocks, nSize);
break;
case FILE_BASE_EX:
if (OnNewCommand(nDataType, pStocks, 300))
nRet = RequestBase(pStocks, nSize);
break;
case FILE_NEWS_EX:
if (OnNewCommand(nDataType, pStocks, 60))
nRet = RequestNews(pStocks, nSize);
break;
case FILE_HTML_EX:
if (OnNewCommand(nDataType, pStocks, 60))
nRet = RequestHtml(pStocks, nSize);
break;
case FILE_SOFTWARE_EX:
if (OnNewCommand(nDataType, pStocks, 60))
nRet = RequestSoftware(pStocks, nSize);
break;
case FILE_SHAZQDATA_EX:
if (OnNewCommand(nDataType, pStocks, 60))
nRet = RequestShazqdata(pStocks, nSize);
break;
default:
break;
}
return nRet;
}
1.4 数据的接收及处理
1.4.1 循环各个股票,调用
/有数据传过来
LRESULT CRealTimeView::OnStkReceiverData(WPARAM wParam, LPARAM lParam)
{
for(int i = 0; i < m_nMultiStockCount && i < RTV_MAX_MULTICOUNT; i++)
m_realtime[i].OnStkReceiverData(wParam,lParam);
return 0;
}
只对分时数据和分笔数据进行处理
//接收数据的消息处理函数
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;
}
1.确定显示股票分时图的股票目标
int m_nMultiStockCount
CRealTimeView类定义了一个变量int m_nMultiStockCount;显示多只股票的个数,由void CRealTimeView::ShowMultiStock(int nMultiStockCount)函数设置。
G:\stock\TskingVS2019\src\Client\StkUI\View\RealTimeView.h
#define RTV_MAX_MULTICOUNT 9
class CRealTimeView : public CView, public CTSKTabManager
{
DECLARE_DYNCREATE(CRealTimeView)
protected:
CRealTimeView();
virtual ~CRealTimeView();
protected:
int m_nMultiStockCount;//显示多只股票的个数,由void CRealTimeView::ShowMultiStock(int nMultiStockCount)函数设置 2019/06/08 by freeman
CRealTime m_realtime[RTV_MAX_MULTICOUNT];
画图部分说明
1.CRealTime
G:\stock\TskingVS2019\src\Client\StkUI\View\RealTime.cpp
分时线,多股同列的分时线。
负责画图
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;//盘 8档
case CRealTime::reportValue: DrawReportValue(pDC); break;//值
case CRealTime::reportDistribute: DrawReportDistribute(pDC); break;//筹
case CRealTime::reportBigTrade: DrawReportBigTrade(pDC); break;//单
}
}
}
分时图画窗口顶部的时间 价格 成交量等信息
G:\stock\TskingVS2019\src\Client\StkUI\View\RealTime.cpp
void CRealTime::OnIndexCurrentChanged( )
{
if( CRealTime::modePriceLine != m_nDrawMode )
return;
DECLARE_COLOR_DEFINATION
if( !m_pParent || !::IsWindow(m_pParent->GetSafeHwnd()) )
return;
CClientDC dc(m_pParent);
CDC *pDC = &dc;
CRect rectTop(m_rectPrice.left+135,m_rectAll.top,m_rectPrice.right,m_rectPrice.top-1 );
pDC->FillSolidRect( &rectTop, clrBK );
if( m_nIndexCurrent < 0 || m_nIndexCurrent >= m_CurStock.GetMinute().GetSize() )
return;
MINUTE minute = m_CurStock.GetMinute().ElementAt(m_nIndexCurrent);
// Fill Background
pDC->SetBkColor( clrBK );
CString strTemp;
CFont * pOldFont = AfxSelectDCFont( pDC, 12 );
int x = rectTop.left;
int y = rectTop.top + 4;
int right = rectTop.right-100;
pDC->SetTextColor( clrText );
strTemp.LoadString( IDS_REALTIME_TIME );
if( x < right ) pDC->TextOut( x, y, strTemp );
strTemp.LoadString( IDS_REALTIME_PRICE );
if( x+80 < right ) pDC->TextOut( x+80, y, strTemp );
strTemp.LoadString( IDS_REALTIME_VOLUME );
if( x+160 < right ) pDC->TextOut( x+160, y, strTemp );
strTemp.LoadString( IDS_REALTIME_AMOUNT );
if( x+290 < right ) pDC->TextOut( x+290, y, strTemp );
//分时图画窗口顶部的时间 价格 成交量等信息 by freeman
// Time
CSPTime time(minute.m_time);
strTemp = time.Format( "%H:%M" );
pDC->SetTextColor( clrPlane );
if( x+30 < right ) pDC->TextOut( x+30, y, strTemp );
// Price
CString strPriceFmt;
strPriceFmt.Format( "%%.%df", m_CurStock.GetStockInfo().DigitBit() );
strTemp.Format( strPriceFmt, minute.m_fNew );
pDC->SetTextColor( RT_DETERMINE_COLOR( minute.m_fNew, m_CurStock.GetStockInfo().m_fLast ) );
if( x+110 < right ) pDC->TextOut( x+110, y, strTemp );
// Volume
double dVolume = minute.m_fVolume;
if( m_nIndexCurrent > 0 )
dVolume -= m_CurStock.GetMinute()[m_nIndexCurrent-1].m_fVolume;
strTemp.Format( "%.0f", dVolume*0.01 );
pDC->SetTextColor( clrTitle );
if( x+220 < right ) pDC->TextOut( x+220, y, strTemp );
// Amount
double dAmount = minute.m_fAmount;
if( m_nIndexCurrent > 0 )
dAmount -= m_CurStock.GetMinute()[m_nIndexCurrent-1].m_fAmount;
strTemp.Format( "%.2f", dAmount*0.001 );
pDC->SetTextColor( clrTitle );
if( x+350 < right ) pDC->TextOut( x+350, y, strTemp );
pDC->SelectObject( pOldFont );
}
2.G:\stock\TskingVS2019\src\Client\StkUI\View\RealTimeView.cpp
成交明细由接口Loadreport提供明细数据(按F1时)
//实时行情,画右上角信息
int CRealTime::DrawBuySell( CDC * pDC, int xStart, int yStart, int nWidth )
////////////////////////////////////////////////////////////////////////////
// 函 数 名: CRealTime::DrawBuySellEx()
// 功能说明:实时行情,画右上角买卖成交信息,8档行情 by freeman
// 入口参数:
// 出口参数:
// 返回参数:
////////////////////////////////////////////////////////////////////////////
int CRealTime::DrawBuySellEx( CDC * pDC, int xStart, int yStart, int nWidth )
笔:Redraw->DrawReportRegion( pDC )->DrawReportQuote( pDC );
DrawReportQuote( pDC )
{
...
int nBuySellHeight = DrawBuySell( pDC, m_rectReport.left, m_rectReport.top, m_rectReport.Width() );//画右上角5档信息,返回总高度,下面的框用此高度继续
DrawReportColumn( pDC, info, aReport, m_nCurrentStartPos, m_nCurrentPageCount, rect );//画右下角“笔”成交明细
....
}
接收的到数据时的处理
1.stkReciver会管理通视驱动和行情服务器驱动
2.发送消息
3.接收数据消息
由LRESULT CSListView::OnStkReceiverData(WPARAM wParam, LPARAM lParam)负责处理
其他
#define IDS_REALTIME_TITLE 45914
#define IDS_REALTIME_BSRATIO 45915
#define IDS_REALTIME_BSDIFF 45916
#define IDS_REALTIME_SELL5 45917
#define IDS_REALTIME_SELL4 45918
#define IDS_REALTIME_SELL3 45919
#define IDS_REALTIME_SELL2 45920
#define IDS_REALTIME_SELL1 45921
#define IDS_REALTIME_BUY1 45922
#define IDS_REALTIME_BUY2 45923
#define IDS_REALTIME_BUY3 45924
#define IDS_REALTIME_BUY4 45925
#define IDS_REALTIME_BUY5 45926
#define IDS_REALTIME_PRICENOW 45927
#define IDS_REALTIME_PRICEAVE 45928
#define IDS_REALTIME_PRICEDIFF 45929
#define IDS_REALTIME_PRICEOPEN 45930
#define IDS_REALTIME_PRICEDIFFPERCENT 45931
#define IDS_REALTIME_PRICEHIGH 45932
#define IDS_REALTIME_VOLSUM 45933
#define IDS_REALTIME_PRICELOW 45934
#define IDS_REALTIME_VOLNOW 45935
#define IDS_REALTIME_VOLRATION 45936
#define IDS_REALTIME_VOLOUTER 45937
#define IDS_REALTIME_VOLINNER 45938
#define IDS_REALTIME_TIME 45939
#define IDS_REALTIME_PRICE 45940
#define IDS_REALTIME_VOLUME 45941
#define IDS_REALTIME_AMOUNT 45942
#define IDS_REALTIME_ADVANCE 45943
#define IDS_REALTIME_DECLINE 45944
#define IDS_REALTIME_LBDK 45945
#define IDS_REALTIME_MMLD 45946
#define IDS_REALTIME_REPORTDETAILTITLE 45947
#define IDS_REALTIME_MINUTEDETAILTITLE 45948
#define IDS_REALTIME_BIGTRADEDETAILTITLE 45949
#define IDS_REALTIME_STOCKNAME 45950
#define IDS_REALTIMETAB_QUOTE 45951
#define IDS_REALTIMETAB_PRICE 45952
#define IDS_REALTIMETAB_MINUTE 45953
#define IDS_REALTIMETAB_BUYSELLEX 45954
#define IDS_REALTIMETAB_VALUE 45955
#define IDS_REALTIMETAB_DISTRIBUTE 45956
#define IDS_REALTIMETAB_BIGTRADE 45957
#define IDS_REALTIME_RISINGLIMIT 45958
#define IDS_REALTIME_FALLINGLIMIT 45959
#define IDS_REALTIME_AH 45960
#define IDS_REALTIME_NH 45961
#define IDS_REALTIME_NL 45962
#define IDS_REALTIME_AL 45963
#define IDS_REALTIME_SELL8 45964
#define IDS_REALTIME_SELL7 45965
#define IDS_REALTIME_SELL6 45966
#define IDS_REALTIME_BUY6 45967
#define IDS_REALTIME_BUY7 45968
#define IDS_REALTIME_BUY8 45969
STRINGTABLE
BEGIN
IDS_SIMUREALOP_EXPLAINNEXTOP "下一步操作是操作计划,成功后自动加入历史操作记录。"
IDS_SIMUREALOP_EXPLAINOPRECORD "操作记录中的股票单价是向下复权后的数值。"
IDS_SIMUREALOP_TIMEEXPLAINFMT "现在日期是%s,请在下一交易日集合竞价时间(9:15-9:25)进行以上委托。"
IDS_SIMUREPORT_BUYPRICE "买入价"
IDS_SIMUREPORT_NOWPRICE "现价"
IDS_STRATEGY_SETRULELONG "设置长周期指标参数"
IDS_STRATEGY_SETRULEINDEX "设置大盘指标参数"
IDS_SIMUADVANCED_NOTNUMBER "请在止损和止赢编辑框中输入数字。"
IDS_SIMUADVANCED_NOSELECTEDLONG "没有选中的长周期指标。请点击按钮“选择长周期指标”来进行选择。"
IDS_SIMUADVANCED_NOSELECTEDINDEX "没有选中的大盘指标。请点击按钮“选择大盘指标”来进行选择。"
IDS_REALTIME_TITLE "分时行情"
IDS_REALTIME_BSRATIO "委比"
IDS_REALTIME_BSDIFF "委差"
IDS_REALTIME_SELL5 "卖⑤"
IDS_REALTIME_SELL4 "卖④"
IDS_REALTIME_SELL3 "卖③"
END
STRINGTABLE
BEGIN
IDS_REALTIME_SELL2 "卖②"
IDS_REALTIME_SELL1 "卖①"
IDS_REALTIME_BUY1 "买①"
IDS_REALTIME_BUY2 "买②"
IDS_REALTIME_BUY3 "买③"
IDS_REALTIME_BUY4 "买④"
IDS_REALTIME_BUY5 "买⑤"
IDS_REALTIME_PRICENOW "成交"
IDS_REALTIME_PRICEAVE "均价"
IDS_REALTIME_PRICEDIFF "涨跌"
IDS_REALTIME_PRICEOPEN "开盘"
IDS_REALTIME_PRICEDIFFPERCENT "幅度"
IDS_REALTIME_PRICEHIGH "最高"
IDS_REALTIME_VOLSUM "总手"
IDS_REALTIME_PRICELOW "最低"
IDS_REALTIME_VOLNOW "现手"
END
STRINGTABLE
BEGIN
IDS_REALTIME_VOLRATION "量比"
IDS_REALTIME_VOLOUTER "外盘"
IDS_REALTIME_VOLINNER "内盘"
IDS_REALTIME_TIME "时间"
IDS_REALTIME_PRICE "价格"
IDS_REALTIME_VOLUME "量(手)"
IDS_REALTIME_AMOUNT "额(千元)"
IDS_REALTIME_ADVANCE "涨家数"
IDS_REALTIME_DECLINE "跌家数"
IDS_REALTIME_LBDK "量比(多空)"
IDS_REALTIME_MMLD "买卖力道"
IDS_REALTIME_REPORTDETAILTITLE "每笔成交明细 PageUp:上翻 PageDown:下翻"
IDS_REALTIME_MINUTEDETAILTITLE "分钟成交明细 PageUp:上翻 PageDown:下翻"
IDS_REALTIME_BIGTRADEDETAILTITLE "大单成交明细 PageUp:上翻 PageDown:下翻"
IDS_REALTIME_STOCKNAME "名称"
IDS_REALTIMETAB_QUOTE "笔"
END
STRINGTABLE
BEGIN
IDS_REALTIMETAB_PRICE "价"
IDS_REALTIMETAB_MINUTE "分"
IDS_REALTIMETAB_BUYSELLEX "盘"
IDS_REALTIMETAB_VALUE "值"
IDS_REALTIMETAB_DISTRIBUTE "筹"
IDS_REALTIMETAB_BIGTRADE "单"
IDS_REALTIME_RISINGLIMIT "涨停价"
IDS_REALTIME_FALLINGLIMIT "跌停价"
IDS_REALTIME_AH "AH"
IDS_REALTIME_NH "NH"
IDS_REALTIME_NL "NL"
IDS_REALTIME_AL "AL"
IDS_REALTIME_SELL8 "卖⑧"
IDS_REALTIME_SELL7 "卖⑦"
IDS_REALTIME_SELL6 "卖⑥"
IDS_REALTIME_BUY6 "买⑥"
END
STRINGTABLE
BEGIN
IDS_REALTIME_BUY7 "买⑦"
IDS_REALTIME_BUY8 "买⑧"
END