欢迎分享,转载请注明来源:内存溢出
切换到类视图,比如说我的工程名为:ClientOCX,那么展开ClientOCXLib,在下面的_DClientOCX上面点击右键,就可以添加属性和方法了,下面的那个_DClientOCXEvents上也可以点右键添加。 添加事件,可以直接在CClientOCXCtrl类上点右键添加。进行程序设计时,选用一个合适的ActiveX控件,有时可大大减少编程工作量。ActiveX 控件(又称OCX)基于COM技术,作为独立的软件模块,它可以在任何程序设计语言中插入使用。本文仅以VC++为例说明Chart控件的使用。 Chart控件指Mschart.ocx(5.0版)或Mschrt20.ocx(6.0 版),是Visual Studio自带的ActiveX控件之一,其属性、事件很多,功能非常强大,可实现柱状直方图、曲线走势图、饼状比例图等,甚至可以是混合图表,可以是二维或三维图表,可以带或不带坐标系,可以自由配置各条目的颜色、字体等等。 一 安装和使用Chart控件在用到Chart控件的项目中安装该控件:从Project->Add to Project->Components And Controls->Registered Active Xcontrols,选择Chart控件,则 ClassWizard会生成相应的C++类,其中类CMSChart是由CWnd派生来的,它是Chart 控件的主要类,其他的类全部是由COleDispatchDriver派生来,控制控件中的相应对象,完成各部分相关功能,如CvcAxis类是实现坐标轴相关功能的源代码。同时在项目的控件工具箱上会出现代表Chart控件的按钮,使用时把Chart控件按钮从工具箱拖到对话框中,调整大小即可。 Chart控件至少有45个属性、9个方法、49个事件,在这里就不一一列举了。 在设计中,我们可以在主要属性页里修改各属性的属性值:右击对话框窗口中的Chart控件,选择“Properties”菜单项,就会d出主要属性页对话框,对其中各属性值进行设置。有些属性在主要属性页里没有列出,只能编程修改。另外要动态绘制图表,必须掌握对控件的编程控制。 首先在对话框类中定义控件变量,以便编程时 *** 纵控件。如对话框类定义如下: class CAbcDlg : public CDialog{public: CAbcDlg(CWnd* pParent = NULL)//{{AFX_DATA(CAbcDlg) enum { IDD = IDD_ABC_DIALOG } CMSChartm_Chart //}}AFX_DATA }ActiveX控件的属性和方法在控件内部对应唯一一个整数索引值,编程时可以通过索引来设置或获取控件的属性值,也可以通过调用控件的C++类(在这里就是CMSChart)的成员函数设置或获取控件的属性值及调用控件的方法。例如: 在CMSChart类实现中有如下代码: CString CMSChart::GetData(){ CString resultInvokeHelper(0x9, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL) return result}void CMSChart::SetData(LPCTSTR lpszNewValue){ static BYTE parms[] =VTS_BSTR InvokeHelper(0x9, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,lpszNewValue)}void CMSChart::Refresh(){InvokeHelper(DISPID_REFRESH, DISPATCH_METHOD, VT_EMPTY, NULL, NULL)}这段代码表明:属性“Data”索引值为0x9,我们可以调用函数SetData对图表中某点的值进行设置。索引值为DISPID_REFRESH的方法 “Refresh”,调用它进行刷新。如: CString str=“34.5"m_Chart.SetData(str)m_Chart.Refresh()阅读CMSChart类的实现会发现,有些属性的值不是普通的BOOL、CString等数据类型,而是另一个控件驱动类的类变量,如: CVcPlot CMSChart::GetPlot(){ LPDISPATCH pDispatchInvokeHelper(0x28, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&pDispatch, NULL) return CVcPlot(pDispatch)}在CVcPlot类的实现中有如下代码: CVcAxis CVcPlot::GetAxis (long axisID, const VARIANT& Index){ LPDISPATCH pDispatch static BYTE parms[] =VTS_I4 VTS_VARIANTInvokeHelper(0x1f, DISPATCH_PROPERTYGET,VT_DISPATCH, (void*)&pDispatch, parms, axisID, &Index) return CVcAxis(pDispatch)}而CVcAxis类的实现中有如下代码: CVcValueScale CVcAxis::GetValueScale(){ LPDISPATCH pDispatchInvokeHelper(0x9, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&pDispatch, NULL) return CVcValueScale(pDispatch)}而CVcValueScale类的实现中又有如下代码: void CVcValueScale::SetMaximum(double newValue){ static BYTE parms[] =VTS_R8InvokeHelper(0x3, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,newValue)}这正是Chart控件的灵活性所在,根据上述代码,如下的调用: VARIANT varm_Chart.GetPlot().GetAxis(1, var).GetValueScale().SetMaximum(50.0)可实现把纵坐标的最大刻度设为50.0。控件触发的事件,如Click、MouseDown等,如果需要处理,可以通过ClassWizard在对话框类中定义相应的处理函数,实现相关的处理功能。 二 动态绘制图表实例在一个温度采集系统中,希望把采集来的各项温度值实时显示,用Chart控件绘制曲线走势图: 各温度项以不同颜色的曲线表示; 横坐标为时间,纵坐标为温度值,均要求滚动显示; 在每次采样完成后,刷新屏幕。 设计思路 随着时间的推移,采集来的数据不断增加,不一定在一屏中显示,所以系统打开一个实时数据库,存放采集来的实时数据。显示时,需要哪个时间段的数据,就从数据库中读取。 在对话框资源编辑时,增加水平滚动条和垂直滚动条,以便配合Chart控件进行滚动显示。 为对话框启动定时器,按采样间隔进行采样,并刷新屏幕显示。 主要相关代码如下: BOOL CAbcDlg::OnInitDialog(){ CDialog::OnInitDialog()pDataDB = new dbase//实时数据记录库,类dbase的基类为CDaoRecordset pDataDB->Open(dbOpenDynaset, “select* from data") VARIANT varm_Chart.GetPlot().GetAxis(1,var).GetValueScale(). SetAuto(FALSE)//不自动标注y轴刻度m_Chart.GetPlot().GetAxis(1, var).GetValueScale(). SetMaximum(37)//y轴最大刻度m_Chart.GetPlot().GetAxis(1, var).GetValueScale(). SetMinimum(32)//y轴最小刻度m_Chart.GetPlot().GetAxis(1,var).GetValueScale(). SetMajorDivision(5)//y轴刻度5等分m_Chart.GetPlot().GetAxis(1,var).GetValueScale(). SetMinorDivision(1)//每刻度一个刻度线m_Chart.SetColumnCount(3)//3个温度项,3条曲线 m_Chart.GetPlot().GetSeriesCollection().GetItem(1). GetPen().GetVtColor().Set(0, 0, 255)//线色 m_Chart.GetPlot().GetSeriesCollection().GetItem(2). GetPen().GetVtColor().Set(255, 0, 0) m_Chart.GetPlot().GetSeriesCollection().GetItem(3). GetPen().GetVtColor().Set(0, 255, 0) m_Chart.GetPlot().GetSeriesCollection(). GetItem(1).GetPen().SetWidth(2)//线宽 m_Chart.GetPlot().GetSeriesCollection(). GetItem(2).GetPen().SetWidth(2) m_Chart.GetPlot().GetSeriesCollection(). GetItem(3).GetPen().SetWidth(2) m_Chart.SetRowCount(10)//一屏显示10个采样时刻 m_Chart.GetPlot().GetAxis(0,var).GetCategoryScale(). SetAuto(FALSE)//不自动标注x轴刻度 m_Chart.GetPlot().GetAxis(0,var).GetCategoryScale(). SetDivisionsPerLabel(1)//每时刻一个标注 m_Chart.GetPlot().GetAxis(0,var).GetCategoryScale(). SetDivisionsPerTick(1)//每时刻一个刻度线 m_ScrLeft.SetScrollRange(0,45) //垂直滚动条可滚动范围(温度值范围0-50, 每滚动1度,一屏显示5度) m_ScrLeft.SetScrollPos(45-32)//垂直滚动条的当前位置 m_ScrBottom.SetScrollRange(0, 0)//水平滚动条的可滚动范围 m_ScrBottom.SetScrollPos(0)//水平滚动条的当前位置 SetTimer(23, 300000, NULL)//启动定时器,定时间隔5分钟 Sample()//调用采样函数进行第一次采样,并把数据记录入库 return TRUE}void CAbcDlg::OnTimer(UINT nIDEvent) { Sample()//采样,并把数据记录入库 if (pDataDB->GetRecordCount()>10) theApp.nBottomRange = pDataDB->GetRecordCount()-10 elsetheApp.nBottomRange = 0//用全局变量保存水平滚动条的范围值m_ScrBottom.SetScrollRange(0,theApp.nBottomRange) theApp.nBottomPos = theApp.nBottomRange m_ScrBottom.SetScrollPos(theApp.nBottomPos) //修正水平滚动条的显示 DrawPic()//调用函数,刷新曲线显示 CDialog::OnTimer(nIDEvent)}void CAbcDlg::DrawPic() {char s[10] UINT row = 1 pDataDB->MoveFirst()pDataDB->Move(theApp.nBottomPos)//只从数据库中取某时间段的数据进行显示 while ((!pDataDB->IsEOF()) && (row m_date_time.Format(“%H:%M"))//以采样时刻做x轴的标注 m_Chart.SetColumn(1) sprintf(s, “%6.2f", pDataDB->m_No1) m_Chart.SetData((LPCSTR)s) m_Chart.SetColumn(2) sprintf(s, “%6.2f", pDataDB->m_No2) m_Chart.SetData((LPCSTR)s) m_Chart.SetColumn(3) sprintf(s, “%6.2f", pDataDB->m_No3) m_Chart.SetData((LPCSTR)s) pDataDB->MoveNext() row++ } while ((row GetRecordCount()>10) theApp.nBottomRange = pDataDB->GetRecordCount()-10 else theApp.nBottomRange = 0m_ScrBottom.SetScrollRange(0, theApp.nBottomRange) switch (nSBCode){ case SB_LINERIGHT: if (theApp.nBottomPos 0){ theApp.nBottomPos = theApp.nBottomPos - 1 m_ScrBottom.SetScrollPos(theApp.nBottomPos) DrawPic() } break } CDialog::OnHScroll(nSBCode, nPos, pScrollBar)}void CAbcDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { VARIANT var double max1,min1,f switch (nSBCode){ case SB_LINEDOWN:f = m_Chart.GetPlot().GetAxis(1, var). GetValueScale().GetMinimum() - 1 if (f>=0) {//最小刻度大于等于0, 则可以滚动m_Chart.GetPlot().GetAxis(1, var).GetValueScale(). SetMinimum(f)f = m_Chart.GetPlot().GetAxis (1, var).GetValueScale().GetMaximum() - 1m_Chart.GetPlot().GetAxis(1, var).GetValueScale().SetMaximum(f)pScrollBar->SetScrollPos(pScrollBar->GetScrollPos() + 1) m_Chart.Refresh() } break case SB_LINEUP:f = m_Chart.GetPlot().GetAxis(1, var).GetValueScale().GetMaximum() + 1 if (f SetScrollPos(pScrollBar->GetScrollPos() - 1) m_Chart.Refresh() } break } CDialog::OnVScroll(nSBCode, nPos, pScrollBar)}特别注意,程序中用到的关于控件的类,如CVcAxis等,需要在AbcDlg.cpp文件的开始处说明:#include “VcAxis.h"。 限于篇幅,文中仅仅是一个简单示例的部分代码。在实际应用中,一般会有的需求,比如:对坐标轴进行缩放显示;采样有可能得不到正确的采样值时曲线显示不连续等等,这时需要根据需求编写相应代码。
赞
(0)
打赏
微信扫一扫
支付宝扫一扫
excel单元格下拉选项怎么添加
上一篇
2023-05-18
input type="file" 理解
下一篇
2023-05-18
评论列表(0条)