PropertyGrid—为复杂属性提供下拉式编辑框和弹出式编辑框

零.引言

  PropertyGrid中我们经常看到一些下拉式的编辑方式(Color属性)和弹出式编辑框(字体),这些都是为一些复杂的属性提供的编辑方式,本文主要说明如何实现这样的编辑方式。

一.为属性提供编辑类

  弹出式和下拉式是如何实现的呢,这需要为属性提供一个专门的编辑类。.Net为我们提供了一个System.Drawing.Design.UITypeEditor类,它是所有编辑类的基类,从他继承出了诸如ColorEditor、FontEditor的类,因此我们可以在属性框中编辑颜色和字体。定义了这样的类,我们也可以为自己的属性实现弹出式和下拉式编辑方式。

  先看一下MSDN中对UITypeEditor的介绍:提供可用于设计值编辑器的基类,这些编辑器可提供用户界面 (UI),用来表示和编辑所支持的数据类型的对象值。

  UITypeEditor 类提供一种基类,可以从该基类派生和进行扩展,以便为设计时环境实现自定义类型编辑器。通常,您的自定义类型编辑器与 PropertyGrid 控件进行交互。在文本框值编辑器不足以有效地选择某些类型的值的情况下,自定义类型编辑器非常有用。

  继承者说明:

  若要实现自定义设计时 UI 类型编辑器,必须执行下列步骤:

  • 定义一个从 UITypeEditor 派生的类。
  • 重写 EditValue 方法以处理用户界面、用户输入操作以及值的分配。
  • 重写 GetEditStyle 方法,以便将编辑器将使用的编辑器样式的类型通知给“属性”窗口。

  通过执行下列步骤,可以为在“属性”窗口中绘制值的表示形式添加附加支持:

  • 重写 GetPaintValueSupported 方法以指示编辑器支持显示值的表示形式。
  • 重写 PaintValue 方法以实现该值的表示形式的显示。
  • 如果编辑器应具有初始化行为,则重写 UITypeEditor 构造函数方法。

二.下拉式编辑方式

  接下来我们来实现下拉式编辑方式,接下来举一个具体的例子来说明。

  首先假如我们有一个控件类MyControl:

  
 1 public class MyControl : System.Windows.Forms.UserControl
 2 {
 3         private double _angle;
 4 
 5         [BrowsableAttribute(true)]
 6         public double Angle
 7         {
 8             get
 9             { return _angle; }
10             set
11             { _angle = value; }
12         }
13 
14         public MyControl()
15         {
16             this._angle = 90;
17         }
18 
19         protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
20         {
21             e.Graphics.DrawString("The Angle is " + _angle, this.Font, Brushes.Red,0,0);
22         }
23 }
View Code

  其中有个属性Angle,我们要为其提供下拉式和弹出式编辑方式,当然了,一般都是较为复杂的属性才需要,这里只是为了举例说明。

  我们为其设计一个编辑类AngleEditor,在第二节中,继承说明中的第一条和第二条,EditValue和GetEditStyle两个函数,这是必须要重写的:

  
  1 [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
  2     public class AngleEditor : System.Drawing.Design.UITypeEditor
  3 {
  4         public AngleEditor()
  5         {
  6         }
  7         //下拉式还是弹出式
  8         public override System.Drawing.Design.UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
  9         {
 10             return UITypeEditorEditStyle.DropDown;
 11         }
 12 
 13         // 为属性显示UI编辑框
 14         public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, System.IServiceProvider provider, object value)
 15         {
 16             //值类型不为double,直接返回value
 17             if (value.GetType() != typeof(double))
 18                 return value;
 19 
 20             //值为double,显示下拉式或弹出编辑框
 21             IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
 22             if (edSvc != null)
 23             {
 24                 // 显示编辑框并初始化编辑框的值
 25                 AngleControl angleControl = new AngleControl((double)value);
 26                 edSvc.DropDownControl(angleControl);
 27                 // 返回编辑框中编辑的值.
 28                 if (value.GetType() == typeof(double))
 29                     return angleControl.angle;
 30             }
 31             return value;
 32         }
 33 
 34         //下面两个函数是为了在PropertyGrid中显示一个辅助的效果
 35         //可以不用重写
 36         public override void PaintValue(System.Drawing.Design.PaintValueEventArgs e)
 37         {
 38             int normalX = (e.Bounds.Width / 2);
 39             int normalY = (e.Bounds.Height / 2);
 40 
 41             e.Graphics.FillRectangle(new SolidBrush(Color.DarkBlue), e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height);
 42             e.Graphics.FillEllipse(new SolidBrush(Color.White), e.Bounds.X + 1, e.Bounds.Y + 1, e.Bounds.Width - 3, e.Bounds.Height - 3);
 43             e.Graphics.FillEllipse(new SolidBrush(Color.SlateGray), normalX + e.Bounds.X - 1, normalY + e.Bounds.Y - 1, 3, 3);
 44 
 45             double radians = ((double)e.Value * Math.PI) / (double)180;
 46             e.Graphics.DrawLine(new Pen(new SolidBrush(Color.Red), 1), normalX + e.Bounds.X, normalY + e.Bounds.Y,
 47                 e.Bounds.X + (normalX + (int)((double)normalX * Math.Cos(radians))),
 48                 e.Bounds.Y + (normalY + (int)((double)normalY * Math.Sin(radians))));
 49         }
 50 
 51         public override bool GetPaintValueSupported(System.ComponentModel.ITypeDescriptorContext context)
 52         {
 53             return true;
 54         }
 55     }
 56 
 57     // 这里是我们要显示出来的编辑器,把它作为一个内置类
 58     //从UserControl继承,要在上面EditValue函数中使用的
 59     internal class AngleControl : System.Windows.Forms.UserControl
 60     {
 61         public double angle; //编辑的角度
 62         private float x;     //鼠标位置
 63         private float y;
 64 
 65         public AngleControl(double initial_angle)
 66         {
 67             this.angle = initial_angle;
 68         }
 69         //显现时,显示属性的当前值
 70         protected override void OnLoad(EventArgs e)
 71         {
 72             int originX = (this.Width / 2);
 73             int originY = (this.Height / 2);
 74             this.x = (float)(50 * Math.Cos(this.angle * Math.PI / 180) + originX);
 75             this.y = (float)(50 * Math.Sin(this.angle * Math.PI / 180) + originY);
 76             base.OnLoad(e);
 77         }
 78 
 79         //绘制控件,用来显示编辑角度
 80         protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
 81         {
 82             int originX = (this.Width / 2);
 83             int originY = (this.Height / 2);
 84 
 85             e.Graphics.DrawEllipse(Pens.Black, originX - 50, originY - 50, 100, 100);
 86             e.Graphics.DrawLine(Pens.Black, originX, originY, x, y);
 87 
 88             e.Graphics.DrawString("Angle:" + this.angle, this.Font, Brushes.Red, 0, 0);
 89         }
 90         //鼠标移动时设置角度
 91         protected override void OnMouseMove(System.Windows.Forms.MouseEventArgs e)
 92         {
 93             if (e.Button == MouseButtons.Left)
 94             {
 95                 int originX = (this.Width / 2);
 96                 int originY = (this.Height / 2);
 97                 double len = Math.Sqrt(Math.Pow(e.X - originX, 2) + Math.Pow(e.Y - originY, 2));
 98                 double h = e.Y - originY;
 99                 this.angle = Math.Asin(h / len);
100                 if ((e.X >= originX && e.Y >= originY))
101                 {
102                     this.x = (float)(50 * Math.Cos(this.angle) + originX);
103                     this.y = (float)(50 * Math.Sin(this.angle) + originY);
104                     this.angle = this.angle * 180 / Math.PI;
105                 }
106                 else if (e.X < originX && e.Y > originY)
107                 {
108                     this.x = (float)(originX - 50 * Math.Cos(this.angle));
109                     this.y = (float)(50 * Math.Sin(this.angle) + originY);
110                     this.angle = 180 - this.angle * 180 / Math.PI;
111                 }
112                 else if (e.X < originX && e.Y < originY)
113                 {
114                     this.x = (float)(originX - 50 * Math.Cos(this.angle));
115                     this.y = (float)(originY + 50 * Math.Sin(this.angle));
116                     this.angle = 180 - this.angle * 180 / Math.PI;
117                 }
118                 else if (e.X >= originX && e.Y <= originY)
119                 {
120                     this.x = (float)(originX + 50 * Math.Cos(this.angle));
121                     this.y = (float)(originY + 50 * Math.Sin(this.angle));
122                     this.angle = 360 + this.angle * 180 / Math.PI;
123                 }
124                 this.Invalidate();
125             }
126           
127         }
128       
129 }
View Code

  这里有两个类,一个是AngleEditor,他就是我们要用于到属性特性中的编辑类,一个是AngleControl,他是辅助AngleEditor来编辑属性的,也就是说,他就是一个form,当我们编辑属性时,他会显现出来,供我们编辑属性值,可以是textBox,图形,表格,各种方式,只需要最后他返回编辑好的属性值给AngleEditor类。在AngleEditor类中的EditValue函数中,我们会调用AngleControl类,并接受它返回的值。

  设计好编辑类后,把它应用到MyControl类中的Angle属性中,在Angle属性中增加特性[EditorAttribute(typeof(AngleEditor), typeof(System.Drawing.Design.UITypeEditor))],相当于告诉PropertyGrid我们要用AngleEditor来编辑这个属性。

  
1         [BrowsableAttribute(true)]
2         [EditorAttribute(typeof(AngleEditor), typeof(System.Drawing.Design.UITypeEditor))]
3         public double Angle
4         {
5             get
6             { return _angle; }
7             set
8             { _angle = value; }
9         }
View Code

  好了,现在就可以使用下拉框来编辑我们的Angle属性了,效果如下:

  

  上面那个圆圈就是我们用来编辑角度的。

三.弹出式编辑方式

  实现了下拉式,我们来实现弹出式,弹出式和下拉式非常的相像,现在要弹出一个编辑框,因此我们的AngleControl类不能从UserControl继承,而从From继承,让他成为一个对话框,在AngleEditor的EditValue函数中,弹出他并接受返回值,如下:

  
  1 [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
  2     public class AngleEditor : System.Drawing.Design.UITypeEditor
  3 {
  4         public AngleEditor()
  5         {
  6         }
  7         //下拉式还是弹出式
  8         public override System.Drawing.Design.UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
  9         {
 10             return UITypeEditorEditStyle.Modal;//弹出式
 11         }
 12 
 13         // 为属性显示UI编辑框
 14         public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, System.IServiceProvider provider, object value)
 15         {
 16             //值类型不为double,直接返回value
 17             if (value.GetType() != typeof(double))
 18                 return value;
 19 
 20             //值为double,显示下拉式或弹出编辑框
 21             IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
 22             if (edSvc != null)
 23             {
 24                 // 显示编辑框并初始化编辑框的值
 25                 AngleControl2 angleControl = new AngleControl2((double)value);
 26                 edSvc.ShowDialog(angleControl);                
 27 // 返回编辑框中编辑的值.
 28                 if (value.GetType() == typeof(double))
 29                     return angleControl.angle;
 30             }
 31             return value;
 32         }
 33 
 34         //下面两个函数是为了在PropertyGrid中显示一个辅助的效果
 35         //可以不用重写
 36         public override void PaintValue(System.Drawing.Design.PaintValueEventArgs e)
 37         {
 38             int normalX = (e.Bounds.Width / 2);
 39             int normalY = (e.Bounds.Height / 2);
 40 
 41             e.Graphics.FillRectangle(new SolidBrush(Color.DarkBlue), e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height);
 42             e.Graphics.FillEllipse(new SolidBrush(Color.White), e.Bounds.X + 1, e.Bounds.Y + 1, e.Bounds.Width - 3, e.Bounds.Height - 3);
 43             e.Graphics.FillEllipse(new SolidBrush(Color.SlateGray), normalX + e.Bounds.X - 1, normalY + e.Bounds.Y - 1, 3, 3);
 44 
 45             double radians = ((double)e.Value * Math.PI) / (double)180;
 46             e.Graphics.DrawLine(new Pen(new SolidBrush(Color.Red), 1), normalX + e.Bounds.X, normalY + e.Bounds.Y,
 47                 e.Bounds.X + (normalX + (int)((double)normalX * Math.Cos(radians))),
 48                 e.Bounds.Y + (normalY + (int)((double)normalY * Math.Sin(radians))));
 49         }
 50 
 51         public override bool GetPaintValueSupported(System.ComponentModel.ITypeDescriptorContext context)
 52         {
 53             return true;
 54         }
 55     }
 56 
 57     // 这里是我们要显示出来的编辑器,把它作为一个内置类
 58     //从UserControl继承,要在上面EditValue函数中使用的
 59     internal class AngleControl2 : System.Windows.Forms.Form
 60     {
 61         public double angle; //编辑的角度
 62         private float x;     //鼠标位置
 63         private float y;
 64 
 65         public AngleControl(double initial_angle)
 66         {
 67             this.angle = initial_angle;
 68         }
 69         //显现时,显示属性的当前值
 70         protected override void OnLoad(EventArgs e)
 71         {
 72             int originX = (this.Width / 2);
 73             int originY = (this.Height / 2);
 74             this.x = (float)(50 * Math.Cos(this.angle * Math.PI / 180) + originX);
 75             this.y = (float)(50 * Math.Sin(this.angle * Math.PI / 180) + originY);
 76             base.OnLoad(e);
 77         }
 78 
 79         //绘制控件,用来显示编辑角度
 80         protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
 81         {
 82             int originX = (this.Width / 2);
 83             int originY = (this.Height / 2);
 84 
 85             e.Graphics.DrawEllipse(Pens.Black, originX - 50, originY - 50, 100, 100);
 86             e.Graphics.DrawLine(Pens.Black, originX, originY, x, y);
 87 
 88             e.Graphics.DrawString("Angle:" + this.angle, this.Font, Brushes.Red, 0, 0);
 89         }
 90         //鼠标移动时设置角度
 91         protected override void OnMouseMove(System.Windows.Forms.MouseEventArgs e)
 92         {
 93             if (e.Button == MouseButtons.Left)
 94             {
 95                 int originX = (this.Width / 2);
 96                 int originY = (this.Height / 2);
 97                 double len = Math.Sqrt(Math.Pow(e.X - originX, 2) + Math.Pow(e.Y - originY, 2));
 98                 double h = e.Y - originY;
 99                 this.angle = Math.Asin(h / len);
100                 if ((e.X >= originX && e.Y >= originY))
101                 {
102                     this.x = (float)(50 * Math.Cos(this.angle) + originX);
103                     this.y = (float)(50 * Math.Sin(this.angle) + originY);
104                     this.angle = this.angle * 180 / Math.PI;
105                 }
106                 else if (e.X < originX && e.Y > originY)
107                 {
108                     this.x = (float)(originX - 50 * Math.Cos(this.angle));
109                     this.y = (float)(50 * Math.Sin(this.angle) + originY);
110                     this.angle = 180 - this.angle * 180 / Math.PI;
111                 }
112                 else if (e.X < originX && e.Y < originY)
113                 {
114                     this.x = (float)(originX - 50 * Math.Cos(this.angle));
115                     this.y = (float)(originY + 50 * Math.Sin(this.angle));
116                     this.angle = 180 - this.angle * 180 / Math.PI;
117                 }
118                 else if (e.X >= originX && e.Y <= originY)
119                 {
120                     this.x = (float)(originX + 50 * Math.Cos(this.angle));
121                     this.y = (float)(originY + 50 * Math.Sin(this.angle));
122                     this.angle = 360 + this.angle * 180 / Math.PI;
123                 }
124                 this.Invalidate();
125             }
126           
127         }
128       
129 }
View Code

  可以看到,只修改了三个地方:

  1. AngleEditor类中GetEditStyle函数返回Modal,表明是以弹出式编辑。
  2. AngleEditor类中EditValue函数中调用编辑控件的方式:

    AngleControl2 angleControl = new AngleControl2((double)value);

    edSvc.ShowDialog(angleControl);

  3.AngleControl2从Form继承,让他显示为对话框,这里为了区别上面的AngleControl类,将其改成了AngleControl2。

  现在看看效果:

  

  实现了弹出式的编辑方式。

四.完整代码

  下面是完整的代码:

  
  1 using System;
  2 using System.ComponentModel;
  3 using System.Drawing;
  4 using System.Drawing.Design;
  5 using System.Windows.Forms;
  6 using System.Windows.Forms.Design;
  7 
  8 namespace TestUITypeEditor
  9 {
 10     //编辑器类
 11  [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
 12     public class AngleEditor : System.Drawing.Design.UITypeEditor
 13     {
 14         public AngleEditor()
 15         {
 16         }
 17 
 18         //下拉式还是弹出式
 19         public override System.Drawing.Design.UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
 20         {
 21             return UITypeEditorEditStyle.DropDown;
 22             //return UITypeEditorEditStyle.Modal;
 23         }
 24 
 25         //编辑属性值
 26         public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, System.IServiceProvider provider, object value)
 27         {
 28             if (value.GetType() != typeof(double))
 29                 return value;
 30 
 31             //显示编辑框
 32             IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
 33             if (edSvc != null)
 34             {
 35                 AngleControl angleControl = new AngleControl((double)value);
 36                 edSvc.DropDownControl(angleControl);
 37                 //AngleControl2 angleControl = new AngleControl2((double)value);
 38                 //edSvc.ShowDialog(angleControl);
 39 
 40                 // 获取返回值
 41                 if (value.GetType() == typeof(double))
 42                     return angleControl.angle;
 43             }
 44             return value;
 45         }
 46 
 47         //绘制辅助属性显示
 48         public override void PaintValue(System.Drawing.Design.PaintValueEventArgs e)
 49         {
 50             int normalX = (e.Bounds.Width / 2);
 51             int normalY = (e.Bounds.Height / 2);
 52 
 53             e.Graphics.FillRectangle(new SolidBrush(Color.DarkBlue), e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height);
 54             e.Graphics.FillEllipse(new SolidBrush(Color.White), e.Bounds.X + 1, e.Bounds.Y + 1, e.Bounds.Width - 3, e.Bounds.Height - 3);
 55             e.Graphics.FillEllipse(new SolidBrush(Color.SlateGray), normalX + e.Bounds.X - 1, normalY + e.Bounds.Y - 1, 3, 3);
 56 
 57             double radians = ((double)e.Value * Math.PI) / (double)180;
 58             e.Graphics.DrawLine(new Pen(new SolidBrush(Color.Red), 1), normalX + e.Bounds.X, normalY + e.Bounds.Y,
 59                 e.Bounds.X + (normalX + (int)((double)normalX * Math.Cos(radians))),
 60                 e.Bounds.Y + (normalY + (int)((double)normalY * Math.Sin(radians))));
 61         }
 62 
 63         //使用辅助属性显示
 64         public override bool GetPaintValueSupported(System.ComponentModel.ITypeDescriptorContext context)
 65         {
 66             return true;
 67         }
 68     }
 69 
 70     // 下拉式编辑方式
 71     internal class AngleControl : System.Windows.Forms.UserControl
 72     {
 73         public double angle;
 74         private float x;
 75         private float y;
 76 
 77         public AngleControl(double initial_angle)
 78         {
 79             this.angle = initial_angle;
 80         }
 81 
 82         protected override void OnLoad(EventArgs e)
 83         {
 84             int originX = (this.Width / 2);
 85             int originY = (this.Height / 2);
 86 
 87             this.x = (float)(50 * Math.Cos(this.angle * Math.PI / 180) + originX);
 88             this.y = (float)(50 * Math.Sin(this.angle * Math.PI / 180) + originY);
 89 
 90             base.OnLoad(e);
 91         }
 92 
 93         protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
 94         {
 95             int originX = (this.Width / 2);
 96             int originY = (this.Height / 2);
 97 
 98             e.Graphics.DrawEllipse(Pens.Black, originX - 50, originY - 50, 100, 100);
 99             e.Graphics.DrawLine(Pens.Black, originX, originY, x, y);
100 
101             e.Graphics.DrawString("Angle:" + this.angle, this.Font, Brushes.Red, 0, 0);
102         }
103 
104         protected override void OnMouseMove(System.Windows.Forms.MouseEventArgs e)
105         {   
106             if (e.Button == MouseButtons.Left)
107             {
108                 int originX = (this.Width / 2);
109                 int originY = (this.Height / 2);
110                 double len = Math.Sqrt(Math.Pow(e.X - originX, 2) + Math.Pow(e.Y - originY, 2));
111                 double h = e.Y - originY;
112                 this.angle = Math.Asin(h / len);
113                 if ((e.X >= originX && e.Y >= originY))
114                 {
115                     this.x = (float)(50 * Math.Cos(this.angle) + originX);
116                     this.y = (float)(50 * Math.Sin(this.angle) + originY);
117 
118                     this.angle = this.angle * 180 / Math.PI;
119                 }
120                 else if (e.X < originX && e.Y > originY)
121                 {
122                     this.x = (float)(originX - 50 * Math.Cos(this.angle));
123                     this.y = (float)(50 * Math.Sin(this.angle) + originY);
124 
125                     this.angle = 180 - this.angle * 180 / Math.PI;
126                 }
127                 else if (e.X < originX && e.Y < originY)
128                 {
129                     this.x = (float)(originX - 50 * Math.Cos(this.angle));
130                     this.y = (float)(originY + 50 * Math.Sin(this.angle));
131 
132                     this.angle = 180 - this.angle * 180 / Math.PI;
133                 }
134                 else if (e.X >= originX && e.Y <= originY)
135                 {
136                     this.x = (float)(originX + 50 * Math.Cos(this.angle));
137                     this.y = (float)(originY + 50 * Math.Sin(this.angle));
138 
139                     this.angle = 360 + this.angle * 180 / Math.PI;
140                 }
141 
142                 this.Invalidate();
143             }
144         } 
145     }
146 
147 
148     //弹出式编辑框
149     internal class AngleControl2 : System.Windows.Forms.Form
150     {
151         public double angle;
152         private float x;
153         private float y;
154 
155         public AngleControl2(double initial_angle)
156         {
157             this.angle = initial_angle;
158         }
159 
160         protected override void OnLoad(EventArgs e)
161         {
162             int originX = (this.Width / 2);
163             int originY = (this.Height / 2);
164 
165             this.x = (float)(50 * Math.Cos(this.angle * Math.PI / 180) + originX);
166             this.y = (float)(50 * Math.Sin(this.angle * Math.PI / 180) + originY);
167 
168             base.OnLoad(e);
169         }
170 
171         protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
172         {
173             int originX = (this.Width / 2);
174             int originY = (this.Height / 2);
175 
176             e.Graphics.DrawEllipse(Pens.Black, originX - 50, originY - 50, 100, 100);
177             e.Graphics.DrawLine(Pens.Black, originX, originY, x, y);
178 
179             e.Graphics.DrawString("Angle:" + this.angle, this.Font, Brushes.Red, 0, 0);
180         }
181 
182         protected override void OnMouseMove(System.Windows.Forms.MouseEventArgs e)
183         {
184             if (e.Button == MouseButtons.Left)
185             {
186                 int originX = (this.Width / 2);
187                 int originY = (this.Height / 2);
188                 double len = Math.Sqrt(Math.Pow(e.X - originX, 2) + Math.Pow(e.Y - originY, 2));
189                 double h = e.Y - originY;
190                 this.angle = Math.Asin(h / len);
191                 if ((e.X >= originX && e.Y >= originY))
192                 {
193                     this.x = (float)(50 * Math.Cos(this.angle) + originX);
194                     this.y = (float)(50 * Math.Sin(this.angle) + originY);
195 
196                     this.angle = this.angle * 180 / Math.PI;
197                 }
198                 else if (e.X < originX && e.Y > originY)
199                 {
200                     this.x = (float)(originX - 50 * Math.Cos(this.angle));
201                     this.y = (float)(50 * Math.Sin(this.angle) + originY);
202 
203                     this.angle = 180 - this.angle * 180 / Math.PI;
204                 }
205                 else if (e.X < originX && e.Y < originY)
206                 {
207                     this.x = (float)(originX - 50 * Math.Cos(this.angle));
208                     this.y = (float)(originY + 50 * Math.Sin(this.angle));
209 
210                     this.angle = 180 - this.angle * 180 / Math.PI;
211                 }
212                 else if (e.X >= originX && e.Y <= originY)
213                 {
214                     this.x = (float)(originX + 50 * Math.Cos(this.angle));
215                     this.y = (float)(originY + 50 * Math.Sin(this.angle));
216 
217                     this.angle = 360 + this.angle * 180 / Math.PI;
218                 }
219 
220                 this.Invalidate();
221             }
222         }
223     }
224 
225 
226     //控件
227     public class MyControl : System.Windows.Forms.UserControl
228     {
229         private double _angle;
230 
231         [BrowsableAttribute(true)]
232         [EditorAttribute(typeof(AngleEditor), typeof(System.Drawing.Design.UITypeEditor))]
233         public double Angle
234         {
235             get
236             { return _angle; }
237             set
238             { _angle = value; }
239         }
240 
241 
242         public MyControl()
243         {
244             this._angle = 90;
245         }
246 
247         protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
248         {
249             e.Graphics.DrawString("The Angle is " + _angle, this.Font, Brushes.Red,0,0);
250         }
251     }
252 }
View Code

  新建Window工程,添加该文件,在工具箱中将MyControl控件拖入Form,在属性框中编辑Angle属性。

  这里我们把AngleControl和AngleControl2都集成在里面了,当然实际只需选中一种,要实现弹出式,只需按照(三)中的方法,修改AngleEditor中两个地方即可。

原文地址:https://www.cnblogs.com/yongyu/p/4230331.html