上一篇中介绍了动态添加Silverlight绘图元素,由于这些绘图元素的使用并不简洁,接着就要构造基本图形库了。
工程应用中的图形库,基本有两种构建方式:一种是类似Win Form中的Graphics类,绘制图形简洁,但这种图形不是以“元素”的形式出现,绘制之后图形元素不能被索引,它自身没有属性或事件的概念,因此这种方式适用于“一次绘制好后,只供用户观看”的场合,例如背景图的绘制、示意曲线的绘制等;另一种是类似Silverlight中的图形绘制方式,各图形元素是一个真正的类,自身有属性或事件,可以被索引,相比第一种情况,这是一种“重量级”的绘图方式,适用于“随时捕捉图形,并对其施加操作”的场合,例如绘制工作流图等。本文称第一种库为图形绘制库,称第二种库为图形元素库。本文只关注图形绘制库的建立。
本文还有一个目的,尽量消除在WinForm和Silverlight中绘制图形的不同,同一套代码,几乎不用修改就能在WinForm和Silverlight中绘制出相同的图形。由于Silverlight应用中不能随便引用其他C#类库,所以Silverlight应用与其他应用中的通用功能,只能通过代码共用。
WinFormGraphics的源代码。
工程应用中的图形库,基本有两种构建方式:一种是类似Win Form中的Graphics类,绘制图形简洁,但这种图形不是以“元素”的形式出现,绘制之后图形元素不能被索引,它自身没有属性或事件的概念,因此这种方式适用于“一次绘制好后,只供用户观看”的场合,例如背景图的绘制、示意曲线的绘制等;另一种是类似Silverlight中的图形绘制方式,各图形元素是一个真正的类,自身有属性或事件,可以被索引,相比第一种情况,这是一种“重量级”的绘图方式,适用于“随时捕捉图形,并对其施加操作”的场合,例如绘制工作流图等。本文称第一种库为图形绘制库,称第二种库为图形元素库。本文只关注图形绘制库的建立。
本文还有一个目的,尽量消除在WinForm和Silverlight中绘制图形的不同,同一套代码,几乎不用修改就能在WinForm和Silverlight中绘制出相同的图形。由于Silverlight应用中不能随便引用其他C#类库,所以Silverlight应用与其他应用中的通用功能,只能通过代码共用。
Graphics类是一个“天然”的编制图形绘制库,本文将以它为基础,主要对Silverlight中的绘图元素进行改造。由于Silverlight独立部署的特性,使Silverlight与WinForm的绘图类之间无任何共有部分,但是为达到“同一代码,两处通用”的目的,两者的绘图类都不能使用,必须重新定义一套接口及相关辅助类。下图是本文图形绘制库中所涉及的类。
IGraphBase是一个接口类,它定义了类似Graphics类中的各类图形绘制方法,LinePen、PaintBrush等类是图形绘制过程中用到的辅助类,例如LinePen包装了Pen类等。WinFormGraphics和SilverlightGraphics实现了IGraphBase接口,分别用于在WinForm和Silverlight中绘制基本图形。
IGraphBase和辅助绘图类放在一个文件中(Helper.cs),以下是代码。
public class DrawColor
{
#region Member Variables
private Byte _r, _g, _b, _a;
#endregion Member Variables
#region Properties
public Byte R
{
set { this._r = value; }
get { return this._r; }
}
public Byte G
{
set { this._g = value; }
get { return this._g; }
}
public Byte B
{
set { this._b = value; }
get { return this._b; }
}
public Byte A
{
set { this._a = value; }
get { return this._a; }
}
#endregion Properties
#region Public Methods
public DrawColor(Byte a=255, Byte r =0,Byte g=0, Byte b=0)
{
_r = r;
_g = g;
_b = b;
_a = a;
}
public DrawColor(Byte r = 0, Byte g = 0, Byte b = 0)
{
_a = 255;
_g = g;
_b = b;
_r = r;
}
public UInt32 ToArgb()
{
return (((UInt32)_a) << 24) + (((UInt32)_r) << 16) + (((UInt32)_g) << 8) + ((UInt32)_b);
}
public static DrawColor FromArgb(int red, int green, int blue)
{
return new DrawColor((Byte)red, (Byte)green, (Byte)blue);
}
public static DrawColor FromArgb(UInt32 cl)
{
return new DrawColor((Byte)(cl>>24),(Byte)(cl>>16),(Byte)(cl>>8),(Byte)(cl&0xff));
}
#endregion Public Methods
}
public class DrawColors
{
public static DrawColor Black = DrawColor.FromArgb(0xFF000000);
public static DrawColor Blue = DrawColor.FromArgb(0xFF0000FF);
public static DrawColor Brown = DrawColor.FromArgb(0xFFA52A2A);
public static DrawColor Cyan = DrawColor.FromArgb(0xFF00FFFF);
public static DrawColor DarkGray = DrawColor.FromArgb(0xFFA9A9A9);
public static DrawColor Gray = DrawColor.FromArgb(0xFF808080);
public static DrawColor Green = DrawColor.FromArgb(0xFF008000);
public static DrawColor LightGray = DrawColor.FromArgb(0xFFD3D3D3);
public static DrawColor Magenta = DrawColor.FromArgb(0xFFFF00FF);
public static DrawColor Orange = DrawColor.FromArgb(0xFFFFA500);
public static DrawColor Purple = DrawColor.FromArgb(0xFF800080);
public static DrawColor Red = DrawColor.FromArgb(0xFFFF0000);
public static DrawColor Transparent = DrawColor.FromArgb(0x00FFFFFF);
public static DrawColor White = DrawColor.FromArgb(0xFFFFFFFF);
public static DrawColor Yellow = DrawColor.FromArgb(0xFFFFFF00);
}
public class LinePen
{
public enum StyleEnum
{
SOLID,
DOT,
DASH,
DASHDOT,
DASHDOTDOT,
CUSTOM
}
#region Member Variables
private Single[] _customDashGapArray = null;
#endregion Member Variables
#region Properties
public StyleEnum Style { get; set; }
public DrawColor Color { get; set; }
public Single Width { get; set; }
public Single[] CustomDashGapArray
{
get
{
return _customDashGapArray;
}
set
{
if (value != null)
{
_customDashGapArray = new Single[value.Length];
value.CopyTo(_customDashGapArray, 0);
}
}
}
#endregion Properties
public LinePen(DrawColor color, Single width = 1.0f, StyleEnum style = LinePen.StyleEnum.SOLID, Single[] customDashGap = null)
{
Color = color;
Width = width;
Style = style;
CustomDashGapArray = customDashGap;
}
public LinePen Clone()
{
return new LinePen(this.Color, this.Width, this.Style, this._customDashGapArray);
}
}
public abstract class PaintBrush
{
#region Member Variables
#endregion Member Variables
#region Properties
#endregion Properties
public PaintBrush()
{
}
}
public class SolidPaintBrush: PaintBrush
{
#region Properties
public DrawColor Color { get; set; }
#endregion Properties
public SolidPaintBrush(DrawColor color)
{
Color = color;
}
}
public class TextFont
{
public enum StyleEnum
{
REGULAR,
BOLD,
ITALIC
}
public enum AlignmentEnum
{
LEFT,
RIGHT,
CENTER,
JUSTIFY
}
#region Member Variables
private string _family;
#endregion Member Variables
#region Properties
public bool Clip { get; set; }
public bool Wrap { get; set; }
public float Size {get; set; }
public StyleEnum Style { get; set; }
public AlignmentEnum Alignment { get; set; }
public string Family
{
set { this._family = value; }
get { return this._family; }
}
#endregion Properties
#region Public Methods
public TextFont(string family="宋体", float size=10.0f, TextFont.StyleEnum style = StyleEnum.REGULAR,
TextFont.AlignmentEnum alignment = AlignmentEnum.LEFT, bool wrap= false, bool clip =false)
{
_family = family;
Size = size;
Style = style;
Alignment = alignment;
Wrap = wrap;
Clip = clip;
}
public TextFont(float size)
{
_family = "宋体";
Size = size;
Style = StyleEnum.REGULAR;
Alignment = AlignmentEnum.LEFT;
Wrap = false;
Clip = false;
}
#endregion Public Methods
}
public class Dot
{
public Int32 X=0,Y=0;
public Dot(Int32 x, Int32 y)
{
this.X = x;
this.Y = y;
}
}
public class DotF
{
public Single X=0.0f,Y=0.0f;
public DotF(Single x, Single y)
{
this.X = x;
this.Y = y;
}
}
public class Area
{
public Int32 X1,Y1,X2,Y2;
public Area()
{
X1 = Y1 = X2 = Y2 = 0;
}
public Area(Int32 x1, Int32 y1, Int32 x2, Int32 y2)
{
this.X1 = x1;
this.Y1 = y1;
this.X2 = x2;
this.Y2 = y2;
}
public Int32 Width
{
get { return X2 - X1; }
set { X2 = X1 + value; }
}
public Int32 Height
{
get { return Y2 - Y1; }
set { Y2 = Y1 + value; }
}
public void Reset()
{
int s;
if (X2 < X1)
{
s = X2; X2 = X1; X1 = s;
}
if (Y2 < Y1)
{
s = Y2; Y2 = Y1; Y1 = s;
}
}
public static Area FromRange(Int32 x, Int32 y, Int32 width, Int32 height)
{
return new Area(x, y, x + width, y + height);
}
}
public class AreaF
{
public Single X1,Y1, X2,Y2;
public AreaF()
{
X1 = Y1 = X2 = Y2 = 0.0f;
}
public AreaF(Single x1, Single y1, Single x2, Single y2)
{
this.X1 = x1;
this.Y1 = y1;
this.X2 = x2;
this.Y2 = y2;
}
public Single Width
{
get { return X2 - X1; }
set { X2 = X1 + value; }
}
public Single Height
{
get { return Y2 - Y1; }
set { Y2 = Y1 + value; }
}
public void Reset()
{
Single s;
if (X2 < X1)
{
s = X2; X2 = X1; X1 = s;
}
if (Y2 < Y1)
{
s = Y2; Y2 = Y1; Y1 = s;
}
}
public static AreaF FromRange(Single x, Single y, Single width, Single height)
{
return new AreaF(x, y, x + width, y + height);
}
}
public enum ImageStretch
{
NONE,
FILL,
UNIFORM,
UNIFORMTOFILL
}
public interface IGraphBase
{
void Clear(DrawColor cl);
void SetClip(AreaF area );
void ClearClip();
void SetLinePen(LinePen pen);
void DrawLine(LinePen pen, Int32 x1, Int32 y1, Int32 x2, Int32 y2);
void DrawLine(LinePen pen, Single x1, Single y1, Single x2, Single y2);
void StartPolyline(LinePen pen);
void AddPolylinePoint(Single x, Single y);
void AddPolylinePoint(Int32 x, Int32 y);
void EndPolyline();
void DrawRectangle(LinePen pen, PaintBrush brush, Area area);
void DrawRectangle(LinePen pen, PaintBrush brush, AreaF area);
void DrawRectangle(LinePen pen, PaintBrush brush, Int32 x1, Int32 y1, Int32 x2, Int32 y2);
void DrawRectangle(LinePen pen, PaintBrush brush, Single x1, Single y1, Single x2, Single y2);
void DrawPolygon(LinePen pen, PaintBrush brush, ICollection<Dot> edges);
void DrawPolygon(LinePen pen, PaintBrush brush, ICollection<DotF> edges);
void DrawCircle(LinePen pen, PaintBrush brush, Int32 x, Int32 y, Int32 radius);
void DrawCircle(LinePen pen, PaintBrush brush, Single x, Single y, Single radius);
void DrawEllipse(LinePen pen, PaintBrush brush, Area area);
void DrawEllipse(LinePen pen, PaintBrush brush, AreaF area);
void DrawEllipse(LinePen pen, PaintBrush brush, Int32 x1, Int32 y1, Int32 x2, Int32 y2);
void DrawEllipse(LinePen pen, PaintBrush brush, Single x1, Single y1, Single x2, Single y2);
void DrawString(Single x, Single y, string text, DrawColor fontcolor, float fontsize, string fontname);
void DrawString(string text, TextFont font, PaintBrush brush, AreaF area);
void DrawImage(Area area, string sourceUrl, ImageStretch st);
void DrawImage(AreaF area, string sourceUrl, ImageStretch st);
}
}
SilverlightGraphics的源代码。
public class SilverlightGraphics : IGraphBase
{
#region Consts & Enum
#endregion Consts & Enum
#region Member Variables
private Canvas _slCanvas;
private UInt32 _elementCount = 0;
private LinePen _defaultPen = new LinePen(DrawColors.Black);
private LinePen _polylinePen = null;
private PointCollection _polylinePoints = null;
private DoubleCollection _dotLineStrokeArray = new DoubleCollection();
private DoubleCollection _dashLineStrokeArray = new DoubleCollection();
private DoubleCollection _dashdotLineStrokeArray = new DoubleCollection();
private DoubleCollection _dashdotdotLineStrokeArray = new DoubleCollection();
private Brush _defaultTextBrush = new SolidColorBrush(Colors.Black);
private System.Windows.FrameworkElement _lastAddedShape = null;
#endregion Member Variables
#region Properties
public Canvas GraphObject
{
get { return _slCanvas; }
}
public System.Windows.FrameworkElement LastAddedShape
{
get { return _lastAddedShape; }
}
#endregion Properties
#region Pulbic Methods
public SilverlightGraphics(Canvas cs)
{
_slCanvas = cs;
_dotLineStrokeArray.Add(1.0); _dotLineStrokeArray.Add(1.0);
_dashLineStrokeArray.Add(3.0); _dashLineStrokeArray.Add(1.0);
_dashdotLineStrokeArray.Add(3.0); _dashdotLineStrokeArray.Add(1.0); _dashdotLineStrokeArray.Add(1.0); _dashdotLineStrokeArray.Add(1.0);
_dashdotdotLineStrokeArray.Add(3.0); _dashdotdotLineStrokeArray.Add(1.0); _dashdotdotLineStrokeArray.Add(1.0); _dashdotdotLineStrokeArray.Add(1.0); _dashdotdotLineStrokeArray.Add(1.0); _dashdotdotLineStrokeArray.Add(1.0);
}
public void SetLinePen(LinePen pen)
{
_defaultPen = pen.Clone();
}
public void Clear(DrawColor cl)
{
_slCanvas.Children.Clear();
_slCanvas.Background = new SolidColorBrush(converttoColor(cl));
}
public void SetClip(AreaF area = null)
{
Rect rt = (area == null) ? new Rect(0, 0, _slCanvas.Width, _slCanvas.Height) : new Rect(area.X1, area.Y1, area.Width, area.Height);
_slCanvas.Clip = new RectangleGeometry() { Rect = rt };
}
public void ClearClip()
{
_slCanvas.Clip = null;
}
public void DrawLine(LinePen pen, Int32 x1, Int32 y1, Int32 x2, Int32 y2)
{
DrawLine(pen, (Single)x1, (Single)y1, (Single)x2, (Single)y2);
}
public void DrawLine(LinePen pen, Single x1, Single y1, Single x2, Single y2)
{
Line shp = new System.Windows.Shapes.Line();
prepareLinePen(shp, (pen==null)?_defaultPen.Clone() :pen);
shp.X1 = x1;
shp.Y1 = y1;
shp.X2 = x2;
shp.Y2 = y2;
addShape(shp, "Line");
}
public void StartPolyline(LinePen pen)
{
if(_polylinePoints!=null) _polylinePoints.Clear(); // need new ??????
_polylinePen = (pen == null) ? _defaultPen.Clone() : pen;
}
public void AddPolylinePoint(Single x, Single y)
{
if (_polylinePoints == null)
{
_polylinePoints = new PointCollection();
}
_polylinePoints.Add(new Point(x, y));
}
public void AddPolylinePoint(Int32 x, Int32 y)
{
AddPolylinePoint((Single)x, (Single)y);
}
public void EndPolyline()
{
Polyline shp = new System.Windows.Shapes.Polyline();
prepareLinePen(shp, _polylinePen);
shp.Points = _polylinePoints;
addShape(shp, "Pyln");
}
public void DrawRectangle(LinePen pen, PaintBrush brush, Area area)
{
DrawRectangle(pen, brush, (Single)area.X1,(Single)area.Y1, (Single)area.Width, (Single)area.Height);
}
public void DrawRectangle(LinePen pen, PaintBrush brush, AreaF area)
{
DrawRectangle(pen, brush, area.X1,area.Y1, area.Width, area.Height);
}
public void DrawRectangle(LinePen pen, PaintBrush brush, Int32 x, Int32 y, Int32 width, Int32 height)
{
DrawRectangle(pen, brush, (Single)x, (Single)y, (Single)width, (Single)height);
}
public void DrawRectangle(LinePen pen, PaintBrush brush, Single x, Single y, Single width, Single height)
{
Rectangle shp = new System.Windows.Shapes.Rectangle();
prepareLinePen(shp, (pen == null) ? _defaultPen.Clone() : pen);
prepareFillBrush(shp, brush);
setRectValue(shp, x, y, width, height);
addShape(shp, "Rect");
}
public void DrawPolygon(LinePen pen, PaintBrush brush, ICollection<Dot> edges)
{
Polygon tmpgon = new System.Windows.Shapes.Polygon();
prepareLinePen(tmpgon, (pen == null) ? _defaultPen.Clone() : pen);
prepareFillBrush(tmpgon, brush);
PointCollection points = new PointCollection();
foreach (Dot dt in edges)
{
points.Add(new Point(dt.X, dt.Y));
}
tmpgon.Points = points;
addShape(tmpgon, "Pygn");
}
public void DrawPolygon(LinePen pen, PaintBrush brush, ICollection<DotF> edges)
{
Polygon tmpgon = new System.Windows.Shapes.Polygon();
prepareLinePen(tmpgon, (pen == null) ? _defaultPen.Clone() : pen);
prepareFillBrush(tmpgon, brush);
PointCollection points = new PointCollection();
foreach (DotF dot in edges)
{
points.Add(new Point(dot.X, dot.Y));
}
tmpgon.Points = points;
addShape(tmpgon, "Pygn");
}
public void DrawCircle(LinePen pen, PaintBrush brush, Int32 x, Int32 y, Int32 radius)
{
DrawCircle(pen, brush, (Single)x, (Single)y, (Single)radius);
}
public void DrawCircle(LinePen pen, PaintBrush brush, Single x, Single y, Single radius)
{
Ellipse shp = new System.Windows.Shapes.Ellipse();
prepareLinePen(shp, (pen == null) ? _defaultPen.Clone() : pen);
prepareFillBrush(shp, brush);
setRectValue(shp, x - radius, y - radius, radius, radius);
addShape(shp, "Crcl");
}
public void DrawEllipse(LinePen pen, PaintBrush brush, Area area)
{
DrawEllipse(pen, brush, (Single)area.X1, (Single)area.Y1, (Single)area.Width, (Single)area.Height);
}
public void DrawEllipse(LinePen pen, PaintBrush brush, AreaF area)
{
DrawEllipse(pen, brush, area.X1, area.Y1, area.Width, area.Height);
}
public void DrawEllipse(LinePen pen, PaintBrush brush, Int32 x, Int32 y, Int32 width, Int32 height)
{
DrawEllipse(pen, brush, (Single)x, (Single)y, (Single)width, (Single)height);
}
public void DrawEllipse(LinePen pen, PaintBrush brush, Single x, Single y, Single width, Single height)
{
Ellipse shp = new System.Windows.Shapes.Ellipse();
prepareLinePen(shp, (pen == null) ? _defaultPen.Clone() : pen);
prepareFillBrush(shp, brush);
setRectValue(shp, x, y, width, height);
addShape(shp, "Elps");
}
public void DrawString(string text, TextFont font, PaintBrush brush, AreaF area)
{
System.Windows.Controls.TextBlock shp = new TextBlock();
switch (font.Alignment)
{
case TextFont.AlignmentEnum.LEFT:
shp.TextAlignment = TextAlignment.Left;
break;
case TextFont.AlignmentEnum.RIGHT:
shp.TextAlignment = TextAlignment.Right;
break;
case TextFont.AlignmentEnum.CENTER:
shp.TextAlignment = TextAlignment.Center;
break;
case TextFont.AlignmentEnum.JUSTIFY:
shp.TextAlignment = TextAlignment.Justify;
break;
}
switch (font.Style)
{
case TextFont.StyleEnum.REGULAR:
break;
case TextFont.StyleEnum.BOLD:
shp.FontWeight = FontWeights.Bold;
break;
case TextFont.StyleEnum.ITALIC:
shp.FontStyle = FontStyles.Italic;
break;
}
if (font.Clip)
{
shp.Clip = new RectangleGeometry() { Rect = new Rect(0, 0, area.Width, area.Height) };
}
shp.TextWrapping = (font.Wrap) ? TextWrapping.Wrap : TextWrapping.NoWrap;
shp.Foreground = (brush == null) ? _defaultTextBrush : converttoBrush(brush);
shp.Text = text;
setRectValue(shp, area.X1, area.Y1, area.Width, area.Height);
shp.FontSize = font.Size;
shp.FontFamily = new FontFamily(font.Family);
addShape(shp, "Text");
}
public void DrawString(Single x, Single y, string text, DrawColor fontcolor , float fontsize=10.0f, string fontname = "宋体")
{
AreaF area = new AreaF(){ X1 = x,Y1= y,X2=x+10, Y2= y+10};
TextFont font = new TextFont(fontname,fontsize);
SolidPaintBrush brush = new SolidPaintBrush (fontcolor);
DrawString(text, font, brush, area);
}
public void DrawImage(Area area, string sourceUrl, ImageStretch st)
{
DrawImage(area.X1, area.Y1, area.Width, area.Height, sourceUrl, st);
}
public void DrawImage(AreaF area, string sourceUrl, ImageStretch st)
{
DrawImage(area.X1, area.Y1, area.Width, area.Height, sourceUrl, st);
}
public void DrawImage(Single x, Single y, Single width, Single height, string sourceUrl, ImageStretch st)
{
Image shp = new System.Windows.Controls.Image();
setRectValue(shp, x, y, width , height);
shp.Stretch = converttoStretch(st);
shp.Source = new BitmapImage(new Uri(sourceUrl, UriKind.RelativeOrAbsolute));
addShape(shp, "Imag");
}
#endregion Pulbic Methods
#region Private Methods
private Color converttoColor(DrawColor cl)
{
Color clr= new Color();
clr.A = cl.A;
clr.B = cl.B;
clr.G = cl.G;
clr.R = cl.R;
return clr;
}
private Brush converttoBrush(PaintBrush pbr)
{
if (pbr is SolidPaintBrush)
{
return new SolidColorBrush(converttoColor((((SolidPaintBrush)pbr).Color)));
}
return null;
}
private Stretch converttoStretch(ImageStretch st)
{
switch(st)
{
case ImageStretch.NONE:
return Stretch.None;
case ImageStretch.FILL:
return Stretch.Fill;
case ImageStretch.UNIFORM:
return Stretch.Uniform;
case ImageStretch.UNIFORMTOFILL:
return Stretch.UniformToFill;
}
return Stretch.None;
}
private void prepareLinePen(System.Windows.Shapes.Shape shp, LinePen pen)
{
switch (pen.Style)
{
case LinePen.StyleEnum.SOLID:
shp.Stroke = new SolidColorBrush(converttoColor(pen.Color));
break;
case LinePen.StyleEnum.DOT:
shp.Stroke = new SolidColorBrush(converttoColor(pen.Color));
shp.StrokeDashArray = _dotLineStrokeArray;
break;
case LinePen.StyleEnum.DASH:
shp.Stroke = new SolidColorBrush(converttoColor(pen.Color));
shp.StrokeDashArray = _dashLineStrokeArray;
break;
case LinePen.StyleEnum.DASHDOT:
shp.Stroke = new SolidColorBrush(converttoColor(pen.Color));
shp.StrokeDashArray = _dashdotdotLineStrokeArray;
break;
case LinePen.StyleEnum.DASHDOTDOT:
shp.Stroke = new SolidColorBrush(converttoColor(pen.Color));
shp.StrokeDashArray = _dashdotdotLineStrokeArray;
break;
case LinePen.StyleEnum.CUSTOM:
shp.Stroke = new SolidColorBrush(converttoColor(pen.Color));
Single[] dashgapArray = pen.CustomDashGapArray;
DoubleCollection customLineStrokeArray = new DoubleCollection();
foreach (Single i in dashgapArray)
{
customLineStrokeArray.Add(i);
}
shp.StrokeDashArray = customLineStrokeArray;
break;
}
shp.StrokeThickness = pen.Width;
}
private void prepareFillBrush(System.Windows.Shapes.Shape shp, PaintBrush brh)
{
if (brh != null)
{
shp.Fill = converttoBrush(brh);
}
}
private void setRectValue(System.Windows.FrameworkElement shp, double x, double y, double width, double height)
{
shp.Width = width;
shp.Height = height;
shp.SetValue(Canvas.LeftProperty, x);
shp.SetValue(Canvas.TopProperty, y);
}
private void addShape(System.Windows.FrameworkElement tmpshape, string namePrefix)
{
tmpshape.Name = namePrefix + _elementCount.ToString();
_slCanvas.Children.Add(tmpshape);
_elementCount++;
_lastAddedShape = tmpshape;
}
#endregion Private Methods
}
WinFormGraphics的源代码。
public class WinFormGraphics:IGraphBase
{
#region Consts & Enum
#endregion Consts & Enum
#region Member Variables
private Graphics _canvas;
private UInt32 _elementCount = 0;
private Pen _defaultPen = new Pen(Color.Black);
private Pen _polylinePen = null;
private List<PointF> _polylinePoints = null;
//private Brush _defaultTextBrush = new SolidColorBrush(Colors.Black);
//private System.Windows.FrameworkElement _lastAddedShape = null;
#endregion Member Variables
#region Properties
public Graphics GraphObject
{
get { return _canvas; }
}
//public System.Windows.FrameworkElement LastAddedShape
//{
// get { return _lastAddedShape; }
//}
#endregion Properties
#region Pulbic Methods
public WinFormGraphics(Graphics cs)
{
_canvas = cs;
}
public void SetLinePen(LinePen pen)
{
_defaultPen = (pen==null)?null: converttoPen(pen);
}
public void Clear(DrawColor cl)
{
_canvas.Clear(converttoColor(cl));
}
public void SetClip(AreaF area)
{
if(area != null)
{
_canvas.SetClip(new RectangleF(area.X1, area.Y1, area.Width, area.Height));
}
}
public void ClearClip()
{
_canvas.ResetClip();
}
public void DrawLine(LinePen pen, Int32 x1, Int32 y1, Int32 x2, Int32 y2)
{
DrawLine(pen, (Single)x1, (Single)y1, (Single)x2, (Single)y2);
}
public void DrawLine(LinePen pen, Single x1, Single y1, Single x2, Single y2)
{
Pen pp = converttoPen(pen);
_canvas.DrawLine(pp, x1, y1, x2, y2);
_elementCount++;
}
public void StartPolyline(LinePen pen)
{
if(_polylinePoints!=null) _polylinePoints.Clear(); // need new ??????
_polylinePen = (pen == null) ? _defaultPen : converttoPen(pen);
}
public void AddPolylinePoint(Single x, Single y)
{
if (_polylinePoints == null)
{
_polylinePoints = new List<PointF>();
}
_polylinePoints.Add(new PointF(x, y));
}
public void AddPolylinePoint(Int32 x, Int32 y)
{
AddPolylinePoint((Single)x, (Single)y);
}
public void EndPolyline()
{
_canvas.DrawLines(_polylinePen, _polylinePoints.ToArray());
_elementCount++;
}
public void DrawRectangle(LinePen pen, PaintBrush brush, Area area)
{
DrawRectangle(pen, brush, (Single)area.X1,(Single)area.Y1, (Single)area.Width, (Single)area.Height);
}
public void DrawRectangle(LinePen pen, PaintBrush brush, AreaF area)
{
DrawRectangle(pen, brush, area.X1,area.Y1, area.Width, area.Height);
}
public void DrawRectangle(LinePen pen, PaintBrush brush, Int32 x, Int32 y, Int32 width, Int32 height)
{
if (brush == null)
{
Pen pp = (pen == null) ? _defaultPen : converttoPen(pen);
_canvas.DrawRectangle(pp, x, y, width, height);
}
else
{
Brush bb = converttoBrush(brush);
_canvas.FillRectangle(bb, x, y, width, height);
}
_elementCount++;
}
public void DrawRectangle(LinePen pen, PaintBrush brush, Single x, Single y, Single width, Single height)
{
if (brush == null)
{
Pen pp = (pen == null) ? _defaultPen : converttoPen(pen);
_canvas.DrawRectangle(pp, x, y, width, height);
}
else
{
Brush bb = converttoBrush(brush);
_canvas.FillRectangle(bb, x, y, width, height);
}
_elementCount++;
}
public void DrawPolygon(LinePen pen, PaintBrush brush, ICollection<Dot> edges)
{
Point[] points = new Point[edges.Count];
int i=0;
foreach(Dot dot in edges)
{
points[i].X = dot.X;
points[i].Y = dot.Y;
i++;
}
if (brush == null)
{
Pen pp = (pen == null) ? _defaultPen : converttoPen(pen);
_canvas.DrawPolygon(pp, points);
}
else
{
Brush bb = converttoBrush(brush);
_canvas.FillPolygon (bb, points);
}
_elementCount++;
}
public void DrawPolygon(LinePen pen, PaintBrush brush, ICollection<DotF> edges)
{
PointF[] points = new PointF[edges.Count];
int i = 0;
foreach (DotF dot in edges)
{
points[i].X = dot.X;
points[i].Y = dot.Y;
i++;
}
if (brush == null)
{
Pen pp = (pen == null) ? _defaultPen : converttoPen(pen);
_canvas.DrawPolygon(pp, points);
}
else
{
Brush bb = converttoBrush(brush);
_canvas.FillPolygon(bb, points);
}
_elementCount++;
}
public void DrawCircle(LinePen pen, PaintBrush brush, Int32 x, Int32 y, Int32 radius)
{
DrawCircle(pen, brush, (Single)x, (Single)y, (Single)radius);
}
public void DrawCircle(LinePen pen, PaintBrush brush, Single x, Single y, Single radius)
{
DrawEllipse(pen, brush, x - radius, y - radius, radius, radius);
}
public void DrawEllipse(LinePen pen, PaintBrush brush, Area area)
{
DrawEllipse(pen, brush, (Single)area.X1, (Single)area.Y1, (Single)area.Width, (Single)area.Height);
}
public void DrawEllipse(LinePen pen, PaintBrush brush, AreaF area)
{
DrawEllipse(pen, brush, area.X1, area.Y1, area.Width, area.Height);
}
public void DrawEllipse(LinePen pen, PaintBrush brush, Int32 x, Int32 y, Int32 width, Int32 height)
{
if (brush == null)
{
Pen pp = (pen == null) ? _defaultPen : converttoPen(pen);
_canvas.DrawEllipse(pp, x, y, width, height);
}
else
{
Brush bb = converttoBrush(brush);
_canvas.FillEllipse(bb, x, y, width, height);
}
_elementCount++;
}
public void DrawEllipse(LinePen pen, PaintBrush brush, Single x, Single y, Single width, Single height)
{
if (brush == null)
{
Pen pp = (pen == null) ? _defaultPen : converttoPen(pen);
_canvas.DrawEllipse(pp, x, y, width, height);
}
else
{
Brush bb = converttoBrush(brush);
_canvas.FillEllipse(bb, x, y, width, height);
}
_elementCount++;
}
public void DrawString(string text, TextFont font, PaintBrush brush, AreaF area)
{
StringFormat ft = new StringFormat();
if (!font.Wrap) ft.FormatFlags = StringFormatFlags.NoWrap;
if (!font.Clip) ft.FormatFlags = ft.FormatFlags|StringFormatFlags.NoClip ;
switch (font.Alignment)
{
case TextFont.AlignmentEnum.LEFT:
ft.Alignment = StringAlignment.Near;
break;
case TextFont.AlignmentEnum.RIGHT:
ft.Alignment = StringAlignment.Far;
break;
case TextFont.AlignmentEnum.CENTER:
ft.Alignment = StringAlignment.Center;
break;
case TextFont.AlignmentEnum.JUSTIFY:
ft.Alignment = StringAlignment.Near;
break;
}
FontStyle ftstyle = FontStyle.Regular;
switch (font.Style)
{
case TextFont.StyleEnum.REGULAR:
break;
case TextFont.StyleEnum.BOLD:
ftstyle = FontStyle.Bold;
break;
case TextFont.StyleEnum.ITALIC:
ftstyle = FontStyle.Italic;
break;
}
Font fot = new Font(new FontFamily(font.Family), font.Size, ftstyle);
RectangleF rt = new RectangleF(area.X1, area.Y1, area.Width, area.Height);
if (!font.Clip) //it seems that StringFormatFlags.NoClip does not work! here donot use that flag.
{
SizeF stringSize = new SizeF();
if (font.Wrap)
{
stringSize = _canvas.MeasureString(text, fot, (int)area.Width, ft);
}
else
{
stringSize = _canvas.MeasureString(text, fot, new PointF(area.X1, area.Y1), ft);
}
rt.Width = (area.Width > stringSize.Width) ? area.Width : stringSize.Width;
rt.Height= (area.Height>stringSize.Height)?area.Height:stringSize.Height;
}
_canvas.DrawString(text, fot, converttoBrush(brush), rt, ft);
_elementCount++;
}
public void DrawString(Single x, Single y, string text, DrawColor fontcolor , float fontsize=10.0f, string fontname = "宋体")
{
Font fot = new Font(new FontFamily(fontname), fontsize, FontStyle.Regular);
_canvas.DrawString(text, fot, new SolidBrush(converttoColor(fontcolor)), new PointF(x,y));
_elementCount++;
}
public void DrawImage(Area area, string sourceUrl, ImageStretch st)
{
DrawImage(area.X1, area.Y1, area.Width, area.Height, sourceUrl, st);
}
public void DrawImage(AreaF area, string sourceUrl, ImageStretch st)
{
DrawImage(area.X1, area.Y1, area.Width, area.Height, sourceUrl, st);
}
public void DrawImage(Single x, Single y, Single width, Single height, string sourceUrl, ImageStretch st)
{
Image newImage = Image.FromFile(sourceUrl);
switch (st)
{
case ImageStretch.UNIFORMTOFILL:
case ImageStretch.NONE:
_canvas.DrawImage(newImage,x,y);
break;
case ImageStretch.FILL: //to be stretched to the size of the holder
_canvas.DrawImage(newImage, new RectangleF(x, y, width, height));
break;
case ImageStretch.UNIFORM: //to be stretched according to the proportion of the image
if (height / newImage.Size.Height > width / newImage.Size.Width)
{
_canvas.DrawImage(newImage, new RectangleF(x, y, width, newImage.Size.Height * width / newImage.Size.Width));
}
else
{
_canvas.DrawImage(newImage, new RectangleF(x, y, newImage.Size.Width * height / newImage.Size.Height, height));
}
break;
}
_elementCount++;
}
#endregion Pulbic Methods
#region Private Methods
private Color converttoColor(DrawColor cl)
{
return Color.FromArgb(cl.A, cl.R, cl.G, cl.B);
}
private Pen converttoPen(LinePen pen)
{
Pen pp = new Pen(converttoColor(pen.Color), pen.Width);
switch (pen.Style)
{
case LinePen.StyleEnum.SOLID:
pp.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
break;
case LinePen.StyleEnum.DOT:
pp.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
break;
case LinePen.StyleEnum.DASH:
pp.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
break;
case LinePen.StyleEnum.DASHDOT:
pp.DashStyle = System.Drawing.Drawing2D.DashStyle.DashDot;
break;
case LinePen.StyleEnum.DASHDOTDOT:
pp.DashStyle = System.Drawing.Drawing2D.DashStyle.DashDotDot;
break;
case LinePen.StyleEnum.CUSTOM:
pp.DashPattern = pen.CustomDashGapArray;
break;
}
return pp;
}
private Brush converttoBrush(PaintBrush pbr)
{
if (pbr is SolidPaintBrush)
{
return new SolidBrush(converttoColor((((SolidPaintBrush)pbr).Color)));
}
return null;
}
#endregion Private Methods
}