using System; using System.Collections; using System.ComponentModel; using System.Drawing; using System.Data; using System.Windows.Forms; using System.Drawing.Drawing2D; using System.IO; namespace ShapeControl { public enum LineDirection { None, RightUp, RightDown, LeftUp, LeftDown } public enum ConnecterType { Top, Right, Bottom, Left, Center } //All the defined shape type public enum ShapeType{ Rectangle, RoundedRectangle, Diamond, Ellipse, TriangleUp, TriangleDown, TriangleLeft, TriangleRight, BallonNE, BallonNW, BallonSW, BallonSE, CustomPolygon, CustomPie, LineDown, LineUp, LineHorizontal, LineVertical } public class CustomControl1 : System.Windows.Forms.Control { private string _shapestorageloadfile = ""; private string _shapestoragesavefile = ""; private GraphicsPath _custompath = new GraphicsPath(); private IContainer components; ConnecterType _connector = ConnecterType.Center; LineDirection _direction = LineDirection.None; ShapeType _shape=ShapeType.Rectangle; DashStyle _borderstyle=DashStyle.Solid; Color _bordercolor=Color.FromArgb(255,255,0,0); int _borderwidth=3; GraphicsPath _outline=new GraphicsPath(); bool _usegradient=false; bool _blink = false; bool _vibrate = false; bool _voffseted = false; bool _animateborder = false; int _prevborderwidth = 3; Color _prevbordercolor = Color.Red; bool _btoggled = false; int _static_ds = 0; DashStyle _prevborderstyle = DashStyle.Solid; Color _centercolor=Color.FromArgb(100,255,0,0) ; Color _surroundcolor=Color.FromArgb(100,0,255,255); private Timer timer1; private Timer timer2; string _tag2 = ""; private Timer timer3; Bitmap _bm; //for shapeimage property Bitmap _bmtexture; //for shapeimagetexture property private int _shapeimagerotation=0; public GraphicsPath Outline { get { return _outline; } } [Category("Shape"), Description("Shape Storage Load File")] [EditorAttribute(typeof(FileLoadEditor), typeof(System.Drawing.Design.UITypeEditor))] public string ShapeStorageLoadFile { set { LoadFromFile(this, value, true); } get { return _shapestorageloadfile; } } [Category("Shape"), Description("Shape Storage Save File")] [EditorAttribute(typeof(FileSaveEditor), typeof(System.Drawing.Design.UITypeEditor))] public string ShapeStorageSaveFile { set { if(value.Length<8) return; if (value.ToUpper().IndexOf(".SHP.JPG") != value.Length - 8) { SaveToFile(this, value + ".shp.jpg", true); } else SaveToFile(this, value, true); } get { return _shapestoragesavefile; } } [Category("Shape"), Description("Connect at")] public ConnecterType Connector { get { return _connector; } set {_connector =value; } } [Category("Shape"), Description("For Directional Line")] public LineDirection Direction { get { return _direction; } set { _direction = value; OnResize(null); } } [Category("Shape"), Description("Additional user-defined data")] public string Tag2 { get { return _tag2; } set { _tag2 = value; } } [Category("Shape"), Description("Causes the control border to animate")] public bool AnimateBorder { get { return _animateborder; } set { _animateborder = value; if (_animateborder) { //save all the border _prevborderstyle = _borderstyle; _prevborderwidth = _borderwidth; _prevbordercolor = _bordercolor; if (_borderwidth == 0) _borderwidth = 3; int a, r, g, b; a = _bordercolor.A; r = _bordercolor.R; g = _bordercolor.G; b = _bordercolor.B; _bordercolor = Color.FromArgb(255, r, g, b); } else { _borderwidth=_prevborderwidth ; _bordercolor=_prevbordercolor ; this.BorderStyle =_prevborderstyle; } timer3.Enabled = _animateborder; } } [Category("Shape"), Description("Causes the control to blink")] public bool Blink { get { return _blink; } set { _blink = value; timer1.Enabled = _blink; if (!_blink) this.Visible = true; } } [Category("Shape"), Description("Causes the control to vibrate")] public bool Vibrate { get { return _vibrate; } set { _vibrate = value; timer2.Enabled = _vibrate; if (!_vibrate) if (_voffseted) { this.Top += 5; _voffseted = false; } } } [Category("Shape"), Description("Rotation angle in deg for ShapeImage\nValid values between -180 and 180")] public int ShapeImageRotation { get { return _shapeimagerotation; } set { if (value >= -180 && value <= 180) { _shapeimagerotation = value; if (_bm != null) { OnResize(null); } } } } [Category("Shape"), Description("Background Image to define outline")] public Image ShapeImage { get { return _bm; } set { if (value != null) { _bm = (Bitmap)value.Clone(); Width = 150; Height = 150; OnResize(null); } else { if(_bm!=null) _bm = null; OnResize(null); } } } [Category("Shape"), Description("Texture Image for ShapeImage")] public Image ShapeImageTexture { get { return _bmtexture; } set { if (value != null) { _bmtexture = (Bitmap)value.Clone(); OnResize(null); } else { if (_bmtexture != null) _bmtexture = null; OnResize(null); } } } [Category("Shape"),Description("Text to display")] public override string Text { get { return base.Text; } set { base.Text = value; } } //Overide the BackColor Property to be associated with our custom editor [Category("Shape"),Description("Back Color")] [BrowsableAttribute(true)] [EditorAttribute(typeof(ColorEditor), typeof(System.Drawing.Design.UITypeEditor))] public override Color BackColor { get { return base.BackColor; } set { base.BackColor = value; this.Refresh(); } } [Category("Shape"),Description("Using Gradient to fill Shape")] public bool UseGradient { get{ return _usegradient;} set{ _usegradient=value; this.Refresh();} } //For Gradient Rendering, this is the color at the center of the shape [Category("Shape"),Description("Color at center")] [BrowsableAttribute(true)] [EditorAttribute(typeof(ColorEditor), typeof(System.Drawing.Design.UITypeEditor))] public Color CenterColor { get {return _centercolor;} set { _centercolor=value; this.Refresh();} } //For Gradient Rendering, this is the color at the edges of the shape [Category("Shape"),Description("Color at the edges of the Shape")] [BrowsableAttribute(true)] [EditorAttribute(typeof(ColorEditor), typeof(System.Drawing.Design.UITypeEditor))] public Color SurroundColor { get {return _surroundcolor;} set { _surroundcolor=value; this.Refresh();} } [Category("Shape"),Description("Border Width")] public int BorderWidth { get{ return _borderwidth; } set{ _borderwidth=value; if (_borderwidth<0) _borderwidth=0; OnResize(null); } } [Category("Shape"),Description("Border Color")] [BrowsableAttribute(true)] [EditorAttribute(typeof(ColorEditor), typeof(System.Drawing.Design.UITypeEditor))] public Color BorderColor { get{return _bordercolor;} set{_bordercolor=value;this.Refresh();} } [Category("Shape"),Description("Border Style")] public DashStyle BorderStyle { get{return _borderstyle;} set{_borderstyle=value;this.Refresh();} } [Category("Shape"),Description("Select Shape")] [BrowsableAttribute(true)] [EditorAttribute(typeof(ShapeTypeEditor), typeof(System.Drawing.Design.UITypeEditor))] public ShapeType Shape { get{return _shape;} set { _shape=value; if (_shape == ShapeType.LineVertical || _shape == ShapeType.LineHorizontal || _shape == ShapeType.LineUp || _shape == ShapeType.LineDown) ForeColor = Color.FromArgb(0, 255, 255, 255); if (_shape == ShapeType.LineVertical) this.Width = 20; if (_shape == ShapeType.LineHorizontal) this.Height = 20; OnResize(null); } } public CustomControl1() { // This call is required by the Windows.Forms Form Designer. InitializeComponent(); this.DoubleBuffered = true; //Using of Double Buffer allow for smooth rendering //minizing flickering this.SetStyle(ControlStyles.SupportsTransparentBackColor | ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint,true); //set the default backcolor and font this.BackColor=Color.FromArgb(0,255,255,255); this.Font =new Font("Arial",12,FontStyle.Bold); this.Width = 100; this.Height = 100; this.Text = ""; } protected override void Dispose( bool disposing ) { if( disposing ) { if( components != null ) components.Dispose(); } base.Dispose( disposing ); } #region Component Designer generated code private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.timer1 = new System.Windows.Forms.Timer(this.components); this.timer2 = new System.Windows.Forms.Timer(this.components); this.timer3 = new System.Windows.Forms.Timer(this.components); this.SuspendLayout(); // // timer1 // this.timer1.Interval = 200; this.timer1.Tick += new System.EventHandler(this.timer1_Tick); // // timer2 // this.timer2.Interval = 200; this.timer2.Tick += new System.EventHandler(this.timer2_Tick); // // timer3 // this.timer3.Tick += new System.EventHandler(this.timer3_Tick); // // CustomControl1 // this.TextChanged += new System.EventHandler(this.ShapeControl_TextChanged); this.ResumeLayout(false); } #endregion //This function creates the path for each shape //It is also being used by the ShapeTypeEditor to create the various shapes //for the Shape property editor UI internal static void updateOutline(ref GraphicsPath outline,ShapeType shape,int width,int height,int borderwidth) { switch(shape) { case ShapeType.LineVertical : outline.AddLine(new PointF((float)width / 2, borderwidth), new PointF((float)width / 2, height - borderwidth)); break; case ShapeType.LineHorizontal: outline.AddLine(new PointF(borderwidth, (float)height / 2 ) , new PointF(width - borderwidth, (float)height / 2 )); break; ///////////////////////////// // * // * // * // * //* ////////////////////////////// case ShapeType.LineUp: outline.AddLine(new PointF(borderwidth, height - borderwidth), new PointF(width - borderwidth, borderwidth)); break; //////////////////////////// // * // * // * // * // * ///////////////////////////// case ShapeType.LineDown : outline.AddLine(new PointF(borderwidth , borderwidth ), new PointF(width - borderwidth , height - borderwidth)); break; case ShapeType.CustomPie: outline.AddPie(0,0,width,height,180,270); break; case ShapeType.CustomPolygon: outline.AddPolygon(new PointF[]{ new PointF(0,0), new PointF((float)width/2,(float)height/4), new PointF((float)width,0), new PointF(((float)width*3)/4,(float)height/2), new PointF((float)width,(float)height), new PointF((float)width/2,((float)height*3)/4), new PointF(0,(float)height), new PointF((float)width/4,(float)height/2) } ); break; case ShapeType.Diamond : outline.AddPolygon(new PointF[]{ new PointF(0,(float)height/2), new PointF((float)width/2,0), new PointF((float)width,(float)height/2), new PointF((float)width/2,(float)height) }); break; case ShapeType.Rectangle : outline.AddRectangle(new RectangleF(0,0,width,height)); break; case ShapeType.Ellipse: outline.AddEllipse(0,0,(float)width,(float)height); break; case ShapeType.TriangleUp: outline.AddPolygon(new PointF[]{new PointF(0,(float)height),new PointF((float)width,(float)height),new PointF((float)width/2,0)}); break; case ShapeType.TriangleDown: outline.AddPolygon(new PointF[]{new PointF(0,0),new PointF(width,0),new PointF(width/2,(float)(float)height)}); break; case ShapeType.TriangleLeft: outline.AddPolygon(new PointF[]{new PointF(width,0),new PointF(0,(float)(float)height/2),new PointF(width,(float)(float)height)}); break; case ShapeType.TriangleRight: outline.AddPolygon(new PointF[]{new PointF(0,0),new PointF(width,(float)(float)height/2),new PointF(0,(float)(float)height)}); break; case ShapeType.RoundedRectangle: outline.AddArc(0,0,(float)width/4,(float)width/4,180,90); outline.AddLine((float)width/8,0,(float)width-(float)width/8,0); outline.AddArc((float)width-(float)width/4,0,(float)width/4,(float)width/4,270,90); outline.AddLine((float)width,(float)width/8,(float)width,(float)height-(float)width /8); outline.AddArc((float)width-(float)width/4,(float)height-(float)width/4,(float)width/4,(float)width/4,0,90); outline.AddLine((float)width-(float)width/8,(float)height,(float)width/8,(float)height); outline.AddArc(0,(float)height-(float)width/4,(float)width/4,(float)width/4,90,90); outline.AddLine(0,(float)height-(float)width/8,0,(float)width/8); break; case ShapeType.BallonSW: outline.AddArc(0,0,(float)width/4,(float)width/4,180,90); outline.AddLine((float)width/8,0,(float)width-(float)width/8,0); outline.AddArc((float)width-(float)width/4,0,(float)width/4,(float)width/4,270,90); outline.AddLine((float)width,(float)width/8,(float)width,((float)height*0.75f)-(float)width /8); outline.AddArc((float)width-(float)width/4,((float)height *0.75f )-(float)width/4,(float)width/4,(float)width/4,0,90); outline.AddLine((float)width-(float)width/8,((float)height*0.75f),(float)width/8 +((float)width/4),((float)height*0.75f)); outline.AddLine((float)width/8 +((float)width/4),(float)height*0.75f,(float)width/8 +((float)width/8),(float)height); outline.AddLine((float)width/8 +((float)width/8),(float)height,(float)width/8 +((float)width/8),((float)height*0.75f)); outline.AddLine((float)width/8 +((float)width/8),((float)height*0.75f),(float)width/8,((float)height*0.75f)); outline.AddArc(0,((float)height*0.75f)-(float)width/4,(float)width/4,(float)width/4,90,90); outline.AddLine(0,((float)height*0.75f)-(float)width/8,0,(float)width/8); break; case ShapeType.BallonSE: outline.AddArc(0,0,(float)width/4,(float)width/4,180,90); outline.AddLine((float)width/8,0,(float)width-(float)width/8,0); outline.AddArc((float)width-(float)width/4,0,(float)width/4,(float)width/4,270,90); outline.AddLine((float)width,(float)width/8,(float)width,((float)height*0.75f)-(float)width /8); outline.AddArc((float)width-(float)width/4,((float)height *0.75f )-(float)width/4,(float)width/4,(float)width/4,0,90); outline.AddLine((float)width-(float)width/8,((float)height*0.75f),(float)width-((float)width/4),((float)height*0.75f)); outline.AddLine((float)width-((float)width/4),(float)height*0.75f,(float)width-((float)width/4),(float)height); outline.AddLine((float)width-((float)width/4),(float)height,(float)width -(3*(float)width/8),((float)height*0.75f)); outline.AddLine((float)width -(3*(float)width/8),((float)height*0.75f),(float)width/8,((float)height*0.75f)); outline.AddArc(0,((float)height*0.75f)-(float)width/4,(float)width/4,(float)width/4,90,90); outline.AddLine(0,((float)height*0.75f)-(float)width/8,0,(float)width/8); break; case ShapeType.BallonNW: outline.AddArc((float)width-(float)width/4,((float)height )-(float)width/4,(float)width/4,(float)width/4,0,90); outline.AddLine((float)width-(float)width/8,((float)height),(float)width-((float)width/4),((float)height)); outline.AddArc(0,((float)height)-(float)width/4,(float)width/4,(float)width/4,90,90); outline.AddLine(0,((float)height)-(float)width/8,0,(float)height *0.25f+(float)width/8); outline.AddArc(0,(float)height *0.25f,(float)width/4,(float)width/4,180,90); outline.AddLine((float)width/8,(float)height *0.25f,(float)width/4,(float)height *0.25f); outline.AddLine((float)width/4,(float)height *0.25f,(float)width/4,0); outline.AddLine((float)width/4,0,3*(float)width/8 ,(float)height *0.25f); outline.AddLine(3*(float)width/8 ,(float)height *0.25f,(float)width -(float)width/8,(float)height *0.25f); outline.AddArc((float)width-(float)width/4,(float)height *0.25f,(float)width/4,(float)width/4 ,270,90); outline.AddLine((float)width,(float)width/8+(float)height *0.25f,(float)width,((float)height)-(float)width /8); break; case ShapeType.BallonNE: outline.AddArc((float)width-(float)width/4,((float)height )-(float)width/4,(float)width/4,(float)width/4,0,90); outline.AddLine((float)width-(float)width/8,((float)height),(float)width-((float)width/4),((float)height)); outline.AddArc(0,((float)height)-(float)width/4,(float)width/4,(float)width/4,90,90); outline.AddLine(0,((float)height)-(float)width/8,0,(float)height *0.25f+(float)width/8); outline.AddArc(0,(float)height *0.25f,(float)width/4,(float)width/4,180,90); outline.AddLine((float)width/8,(float)height *0.25f,5*(float)width/8,(float)height *0.25f); outline.AddLine(5*(float)width/8,(float)height *0.25f,3*(float)width/4,0); outline.AddLine(3*(float)width/4,0,3*(float)width/4 ,(float)height *0.25f); outline.AddLine(3*(float)width/4 ,(float)height *0.25f,(float)width -(float)width/8,(float)height *0.25f); outline.AddArc((float)width-(float)width/4,(float)height *0.25f,(float)width/4,(float)width/4 ,270,90); outline.AddLine((float)width,(float)width/8+(float)height *0.25f,(float)width,((float)height)-(float)width /8); break; default:break; } } protected override void OnResize(EventArgs e) { if (this.Width < 2 * _borderwidth) { this.Width = 2 * _borderwidth; return; } if (this.Height < 2 * _borderwidth) { this.Height = 2 * _borderwidth; return; } // if (this.Width <= 0 || this.Height <= 0) return; if (_bm == null) { _outline = new GraphicsPath(); updateOutline(ref _outline, _shape, this.Width, this.Height,this.BorderWidth); } else { Bitmap bm = (Bitmap)_bm.Clone(); Bitmap bm2 = new Bitmap(Width, Height); // System.Diagnostics.Debug.WriteLine(bm2.Width + "," + bm2.Height); Graphics g = Graphics.FromImage(bm2); Matrix _m = new Matrix(); if(_shapeimagerotation!=0) { _m.RotateAt(_shapeimagerotation, new PointF(this.Width / 2, this.Height / 2)); // g.Transform = _m; } // Graphics.FromImage(bm2).DrawImage(bm, new RectangleF(0, 0, bm2.Width, bm2.Height), new RectangleF(0, 0, bm.Width, bm.Height), GraphicsUnit.Pixel); g.DrawImage(bm, new RectangleF(0, 0, bm2.Width, bm2.Height), new RectangleF(0, 0, bm.Width, bm.Height), GraphicsUnit.Pixel); TraceOutline.CTraceOuline trace = new TraceOutline.CTraceOuline(); string s = trace.TraceOutlineN(bm2, 0, bm2.Height / 2, bm2.Width / 2, Color.Black, Color.White, true, 1); if (s == "") return; Point[] p = trace.StringOutline2Polygon(s); _outline = new GraphicsPath(); _outline.AddPolygon(p); _outline.Transform(_m); if (_bmtexture != null) { g.Transform = _m; g.DrawImage(_bmtexture, new RectangleF(0, 0, bm2.Width, bm2.Height), new RectangleF(0, 0, _bmtexture.Width, _bmtexture.Height), GraphicsUnit.Pixel); } g.Dispose(); if (_bmtexture != null) { this.BackgroundImage = bm2; } else { this.BackgroundImage = null; this.Refresh(); } this.Region = new Region(_outline); } if (_outline != null && _bm==null) { //these require widening if ( this.Shape == ShapeType.LineDown || this.Shape == ShapeType.LineUp || this.Shape == ShapeType.LineHorizontal || this.Shape == ShapeType.LineVertical || this.Shape == ShapeType.Rectangle ) { //border width to widen by int bw = (this.Shape == ShapeType.Rectangle) ? 1 : _borderwidth; GraphicsPath tmpoutline = (GraphicsPath)_outline.Clone(); Pen p = new Pen(_bordercolor, bw); //line is always generated from left to right //defaults no direction caps //leftmost or topmost for vertical line p.StartCap = LineCap.Round; //rigtmost or bottommost for vertical line p.EndCap = LineCap.Round; if (_direction != LineDirection.None) switch (this.Shape) { //case ShapeType.LineHorizontal: // // // if (_direction == LineDirection.LeftDown || _direction == LineDirection.LeftUp) // p.StartCap = LineCap.ArrowAnchor; // else // p.EndCap = LineCap.ArrowAnchor; // break; case ShapeType.LineVertical: if (_direction == LineDirection.LeftUp || _direction == LineDirection.RightUp) p.StartCap = LineCap.ArrowAnchor; else p.EndCap = LineCap.ArrowAnchor; break; case ShapeType.LineHorizontal: case ShapeType.LineUp: case ShapeType.LineDown: if (_direction == LineDirection.LeftUp || _direction == LineDirection.LeftDown) p.StartCap = LineCap.ArrowAnchor; else p.EndCap = LineCap.ArrowAnchor; break; } try { tmpoutline.Widen(p); } catch { } if (this.Shape != ShapeControl.ShapeType.Rectangle) { //widen region this.Region = new Region(tmpoutline); //original region Region org = new Region(_outline); //add up both this.Region.Union(org); } else { _outline.AddPath(tmpoutline, true); _outline.CloseAllFigures(); this.Region = new Region(_outline); } } else { this.Region = new Region(_outline); } } this.Refresh(); base.OnResize (e); } protected override void OnPaint(PaintEventArgs pe) { //Rendering with Gradient if (_usegradient) { try { PathGradientBrush br = new PathGradientBrush(this._outline); br.CenterColor = this._centercolor; br.SurroundColors = new Color[] { this._surroundcolor }; pe.Graphics.FillPath(br, this._outline); } catch { } } //Rendering with Border if(_borderwidth>0) { Pen p=new Pen(_bordercolor,_borderwidth*2); //setting for lines if (this.Shape == ShapeType.LineDown || this.Shape == ShapeType.LineUp || this.Shape == ShapeType.LineHorizontal || this.Shape == ShapeType.LineVertical) { p = new Pen(_bordercolor, _borderwidth); p.StartCap = LineCap.Round; p.EndCap = LineCap.Round; if (_direction != LineDirection.None) switch (this.Shape) { //case ShapeType.LineHorizontal: // if (_direction == LineDirection.LeftDown || _direction == LineDirection.LeftUp) // p.StartCap = LineCap.ArrowAnchor; // else // p.EndCap = LineCap.ArrowAnchor; // break; case ShapeType.LineVertical: if (_direction == LineDirection.LeftUp || _direction == LineDirection.RightUp) p.StartCap = LineCap.ArrowAnchor; else p.EndCap = LineCap.ArrowAnchor; break; case ShapeType.LineHorizontal: case ShapeType.LineUp: case ShapeType.LineDown: if (_direction == LineDirection.LeftUp || _direction == LineDirection.LeftDown ) p.StartCap = LineCap.ArrowAnchor; else p.EndCap = LineCap.ArrowAnchor; break; } } //set border style p.DashStyle=_borderstyle; if (p.DashStyle == DashStyle.Custom) p.DashPattern = new float[] { 1, 1,1,1 }; //animate border by using a one of sequence of 10 generated dash style with every call if(this.AnimateBorder) { p.DashStyle =DashStyle.Custom; _static_ds = (_static_ds++) % 10; p.DashPattern = this._btoggled ? new float[] { 1, 0.01f+0.05f * _static_ds, 1, 1, 1 } : new float[] { 1, 1, 1, 1 }; } pe.Graphics.SmoothingMode=SmoothingMode.HighQuality; pe.Graphics.DrawPath(p,this._outline); p.Dispose(); } //Rendering the text to be at the center of the shape StringFormat sf=new StringFormat(); sf.Alignment=StringAlignment.Center; sf.LineAlignment=StringAlignment.Center; switch(_shape) { case ShapeType.BallonNE: case ShapeType.BallonNW: pe.Graphics.DrawString(this.Text,this.Font,new SolidBrush(this.ForeColor),new RectangleF(0,this.Height*0.25f,this.Width ,this.Height*0.75f),sf); break; case ShapeType.BallonSE: case ShapeType.BallonSW: pe.Graphics.DrawString(this.Text,this.Font,new SolidBrush(this.ForeColor),new RectangleF(0,0,this.Width ,this.Height*0.75f),sf); break; default: pe.Graphics.DrawString(this.Text,this.Font,new SolidBrush(this.ForeColor),new Rectangle(0,0,this.Width ,this.Height),sf); break; } // Calling the base class OnPaint base.OnPaint(pe); } private void ShapeControl_TextChanged(object sender, System.EventArgs e) { this.Refresh(); } private void timer1_Tick(object sender, EventArgs e) { this.Visible = !this.Visible; } private void timer2_Tick(object sender, EventArgs e) { if (!_vibrate) return; _voffseted = !_voffseted; this.Top =_voffseted ?this.Top -5:this.Top +5; } private void timer3_Tick(object sender, EventArgs e) { this.Refresh(); _btoggled = !_btoggled; } public static bool SaveToFile(ShapeControl.CustomControl1 ctrl1, string filename, bool bFromDesigner) { string path = ""; try { if (filename.Length < 8) return false; //min name .shp.jpg if (filename.ToUpper().IndexOf(".SHP.JPG") != (filename.Length - 8)) return false; if (filename != "") { if (filename.IndexOf("\\") >= 0) path = filename; else path = Application.UserAppDataPath + "\\" + filename; if (bFromDesigner) { if (MessageBox.Show("Save to " + path, "Confirm", MessageBoxButtons.OKCancel) != DialogResult.OK) return false; } string shapepath = path.Substring(0, path.Length - 4); if (File.Exists(path)) { if (bFromDesigner) { if (MessageBox.Show(path + " already exist. Overwrite", "Confirm", MessageBoxButtons.OKCancel) != DialogResult.OK) return false; } File.Delete(path); if (File.Exists(shapepath)) File.Delete(shapepath); } if (!File.Exists(shapepath)) { // Create a file to write to. using (StreamWriter sw = File.CreateText(shapepath)) { sw.WriteLine("AnimateBorder<" + ctrl1.AnimateBorder.ToString()+">"); sw.WriteLine("Vibrate<" + ctrl1.Vibrate.ToString() + ">"); sw.WriteLine("Blink<" + ctrl1.Blink.ToString() + ">"); sw.WriteLine("BackColor<" + ctrl1.BackColor.ToArgb() + ">"); sw.WriteLine("BorderColor<" + ctrl1.BorderColor.ToArgb() + ">"); sw.WriteLine("BorderColor<" + ctrl1.BorderColor.ToArgb() + ">"); sw.WriteLine("BorderStyle<" + ctrl1.BorderStyle.ToString() + ">"); sw.WriteLine("BorderWidth<" + ctrl1.BorderWidth + ">"); sw.WriteLine("CenterColor<" + ctrl1.CenterColor.ToArgb() + ">"); sw.WriteLine("Connector<" + ctrl1.Connector + ">"); sw.WriteLine("Direction<" + ctrl1.Direction + ">"); sw.WriteLine("Font"); sw.WriteLine("Shape<" + ctrl1.Shape.ToString() + ">"); if (ctrl1.ShapeImage != null) { //sw.WriteLine("ShapeImage>shapeimage.jpg"); //ctrl1.ShapeImage.Save(path + ".shapeimage.jpg", // System.Drawing.Imaging.ImageFormat.Jpeg); sw.WriteLine("ShapeImage<" + BitmapToBase64String((Bitmap)ctrl1.ShapeImage) + ">"); } else sw.WriteLine("ShapeImage"); sw.WriteLine("ShapeImageRotation<" + ctrl1.ShapeImageRotation + ">"); if (ctrl1.ShapeImageTexture != null) { //sw.WriteLine("ShapeImageTexture>shapeimagetexture.jpg"); //ctrl1.ShapeImageTexture.Save(path + ".shapeimagetexture.jpg", // System.Drawing.Imaging.ImageFormat.Jpeg); sw.WriteLine("ShapeImageTexture<" + BitmapToBase64String((Bitmap)ctrl1.ShapeImageTexture) + ">"); } else sw.WriteLine("ShapeImageTexture"); sw.WriteLine("SurroundColor<" + ctrl1.SurroundColor.ToArgb() + ">"); sw.WriteLine("UseGradient<" + ctrl1.UseGradient.ToString() + ">"); sw.WriteLine("ForeColor<" + ctrl1.ForeColor.ToArgb() + ">"); sw.WriteLine("Text<" + ctrl1.Text.ToString() + ">"); sw.WriteLine("Width<" + ctrl1.Width + ">"); sw.WriteLine("Height<" + ctrl1.Height + ">"); if (ctrl1.BackgroundImage == null) sw.WriteLine("BackgroundImage"); else { //sw.WriteLine("BackgroundImage>backgroundimage.jpg"); //ctrl1.BackgroundImage.Save(path + ".backgroundimage.jpg", // System.Drawing.Imaging.ImageFormat.Jpeg); sw.WriteLine("BackgroundImage<" + BitmapToBase64String((Bitmap)ctrl1.BackgroundImage) + ">"); } Bitmap bm=new Bitmap(ctrl1.Width ,ctrl1.Height,System.Drawing.Imaging.PixelFormat.Format32bppArgb ); Bitmap mask =(Bitmap) bm.Clone(); Graphics g = Graphics.FromImage(mask); g.FillRectangle(new SolidBrush(Color.Black), 0, 0, mask.Width, mask.Height); Region maskregion = ctrl1.Region;//new Region(ctrl1._outline); g.FillRegion(new SolidBrush(Color.White), maskregion); g.Dispose(); //for debugging purpose //mask.Save(path + ".mask.jpg", System.Drawing.Imaging.ImageFormat.Jpeg); ctrl1.DrawToBitmap(bm, ctrl1.ClientRectangle); // bm.Save(path + ".bm.jpg", System.Drawing.Imaging.ImageFormat.Jpeg); Bitmap bmout = CBitmapOps.DoBitOpsForBitmap(bm, mask, "AND"); CBitmapOps.DoInvertBitmap(mask); //mask.Save(path + ".mask_inv.jpg", System.Drawing.Imaging.ImageFormat.Jpeg); bmout = CBitmapOps.DoBitOpsForBitmap(bmout, mask, "OR"); // bmout.Save(path + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg); bmout.Save(path , System.Drawing.Imaging.ImageFormat.Jpeg); if (bFromDesigner) MessageBox.Show("Shape saved to " + path); } } //if } //if } //try catch (Exception e) { if (bFromDesigner) MessageBox.Show(e.ToString()); return false; } return true; } private static string UnicodeToHex(string uni) { return ""; } private static string BitmapToBase64String(Bitmap bm) { using( MemoryStream ms = new MemoryStream()) { bm.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); byte[] bms = ms.GetBuffer(); ms.Close(); ms.Dispose(); string b64str = Convert.ToBase64String(bms); return b64str; } } private static Bitmap BitmapFromBase64String(string b64str) { byte[] b = Convert.FromBase64String(b64str); using (MemoryStream ms = new MemoryStream(b)) { Bitmap bm = (Bitmap)Bitmap.FromStream(ms); return bm; } } public static bool LoadFromFile(ShapeControl.CustomControl1 ctrl1, string filename,bool bFromDesigner) { try { if (filename != "") { if (filename.Length < 8) return false; //min name .shp.jpg if (filename.ToUpper().IndexOf(".SHP.JPG") != (filename.Length - 8)) return false; if (bFromDesigner) { if (MessageBox.Show("Load from " + filename, "Confirm", MessageBoxButtons.OKCancel) != DialogResult.OK) return false; } //remove the .jpg to get the .shp filename string shapefilename = filename.Substring(0, filename.Length - 4); var v = System.IO.File.ReadAllLines(shapefilename); for (int i = 0; i < v.Length; i++) { // var v1 = v[i].Split('>'); //find first "<" int startindex = v[i].IndexOf("<"); int endindex = v[i].LastIndexOf(">"); var v1 = new string[2]; if ((endindex > 0) && (startindex > 0) && (endindex > startindex)) { v1[0] = v[i].Substring(0, startindex ); //last char before < v1[1] = v[i].Substring(startindex+1); //from char after < v1[1] = v1[1].Substring(0, v1[1].Length - 1); //remove > } else continue; switch (v1[0]) { case "BackgroundImage": if (v1[1] == "null") { ctrl1.BackgroundImage = null; } else { //using (var bmpTemp = new Bitmap(filename + "." + v1[1])) //{ // ctrl1.BackgroundImage = new Bitmap(bmpTemp); //} using (var bmpTemp =BitmapFromBase64String(v1[1])) { ctrl1.BackgroundImage = new Bitmap(bmpTemp); } } break; case "ShapeImage": if (v1[1] == "null") { ctrl1.ShapeImage = null; } else { //using (var bmpTemp = new Bitmap(filename + "." + v1[1])) //{ // ctrl1.ShapeImage = new Bitmap(bmpTemp); //} using (var bmpTemp = BitmapFromBase64String(v1[1])) { ctrl1.ShapeImage = new Bitmap(bmpTemp); } } break; case "Shape": ctrl1.Shape = (ShapeControl.ShapeType)Enum.Parse(typeof(ShapeControl.ShapeType), v1[1], true); break; case "ForeColor": ctrl1.ForeColor = Color.FromArgb(int.Parse(v1[1])); break; case "Text": ctrl1.Text = v1[1]; break; case "BorderColor": ctrl1.BorderColor = Color.FromArgb(int.Parse(v1[1])); break; case "AnimateBorder": ctrl1.AnimateBorder = bool.Parse(v1[1]); break; case "BackColor": ctrl1.BackColor = Color.FromArgb(int.Parse(v1[1])); break; case "BorderWidth": ctrl1.BorderWidth = int.Parse(v1[1]); break; case "BorderStyle": ctrl1.BorderStyle = (System.Drawing.Drawing2D.DashStyle)Enum.Parse(typeof(System.Drawing.Drawing2D.DashStyle), v1[1]); break; case "CenterColor": ctrl1.CenterColor = Color.FromArgb(int.Parse(v1[1])); break; case "SurroundColor": ctrl1.SurroundColor = Color.FromArgb(int.Parse(v1[1])); break; case "Connector": ctrl1.Connector = (ShapeControl.ConnecterType)Enum.Parse(typeof(ShapeControl.ConnecterType), v1[1], true); break; case "Direction": ctrl1.Direction = (ShapeControl.LineDirection)Enum.Parse(typeof(ShapeControl.LineDirection), v1[1], true); break; case "Font": var v2 = v1[1].Split(','); string familyname = "Arial"; float size = 8f; GraphicsUnit gu = GraphicsUnit.Point; FontStyle fs = FontStyle.Regular; for (int j = 0; j < v2.Length; j++) { var v3 = v2[j].Trim().Split(':'); switch (v3[0].Trim()) { case "Name": familyname = v3[1]; break; case "Size": size = float.Parse(v3[1]); break; case "GraphicalUnits": gu = (GraphicsUnit)Enum.Parse(typeof(GraphicsUnit), v3[1], true); break; case "Style": fs = (FontStyle)Enum.Parse(typeof(FontStyle), v3[1], true); break; } } ctrl1.Font = new Font(familyname, size, fs, gu); break; case "UseGradient": ctrl1.UseGradient = bool.Parse(v1[1]); break; case "ShapeImageRotation": ctrl1.ShapeImageRotation = int.Parse(v1[1]); break; case "ShapeImageTexture": if (v1[1] == "null") { ctrl1.ShapeImageTexture = null; } else { //using (var bmpTemp = new Bitmap(filename + "." + v1[1])) //{ // ctrl1.ShapeImageTexture = new Bitmap(bmpTemp); //} using (var bmpTemp = BitmapFromBase64String(v1[1])) { ctrl1.ShapeImageTexture = new Bitmap(bmpTemp); } } break; case "Width": ctrl1.Width = int.Parse(v1[1]); break; case "Height": ctrl1.Height = int.Parse(v1[1]); break; } } } } catch (Exception e) { if(bFromDesigner ) MessageBox.Show(e.ToString()); return false; } return true; } } public class Line { public static void setConnectors(ref ShapeControl.CustomControl1 ctrl1, ref ShapeControl.CustomControl1 ctrl2) { //defaults ctrl1.Connector = ShapeControl.ConnecterType.Center; ctrl2.Connector = ShapeControl.ConnecterType.Center; int maxwidth = (ctrl1.Width > ctrl2.Width) ? ctrl1.Width : ctrl2.Width; int maxheight = (ctrl1.Height > ctrl2.Height) ? ctrl1.Height : ctrl2.Height; //check y delta int ydelta = ctrl1.Top - ctrl2.Top; int xdelta = ctrl1.Left - ctrl2.Left; //overlapped if (Math.Abs(ydelta) < maxheight && Math.Abs(xdelta) < maxwidth) return; if (Math.Abs(ydelta) > Math.Abs(xdelta)) //use top and bottom connector { if (ydelta > 0) //ctrl1 is lower { ctrl1.Connector = ShapeControl.ConnecterType.Top; ctrl2.Connector = ShapeControl.ConnecterType.Bottom; } else { ctrl1.Connector = ShapeControl.ConnecterType.Bottom; ctrl2.Connector = ShapeControl.ConnecterType.Top; } } else //use left and right connector { if (xdelta > 0) // ctrl1 on the right { ctrl1.Connector = ShapeControl.ConnecterType.Left; ctrl2.Connector = ShapeControl.ConnecterType.Right; } else { ctrl1.Connector = ShapeControl.ConnecterType.Right; ctrl2.Connector = ShapeControl.ConnecterType.Left; } } } public static void setConnectorPoint(ref int x, ref int y, ShapeControl.CustomControl1 ctrl) { int x0 = ctrl.Location.X; int y0 = ctrl.Location.Y; int x0delta = 0, y0delta = 0; switch (ctrl.Connector) { case ShapeControl.ConnecterType.Left: y0delta = ctrl.Height / 2; break; case ShapeControl.ConnecterType.Right: x0delta = ctrl.Width; y0delta = ctrl.Height / 2; break; case ShapeControl.ConnecterType.Top: x0delta = ctrl.Width / 2; break; case ShapeControl.ConnecterType.Bottom: x0delta = ctrl.Width / 2; y0delta = ctrl.Height; break; case ShapeControl.ConnecterType.Center: x0delta = ctrl.Width / 2; y0delta = ctrl.Height / 2; break; } x = x0 + x0delta; y = y0 + y0delta; } //generic //can be used for any line shape control //x0,y0 is source pt, x1,y1 is the dest point //for directional line, the arrow would appear in x1,y1 public static void setLine(ref ShapeControl.CustomControl1 ctrl1, int x0, int y0, int x1, int y1) { int xx0 = 0; //left int yy0 = 0; //top int xx1 = 0; //right int yy1 = 0; //bottom //set direction based on location of dest_cm in relation to src_cam if (x0 <= x1) // dest on the right { if (ctrl1.Direction != ShapeControl.LineDirection.None) { if (y0 < y1) // dest_cam at the bottom ctrl1.Direction = ShapeControl.LineDirection.RightDown; else ctrl1.Direction = ShapeControl.LineDirection.RightUp; } //left src xx0 = x0; yy0 = y0; //right dest xx1 = x1; yy1 = y1; } else //dest on the left { if (ctrl1.Direction != ShapeControl.LineDirection.None) { if (y0 < y1) //dest_cam at the bottom ctrl1.Direction = ShapeControl.LineDirection.LeftDown; else ctrl1.Direction = ShapeControl.LineDirection.LeftUp; } //left dest xx0 = x1; yy0 = y1; //right src xx1 = x0; yy1 = y0; } float gradient = 0f; //check for vert and horizontal line if (Math.Abs(xx0 - xx1) <= 0 || Math.Abs(yy0 - yy1) <= 0) { ctrl1.Shape = (Math.Abs(xx0 - xx1) <= 0) ? ShapeControl.ShapeType.LineVertical : ShapeControl.ShapeType.LineHorizontal; } //normal line else { gradient = (float)(yy0 - yy1) / (float)(xx0 - xx1); ctrl1.Shape = (gradient > 0f) ? ShapeControl.ShapeType.LineDown : ShapeControl.ShapeType.LineUp; } //all shape control are specified by //the top-left corner, width and height //lx0,ly0 : location for top-left of shape control //lx1,ly1 : location for bottom-right of shape control //lw: width of shape control //lh: height of shape control int lx0 = 0, ly0 = 0, lx1 = 0, ly1 = 0, lw = 0, lh = 0; //offset from to cater for line width int delta = (4 * ctrl1.BorderWidth) / 4; switch (ctrl1.Shape) { case ShapeControl.ShapeType.LineVertical: lx0 = xx0 - delta; lx1 = xx1 + delta; ly0 = yy0 - delta; ly1 = yy1 + delta; lw = Math.Abs(lx0 - lx1); lh = Math.Abs(ly0 - ly1); break; case ShapeControl.ShapeType.LineHorizontal: ly0 = yy0 - delta; ly1 = yy1 + delta; lx0 = xx0 - delta; lx1 = xx1 + delta; lh = Math.Abs(ly0 - ly1); lw = Math.Abs(lx0 - lx1); break; case ShapeControl.ShapeType.LineUp: lx0 = xx0 - delta; ly0 = yy1 - delta; lx1 = xx1 + delta; ly1 = yy0 + delta; lw = Math.Abs(lx0 - lx1); lh = Math.Abs(ly0 - ly1); break; case ShapeControl.ShapeType.LineDown: lx0 = xx0 - delta; ly0 = yy0 - delta; lx1 = xx1 + delta; ly1 = yy1 + delta; lw = Math.Abs(lx0 - lx1); lh = Math.Abs(ly0 - ly1); break; } //set the location and sie of the line shape control ctrl1.Size = new System.Drawing.Size(lw, lh); ctrl1.Location = new Point(lx0, ly0); } } }