using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms;namespace ImageControls {/// <summary>/// 控件/// </summary> public class ShapeEx : Control{#region 字段private Color _BackColor; //背景颜色/// <summary>/// 必需的设计器变量。/// </summary>private Color _BorderColor; //边框颜色private Point _MouseLocation;private bool _ReSizeble; //是否可调整大小private int _SelectSelctedIndex; //0-8,0:SizeAllprivate int _SelfHeight;private Point _SelfLocation;private int _SelfWidth;private Rectangle _rectBottomSelector;private Rectangle _rectLeftBottomSelector;private Rectangle _rectLeftSelector;private Rectangle _rectLeftTopSelector;private Rectangle _rectRightBottomSelector;private Rectangle _rectRightSelector;private Rectangle _rectRightTopSelector;private Rectangle _rectTopSelector;private Container components;#region modify by anbyprivate float _ShapeExAngle; //控件的旋转角度private int _ShapeExIsFocus; //0表示没有获取焦点,1表示获取焦点#endregion#endregion#region 构造函数public ShapeEx(){// 该调用是 Windows.Forms 窗体设计器所必需的。 InitializeComponent();}#endregion#region 属性[DefaultValue("Black"), Description("边框颜色"), Category("Appearance")]public Color BorderColor{get{// Insert code here.return _BorderColor;}set{_BorderColor = value;Invalidate();}}[Description("控件ID号,自增长"), Category("Appearance")]public int ShapeExControlID { get; set; }[Description("用于连接外部控件ID"), Category("Appearance")]public int ShapeExJoinID { get; set; }[DefaultValue("Control"), Description("背景颜色"), Category("Appearance")]public override Color BackColor{get{// Insert code here.return _BackColor;}set{_BackColor = value;Invalidate();}}[DefaultValue(false), Description("运行中控件大小是否可拖拽编辑"), Category("Behavior")]public bool ReSizeble{get{// Insert code here.return _ReSizeble;}set{_ReSizeble = value;Invalidate();}}[Description("控件选择区域"), Category("Behavior")]public Rectangle SelectRectangle{get{var selectRectangler = new Rectangle();selectRectangler.X = Location.X + 7;selectRectangler.Y = Location.Y + 7;selectRectangler.Height = Height - 15;selectRectangler.Width = Width - 15;return selectRectangler;}}/// <summary>/// 是否被获取焦点/// </summary>[Description("控件是否获取焦点"), Category("Focus")]public int ShapeExIsFocus{get { return _ShapeExIsFocus; }set { _ShapeExIsFocus = value; }}[Description("控件旋转角度"), Category("Angle")]public float ShapeExAngle{get { return _ShapeExAngle; }set{_ShapeExAngle = value;this.Invalidate();this.Visible = false;this.Visible = true;}}//CreateParamsprotected override CreateParams CreateParams{get{CreateParams cp = base.CreateParams;cp.ExStyle |= 0x00000020;return cp;}}#endregion#region 私有方法private void DrawSelector(Graphics graphics,Rectangle rect,Point[] Points) {//graphics.TranslateTransform(Pcenter.X, Pcenter.Y);//graphics.RotateTransform(_ShapeExAngle);////恢复绘图平面在水平和垂直方向的平移 rPoints[0]//graphics.TranslateTransform(-Pcenter.X, -Pcenter.Y);var SelectorPen = new SolidBrush(Color.White);var borderPen = new Pen(_BorderColor, 1);try{//实心Point[] LeftPoints = RPoints(getPoint(rect.X - 7, Height / 2 - 3, 6, 6));graphics.FillClosedCurve(SelectorPen, LeftPoints);Point[] TopPoints = RPoints(getPoint(Width / 2 - 3, rect.Y - 7, 6, 6));graphics.FillClosedCurve(SelectorPen, TopPoints);Point[] RightPoints = RPoints(getPoint(rect.X + rect.Width, Height / 2 - 3, 6, 6));graphics.FillClosedCurve(SelectorPen, RightPoints);Point[] BottomPoints = RPoints(getPoint(Width / 2 - 3, rect.Y + rect.Height, 6, 6));graphics.FillClosedCurve(SelectorPen, BottomPoints);Point[] LeftTopPoints = RPoints(getPoint(rect.X - 7, rect.Y - 7, 6, 6));graphics.FillClosedCurve(SelectorPen, LeftTopPoints);Point[] RightTopPoints =RPoints(getPoint(rect.X + rect.Width, rect.Y - 7, 6, 6));graphics.FillClosedCurve(SelectorPen, RightTopPoints);Point[] RightBottomPoints = RPoints(getPoint(rect.X + rect.Width, rect.Y + rect.Height, 6, 6));graphics.FillClosedCurve(SelectorPen, RightBottomPoints);Point[] LeftBottomPoints = RPoints(getPoint(rect.X - 7, rect.Y + rect.Height, 6, 6));graphics.FillClosedCurve(SelectorPen, LeftBottomPoints);//边框_rectLeftSelector.X = rect.X-7;_rectLeftSelector.Y =Height/2-3;_rectLeftSelector.Height = 6;_rectLeftSelector.Width = 6;var leftRpoints = RPoints(getPoint(_rectLeftSelector.X, _rectLeftSelector.Y, 6, 6));graphics.DrawPolygon(borderPen, leftRpoints);_rectLeftSelector.X = leftRpoints[0].X;_rectLeftSelector.Y = leftRpoints[0].Y;//graphics.DrawRectangle(borderPen, _rectLeftSelector); _rectTopSelector.X = Width/2 - 3;_rectTopSelector.Y =rect.Y-7;_rectTopSelector.Height = 6;_rectTopSelector.Width = 6;var topRpoints = RPoints(getPoint(_rectTopSelector.X, _rectTopSelector.Y, 6, 6));graphics.DrawPolygon(borderPen, topRpoints);_rectTopSelector.X = topRpoints[0].X;_rectTopSelector.Y = topRpoints[0].Y;//graphics.DrawRectangle(borderPen, _rectTopSelector); _rectRightSelector.X = rect.X+rect.Width;_rectRightSelector.Y = Height/2-3;_rectRightSelector.Height = 6;_rectRightSelector.Width = 6;var rightRpoints = RPoints(getPoint(_rectRightSelector.X, _rectRightSelector.Y, 6, 6));graphics.DrawPolygon(borderPen, rightRpoints);_rectRightSelector.X = rightRpoints[0].X;_rectRightSelector.Y = rightRpoints[0].Y;//graphics.DrawRectangle(borderPen, _rectRightSelector); _rectBottomSelector.X = Width/2-3;_rectBottomSelector.Y = rect.Y+rect.Height;_rectBottomSelector.Height = 6;_rectBottomSelector.Width = 6;var bottomRpoints = RPoints(getPoint(_rectBottomSelector.X, _rectBottomSelector.Y, 6, 6));graphics.DrawPolygon(borderPen, bottomRpoints);_rectBottomSelector.X = bottomRpoints[0].X;_rectBottomSelector.Y = bottomRpoints[0].Y;////graphics.DrawRectangle(borderPen, _rectBottomSelector); _rectLeftTopSelector.X = rect.X-7;_rectLeftTopSelector.Y = rect.Y-7;_rectLeftTopSelector.Width = 6;_rectLeftTopSelector.Height = 6;var lefttopRpoints = RPoints(getPoint(_rectLeftTopSelector.X, _rectLeftTopSelector.Y, 6, 6));graphics.DrawPolygon(borderPen, lefttopRpoints);_rectLeftTopSelector.X = lefttopRpoints[0].X;_rectLeftTopSelector.Y = lefttopRpoints[0].Y;//graphics.DrawRectangle(borderPen, _rectLeftTopSelector); _rectRightTopSelector.X = rect.X+rect.Width;_rectRightTopSelector.Y = rect.Y-7;_rectRightTopSelector.Width = 6;_rectRightTopSelector.Height = 6;var righttopRpoints= RPoints(getPoint(_rectRightTopSelector.X, _rectRightTopSelector.Y, 6, 6));graphics.DrawPolygon(borderPen, righttopRpoints);_rectRightTopSelector.X = righttopRpoints[0].X;_rectRightTopSelector.Y = righttopRpoints[0].Y;//graphics.DrawRectangle(borderPen, _rectRightTopSelector); _rectRightBottomSelector.X = rect.X + rect.Width;_rectRightBottomSelector.Y = rect.Y+rect.Height;_rectRightBottomSelector.Width = 6;_rectRightBottomSelector.Height = 6;var rightbottomRpoints = RPoints(getPoint(_rectRightBottomSelector.X, _rectRightBottomSelector.Y, 6, 6));graphics.DrawPolygon(borderPen, rightbottomRpoints);_rectRightBottomSelector.X = rightbottomRpoints[0].X;_rectRightBottomSelector.Y = rightbottomRpoints[0].Y;//graphics.DrawRectangle(borderPen, _rectRightBottomSelector); _rectLeftBottomSelector.X = rect.X-7;_rectLeftBottomSelector.Y = rect.Y + rect.Height;_rectLeftBottomSelector.Width = 6;_rectLeftBottomSelector.Height = 6;var leftbottompointRPoints = RPoints(getPoint(_rectLeftBottomSelector.X, _rectLeftBottomSelector.Y, 6, 6));graphics.DrawPolygon(borderPen,leftbottompointRPoints);_rectLeftBottomSelector.X = leftbottompointRPoints[0].X;_rectLeftBottomSelector.Y = leftbottompointRPoints[0].Y;//graphics.DrawRectangle(borderPen, _rectLeftBottomSelector); }catch (Exception E){throw E;}finally{SelectorPen.Dispose();borderPen.Dispose();}}public PointF Pcenter = new PointF();public Point[] rPoints = null;private PointF center = new PointF();private void ReDrawControl(Graphics graphics){try{var borderPen = new Pen(_BorderColor, 1);//绘制边框 var rectBorder = new Rectangle();rectBorder.X = 7;rectBorder.Y = 7;rectBorder.Height = Height - 15;rectBorder.Width = Width - 15;center = new PointF(this.Width/2, this.Height/2);//算出要平移的坐标Point RationPoint = new Point((int)(center.X - rectBorder.Width / 2), (int)(center.Y - rectBorder.Height / 2));//要绘制的矩形var picRect = new RectangleF(RationPoint.X, RationPoint.Y, (float)rectBorder.Width, (float)rectBorder.Height);//圆心坐标Pcenter = new PointF(picRect.X + picRect.Width/2, picRect.Y + picRect.Height/2);#region 最后修改PointF leftToppoint = new PointF(picRect.X,picRect.Y);PointF leftBottompoint = new PointF(picRect.X, (picRect.Y + picRect.Height));PointF rightToppoint = new PointF((picRect.X + picRect.Width), picRect.Y);PointF rightBottompoint = new PointF((picRect.X + picRect.Width), (picRect.Y + picRect.Height));rPoints = RPoints(Point.Ceiling(leftToppoint),Point.Ceiling(rightToppoint), Point.Ceiling(rightBottompoint), Point.Ceiling(leftBottompoint));RectangleF controlRect = new RectangleF(this.Location.X, this.Location.Y, this.Width, this.Height);getNewRectangle(rPoints);graphics.DrawPolygon(borderPen, rPoints);#endregion#region 旋转内,但是无法获取旋转后的坐标,程序失控// //绘图平面以图片的中心点旋转//graphics.TranslateTransform(Pcenter.X, Pcenter.Y);//graphics.RotateTransform(_ShapeExAngle);////恢复绘图平面在水平和垂直方向的平移//graphics.TranslateTransform(-Pcenter.X, -Pcenter.Y);//绘制图片//graphics.DrawRectangle(borderPen, Rectangle.Ceiling(picRect));//重置绘图平面的所有变换//graphics.ResetTransform();#endregion#region 图片旋转 图片超出边界////圆心坐标//var center = new PointF(rectBorder.Width/2, rectBorder.Height/2);////矩形左上坐标//float offsetX = 0;//float offsetY = 0;//offsetX = center.X - rectBorder.Width/2;//offsetY = center.Y - rectBorder.Height/2;////要画的图//var picRect = new RectangleF(offsetX, offsetY, rectBorder.Width, rectBorder.Height);//var Pcenter = new PointF(picRect.X + picRect.Width/2, picRect.Y + picRect.Height/2);////让图片绕中心旋转一周////for (int i = 0; i < 361; i += 10) ////{//var changeRect = new Rectangle((int) picRect.X, (int) picRect.Y, (int) picRect.Width,// (int) picRect.Height);////绘图平面以图片的中心点旋转//graphics.TranslateTransform(Pcenter.X, Pcenter.Y);//graphics.RotateTransform(_ShapeExAngle);////恢复绘图平面在水平和垂直方向的平移//graphics.TranslateTransform(-Pcenter.X, -Pcenter.Y);////绘制图片并延时//graphics.DrawRectangle(borderPen, changeRect);////重置绘图平面的所有变换//graphics.ResetTransform();////}#endregion//绘制编辑框if (_ReSizeble){DrawSelector(graphics,Rectangle.Ceiling(picRect),rPoints);}}catch (Exception E){throw E;}finally{graphics.Dispose();}}/// <summary>/// 根据数组坐标获取新的矩形/// </summary>/// <param name="rPoints"></param>private void getNewRectangle(Point[] rPoints){try{int maxCoorX = getPointCoorX(rPoints, true);int minCoorX = getPointCoorX(rPoints, false);int maxCoorY = getPointCoorY(rPoints, true);int minCoorY = getPointCoorY(rPoints, false);//获得width和heightdouble width = Math.Sqrt(maxCoorX*maxCoorX + minCoorX*minCoorX);double height = Math.Sqrt(maxCoorY*maxCoorY + minCoorY*minCoorY);_SelfWidth = (int) width;_SelfHeight = (int) height;}catch (Exception){}}private PointF[] getPointF(int x, int y, int Width, int Height){var point1 = new PointF(x, y);var point2 = new PointF(x + Width, y);var point3 = new PointF(x + Width, y + Height);var point4 = new PointF(x, y + Height);PointF[] points = {point1, point2, point3, point4};return points;}private Point[] getPoint(int x, int y, int Width, int Height){ var point1 = new Point(x, y);var point2 = new Point(x + Width, y);var point3 = new Point(x + Width, y + Height);var point4 = new Point(x, y + Height);Point[] points = { point1, point2, point3, point4 };return points;}protected override void Dispose(bool disposing){if (disposing){if (components != null)components.Dispose();}base.Dispose(disposing);}#endregion#region 组件设计器生成的代码private void InitializeComponent(){components = new Container();Resize += ShapeEx_Resize;MouseDown += ShapeEx_MouseDown;MouseMove += ShapeEx_MouseMove;MouseLeave += ShapeEx_MouseLeave;MouseUp += ShapeEx_MouseUp;//this.GotFocus += new EventHandler(ShapeEx_GotFocus);//this.LostFocus += new EventHandler(ShapeEx_LostFocus); _ShapeExAngle = 30;_BorderColor = Color.Black;_BackColor = Color.FromName("Control");_ReSizeble = false;_SelectSelctedIndex = -1;SetStyle(ControlStyles.SupportsTransparentBackColor| ControlStyles.UserPaint| ControlStyles.AllPaintingInWmPaint| ControlStyles.Opaque, true);BackColor = Color.Transparent;}#endregion#region 事件protected override void OnPaint(PaintEventArgs pe){base.OnPaint(pe);ReDrawControl(pe.Graphics);}private void ShapeEx_Resize(object sender, EventArgs e){if (Width < 16 || Height < 16){Width = 16;Height = 16;}Invalidate();}private void ShapeEx_MouseDown(object sender, MouseEventArgs e){_ShapeExIsFocus = 1;if (_ReSizeble){if (_rectLeftSelector.Contains(e.X, e.Y) ||_rectRightSelector.Contains(e.X, e.Y) ||_rectTopSelector.Contains(e.X, e.Y) ||_rectBottomSelector.Contains(e.X, e.Y) ||_rectLeftTopSelector.Contains(e.X, e.Y) ||_rectRightTopSelector.Contains(e.X, e.Y) ||_rectRightBottomSelector.Contains(e.X, e.Y) ||_rectLeftBottomSelector.Contains(e.X, e.Y)){if (_rectLeftTopSelector.Contains(e.X, e.Y)){Cursor = Cursors.SizeNWSE;_SelectSelctedIndex = 1;}if (_rectTopSelector.Contains(e.X, e.Y)){Cursor = Cursors.SizeNS;_SelectSelctedIndex = 2;}if (_rectRightTopSelector.Contains(e.X, e.Y)){Cursor = Cursors.SizeNESW;_SelectSelctedIndex = 3;}if (_rectRightSelector.Contains(e.X, e.Y)){Cursor = Cursors.SizeWE;_SelectSelctedIndex = 4;}if (_rectRightBottomSelector.Contains(e.X, e.Y)){Cursor = Cursors.SizeNWSE;_SelectSelctedIndex = 5;}if (_rectBottomSelector.Contains(e.X, e.Y)){Cursor = Cursors.SizeNS;_SelectSelctedIndex = 6;}if (_rectLeftBottomSelector.Contains(e.X, e.Y)){Cursor = Cursors.SizeNESW;_SelectSelctedIndex = 7;}if (_rectLeftSelector.Contains(e.X, e.Y)){Cursor = Cursors.SizeWE;_SelectSelctedIndex = 8;}}else{Cursor = Cursors.SizeAll;_SelectSelctedIndex = 0;}_SelfLocation.X = Location.X;_SelfLocation.Y = Location.Y;_MouseLocation.X = Cursor.Position.X;_MouseLocation.Y = Cursor.Position.Y;_SelfWidth = Width;_SelfHeight = Height;}}private void ShapeEx_MouseMove(object sender, MouseEventArgs e){//move and resizeswitch (_SelectSelctedIndex){case 0:Location = new Point(Cursor.Position.X - (_MouseLocation.X - _SelfLocation.X),Cursor.Position.Y - (_MouseLocation.Y - _SelfLocation.Y));break;case 1:Height = _SelfHeight - (Cursor.Position.Y - _MouseLocation.Y);Width = _SelfWidth - (Cursor.Position.X - _MouseLocation.X);Location = new Point(Cursor.Position.X - _MouseLocation.X + _SelfLocation.X,Cursor.Position.Y - _MouseLocation.Y + _SelfLocation.Y);break;case 2:Height = _SelfHeight - (Cursor.Position.Y - _MouseLocation.Y);Location = new Point(_SelfLocation.X, Cursor.Position.Y - _MouseLocation.Y + _SelfLocation.Y);break;case 3:Height = _SelfHeight - (Cursor.Position.Y - _MouseLocation.Y);Width = _SelfWidth + (Cursor.Position.X - _MouseLocation.X);Location = new Point(_SelfLocation.X, Cursor.Position.Y - (_MouseLocation.Y - _SelfLocation.Y));break;case 4:Width = _SelfWidth + (Cursor.Position.X - _MouseLocation.X);break;case 5:Height = _SelfHeight + (Cursor.Position.Y - _MouseLocation.Y);Width = _SelfWidth + (Cursor.Position.X - _MouseLocation.X);break;case 6:Height = _SelfHeight + (Cursor.Position.Y - _MouseLocation.Y);break;case 7:Height = _SelfHeight + (Cursor.Position.Y - _MouseLocation.Y);Width = _SelfWidth - (Cursor.Position.X - _MouseLocation.X);Location = new Point(Cursor.Position.X - _MouseLocation.X + _SelfLocation.X, _SelfLocation.Y);break;case 8:Width = _SelfWidth - (Cursor.Position.X - _MouseLocation.X);Location = new Point(Cursor.Position.X - _MouseLocation.X + _SelfLocation.X, _SelfLocation.Y);break;}Invalidate();}private void ShapeEx_MouseLeave(object sender, EventArgs e){Cursor = Cursors.Default;_SelectSelctedIndex = -1;}private void ShapeEx_MouseUp(object sender, MouseEventArgs e){_ShapeExIsFocus = 0;Cursor = Cursors.Default;_SelectSelctedIndex = -1;}/// <summary>/// 用于减少画面闪烁效果及刷新控件/// </summary>/// <param name="e"></param>protected override void OnLocationChanged(EventArgs e){Visible = false;Visible = true;}#endregion/// <summary> /// 对一个坐标点按照一个中心进行旋转 /// </summary> /// <param name="center">中心点</param> /// <param name="p1">要旋转的点</param> /// <param name="angle">旋转角度,笛卡尔直角坐标</param> /// <returns></returns> private Point PointRotate(Point center, Point p1, double angle){Point tmp = new Point();double angleHude = angle * Math.PI / 180;/*角度变成弧度*/double x1 = (p1.X - center.X) * Math.Cos(angleHude) + (p1.Y - center.Y) * Math.Sin(angleHude) + center.X;double y1 = -(p1.X - center.X) * Math.Sin(angleHude) + (p1.Y - center.Y) * Math.Cos(angleHude) + center.Y;tmp.X = (int)x1;tmp.Y = (int)y1;return tmp;}/// <summary>/// 根据rectangle的4个顶点获取旋转后的坐标/// </summary>/// <param name="leftToppoint">左上角坐标</param>/// <param name="leftBottompoint">左下脚坐标</param>/// <param name="rightToppoint">右上角坐标</param>/// <param name="rightBottompoint">右下角坐标</param>/// <returns>旋转后的4点坐标</returns>private Point[] RPoints(Point leftToppoint, Point rightToppoint, Point rightBottompoint, Point leftBottompoint){//旋转后的点Point rationleftToppoint = PointRotate(Point.Ceiling(Pcenter), leftToppoint, _ShapeExAngle);Point rationleftBottompoint = PointRotate(Point.Ceiling(Pcenter), leftBottompoint, _ShapeExAngle);Point rationrightToppoint = PointRotate(Point.Ceiling(Pcenter), rightToppoint, _ShapeExAngle);Point rationrightBottompoint = PointRotate(Point.Ceiling(Pcenter), rightBottompoint, _ShapeExAngle);Point[] rPoints ={rationleftToppoint, rationrightToppoint, rationrightBottompoint, rationleftBottompoint};return rPoints;}/// <summary>/// 根据rectangle的4个顶点获取旋转后的坐标/// </summary>/// <param name="points">左上角坐标,左下脚坐标,右上角坐标,右下角坐标 </param>/// <returns>旋转后的4点坐标</returns>private Point[] RPoints(Point[] points){//旋转后的点 Point rationleftToppoint = PointRotate(Point.Ceiling(Pcenter), points[0], _ShapeExAngle);Point rationrightToppoint = PointRotate(Point.Ceiling(Pcenter), points[1], _ShapeExAngle);Point rationrightBottompoint = PointRotate(Point.Ceiling(Pcenter), points[2], _ShapeExAngle);Point rationleftBottompoint = PointRotate(Point.Ceiling(Pcenter), points[3], _ShapeExAngle);Point[] rPoints ={rationleftToppoint, rationrightToppoint, rationrightBottompoint, rationleftBottompoint};return rPoints;}private int getPointCoorX (Point[] arr,bool isMax){if (arr == null){throw new Exception();}int max = 0;int[] myarr = new int[5];for (int i = 0; i < arr.Length - 1; i++){myarr[i] = arr[i].X;}Array.Sort(myarr);if (isMax){return myarr[myarr.Length - 1];}else{return myarr[0];}}private int getPointCoorY(Point[] arr,bool isMax){if (arr == null){throw new Exception();}int max = 0;int[] myarr = new int[5];for (int i = 0; i < arr.Length - 1; i++){myarr[i] = arr[i].Y;}Array.Sort(myarr);if (isMax){return myarr[myarr.Length - 1];}else{return myarr[0];}}}}