这个案例指在介绍微软这套免费又功能强大的图表控件Microsoft Chart Controls for Microsoft .NET Framework 3.5,通过它,可让您的项目及报表,轻松套用各种功能强大的 2D、3D、实时变化的动态图表;且透过 AJAX,可让图表及里面的数据,每秒钟都持续更新;使用者透过浏览器,可和图表做各种互动设定
下面结合BBVS项目中温度功能模块中温度曲线的绘制 做了如下Demo,供大家学习微软的这款功能强大的图标控件,这里只是起一个抛砖引玉的作用,更多更好玩的功能还等大家不断进一步去挖掘!
首先,让大家瞧瞧Chart控件的庐山真面目和组成吧,不然有些对不住大家,呵呵
一、需引用的DLL
要想利用这个功能强大的控件,首先必须引用以下DLL和相关文件:
1. 在WinForm应用程序中要想使用该图表控件,需引用如下DLL:
System.Windows.Forms.DataVisualization.Design.dll
System.Windows.Forms.DataVisualization.dll
System.Windows.Forms.DataVisualization.xml
2. 在Web应用程序中要想使用该图表控件,需引用如下DLL:
System.Web.DataVisualization.dll
System.Web.DataVisualization.Design.dll
System.Web.DataVisualization.xml
二、采用WinForm程序使用该图表控件
1. 创建一个WinForm工程: DemoCollection
2. 添加一个Form窗体: FrmChartDemo
3. 添加所需的DLL引用
4. 在该窗体的Load事件函数中动态创建好Chart对象实例
5. 添加一个Timer控件,在Timer控件的Tick事件函数中向Chart中添加坐标值(X值和Y值),然后在窗体中绘制出来.
6. FrmChartDemo的后台代码如下:
FrmChartDemo.cs:
using System.Windows.Forms.DataVisualization.Charting; namespace DemoCollection { public partial class FrmChartDemo : Form { #region the variable definiton private Chart chart1; private Random random = new Random(); private int maxYValue = 20; private int minYValue = 0; #endregion #region Ctor public FrmChartDemo() { InitializeComponent(); this.Load += new EventHandler(FrmChartDemo_Load); this.timer1.Tick += new EventHandler(timer1_Tick); } #endregion #region the event handler void FrmChartDemo_Load(object sender, EventArgs e) { #region from BBVS porject // Create a Chart chart1 = new Chart(); // Create Chart Area ChartArea chartArea1 = new ChartArea(); // Add Chart Area to the Chart chart1.ChartAreas.Add(chartArea1); #region Set the Chart // Set the chart style chart1.BackGradientStyle = System.Windows.Forms.DataVisualization.Charting.GradientStyle.TopBottom; chart1.BackSecondaryColor = System.Drawing.Color.White; chart1.BorderlineColor = System.Drawing.Color.FromArgb(((int)(((byte)(26)))), ((int)(((byte)(59)))), ((int)(((byte)(105))))); chart1.BorderlineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Solid; chart1.BorderlineWidth = 2; chart1.BorderSkin.SkinStyle = System.Windows.Forms.DataVisualization.Charting.BorderSkinStyle.Emboss; chart1.BackColor = Color.SteelBlue; chart1.Dock = DockStyle.Fill; chartArea1.Area3DStyle.Inclination = 15; chartArea1.Area3DStyle.IsClustered = true; chartArea1.Area3DStyle.IsRightAngleAxes = false; chartArea1.Area3DStyle.Perspective = 10; chartArea1.Area3DStyle.Rotation = 10; chartArea1.Area3DStyle.WallWidth = 0; // 设置是否启用 3D 效果 //chartArea1.Area3DStyle.Enable3D = true; chartArea1.AxisX.LabelStyle.Font = new System.Drawing.Font("Trebuchet MS", 8.25F, System.Drawing.FontStyle.Bold); chartArea1.AxisX.LabelStyle.Format = "hh:mm:ss"; chartArea1.AxisX.LabelStyle.Interval = 5D; // 10D; chartArea1.AxisX.LabelStyle.IntervalType = System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType.Seconds; chartArea1.AxisX.LineColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
chartArea1.AxisX.MajorGrid.Interval = 5D; // 10D;
chartArea1.AxisX.MajorGrid.IntervalType = System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType.Seconds;
chartArea1.AxisX.MajorGrid.LineColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
chartArea1.AxisX.MajorTickMark.Interval = 5D; // 10D;
chartArea1.AxisX.MajorTickMark.IntervalType = System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType.Seconds; chartArea1.AxisY.IsLabelAutoFit = false;
chartArea1.AxisY.IsStartedFromZero = false;
chartArea1.AxisY.LabelStyle.Font = new System.Drawing.Font("Trebuchet MS", 8.25F, System.Drawing.FontStyle.Bold);
chartArea1.AxisY.LineColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
chartArea1.AxisY.MajorGrid.LineColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64))))); #region 设置 Y 轴的 最大值和 最小值 chartArea1.AxisY.Maximum = this.maxYValue + 6;
chartArea1.AxisY.Minimum = this.minYValue - 6; #endregion chartArea1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(165)))), ((int)(((byte)(191)))), ((int)(((byte)(228)))));
chartArea1.BackGradientStyle = System.Windows.Forms.DataVisualization.Charting.GradientStyle.TopBottom;
chartArea1.BackSecondaryColor = System.Drawing.Color.White;
chartArea1.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
chartArea1.BorderDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Solid; chartArea1.InnerPlotPosition.Auto = false;
chartArea1.InnerPlotPosition.Height = 85F;
chartArea1.InnerPlotPosition.Width = 86F;
chartArea1.InnerPlotPosition.X = 8.3969F;
chartArea1.InnerPlotPosition.Y = 3.63068F; chartArea1.Name = "Default";
chartArea1.Position.Auto = false;
chartArea1.Position.Height = 86.76062F;
chartArea1.Position.Width = 88F;
chartArea1.Position.X = 5.089137F;
chartArea1.Position.Y = 5.895753F;
chartArea1.ShadowColor = System.Drawing.Color.Transparent; #endregion #region Create a Legend Legend legend1 = new Legend();
legend1.Alignment = System.Drawing.StringAlignment.Far;
legend1.BackColor = System.Drawing.Color.Transparent;
legend1.DockedToChartArea = "Default";
legend1.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
legend1.Font = new System.Drawing.Font("Trebuchet MS", 8.25F, System.Drawing.FontStyle.Bold);
legend1.IsTextAutoFit = false;
legend1.LegendStyle = System.Windows.Forms.DataVisualization.Charting.LegendStyle.Row;
legend1.Name = "Default";
chart1.Legends.Add(legend1); #endregion #region Create a Series Series series1 = new Series();
series1.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(180)))), ((int)(((byte)(26)))), ((int)(((byte)(59)))), ((int)(((byte)(105)))));
series1.ChartArea = "Default";
series1.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastLine;//Line;
series1.Color = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(64)))), ((int)(((byte)(10))))); series1.Legend = "Default";
series1.Name = "Series1";
series1.ShadowOffset = 1;
series1.YValuesPerPoint = 2;
chart1.Series.Add(series1); // 设置是否在 Chart 中显示 坐标点值
series1.IsValueShownAsLabel = true; #endregion // Set chart control location
chart1.Location = new System.Drawing.Point(0, 0); // Add chart control to the form
this.Controls.AddRange(new System.Windows.Forms.Control[] { this.chart1 }); #endregion
} void timer1_Tick(object sender, EventArgs e)
{
double tempValue = 0.0; // 随机产生 温度值
tempValue = random.Next(this.minYValue, this.maxYValue); DateTime timeStamp = DateTime.Now;
double xValue = DateTime.Now.ToOADate(); // 向 Chart中 添加 X轴 和 Y轴的 值
chart1.Series["Series1"].Points.AddXY(xValue, tempValue); // remove all points from the source series older than 20 seconds.
double removeBefore = timeStamp.AddSeconds((double)(20) * (-1)).ToOADate(); //remove oldest values to maintain a constant number of data points
if (chart1.Series[0].Points.Count > 0)
{
while (chart1.Series[0].Points[0].XValue < removeBefore)
{
chart1.Series[0].Points.RemoveAt(0);
} chart1.ChartAreas[0].AxisX.Minimum = chart1.Series[0].Points[0].XValue;
chart1.ChartAreas[0].AxisX.Maximum = DateTime.FromOADate(chart1.Series[0].Points[0].XValue).AddSeconds(20).ToOADate();
}
else
{
//chart1.ChartAreas[0].AxisX.Minimum = (double)minTempThreshold;
//chart1.ChartAreas[0].AxisX.Maximum = (double)maxTempThreshold;
} chart1.Invalidate();
} #endregion
}
}
控件:.NET Framework 3.5 的 Microsoft 图表控件(Microsoft Chart Controls for Microsoft
语言包:Microsoft Chart Controls for Microsoft
.NET Framework 3.5 的Microsoft 图表控件 的语言包,包含23中语言。 Microsoft Chart Controls Add-on for Microsoft Visual Studio 2008 – 这个只有英文的,没找到中文的。 文档 (Microsoft Chart Controls for
[/url][url=http://www.microsoft.com/downloads/details.aspx?FamilyId=1D69CE13-E1E5-4315-825C-F14D33A303E9&displaylang=en]WinForm
和 Asp.net的例子(Samples Environment for Microsoft Chart Controls) – 这个只有英文的,没找到英文的。 Demo 下载:http://code.msdn.microsoft.com/mschart 下了它的示例程序后,运行了一下,非常的强大,可以支持各种各样的图形显示,常见的:点状图、饼图、柱状图、曲线图、面积图、排列图等等,同时也支持3D样式的图表显示,不过我觉得最有用的功能还是支持图形上各个点的属性操作,它可以定义图形上各个点、标签、图形的提示信息(Tooltip)以及超级链接、Javascript动作等,而不是像其它图形类库仅生成一幅图片而已,通过这些,加上微软自己的Ajax框架,可以建立一个可以互动的图形统计报表了。 一。安装 控件的安装相对比较简单,下载完后,先执行“MSChart.exe”程序,它会自动检测你的环境,安装到系统目录中去,如果要在VS
2008环境中直接使用,那么需要安装For
Vs2008的插件,MSChart_VisualStudioAddOn.exe,还有一个中文语言包MSChartLP_chs.exe。安装完后,
打开Vs2008,在建立项目的时候,你就能在工具栏中看到有一个.NET3.5的Web项目,像使用普通控件一样拖放到要使用的Web界面即可。初步研究了一下,整个图形控件主要由以下几个部份组成: 1.Annotations --图形注解集合 2.ChartAreas --图表区域集合 3.Legends --图例集合 4.Series --图表序列集合(即图表数据对象集合) 5.Titles --图标的标题集合 Annotations注解集合 Annotations是一个对图形的一些注解对象的集合,所谓注解对象,类似于对某个点的详细或者批注的说明,比如,在图片上实现各个节点的关键信息,如下图方框和黄色的小方框: 一个图形上可以拥有多个注解对象,可以添加十多种图形样式的注解对象,包括常见的箭头、云朵、矩行、图片等等注解符号,通过各个注解对象的属性,可以方便的设置注解对象的放置位置、呈现的颜色、大小、文字内容样式等常见的属性。 ChartAreas图表区域集合
ChartAreas可以理解为是一个图表的绘图区,例如,你想在一幅图上呈现两个不同属性的内容,一个是用户流量,另一个则是系统资源占用情况,那么你
要在一个图形上绘制这两种情况,明显是不合理的,对于这种情况,可以建立两个ChartArea,一个用于呈现用户流量,另一个则用于呈现系统资源的占用
情况。 当然了,图表控件并不限制你添加多少个绘图区域,你可以根据你的需要进行添加。对于每一个绘图区域,你可以需要注意的是,绘图区域只是一个可以作图的区域范围,它本身并不包含要作图形的各种属性数据。 多绘图区效果图如下,分为上下两个绘图区域,分别表示不同的绘图数据: Legends图例集合
Legends是一个图例的集合,即标注图形中各个线条或颜色的含义,同样,一个图片也可以包含多个图例说明,比如像上面说的多个图表区域的方式,则可以
建立多个图例,每别说明各个绘图区域的信息,具体的图例配置说明此处就不详细说明了,可以参考一下官网的例子,写得丰富的详细了:)也上一张图例的效果图
吧~ Series图表序列 图表序列,应该是整个绘图中最关键的内容了,通俗点说,即是实际的绘图数据区域,实际呈现的图形形状,就是由此集合中的每一个图表来构成的,可以往集合里面添加多个图表,每一个图表可以有自己的绘制形状、样式、独立的数据等。 需要注意的是,每一个图表,你可以指定它的绘制区域(见ChartAreas的说明),让此图表呈现在某个绘图区域,也可以让几个图表在同一个绘图区域叠加,如下图: 上面两幅图,分别表示了把图表放在不同的绘制区域和放在同一个绘制区域的情况。 继续回到ChartAreas章节举的例子,同时要显示用户的流量还要显示系统的占用情况,对于这种时候,应该建立两个Series,一个用于呈现用户的流量,另一个则用于呈现系统的占用情况。它们分别属于各自的绘图区域。 Titles标题合集 根据字面含义即可以理解,是图表的标题配置,同样可以添加多个标题,以及设置标题的样式及文字、位置等属性。多看一下它的属性即能明白各自的含义。 三。其它属性 相对来说,我觉得比较有用的属性有三个,分别是:Label、Tooltip以及Url链接。 Label即标签的含义,可以在图片的关键位置进行一些关键数字或文字的描述,如下图: 像上图:X轴和Y轴的文字便是标签,以及图表曲线中的红点上的文字,也是标签,添加了标签,可以让人更容易的对内容进行理解。
Tooltip即提示的含义,用于在各个关键点,如:标签、图形关键点、标题等当鼠标移动上去的时候,提示用户一些相关的详细或说明信息,例如上图,可以
给曲线中的每一个点增加Tooltip的属性,写上需要详细说明的内容,比如:详细的销售明细,那么,在鼠标移动到这个点的时候,会自动弹出提示信息。 Tooltip可以支持简单方式以及自定义的方式,简单方式即像平时Html页面设置此属性,在鼠标点击的时候,代到其它相应的页面去。 建议大家看看官方例子中的Interactivity and AJAX部份,很精彩:) 例子:建立一个Cpu信息和内存使用的实时统计表 下面写一个小例子,建立一个系统的内存实时统计图表,使用到了Ajax的方法,以及Windows Api取得系统内存的方法。 首先,建立一个Aspx页面,拖动一个图表控件到页面,设置图表控件的EnableViewState属性为True,否则无法记录状态。
Code
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
--><asp:Chart
ID="ChartMemory" runat="server" BackColor="LightSteelBlue"
BackGradientStyle="TopBottom" BackSecondaryColor="White" EnableTheming="False"
EnableViewState="True" Height="363px" Width="415px">
<Legends>
<asp:Legend
Alignment="Center" Docking="Bottom" Name="Legend1"
Title="图例">
</asp:Legend>
</Legends>
<Titles>
<asp:Title
Font="微软雅黑, 16pt" Name="Title1" Text="系统内存监控图表">
</asp:Title>
</Titles>
<Series>
<asp:Series
BorderColor="White" BorderWidth="3" ChartArea="ChartArea1"
ChartType="Spline" Legend="Legend1" Name="已使用物理内存"
XValueType="Double"
YValueType="Double">
</asp:Series>
<asp:Series
BorderWidth="3" ChartArea="ChartArea1" ChartType="Spline"
Legend="Legend1" Name="全部占用内存">
</asp:Series>
<asp:Series
ChartArea="ChartArea2" ChartType="StackedArea" Legend="Legend1"
Name="CPU">
</asp:Series>
</Series>
<ChartAreas>
<asp:ChartArea
BackColor="224, 224, 224" BackGradientStyle="LeftRight"
Name="ChartArea1">
</asp:ChartArea>
<asp:ChartArea
Name="ChartArea2">
</asp:ChartArea>
</ChartAreas>
</asp:Chart>
一共建立了两个绘图区,一个用于呈现内存使用情况的在ChartArea1区域,另一个则是呈现Cpu使用情况的,放置在ChartArea2区域了。一共有三个图表,分别表示已使用的物理内存、全部占用的物理内存,以及Cpu使用显示的情况。
添加一个Ajax的计时器以及Ajax的ScriptManager,UpdatePanel,把计时器和图表控件都拖进UpdatePanel里面。设置计时器的间隔时间为一秒钟(1000),双击计时器,写如下代码:
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
static PerformanceCounter pc
= new PerformanceCounter("Processor",
"% Processor Time",
"_Total");
protected
void Timer1_Tick(object sender, EventArgs e)
{
MEMORY_INFO MemInfo =
new MEMORY_INFO();
ComputerInfo.GlobalMemoryStatus(ref MemInfo);
//UseMemory
Series series = ChartMemory.Series[0];
int xCount
= series.Points.Count
== 0
? 0 : series.Points.Count
- 1;
double lastXValue
= series.Points.Count
== 0
? 1 : series.Points[xCount].XValue
+ 1;
double lastYValue
= (double)(MemInfo.dwTotalPhys-MemInfo.dwAvailPhys)/1024/1024;
series.Points.AddXY(lastXValue, lastYValue);
//Total Memory
series = ChartMemory.Series[1];
lastYValue = (double)(MemInfo.dwTotalVirtual+MemInfo.dwTotalPhys-MemInfo.dwAvailPhys
- MemInfo.dwAvailVirtual)/1024/1024;
series.Points.AddXY(lastXValue, lastYValue);
//CPU
series = ChartMemory.Series[2];
lastYValue = (double)pc.NextValue();
series.Points.AddXY(lastXValue, lastYValue);
// Remove points from the left chart side if number of points exceeds 100.
while (this.ChartMemory.Series[0].Points.Count
> 80)
{
// Remove series points
foreach (Series s
in this.ChartMemory.Series)
{
s.Points.RemoveAt(0);
}
}
// Adjust categorical scale
double axisMinimum
= this.ChartMemory.Series[0].Points[0].XValue;
this.ChartMemory.ChartAreas[0].AxisX.Minimum
= axisMinimum;
this.ChartMemory.ChartAreas[0].AxisX.Maximum
= axisMinimum
+ 99;
}
附上取得内存信息的类代码:
Code
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
/// <summary>
///取得计算机的系统信息
///
</summary>
public
class ComputerInfo
{
///
<summary>
/// 取得Windows的目录
///
</summary>
///
<param name="WinDir"></param>
/// <param name="count"></param>
[DllImport("kernel32")]
public
static extern
void GetWindowsDirectory(StringBuilder WinDir,
int count);
///
<summary>
/// 获取系统路径
///
</summary>
///
<param name="SysDir"></param>
///
<param name="count"></param>
[DllImport("kernel32")]
public
static extern
void GetSystemDirectory(StringBuilder SysDir,
int count);
///
<summary>
/// 取得CPU信息
///
</summary>
///
<param name="cpuinfo"></param>
[DllImport("kernel32")]
public
static extern
void GetSystemInfo(ref CPU_INFO cpuinfo);
///
<summary>
/// 取得内存状态
///
</summary>
///
<param name="meminfo"></param>
[DllImport("kernel32")]
public
static extern
void GlobalMemoryStatus(ref MEMORY_INFO meminfo);
///
<summary>
/// 取得系统时间
///
</summary>
///
<param name="stinfo"></param>
[DllImport("kernel32")]
public
static extern
void GetSystemTime(ref SYSTEMTIME_INFO stinfo);
public ComputerInfo()
{
}
}
//定义CPU的信息结构
[StructLayout(LayoutKind.Sequential)]
public
struct CPU_INFO
{
public
uint dwOemId;
public
uint dwPageSize;
public
uint lpMinimumApplicationAddress;
public
uint lpMaximumApplicationAddress;
public
uint dwActiveProcessorMask;
public
uint dwNumberOfProcessors;
public
uint dwProcessorType;
public
uint dwAllocationGranularity;
public
uint dwProcessorLevel;
public
uint dwProcessorRevision;
}
//定义内存的信息结构
[StructLayout(LayoutKind.Sequential)]
public struct MEMORY_INFO
{
public
uint dwLength;
public
uint dwMemoryLoad;
public
uint dwTotalPhys;
public
uint dwAvailPhys;
public
uint dwTotalPageFile;
public
uint dwAvailPageFile;
public
uint dwTotalVirtual;
public
uint dwAvailVirtual;
}
//定义系统时间的信息结构
[StructLayout(LayoutKind.Sequential)]
public
struct SYSTEMTIME_INFO
{
public
ushort wYear;
public
ushort wMonth;
public
ushort wDayOfWeek;
public
ushort wDay;
public
ushort wHour;
public
ushort wMinute;
public
ushort wSecond;
public
ushort wMilliseconds;
}
运行的效果图如下: