原創(chuàng)|使用教程|編輯:龔雪|2015-06-12 10:33:36.000|閱讀 2767 次
概述:網(wǎng)上的TeeChart控件部分文檔資料十分零碎,且很多不全面,代碼難以使用。作者苦尋數(shù)周在外國(guó)一些網(wǎng)站上尋到了一些有用的信息,把相關(guān)的可運(yùn)行的代碼示例貼在文中,希望能幫到后來者。
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關(guān)鏈接:
最近接手了一個(gè)項(xiàng)目,其中涉及到MFC和實(shí)時(shí)曲線顯示的問題,由于我之前從未接觸過此類技術(shù),現(xiàn)學(xué)現(xiàn)搞,把其間用到的覺得對(duì)初學(xué)者有用的東西,總結(jié)一下。
尤其是關(guān)于TeeChart控件部分,網(wǎng)上資料零碎,且很多不全面,代碼難以使用。我苦尋數(shù)周在外國(guó)一些網(wǎng)站上尋到了一些有用的信息,把相關(guān)的可運(yùn)行的代碼示例貼在文中,希望能幫到后來者。
新建一個(gè)單文檔的MFC工程(注意在向?qū)е性O(shè)置窗口最大化和分割窗口支持)。
新建兩個(gè)對(duì)話框,用于分割窗口。
【注意】對(duì)話框的樣式(Style)屬性改為下層(Child),邊框(Border)屬性改為None,最開始沒有改這個(gè),程序運(yùn)行的時(shí)候報(bào)錯(cuò)了。
【注意】將兩個(gè)對(duì)話框生成從CFormView派生的類。
在CMainFrame的OnCreateClient中添加
【例1】把框架分割成兩列,右邊的一列和對(duì)話框綁定。
m_SplitterWnd.CreateStatic(this,1,2)); //把此框架窗口分割成1行2列。 m_SplitterWnd.SetColumnInfo(0, 200, 0) ; //設(shè)置第0列的最大寬度為200,最小寬度為0 (此句話非常重要) CRect rect; GetClientRect(&rect); //第1行第1列的窗口與CMyView綁定。其寬度為框架寬度的3/4.高度與框架的高度一致 if(!m_SplitterWnd.CreateView(0,0,RUNTIME_CLASS(CMyView),CSize(rect.Width()/4*3,rect.Height()),pContext)|| //第1行第2列的窗口與我們的對(duì)話框CMyDlg綁定。其寬度為框架寬度的1/4. !m_SplitterWnd.CreateView(0,1,RUNTIME_CLASS(CMyDlg), CSize(rect.Width()/4,rect.Height()),pContext)) { return FALSE; } return TRUE;
【例2】在分割后的子窗口上繼續(xù)分割
在CMainFrame中添加兩個(gè)成員變量,類型為CSplitterWnd,如下所示
CSplitterWnd m_splitterWnd1;
CSplitterWnd m_splitterWnd2;
添加虛函數(shù)virtualBOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);
程序代碼修改部分如下:
BOOLCMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) { //創(chuàng)建一個(gè)靜態(tài)分欄窗口,分為一行二列 if(m_splitterWnd1.CreateStatic(this,1,2)==NULL) return FALSE; //設(shè)置分割窗口的大小*** m_splitterWnd1.SetColumnInfo(0, 200, 0) ; //設(shè)置第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,1,WS_CHILD|WS_VISIBLE, m_splitterWnd1.IdFromRowCol(0, 1))==NULL) return FALSE; //將FormView1類連接到第二個(gè)分欄對(duì)象的0行0列 m_splitterWnd2.CreateView(0,0,RUNTIME_CLASS(CForm1),CSize(0,300),pContext);//因?yàn)槭巧舷路指睿氏到y(tǒng)不關(guān)注寬度,只看高度,故寬度可以為0 //將FormView2類連接到第二個(gè)分欄對(duì)象的1行0列 m_splitterWnd2.CreateView(1,0,RUNTIME_CLASS(CForm2),CSize(0,0),pContext); //此高度為0,意為分割后剩下的高度 就是它的了。 return TRUE; } //CsplitterwndView、CForm1、CForm2都是我們自定義的類,可以把他們換成對(duì)話框或表單等。
//初始左右分割框架,要調(diào)用函數(shù)SetColumnInfo來設(shè)定分割線位置。
對(duì)分割出來的一列再進(jìn)行分割,則是由CreateView中CSize的高度來確定分割線位置。
*總結(jié):
* 給框架窗口添加靜態(tài)拆分視圖的過程如下:
* 1. 給框架窗口類添加一個(gè)CsplitterWnd數(shù)據(jù)成員。
* 2. 覆蓋框架窗口的OnCreateClient函數(shù),并調(diào)用CsplitterWnd::CreateStatic來創(chuàng)建靜態(tài)拆分視圖。
* 3. 使用CsplitterWnd::CreateView在每個(gè)靜態(tài)拆分窗口的窗格中創(chuàng)建視圖
* 使用靜態(tài)拆分窗口的一個(gè)優(yōu)點(diǎn)是由于您自己給窗格添加視圖,所以可以控制放入視圖的種類
1、在Resource.h中添加
#define WM_MY_MESSAGE (WM_USER+100)
2、在CMyView的定義中添加: //CMyView是要響應(yīng)自定義消息的我們的視圖類
//{{AFX_MSG(CMyView)
afx_msg LRESULT OnMyMsg(WPARAM, LPARAM) ;
DECLARE_MESSAGE_MAP()
//}}AFX_MSG
3、在CMyView的實(shí)現(xiàn)cpp文件中添加
BEGIN_MESSAGE_MAP(CMyView, CFormView)
//{{AFX_MSG_MAP(CMyView)
ON_MESSAGE(WM_MY_MESSAGE, OnMyMsg) //添加消息映射
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
4、實(shí)現(xiàn)消息映射函數(shù)LRESULT CMyView::OnMyMsg(WPARAM wParam, LPARAM lParam)
5、發(fā)送消息,觸發(fā)消息響應(yīng)函數(shù)
pMyView->PostMessage(WM_MY_MESSAGE,0, 0); //至于PostMessage和SendMessage的區(qū)別 請(qǐng)百度之。
//pMyView是CMyView類對(duì)象的指針。
(以VC++6.0 TeeChart8.0為例)
至于如何獲取TeeChart控件,如何注冊(cè)控件,請(qǐng)百度之,網(wǎng)上有很多。
在相應(yīng)的源文件中添加TeeChart的頭文件 (有需要的自己再添加)
#include "tchart.h"
#include "series.h"
#include "valuelist.h"
#include "axes.h"
#include "axis.h"
#include "pen.h"
#include "axislabels.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"
(解決手工拖動(dòng)添加控件,編譯報(bào)”Debug Assertion Failed” 錯(cuò)的問題)
我們添加對(duì)話框資源讓其繼承自CFromView。首先手工靜態(tài)把控件拖到對(duì)話框上,然后建立類向?qū)В梢粋€(gè)對(duì)象m_chart。
在主框架CMainFrame::OnCreateClient()或OnCreate()中【看在哪個(gè)函數(shù)中分割窗口 產(chǎn)生視圖】
RecalcLayout(); //這一句很重要,沒有它,會(huì)報(bào)錯(cuò)。
pView->OnInitialUpdate(); //pView是我們分割窗口得到的CMyDlgView視圖的指針。
在視圖類CMyDlgView中添加OnInitialUpdate()函數(shù)
CRect rect;
GetClientRect(&rect);
m_chart.MoveWindow(&rect, TRUE);
在視圖類CMyDlgView中添加WM_CREATE消息響應(yīng)函數(shù)OnCreate()在其中添加
m_chart.Create("",WS_VISIBLE, CRect(0, 0, 0, 0), this, 1234) ;//動(dòng)態(tài)生成控件
m_chart.AddSeries(0);//操作控件
m_chart.Series(0).FillSampleValues(50);
//m_chart是我們的控件TeeChart
即可。
//但此為動(dòng)態(tài)添加的控件,所有設(shè)置操作都得通過代碼操作。
這個(gè)在網(wǎng)上有很多資料了。我在這里再簡(jiǎn)單總結(jié)一下其過程。
A、初始化部分:
在TeeChart控件所在的視圖類的OnCreate函數(shù)中,進(jìn)行TeeChart控件的初始化工作。
m_chart.Create("",WS_VISIBLE, CRect(0, 0, 0, 0), this, 1234) ; //動(dòng)態(tài)創(chuàng)建TeeChart控件 m_chart.GetLegend().SetVisible(false);//隱藏圖例 m_chart.GetAspect().SetView3D(FALSE); //取消3D顯示 //設(shè)置圖標(biāo)標(biāo)題 m_chart.GetHeader().GetText().SetItem(0,COleVariant("傳感器實(shí)時(shí)數(shù)據(jù)曲線")); //設(shè)置縱軸標(biāo)題 m_chart.GetAxis().GetLeft().GetTitle().SetCaption("數(shù)值"); //設(shè)置漸變背景 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); //設(shè)置曲線屬性 m_chart.Series(0).SetColor(RGB(255,0,0));//顏色 m_chart.Series(0).GetAsLine().GetLinePen().SetWidth(2); //線型寬度 //設(shè)置x軸的取值范圍 m_chart.GetAxis().GetBottom().SetMinMax(0,100); //設(shè)置x軸上值的格式 m_chart.GetAxis().GetBottom().GetLabels().SetValueFormat("0.0");
B、繪制部分:
在TeeChart控件所在的視圖類的自定義消息響應(yīng)函數(shù)OnMyMsg中,或是在定時(shí)器中,添加:
COleDateTimeCurTime = COleDateTime::GetCurrentTime(); COleDateTimeSpantmSpan = COleDateTimeSpan(0,0,1,0); //1s CStringcsTime ; csTime= CurTime.Format("%H:%M:%S"); //獲取當(dāng)前時(shí)間 //在CMyView中畫曲線 m_chart.Series(0).Add(yVal, csTime,RGB(255,0,0)); //第一個(gè)參數(shù)是y軸值,第二個(gè)參數(shù)是對(duì)應(yīng)的x軸的標(biāo)簽值(此為當(dāng)前時(shí)間字符串),第三個(gè)參數(shù)是所繪點(diǎn)的顏色。 CurTime+= tmSpan; m_chart.Series(0).RefreshSeries(); if(m_chart.Series(0).GetCount() > 100) { m_chart.GetAxis().GetBottom().Scroll(1.0,true); //x坐標(biāo)軸一次移動(dòng)1格 }
由于TeeChart繪制曲線點(diǎn)的函數(shù)Add,每調(diào)用一次才繪制一次,故需要有外部消息激發(fā)消息響應(yīng)函數(shù),才能把曲線動(dòng)態(tài)繪制出來。
可以用設(shè)置定時(shí)器和自定義消息響應(yīng)函數(shù)的方式來實(shí)現(xiàn)。(定時(shí)器比較簡(jiǎn)單,消息響應(yīng)函數(shù)上面MFC部分已經(jīng)講過)
解決TeeChart8中繪制3D圖形報(bào)”Invalid class typecast” 錯(cuò)的問題。
A、在承載TeeChart的對(duì)話框類Dlg的類定義中,添加:VARIANT SeriesIndex;
B、在類的相關(guān)方法中繪制,添加代碼:
m_chart.RemoveAllSeries();
//下面的設(shè)置很重要(沒有的話,會(huì)出錯(cuò))
SeriesIndex.vt=VT_INT;
SeriesIndex.intVal=m_chart.AddSeries(scWaterfall);//scWaterfall=33瀑布圖的編號(hào)
m_chart.Series(0).GetAsWaterfall().SetIrregularGrid(true);
m_chart.Series(0).GetAsWaterfall().AddXYZ(x,y, z, NULL, RGB(255,0,0));
(TeeChart的3D圖有很多種,上面是以瀑布圖為例的,其他圖種的編號(hào)如下:)
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 scFastLine = 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 scErrorBar = 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 unsigned 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 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;
const 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 unsigned 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 unsigned 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;
//如需要相關(guān)圖種,只需把上面代碼
SeriesIndex.intVal= m_chart.AddSeries(scWaterfall);//把scWaterfall改為你所需圖種的編號(hào)
m_chart.Series(0).GetAsWaterfall().SetIrregularGrid(true);// GetAsWaterfall改為你所需圖種的相關(guān)函數(shù)名
----------------
一個(gè)完整的例子:
A、在CMyView(承載TeeChart的對(duì)話框視圖)的定義中,添加VARIANTSeriesIndex;
B、在int CMyView::OnCreate(LPCREATESTRUCT lpCreateStruct)函數(shù)中:
int CMyView::OnCreate(LPCREATESTRUCTlpCreateStruct) { 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.GetAxis().GetDepth().SetVisible(TRUE); //顯示Z軸 m_chart.GetAxis().GetDepth().GetLabels().SetVisible(TRUE); //顯示Z軸上的坐標(biāo) m_chart.GetAxis().GetDepth().GetLabels().SetStyle(0); //設(shè)置顯示坐標(biāo)的風(fēng)格 //設(shè)置漸變背景 m_chart.GetPanel().GetGradient().SetVisible(true); m_chart.GetPanel().GetGradient().SetStartColor(RGB(192,192,192)); m_chart.GetPanel().GetGradient().SetEndColor(RGB(255,255,255)); //設(shè)置圖標(biāo)標(biāo)題 m_chart.GetHeader().GetText().SetItem(0,COleVariant("瀑布圖")); //開始繪制3D m_chart.RemoveAllSeries(); SeriesIndex.vt=VT_INT; SeriesIndex.intVal=m_chart.AddSeries(49);// 49號(hào)圖種,IsoSurface類型3D m_chart.Series(0).GetAsIsoSurface().SetIrregularGrid(true); //設(shè)置曲線顏色 m_chart.Series(0).SetColor(RGB(255,0,0)); m_chart.GetAxis().GetBottom().SetMinMax(0,100); m_chart.GetAxis().GetBottom().GetLabels().SetValueFormat("0.0"); m_chart.GetAspect().SetChart3DPercent(30);//調(diào)整3D縱深比 return0; }
C、在自定義的消息處理函數(shù)中:
LRESULT CMyView::OnMyMsg(WPARAM wParam,LPARAM lParam) { staticdouble xVal = .0 ; doubleyVal = .0 ; CTSDoc* pDoc = (CTSDoc*)(this->GetDocument()) ; yVal= pDoc->clientDataBuff[0] ; for(int zVal=0; zVal<50; zVal++) m_chart.Series(0).GetAsIsoSurface().AddXYZ(xVal,yVal, (double)zVal, NULL,RGB(255,(int)(yVal*30)+160,0)); m_chart.Series(0).RefreshSeries(); if(m_chart.Series(0).GetCount() > 100) { m_chart.GetAxis().GetBottom().Scroll(1.0,true); //坐標(biāo)軸一次移動(dòng)1格 } xVal++; return0 ; }
1、先在TeeChart所在的類中 添加:
COleSafeArray XValues;
COleSafeArray YValues;
2、再在TeeChart的初始化設(shè)置函數(shù)添加:
DWORD numElements[] = {200000}; // Create the safe-arrays... XValues.Create(VT_R8, 1, numElements);YValues.Create(VT_R8,1, numElements); // Initialize them with values... long index; for(index=0; index<200000; index++) { double val = (double)index; XValues.PutElement(&index, &val); }; for(index=0; index<200000; index++) { double val = rand()%100; YValues.PutElement(&index, &val); };
3、在相應(yīng)的位置添加:
m_chart.Series(0).AddArray(200000,YValues,XValues);
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@fc6vip.cn