1、其中涉及到MFC和实时曲线显示的问题由于我之前从未接最近接手了一个项目,其中涉及到MFC和实时曲线显示的问题,由于我之前从未接触过此类技术,现学现搞,把其间用到的觉得对初学者有用的东西,总结一下。尤其是关于TeeChart控件部分,网上资料零碎,且很多不全面,代码难以使用。我苦寻数周在外国一些网站上寻到了一些有用的信息,把相关的可运行的代码示例贴在文中,希望能帮到后来者。/我的博客:MFC部分:一、分割窗体新建一个单文档的MFC工程(注意在向导中设置窗口最大化和分割窗口支持)。新建两个对话框,用于分割窗口【注意】对话框的样式(Style)属性改为下层(Child),边框(Border)属性改为
2、None,最开始没有改这个,程序运行的时候报错了。【注意】将两个对话框生成从CFormView派生的类。在CMainFrame的OnCreateClient中添加【例1】把框架分割成两列,右边的一列和对话框绑定。m_SplitterWnd.CreateStatic(this,1,2); /把此框架窗口分割成1行2列。m_SplitterWnd.SetColumnInfo(0, 200, 0) ; /设置第0列的最大宽度为200,最小宽度为0 (此句话非常重要)CRect rect;GetClientRect(&rect); /第1行第1列的窗口与CMyView绑定。其宽度为框架宽度的3/4.高
3、度与框架的高度一致if(!m_SplitterWnd.CreateView(0,0,RUNTIME_CLASS(CMyView), CSize(rect.Width()/4*3,rect.Height(),pContext)| /第1行第2列的窗口与我们的对话框CMyDlg绑定。其宽度为框架宽度的1/4. !m_SplitterWnd.CreateView(0,1,RUNTIME_CLASS(CMyDlg), CSize(rect.Width()/4,rect.Height(),pContext) return FALSE;return TRUE;【例2】在分割后的子窗口上继续分割在CMain
4、Frame中添加两个成员变量,类型为CSplitterWnd,如下所示CSplitterWnd m_splitterWnd1;CSplitterWnd m_splitterWnd2;添加虚函数virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);程序代码修改部分如下:BOOL CMainFrame:OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) /创建一个静态分栏窗口,分为一行二列 if(m_splitterWnd1.Cre
5、ateStatic(this,1,2)=NULL) return FALSE; /设置分割窗口的大小* m_splitterWnd1.SetColumnInfo(0, 200, 0) ; /设置第0列的最大宽度为200,最小宽度为0 /将CCSplitterWndView连接到0行0列窗格上 m_splitterWnd1.CreateView(0,0,RUNTIME_CLASS(CsplitterwndView),CSize(600,500), pContext); /将第0行1列再分开2行1列 if(m_splitterWnd2.CreateStatic(&m_splitterWnd1,2,
6、1,WS_CHILD|WS_VISIBLE, m_splitterWnd1.IdFromRowCol(0, 1)=NULL) return FALSE; /将FormView1类连接到第二个分栏对象的0行0列 m_splitterWnd2.CreateView(0,0,RUNTIME_CLASS(CForm1),CSize(0,300),pContext); /因为是上下分割,故系统不关注宽度,只看高度,故宽度可以为0 /将FormView2类连接到第二个分栏对象的1行0列 m_splitterWnd2.CreateView(1,0,RUNTIME_CLASS(CForm2),CSize(0,
7、0),pContext); /此高度为0,意为分割后剩下的高度 就是它的了。 return TRUE; /CsplitterwndView、CForm1、CForm2都是我们自定义的类,可以把他们换成对话框或表单等。/初始左右分割框架,要调用函数SetColumnInfo来设定分割线位置对分割出来的一列再进行分割,则是由CreateView中CSize的高度来确定分割线位置*总结:* 给框架窗口添加静态拆分视图的过程如下:* 1 给框架窗口类添加一个CsplitterWnd数据成员。 * 2 覆盖框架窗口的OnCreateClient函数,并调用CsplitterWnd:CreateStati
8、c来创建静态拆分视图。 * 3 使用CsplitterWnd: CreateView在每个静态拆分窗口的窗格中创建视图* 使用静态拆分窗口的一个优点是由于您自己给窗格添加视图,所以可以控制放入视图的种类二、添加自定义消息响应1、在Resource.h中添加 #define WM_MY_MESSAGE (WM_USER+100) 2、在CMyView的定义中添加: /CMyView是要响应自定义消息的我们的视图类/AFX_MSG(CMyView)afx_msg LRESULT OnMyMsg(WPARAM, LPARAM) ;DECLARE_MESSAGE_MAP()/AFX_MSG3、在CMy
9、View的实现cpp文件中添加BEGIN_MESSAGE_MAP(CMyView, CFormView) /AFX_MSG_MAP(CMyView) ON_MESSAGE(WM_MY_MESSAGE, OnMyMsg) /添加消息映射 /AFX_MSG_MAPEND_MESSAGE_MAP()4、实现消息映射函数LRESULT CMyView:OnMyMsg(WPARAM wParam, LPARAM lParam)发送消息,触发消息响应函数(ViewPoints*)p)-pMyView-PostMessage(WM_MY_MESSAGE, 0, 0);/CTSDoc * pDoc = (CT
10、SDoc *)(ViewPoints*)p)-pTeeFFTSIGView-GetDocument() ;/pDoc-clientData = _T(buff) ;TeeChart部分:(以VC+6.0 TeeChart8.0为例)至于如何获取TeeChart控件,如何注册控件,请XX之,网上有很多。零在相应的源文件中添加TeeChart的头文件 (有需要的自己再添加)#include tchart.h#include series.h#include valuelist.h#include axes.h#include axis.h#include pen.h#include axislab
11、els.h#include teefont.h#include axistitle.h#include aspect.h#include fastlineseries.h#include titles.h#include fastlineseries.h#include panel.h#include legend.h#include annotationtool.h#include page.h #include strings.h#include gradient.h#include IsoSurfaceSeries.h一、在视图类中动态添加TeeChart控件。(解决手工拖动添加控件,编
12、译报”Debug Assertion Failed” 错的问题)我们添加对话框资源让其继承自CFromView。首先手工静态把控件拖到对话框上,然后建立类向导,生成一个对象m_chart。在主框架CMainFrame:OnCreateClient()或OnCreate()中【看在哪个函数中分割窗口 产生视图】 RecalcLayout(); /这一句很重要,没有它,会报错。 pView-OnInitialUpdate(); /pView是我们分割窗口得到的CMyDlgView视图的指针。在视图类CMyDlgView中添加OnInitialUpdate()函数 CRect rect; GetCl
13、ientRect(&rect); m_chart.MoveWindow(&rect, TRUE);在视图类CMyDlgView中添加WM_CREATE消息响应函数OnCreate()在其中添加 m_chart.Create( ,WS_VISIBLE, CRect(0, 0, 0, 0), this, 1234) ;/动态生成控件 m_chart.AddSeries(0); /操作控件 m_chart.Series(0).FillSampleValues(50);/m_chart是我们的控件TeeChart即可。/但此为动态添加的控件,所有设置操作都得通过代码操作。二、绘制2D曲线这个在网上有很
14、多资料了。我在这里再简单总结一下其过程。A、初始化部分:在TeeChart控件所在的视图类的OnCreate函数中,进行TeeChart控件的初始化工作。 m_chart.Create( ,WS_VISIBLE, CRect(0, 0, 0, 0), this, 1234) ; /动态创建TeeChart控件 m_chart.GetLegend().SetVisible(false); /隐藏图例 m_chart.GetAspect().SetView3D(FALSE); /取消3D显示 /设置图标标题 m_chart.GetHeader().GetText().SetItem(0, COle
15、Variant(传感器实时数据曲线); /设置纵轴标题 m_chart.GetAxis().GetLeft().GetTitle().SetCaption(数值); /设置渐变背景 m_chart.GetPanel().GetGradient().SetVisible(true); m_chart.GetPanel().GetGradient().SetStartColor(RGB(192,192,192) ; m_chart.GetPanel().GetGradient().SetEndColor(RGB(255,255,255) ; /添加曲线 m_chart.AddSeries(0);
16、/设置曲线属性 m_chart.Series(0).SetColor(RGB(255,0,0); /颜色 m_chart.Series(0).GetAsLine().GetLinePen().SetWidth(2) ; /线型宽度 /设置x轴的取值范围 m_chart.GetAxis().GetBottom().SetMinMax(0,100); /设置x轴上值的格式 m_chart.GetAxis().GetBottom().GetLabels().SetValueFormat(0.0) ;B、绘制部分:在TeeChart控件所在的视图类的自定义消息响应函数OnMyMsg中,或是在定时器中,
17、添加: COleDateTime CurTime = COleDateTime:GetCurrentTime(); COleDateTimeSpan tmSpan = COleDateTimeSpan(0,0,1,0); /1s CString csTime ; csTime = CurTime.Format(%H:%M:%S); /获取当前时间 /在CMyView中画曲线 m_chart.Series(0).Add(yVal, csTime, RGB(255,0,0); /第一个参数是y轴值,第二个参数是对应的x轴的标签值(此为当前时间字符串),第三个参数是所绘点的颜色。 CurTime +
18、= tmSpan; m_chart.Series(0).RefreshSeries() ; if (m_chart.Series(0).GetCount() 100) m_chart.GetAxis().GetBottom().Scroll(1.0,true); /x坐标轴一次移动1格 由于TeeChart绘制曲线点的函数Add,每调用一次才绘制一次,故需要有外部消息激发消息响应函数,才能把曲线动态绘制出来。可以用设置定时器和自定义消息响应函数的方式来实现。(定时器比较简单,消息响应函数上面MFC部分已经讲过)三、绘制3D曲线解决TeeChart8中绘制3D图形报”Invalidclassty
19、pecast” 错的问题。A、在承载TeeChart的对话框类Dlg的类定义中,添加: VARIANT SeriesIndex;B、在类的相关方法中绘制,添加代码:m_chart.RemoveAllSeries();/下面的设置很重要(没有的话,会出错)SeriesIndex.vt=VT_INT;SeriesIndex.intVal= m_chart.AddSeries(scWaterfall);/scWaterfall=33瀑布图的编号m_chart.Series(0).GetAsWaterfall().SetIrregularGrid(true);m_chart.Series(0).Get
20、AsWaterfall().AddXYZ(x, y, z, NULL, RGB(255,0,0);(TeeChart的3D图有很多种,上面是以瀑布图为例的,其他图种的编号如下:)const unsigned long scLine = 0;const unsigned long scBar = 1;const unsigned long scHorizBar = 2;const unsigned long scArea = 3;const unsigned long scPoint = 4;const unsigned long scPie = 5;const unsigned long sc
21、FastLine = 6;const unsigned long scShape = 7;const unsigned long scGantt = 8;const unsigned long scBubble = 9;const unsigned long scArrow = 10;const unsigned long scCandle = 11;const unsigned long scPolar = 12;const unsigned long scSurface = 13;const unsigned long scVolume = 14;const unsigned long s
22、cErrorBar = 15;const unsigned long scBezier = 16;const unsigned long scContour = 17;const unsigned long scError = 18;const unsigned long scPoint3D = 19;const unsigned long scRadar = 20;const unsigned long scClock = 21; const unsigned long scWindRose= 22; const unsigned long scBar3D = 23; const unsig
23、ned long scImageBar = 24; const unsigned long scDonut = 25; const unsigned long scTriSurface = 26; const unsigned long scBox = 27; const unsigned long scHorizBox = 28; const unsigned long scHistogram = 29; const unsigned long scColorGrid = 30; const unsigned long scBarJoin = 31; const unsigned long
24、scHighLow = 32; const unsigned long scWaterfall = 33; const unsigned long scSmith = 34; const unsigned long scPyramid = 35; const unsigned long scMap = 36;const unsigned long scHorizLine = 37;const unsigned long scFunnel = 38;const unsigned long scCalendar = 39;const unsigned long scHorizArea = 40;c
25、onst unsigned long scPointFigure = 41;const unsigned long scGauge = 42;const unsigned long scVector3D = 43;const unsigned long scTower = 44;const unsigned long scPolarBar = 45;const unsigned long scBubble3D = 46;const unsigned long scHorizHistogram = 47;const unsigned long scVolumePipe = 48;const un
26、signed long scIsoSurface = 49;const unsigned long scDarvas = 50;const unsigned long scHighLowLine = 51;const unsigned long scPolarGrid = 52;const unsigned long scDeltaPoint = 53;const unsigned long scImagePoint = 54;const unsigned long scOrganizational = 55;const unsigned long scWorld = 56;const uns
27、igned long scTagCloud = 57;const unsigned long scKagi = 58;const unsigned long scRenko = 59;const unsigned long scNumericGauge = 60;const unsigned long scLinearGauge = 61;const unsigned long scCircularGauge = 62;const unsigned long scBigCandle = 63;const unsigned long scLinePoint = 64;/如需要相关图种,只需把上面
28、代码SeriesIndex.intVal= m_chart.AddSeries(scWaterfall); /把scWaterfall改为你所需图种的编号m_chart.Series(0).GetAsWaterfall().SetIrregularGrid(true); / GetAsWaterfall改为你所需图种的相关函数名-一个完整的例子:A、在CMyView(承载TeeChart的对话框视图)的定义中,添加VARIANT SeriesIndex;B、在int CMyView:OnCreate(LPCREATESTRUCT lpCreateStruct)函数中:int CMyView:O
29、nCreate(LPCREATESTRUCT lpCreateStruct) if (CFormView:OnCreate(lpCreateStruct) = -1) return -1; / TODO: Add your specialized creation code here m_chart.Create( ,WS_VISIBLE, CRect(0, 0, 0, 0), this, 1234) ; m_chart.GetLegend().SetVisible(false); /隐藏图例 m_chart.GetAspect().SetView3D(true); /3D显示 m_chart
30、.GetAxis().GetDepth().SetVisible(TRUE); /显示Z轴 m_chart.GetAxis().GetDepth().GetLabels().SetVisible(TRUE); /显示Z轴上的坐标 m_chart.GetAxis().GetDepth().GetLabels().SetStyle(0); /设置显示坐标的风格 /设置渐变背景 m_chart.GetPanel().GetGradient().SetVisible(true); m_chart.GetPanel().GetGradient().SetStartColor(RGB(192,192,192) ; m_chart.GetPanel().GetGradient().SetEndColor(RGB(255,255,255) ; /设置图标标题 m_chart.GetHeader().GetText().SetItem(0, COleVariant(瀑布图); /开始绘制3D m_chart.RemoveAllSeries(); SeriesIndex.vt=VT_INT; SeriesIndex.intVal= m_cha
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1