一个使用C#绘制图形引擎的Framework

下面将推荐一个可以很方便的生成多种图形格式的,使用了ASP+技术的图形

引擎代码。它的主要描述如下:

1.可以生成的图形文件格式支持BMP

EMF,GIF,Icon,JPEG,PNG,TIFF,WMF

2.在文件ChartEngine.cs中为这个图形引擎的大量关键代码

StockPicker.aspx文件是一个使用该引擎绘图的例子

3.要使用这个图形引擎,需要把所有的代码文件复制到你的web的某个

运用目录(注:不是普通目录)中,然后在该目录下建立一个bin目录,

然后运行mk.bat

4.ImageGenerator_VB.asp文件的头使用了<%@ Page ContentType="image/jpeg"

%>来说明生成的是某种格式的图形文件

5.为了服务器性能考虑,还可以在ImageGenerator_VB.asp中增加以下代码

<%@ OutputCache Duration="60" %>,该代码可以将生成的图形文件缓存起来

这样如果网站访问量大时,可以大大减轻服务器的负担

好了,废话少说,大家可以自己研究研究代码:

1.ChartEngine.cs文件

using System.WinForms;

using System.Collections;

using System.Collections.Bases;

using System.Drawing;

using System.Drawing.Drawing2D;

using System.Drawing.Imaging;

using System.ComponentModel;

using System;

using System.IO;

namespace ChartGenerator {

//Core Line Data structure

public struct LineData {

public float[] LineValues ;

public string LineTitle ;

public string LineSymbol ;

}

//Line Data plus display style information

public class ChartLine {

private Color lineColor ;

private LineData lineData ;

private DashStyle lineStyle ;

private int lineWidth ;

//Constructors

public ChartLine() :base() {}

public ChartLine(LineData lineData) :base() {

this.lineData = lineData;

}

//Properties

public Color Color {

get { return lineColor ; }

set { lineColor = value ; }

}

public DashStyle LineStyle {

get { return lineStyle ; }

set { lineStyle = value ; }

}

public string Symbol {

get { return lineData.LineSymbol ; }

set { lineData.LineSymbol = value ; }

}

public string Title {

get { return lineData.LineTitle ; }

set { lineData.LineTitle = value ; }

}

public float[] Values {

get { return lineData.LineValues ; }

set { lineData.LineValues = value ; }

}

public int Width {

get { return lineWidth ; }

set { lineWidth = value ; }

}

//Methods

public void SetLineData(LineData lineData) {

this.lineData = lineData;

}

}

//Chart Data structure

public class ChartData {

private float yTickSize;

private float yMax;

private float yMin;

private string[] xAxisTitles ;

private ChartLineList lines = new ChartLineList();

private Color gridColor=Color.Blue;

private bool showHGridLines=true;

private bool showVGridLines=true;

//Properties

public float YTickSize {

get { return yTickSize ; }

set { yTickSize = value ; }

}

public float YMax {

get { return yMax ; }

set { yMax = value ; }

}

public float YMin {

get { return yMin ; }

set { yMin = value ; }

}

public string[] XAxisTitles {

get { return xAxisTitles ; }

set { xAxisTitles = value ; }

}

public ChartLineList Lines {

get { return lines ; }

set { lines = value ; }

}

public Color GridColor {

get { return gridColor ; }

set { gridColor = value ; }

}

public bool ShowHGridLines {

get { return showHGridLines ; }

set { showHGridLines = value ; }

}

public bool ShowVGridLines {

get { return showVGridLines ; }

set { showVGridLines = value ; }

}

//Collection of Chart Lines

public class ChartLineList : TypedCollectionBase {

public ChartLine this[int index] {

get {

return (ChartLine)(List[index]);

}

set {

List[index] = value;

}

}

public int Add(ChartLine value) {

return List.Add(value);

}

public void Insert(int index, ChartLine value) {

List.Insert(index, value);

}

public int IndexOf(ChartLine value) {

return List.IndexOf(value);

}

public bool Contains(ChartLine value) {

return List.Contains(value);

}

public void Remove(ChartLine value) {

List.Remove(value);

}

public void CopyTo(ChartLine[] array, int index) {

List.CopyTo(array, index);

}

}

}

//Charting Engine - draws a chart based on the given ChartData

public class ChartEngine {

private ChartData chartData ;

private float left;

private float right;

private float top;

private float bottom;

private float tickCount;

private float yCount;

private float hspacing;

private float vspacing;

private Graphics g;

private Rectangle r;

private Color backColor;

private Color foreColor;

private Font baseFont;

private Font legendFont;

private RectangleF legendRect;

public ChartEngine() {

}

public Bitmap DrawChart(int width, int height, ChartData chartData) {

Bitmap newBitmap = new Bitmap(width,height,PixelFormat.Format32bppARGB);

Graphics g = Graphics.FromImage(newBitmap);

Rectangle r = new Rectangle(0, 0, width, height);

Color myForeColor = Color.Black;

Color myBackColor = Color.White;

Font myFont = new Font("Arial", 10);

this.DrawChart(g, r, myBackColor, myForeColor, myFont, chartData);

return newBitmap;

}

public void DrawChart(Graphics g, Rectangle r, Color backColor,

Color foreColor, Font baseFont, ChartData chartData) {

this.chartData = chartData;

this.g = g;

this.r = r;

this.backColor = backColor;

this.foreColor = foreColor;

this.baseFont = baseFont;

this.legendFont = new Font(baseFont.FontFamily,

(baseFont.Size * 2/3), baseFont.Style | FontStyle.Bold);

g.SmoothingMode = SmoothingMode.AntiAlias;

CalculateChartDimensions();

DrawBackground();

InternalDrawChart() ;

}

private void CalculateChartDimensions() {

right = r.Width - 5;

top = 5 * baseFont.Size ;

bottom = r.Height - baseFont.Size * 2;

tickCount = chartData.YMin ;

yCount = (chartData.YMax-chartData.YMin) / chartData.YTickSize ;

hspacing = (bottom-top) / yCount;

vspacing = (right) / chartData.XAxisTitles.Length;

//Left depends on width of text - for simplicities sake assume that largest yvalue is the biggest

//Take into account the first X Axis title

float maxYTextSize = g.MeasureString(chartData.YMax.ToString(), baseFont).Width;

float firstXTitle = g.MeasureString(chartData.XAxisTitles[0], baseFont).Width;

left = (maxYTextSize > firstXTitle) ? maxYTextSize : firstXTitle ;

left = r.X + left + 5 ;

//Calculate size of legend box

float maxLegendWidth = 0 ;

float maxLegendHeight = 0 ;

//Work out size of biggest legend

foreach (ChartLine cl in chartData.Lines) {

float currentWidth = g.MeasureString(cl.Title, legendFont).Width;

float currentHeight = g.MeasureString(cl.Title, legendFont).Height;

maxLegendWidth = (maxLegendWidth > currentWidth) ? maxLegendWidth : currentWidth ;

maxLegendHeight = (maxLegendHeight > currentHeight) ? maxLegendHeight : currentHeight ;

}

legendRect = new RectangleF(r.X+2, r.Y+2, maxLegendWidth + 25 + 5, ((maxLegendHeight+2)*chartData.Lines.Count) + 3) ;

}

private void DrawBackground() {

LinearGradientBrush b = new LinearGradientBrush(r, Color.SteelBlue, backColor,LinearGradientMode.Horizontal);

g.FillRectangle(b, r);

b.Dispose();

}

private void InternalDrawChart() {

DrawGrid() ;

foreach (ChartLine cl in chartData.Lines) {

DrawLine(cl);

}

DrawLegend() ;

//Draw time on chart

string timeString = DateTime.ToString(DateTime.Now) ;

SizeF textsize = g.MeasureString(timeString,baseFont);

g.DrawString(timeString, baseFont, new SolidBrush(foreColor), r.Width - textsize.Width - 5, textsize.Height * 2 / 3) ;

}

private void DrawGrid() {

Pen gridPen = new Pen(chartData.GridColor) ;

//Vertical - include tick desc's

if (chartData.ShowVGridLines) {

for (int i = 0 ; (vspacing * i) < right; i++) {

float x = left + (vspacing *i);

string desc = chartData.XAxisTitles[i];

g.DrawLine(gridPen, x,top,x,bottom +(baseFont.Size*1/3));

SizeF textsize = g.MeasureString(desc,baseFont);

g.DrawString(desc, baseFont, new SolidBrush(chartData.GridColor), x-(textsize.Width/2), bottom + (baseFont.Size*2/3)) ;

}

}

//Horizontal

if (chartData.ShowHGridLines) {

for (float i = bottom ; i > top; i-=hspacing) {

string desc = tickCount.ToString();

tickCount+=chartData.YTickSize;

g.DrawLine(gridPen, right, i, left-3, i);

SizeF textsize = g.MeasureString(desc,baseFont);

g.DrawString(desc, baseFont, new SolidBrush(chartData.GridColor), left-textsize.Width - 3, i - (textsize.Height/2)) ;

}

}

}

private void DrawLine(ChartLine chartLine) {

Pen linePen = new Pen(chartLine.Color);

linePen.StartCap = LineCap.Round;

linePen.EndCap = LineCap.Round;

linePen.Width = chartLine.Width ;

linePen.DashStyle = chartLine.LineStyle;

PointF[] Values = new PointF[chartLine.Values.Length];

float scale = hspacing / chartData.YTickSize ;

for (int i = 0 ; i < chartLine.Values.Length; i++) {

float x = left + vspacing * i;

Values[i] = new PointF(x, bottom-chartLine.Values[i]*scale);

}

g.DrawLines(linePen, Values);

}

private void DrawLegend() {

//Draw Legend Box

ControlPaint.DrawBorder(g, (Rectangle)legendRect, SystemColors.WindowFrame, ButtonBorderStyle.Solid);

LinearGradientBrush b = new LinearGradientBrush(legendRect, backColor, Color.SteelBlue, LinearGradientMode.Horizontal);

r.Inflate(-1, -1);

g.FillRectangle(b, legendRect);

b.Dispose();

float startY = 5;

foreach (ChartLine cl in chartData.Lines) {

Pen p = new Pen(cl.Color) ;

p.Width = p.Width*4;

SizeF textsize = g.MeasureString(cl.Title, legendFont);

float lineY = startY + textsize.Height / 2 ;

g.DrawLine(p, r.X + 7, lineY, r.X + 25, lineY);

g.DrawString(cl.Title, legendFont, new SolidBrush(foreColor), r.X + 30, startY);

startY += (textsize.Height+2);

}

}

}

}

2.ImageGenerator_Vb.aspx文件

<%@ Page Language="VB" ContentType="image/jpeg" %>

<%@ Import Namespace="System.Drawing" %>

<%@ Import Namespace="System.Drawing.Drawing2D" %>

<%@ Import Namespace="System.Drawing.Imaging" %>

<%@ Import Namespace="ChartGenerator" %>

<script language="VB" runat=server>

Function GetStockDetails(Symbol as String) as ChartLine

Dim myChartLine as new ChartLine

if (symbol = "msft") then

Dim StockValues() as Single = { 60, 110, 120, 180, 185, 190, 240, 290 }

myChartLine.Width = 5

myChartLine.Color = Color.White

myChartLine.LineStyle = DashStyle.Solid

myChartLine.Title = "Microsoft Corp. (MSFT)"

myChartLine.Symbol = "MSFT"

myChartLine.Values = StockValues

return myChartLine

elseif (symbol = "sun") then

Dim StockValues() as Single = { 180, 155, 125, 60, 25, 15, 10, 3 }

myChartLine.Width = 5

myChartLine.Color = Color.Red

myChartLine.LineStyle = DashStyle.Dot

myChartLine.Title = "Sun Corp. (Sun)"

myChartLine.Symbol = "Sun"

myChartLine.Values = StockValues

return myChartLine

end if

return nothing

End Function

Sub Page_Load(Sender as Object, E as EventArgs)

' Generate Chart Data For Image....

Dim XAxes() as String = { "9:00AM", "9:30AM", "10:00AM", "11:00AM", "12:00AM", "1:00PM", "1:30PM" }

Dim MyChartData as New ChartData

MyChartData.YTickSize = 20

MyChartData.YMax = 250

MyChartData.YMin = 0

MyChartData.XAxisTitles = XAxes

Dim Symbols() as String = Request.QueryString.GetValues("symbols")

if (Not Symbols Is Nothing) then

for i=0 to Symbols.Length-1

Dim stockValue as ChartLine = GetStockDetails(symbols(i).ToLower)

if (stockValue <> noting) then

myChartData.Lines.Add(stockValue)

end if

Next

end if

' Create In-Memory BitMap of JPEG

Dim MyChartEngine as New ChartEngine

Dim StockBitMap as BitMap = MyChartEngine.DrawChart(600, 400, myChartData)

' Render BitMap Stream Back To Client

StockBitMap.Save(Response.OutputStream, ImageFormat.JPEG)

End Sub

</script>

3.StockPicker.aspx文件

<script language="C#" runat=server>

void ChartBtn_Click(Object sender, EventArgs e) {

chart.ImageUrl = "ImageGenerator_Vb.aspx?";

chart.Visible = true;

foreach(ListItem item in Stocks.Items) {

if (item.Selected == true) {

chart.ImageUrl += "symbols=" + item.Value + "&";

}

}

}

</script>

<html>

<body>

<form runat=server>

<h1>Scott's Stock Picker</h1>

<asp:checkboxlist Visible=false runat=server/>

</form>

</body>

</html>

4.mk.bat文件

csc /t:library /debug+ /out:bin\chartgen.dll ChartEngine.cs /r:System.Web.dll /r:System.Winforms.dll /r:System.Drawing.dll /r:System.dll

相关文章组 合 语 言 之 艺 术(二)

组 合 语 言 之 艺 术(一)

在C++ Builder3下实现程序自动运行的方法

如何利用C++ Builder 4.0 Enterprise实现对Excel97 的调用

用PHP增强UNIX/LINUX网站功能

<展现 C#> 第一章 C#简介(修订)

定制php4的session功能

发现了第一只php病毒PHP.Pirus

一个简单聊天室的两种实现 (fcntl 和 select)

在C#里如何调用标准DLL函数

如何开发一个虚拟域名系统

一个简单的Webmail系统

用PHP编写email群发器

Win32汇编教程十三 INI 文件的操作

Win32汇编教程十二 管道操作

Win32汇编教程十一 进程控制

Win32汇编教程十 定时器的应用

Win32汇编教程九 复杂形状的窗口

Win32汇编教程八 图形界面的操作

Win32汇编教程七 控件的子类化