数据调用链:硬盘数据---KDATA---CKData---CStock---CStockGraph---CGraphView。
StockGraph.cpp是专门负责画K线图的类;包含数据加载,键盘,鼠标定义等功能。
GraphView.cpp是负责画日K线、其他周期K线的类
function index of table
\src\Client\StkUI\View\StockGraph.cpp
//画周期K线的左上角信息 by freeman
void CStockGraph::DrawKData(CDC* pDC, CRect rect)
//画窗口右上角的参数窗口 by freeman
void CStockGraph::DrawReportParam(CDC* pDC)
第一部分 视图的结构和数据初始化
step 1. 初始化视图结构
当视图切换到GraphView时,首先调用ONCREATE()对view进行初始化,主要是准备窗口右下角的标签项(如火焰山等)、注册窗口句柄。
//准备窗口右下角的标签项,如火焰山等;注册窗口句柄 by freeman
int CGraphView::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);
m_graph.SetParent(this);
// tab
//if (!m_wndReportTab.Create(WS_VISIBLE|WS_CHILD,CRect(0,0,180,19),this,IDC_GRAPHVIEW_REPORTTAB))
// return -1;
//准备窗口右下角的标签项,如火焰山等 by freeman
CTSKTabManagerItem* pItem;
CString strName;
strName.LoadString(IDS_GRAPHTAB_PARAM);
pItem = new CTSKTabManagerItem();
pItem->SetCaption(strName);
AddItem(GV_REPORTTAB_PARAM, pItem);
strName.LoadString(IDS_GRAPHTAB_COST);
pItem = new CTSKTabManagerItem();
pItem->SetCaption(strName);
AddItem(GV_REPORTTAB_COST, pItem);
strName.LoadString(IDS_GRAPHTAB_FLAME);
pItem = new CTSKTabManagerItem();
pItem->SetCaption(strName);
AddItem(GV_REPORTTAB_FLAME, pItem);
strName.LoadString(IDS_GRAPHTAB_ACTIVITY);
pItem = new CTSKTabManagerItem();
pItem->SetCaption(strName);
AddItem(GV_REPORTTAB_ACTIVITY, pItem);
SetSelectedItem(GetItem(0));
m_nMinWidth = 40;
//m_wndReportTab.SetColorTabs(AfxGetProfile().GetColor(CColorClass::clrGraphBK));
//m_wndReportTab.SetSelectTabColor(AfxGetProfile().GetColor(CColorClass::clrGraphBK),
// AfxGetProfile().GetColor(CColorClass::clrTitle));
//m_wndReportTab.SetAutoAjust(FALSE);
//m_wndReportTab.ShowButtonClose(FALSE);
//m_wndReportTab.SetALingTabs(CGuiTabWnd::ALN_BOTTOM);
// 实时行情刷新,注册窗口句柄
AfxGetStkReceiver().AddRcvDataWnd(GetSafeHwnd());
return 0;
}
step 2:初始化视图数据
系统调用OnInitialUpDate()初始化数据。
在OnInitialUpdate() 函数中,
step 1.首先用AfxGetProfile().GetCurrentStock(&info)从全局变量中获取当前股票信息。
step 2.然后初始化用m_graph.SetCurStock(info)设置StockGraph类的当前股票。
step 3.接着调用m_graph.PrepareStockData(),m_graph会根据当前股票代码加载K线数据。
step 4.调用Invalidate()后,系统会发送WM_PAINT消息。由OnPaint消息处理函数来响应。
OnPaint是WM_PAINT消息的消息处理函数,在OnPaint中调用OnDraw。
// 初始化,准备数据
void CGraphView::OnInitialUpdate()
{
CView::OnInitialUpdate();
// TODO: Add your specialized code here and/or call the base class
OnUpdate(NULL, UPDATE_HINT_GRAPHVIEW, NULL);
}
void CGraphView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
// TODO: Add your specialized code here and/or call the base class
if (UPDATE_HINT_GRAPHVIEW != lHint && UPDATE_HINT_GRAPHVIEW_NOTRELOADDATA != lHint)
return;
if (!IsWindowVisible())
return;
SetFocus();
CStockInfo info;
//从配置文件中取出当前股票 by freeman
if (AfxGetProfile().GetCurrentStock(&info))
{
//CStockGraph m_graph;设置当前股票信息
m_graph.SetCurStock(info);
//加载相关数据 ,包括加载K线数据,计算指标等 by freeman
m_graph.PrepareStockData(UPDATE_HINT_GRAPHVIEW_NOTRELOADDATA != lHint);
}
else
{
m_graph.SetCurStock(STKLIB_CODE_MAIN);
m_graph.PrepareStockData(UPDATE_HINT_GRAPHVIEW_NOTRELOADDATA != lHint);
AfxGetProfile().SetCurrentStock(STKLIB_CODE_MAIN, FALSE);
}
Invalidate();
CMainFrame * pFrame = AfxGetMainFrame();
if (pFrame)
pFrame->m_SearchBox.SetCurrentWindowText();
}
CStockGraph类根据当前股票代码加载K线数据、技术指标数据。
//CStockGraph::PrepareStockData( BOOL bReload )加载画图所需要的数据 by freeman
BOOL CStockGraph::PrepareStockData(BOOL bReload)
{
if (!m_CurStock.GetStockInfo().IsValidStock())
return FALSE;
CStockInfo info;
if (AfxGetStockContainer().GetStockInfo(m_CurStock.GetStockCode(), &info)
&& m_CurStock.GetStockInfo().IsEqualTo(info.GetMarket(), info.GetStockCode()))
{
m_CurStock.SetStockInfo(&info);
m_CurStockDown.SetStockInfo(&info);
}
int nOldSize = m_CurStock.GetKData(m_nCurKType).GetSize();
// Prepare Data
AfxPrepareStockData(&AfxGetDB(), m_CurStock, m_nCurKType, m_nCurKFormat, m_nCurMaindataType, FALSE, bReload);
AfxPrepareStockData(&AfxGetDB(), m_CurStockDown, m_nCurKType, CKData::formatXDRdown, m_nCurMaindataType, FALSE, bReload);
if (m_CurStock.GetKData(m_nCurKType).GetSize() != nOldSize)
ResetIndex();
AfxGetStkReceiver().RequestKData(&m_CurStock, m_nCurKType);
m_techparam.Clear();
m_techparam.SetKData(&(m_CurStockDown.GetKData(m_nCurKType)));
m_techparam.volume.SetKData(&(m_CurStock.GetKData(m_nCurKType)));
m_techparam.ma.SetKData(&(m_CurStock.GetKData(m_nCurKType)));
m_techparam.bbi.SetKData(&(m_CurStock.GetKData(m_nCurKType)));
m_techparam.boll.SetKData(&(m_CurStock.GetKData(m_nCurKType)));
m_techparam.pv.SetKData(&(m_CurStock.GetKData(m_nCurKType)));
m_techparam.sar.SetKData(&(m_CurStock.GetKData(m_nCurKType)));
m_techparam.dj.SetKData(&(m_CurStock.GetKData(m_nCurKType)));
m_techparam.mike.SetKData(&(m_CurStock.GetKData(m_nCurKType)));
m_techparam.dj2.SetKData(&(m_CurStock.GetKData(m_nCurKType)));
return TRUE;
}
ONCREATE只是产生VIEW的基本结构和变量而在OnInitialUpDate()中,主要初始化视图中控件等,对各个变量进行初始化操作。OnCreate()是生成结构的,而OnInitialUpDate是对结构进行初始化。两个一个相当于硬件一个相当于软件,功能和作用完全不同。
step 3:发送WM_PAINT消息
数据初始化完成后,调用Invalidate(),系统发送WM_PAINT消息。OnPaint是WM_PAINT消息的消息处理函数,在OnPaint中调用OnDraw()处理。
第二部分 画日K线图
MFC是事件消息响应机制,根据不同的消息,由不同的函数进行处理。
step 4:画K线图
收到WM_PAINT消息后,由画图函数OnDraw()调用了m_graph.Redraw()进行绘图。
G:\stock\TskingVS2019\src\Client\StkUI\View\GraphView.cpp
/////////////////////////////////////////////////////////////////////////////
// CGraphView drawing
//说明:OnPaint是WM_PAINT消息的消息处理函数,在OnPaint中调用OnDraw。
//OnPaint()是CWnd的类成员,负责响应WM_PAINT消息。OnDraw()是CVIEW的成员函数,没有响应消息的功能.当视图变得无效时(包括大小的改变,移动,被遮盖等等),Windows发送WM_PAINT消息。该视图的OnPaint 处理函数通过创建CPaintDC类的DC对象来响应该消息并调用视图的OnDraw成员函数.OnPaint最后也要调用OnDraw,因此一般在OnDraw函数中进行绘制。
void CGraphView::OnDraw(CDC* pDC)
{
CStaticDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CRect rectClient;
GetClientRect(&rectClient);
CMemDC memDC(pDC);
m_graph.Redraw(&memDC, rectClient); //画图
G:\stock\TskingVS2019\src\Client\StkUI\View\StockGraph.cpp
void CStockGraph::Redraw(CDC* pDC, CRect rectAll)
{
ASSERT(m_pParent && ::IsWindow(m_pParent->GetSafeHwnd()));
if (m_rectAll != rectAll)
ResetClient(rectAll);
DrawStock(pDC);
}
CStockGraph中的绘图函数为DrawStock,在这个成员函数里分别调用下面的几个函数画出各个子窗口:
图中1为KDATA,为股票的数据信息,是CStockGraph::DrawKData( )调用画出来的。
图中2为KLINE,为股票的K线图,是CStockGraph::DrawKLine( )调用画出来的。
图中3为TechLine,为技术指标线,是CStockGraph::DrawTechLine( pDC )调用画出来的。
图中3区域的下面为时间轴,是调用CStockGraph::DrawDateAxis( pDC )画出来的
图中4区域为Report信息区域,是调用CStockGraph::DrawReportRegion( pDC )画出来的。
//画股票K线 by freeman
void CStockGraph::DrawStock(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 (!m_CurStock.GetStockInfo().IsValidStock())
return;
CKData& kdata = m_CurStock.GetKData(m_nCurKType);
if (kdata.GetSize() == 0)
{
DrawNoDataInfo(pDC); //股票K线没有数据时,显示获取更多数据请点击菜单“数据->历史数据下载...”。"
}
else if (PrepareDrawKLine()) // Reset m_nIndexStart, m_nIndexEnd, m_nIndexCurrent
{
DrawDateAxis(pDC); //画K线底部的日期提示框里的文字
DrawTechLine(pDC); //画窗口底部的技术指标线
DrawKLine(pDC); //画K线图
DrawKData(); //画周期K线的左上角信息
}
DrawReportRegion(pDC); //画日K线右下角窗口:参数、成本、火焰山、活跃
}
//画周期K线的左上角信息 by freeman
void CStockGraph::DrawKData(CDC* pDC, CRect rect)
{
//画周期K线图 by freeman
void CStockGraph::DrawKLine(CDC* pDC)
//画单根K线 by freeman
void CStockGraph::DrawOneKLine(CDC* pDC, int nIndexPos, int nIndexKD, CKData* pKData, double dMin, double dMax, BOOL bGreyed)
/画窗口右上角的参数窗口 by freeman
void CStockGraph::DrawReportParam(CDC* pDC)
画技术指标的函数
//画周期K线叠加技术指标 如boll线、叠加图等 by freeman
void CStockGraph::DrawKLineAttribute(CDC* pDC, UINT nTech, CRect rect, BOOL bDrawTitle, double dMin, double dMax)
//画窗口底部的技术指标线 by freeman
void CStockGraph::DrawTechLine(CDC* pDC, UINT nTech, CRect rect, BOOL bDrawTitle)
step 1:在各个界面,被选中的股票会存入存入AfxGetProfile().GetCurrentStock(&info)变量
step 2:切换到K线图时,初始化部分会先从配置文件中取出当前股票信息,然后初始化m_graph变量。m_graph是一个StockGraph类。
G:\stock\TskingVS2019\src\Client\StkUI\View\GraphView.cpp
AfxGetProfile().GetCurrentStock(&info)
BOOL CGraphView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
void CGraphView::OnInitialUpdate()
{
CView::OnInitialUpdate();
// TODO: Add your specialized code here and/or call the base class
OnUpdate(NULL, UPDATE_HINT_GRAPHVIEW, NULL);
}
void CGraphView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
// TODO: Add your specialized code here and/or call the base class
if (UPDATE_HINT_GRAPHVIEW != lHint && UPDATE_HINT_GRAPHVIEW_NOTRELOADDATA != lHint)
return;
if (!IsWindowVisible())
return;
SetFocus();
CStockInfo info;
if (AfxGetProfile().GetCurrentStock(&info))
{
m_graph.SetCurStock(info);
m_graph.PrepareStockData(UPDATE_HINT_GRAPHVIEW_NOTRELOADDATA != lHint);
}
else
{
m_graph.SetCurStock(STKLIB_CODE_MAIN);
m_graph.PrepareStockData(UPDATE_HINT_GRAPHVIEW_NOTRELOADDATA != lHint);
AfxGetProfile().SetCurrentStock(STKLIB_CODE_MAIN, FALSE);
}
Invalidate();
CMainFrame * pFrame = AfxGetMainFrame();
if (pFrame)
pFrame->m_SearchBox.SetCurrentWindowText();
}
窗口右下角的标签项
准备窗口右下角的标签项,如火焰山等
/准备窗口右下角的标签项,如火焰山等;注册窗口句柄 by freeman
int CGraphView::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);
m_graph.SetParent(this);
// tab
//if (!m_wndReportTab.Create(WS_VISIBLE|WS_CHILD,CRect(0,0,180,19),this,IDC_GRAPHVIEW_REPORTTAB))
// return -1;
//准备窗口右下角的标签项,如火焰山等 by freeman
CTSKTabManagerItem* pItem;
CString strName;
strName.LoadString(IDS_GRAPHTAB_PARAM);
pItem = new CTSKTabManagerItem();
pItem->SetCaption(strName);
AddItem(GV_REPORTTAB_PARAM, pItem);
strName.LoadString(IDS_GRAPHTAB_COST);
pItem = new CTSKTabManagerItem();
pItem->SetCaption(strName);
AddItem(GV_REPORTTAB_COST, pItem);
strName.LoadString(IDS_GRAPHTAB_FLAME);
pItem = new CTSKTabManagerItem();
pItem->SetCaption(strName);
AddItem(GV_REPORTTAB_FLAME, pItem);
strName.LoadString(IDS_GRAPHTAB_ACTIVITY);
pItem = new CTSKTabManagerItem();
pItem->SetCaption(strName);
AddItem(GV_REPORTTAB_ACTIVITY, pItem);
SetSelectedItem(GetItem(0));
m_nMinWidth = 40;
//m_wndReportTab.SetColorTabs(AfxGetProfile().GetColor(CColorClass::clrGraphBK));
//m_wndReportTab.SetSelectTabColor(AfxGetProfile().GetColor(CColorClass::clrGraphBK),
// AfxGetProfile().GetColor(CColorClass::clrTitle));
//m_wndReportTab.SetAutoAjust(FALSE);
//m_wndReportTab.ShowButtonClose(FALSE);
//m_wndReportTab.SetALingTabs(CGuiTabWnd::ALN_BOTTOM);
// 实时行情刷新,注册窗口句柄
AfxGetStkReceiver().AddRcvDataWnd(GetSafeHwnd());
return 0;
}
窗口右上角的窗口显示内容-标签项-参数
显示的字符串定义
StkUI\StkUI.rc
STRINGTABLE
BEGIN
IDS_STOCKGRAPH_OPEN "开 盘"
IDS_STOCKGRAPH_HIGH "最 高"
IDS_STOCKGRAPH_LOW "最 低"
IDS_STOCKGRAPH_CLOSE "收 盘"
IDS_STOCKGRAPH_VOLUME "成 交 量"
IDS_STOCKGRAPH_AMOUNT "成 交 额"
IDS_STOCKGRAPH_YIELDAVERAGE "年收益率"
IDS_STOCKGRAPH_DAY "日"
IDS_STOCKGRAPH_YIELDSTDDEV "标准差"
IDS_STOCKGRAPH_BEITE "β值"
IDS_STOCKGRAPH_XIAPU "夏普指数"
IDS_STOCKGRAPH_CHANGEHAND "换手"
IDS_STOCKGRAPH_RATIOVOLUME "量比"
//IDS_STOCKGRAPH_SHARECURRENCY "流通股本-万"
IDS_STOCKGRAPH_SHARECURRENCY "流通股本" //changed by freeman
IDS_STOCKGRAPH_NETASSETPS "每股净资产"
IDS_STOCKGRAPH_EPS "每股收益"
END
STRINGTABLE
BEGIN
IDS_STOCKGRAPH_RS "相对强度"
IDS_STOCKGRAPH_TIME2 "时间"
IDS_STOCKGRAPH_PRICEAVERAGE "成交均价"
IDS_STOCKGRAPH_RELATIVECHANGEHAND "相对换手率"
IDS_GRAPHTAB_PARAM "参数"
IDS_GRAPHTAB_COST "成本"
IDS_STOCKGRAPH_SHARETOTAL "总股本-万"
IDS_TITLE_INFOVIEW "在线资讯"
IDS_SETPARAM_INVALID "您设定的参数不正确,请重新设定。"
IDS_TITLE_GROUPVIEW "分组"
IDS_TITLE_TECHSVIEW "指标"
IDS_GROUPVIEW_GROUP "分组"
IDS_GROUPVIEW_DOMAIN "板块"
IDS_STRATEGY_SETPRPT "请设定新策略的名称和一些属性。"
IDS_PROPERTYSHEET_NEXT "下一步(&N) >"
IDS_STOCKGRAPH_NOKDATA "。获取更多数据请点击菜单“数据->历史数据下载...”。"
END
STRINGTABLE
BEGIN
IDS_EXPORTDEST_CONFIRMCLOSE "正在导出,您确定要中断导出,关闭对话框吗?"
IDS_SETDRDATA_DATE "日期"
IDS_SETDRDATA_BONUS "10派X元"
IDS_SETDRDATA_BONUSSHARE "10送X股"
IDS_SETDRDATA_RATIONSHARE "10配X股"
IDS_SETDRDATA_RATIONVALUE "配股价"
IDS_SETDRDATA_NOSTOCK "请在左边选择您要修改的股票。"
IDS_SETCOLUMN_SAMEASYIELDAVERAGE "与年平均收益率相同"
IDS_SETCOLUMN_IFRECALCULATE
"计算年平均收益率天数已经改变,现在重新计算平均收益率、β值并保存吗?否则股票列表中显示的数据还是以前的。\n您可以通过菜单 “数据-〉重新计算平均收益率” 执行该操作。"
IDS_INSTALLPAC_IFRECALCULATE
"数据已经更新,现在重新计算年平均收益率、β值并保存吗?否则股票列表中显示的数据还是以前的。\n您可以通过菜单 “数据-〉重新计算平均收益率” 执行该操作。"
IDS_STOCKGRAPH_KLINE "K 线"
IDS_STOCKGRAPH_FONTNAME "楷体"
IDS_STOCKGRAPH_TIME "时 间"
END
和日K线有关的ID定义
#define IDS_STOCKGRAPH_KLINE 45773
#define IDS_STOCKGRAPH_FONTNAME 45774
#define IDS_STOCKGRAPH_TIME 45775
#define IDS_STOCKGRAPH_OPEN 45776
#define IDS_STOCKGRAPH_HIGH 45777
#define IDS_STOCKGRAPH_LOW 45778
#define IDS_STOCKGRAPH_CLOSE 45779
#define IDS_STOCKGRAPH_VOLUME 45780
#define IDS_STOCKGRAPH_AMOUNT 45781
#define IDS_STOCKGRAPH_YIELDAVERAGE 45782
#define IDS_STOCKGRAPH_DAY 45783
#define IDS_STOCKGRAPH_YIELDSTDDEV 45784
#define IDS_STOCKGRAPH_BEITE 45785
#define IDS_STOCKGRAPH_XIAPU 45786
#define IDS_STOCKGRAPH_CHANGEHAND 45787
#define IDS_STOCKGRAPH_RATIOVOLUME 45788
#define IDS_STOCKGRAPH_SHARECURRENCY 45789
#define IDS_STOCKGRAPH_NETASSETPS 45790
#define IDS_STOCKGRAPH_EPS 45791
#define IDS_STOCKGRAPH_RS 45792
#define IDS_STOCKGRAPH_TIME2 45793
#define IDS_STOCKGRAPH_PRICEAVERAGE 45794
#define IDS_STOCKGRAPH_RELATIVECHANGEHAND 45795
#define IDS_STOCKGRAPH_SHARETOTAL 45798
#define IDS_STOCKGRAPH_NOKDATA 45807
#define IDS_STOCKGRAPH_PROJECT 45808
#define IDS_STOCKGRAPH_PRIMARY 45809
#define IDS_STOCKGRAPH_MEDIATE 45810
#define IDS_STOCKGRAPH_MIGHT 45811
#define IDS_STOCKGRAPH_PRESSURE 45812
#define IDS_STOCKGRAPH_UPHOLD 45813
#define IDS_STOCKGRAPH_RECENTCWDISFMT 45829
#define IDS_STOCKGRAPH_PASTCWDISFMT 45830
#define IDS_STOCKGRAPH_GAINPERCENT 45831
#define IDS_STOCKGRAPH_COSTAVE 45832
#define IDS_STOCKGRAPH_MASSFMT90 45833
#define IDS_STOCKGRAPH_MASSFMT70 45834
#define IDS_STOCKGRAPH_PE 45842
第三部分 事件消息响应
3.1 按键F5的消息响应
G:\stock\TskingVS2019\src\Client\StkUI\View\GraphView.cpp
//处理按键,按F5 切换到 分时线图 by freeman
BOOL CGraphView::PreTranslateMessage(MSG* pMsg)
{
if (WM_KEYDOWN == pMsg->message)
{
switch(pMsg->wParam)
{
case VK_F5: //K线图 F5热键、快捷键定义 by freeman
{
AfxSwitchToStaticView(RUNTIME_CLASS(CRealTimeView));
CRealTimeView * pView = AfxGetRealTimeView();
if (pView)
pView->ChangeDrawMode(CRealTime::modePriceLine);
}
return TRUE;
}
}
return CView::PreTranslateMessage(pMsg);
}
3.2 按键回车键的消息响应
void CGraphView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
switch(nChar)
{
case VK_RETURN:
m_graph.OnReturn(IsSHIFTpressed(), IsCTRLpressed());
break;
.....
}
第四部分 画K线实现原理
//画周期K线图 by freeman
void CStockGraph::DrawKLine(CDC* pDC)
{
// Draw K Line 循环画K线
for (int k = m_nIndexStart; k <= m_nIndexEnd; k++)
{
DrawOneKLine(pDC, k, k, &kdata, dMin, dMax, FALSE);
}
}
//画单根K线 by freeman
void CStockGraph::DrawOneKLine(CDC* pDC, int nIndexPos, int nIndexKD, CKData* pKData, double dMin, double dMax, BOOL bGreyed)
{
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
//画K线上的最高和最低价格的线
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);
}
}
MFC中无标题栏窗口的移动