📄 mschartintroduce.txt
字号:
---- 进行程序设计时,选用一个合适的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”菜单项,就会弹出主要属性页对 话框,对其中各属性值进行设置。有些属性在主要属性页里没有列出,只能编程修改。 另外要动态绘制图表,必须掌握对控件的编程控制。
---- 首先在对话框类中定义控件变量,以便编程时操纵控件。 如对话框类定义如下:
class CAbcDlg : public CDialog{
public:
CAbcDlg(CWnd* pParent = NULL);
//{{AFX_DATA(CAbcDlg)
enum { IDD = IDD_ABC_DIALOG };
CMSChart m_Chart;
//}}AFX_DATA
......
};
----ActiveX控件的属性和方法在控件内部对应唯一一个整数 索引值,编程时可以通过索引来设置或获取控件的属性值,也可以通过调用控件的C+ +类(在这里就是CMSChart)的成员函数设置或获取控件的属性值及调用控件的方法。 例如:
----在CMSChart类实现中有如下代码:
CString CMSChart::GetData(){
CString result;
InvokeHelper(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 pDispatch;
InvokeHelper(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_VARIANT;
InvokeHelper(0x1f, DISPATCH_PROPERTYGET,
VT_DISPATCH, (void*)&pDispatch, parms, axisID, &Index);
return CVcAxis(pDispatch);
}
----而CVcAxis类的实现中有如下代码:
CVcValueScale CVcAxis::GetValueScale(){
LPDISPATCH pDispatch;
InvokeHelper(0x9, DISPATCH_PROPERTYGET,
VT_DISPATCH, (void*)&pDispatch, NULL);
return CVcValueScale(pDispatch);
}
----而CVcValueScale类的实现中又有如下代码:
void CVcValueScale::SetMaximum(double newValue){
static BYTE parms[] =VTS_R8;
InvokeHelper(0x3, DISPATCH_PROPERTYPUT,
VT_EMPTY, NULL, parms,newValue);
}
----这正是Chart控件的灵活性所在,根据上述代码,如下的 调用:
VARIANT var;
m_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 var;
m_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;
else
theApp.nBottomRange = 0;
//用全局变量保存水平滚动条的范围值
m_ScrBottom.SetScrollRange(0,theApp.nBottomRange);
theApp.nBottomPos = theApp.nBottomRange;
m_ScrBottom.SetScrollPos(theApp.nBottomPos);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -