stockpicker.aspx:
<script language="vb" runat=server>
sub chartbtn_click(sender as object, e as eventargs)
chart.imageurl = "imagegenerator_vb.aspx?"
chart.visible = true
for i=0 to stocks.items.count-1
if (stocks.items(i).selected = true) then
chart.imageurl = chart.imageurl & "symbols=" & stocks.items(i).value & "&"
end if
next
end sub
</script>
<html>
<body>
<form runat=server>
<h1>scott's stock picker</h1>
<asp:checkboxlist id="stocks" runat=server>
<asp:listitem>msft</asp:listitem>
<asp:listitem>sun</asp:listitem>
</asp:checkboxlist>
<asp:button text="chart your selected stocks" onclick="chartbtn_click" runat=server/>
<hr>
<asp:image id="chart" imageurl="" visible=false runat=server/>
</form>
</body>
</html>
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" %>
<%@ outputcache duration="10" %>
<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.blue
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 = nothing) then
for i=0 to symbols.length-1
dim stockvalue as chartline = getstockdetails(symbols(i).tolower)
if (stockvalue <> nothing) 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>
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 = "generated:" + datetime.now.tolongtimestring() ;
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);
}
}
}
}
菜鸟学堂: