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 }

  其中有个属性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 }

  这里有两个类,一个是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         }

  好了,现在就可以使用下拉框来编辑我们的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 }

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

  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 }

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

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

时间: 2024-08-04 10:48:41

PropertyGrid—为复杂属性提供下拉式编辑框和弹出式编辑框的相关文章

上拉、下拉UITableView,交互式 模态弹出(自定义弹出动画)

部分代码 InteractiveTransition 类继承NSObject: - (instancetype)initWithPresentingController:(UITableViewController *)presentingVc presentedController:(UIViewController *)presentedVc { self = [super init]; if (self) { self.vc = presentedVc; self.vc.transitio

[WinForm]为ComboBox绑定数据源并提供下拉提示

关键代码: /// <summary> /// 为ComboBox绑定数据源并提供下拉提示 /// </summary> /// <typeparam name="T">泛型</typeparam> /// <param name="combox">ComboBox</param> /// <param name="list">数据源</param>

让小区运营再智能一点,EasyRadius正式向WayOs用户提供到期弹出式提示充值页面

其实一直没向用户提供到期弹出式页面,主要是给VIP群的用户一点优越感,随着这次EasyRadius的更新,海哥就免费向普通easyRadius用户提供这两个模板下载. 有些人会问,什么样的模板.有什么功能? 你先看看下面的图片,休息片刻,我再接下去为你简单说明下吧. 下载地址:登陆oa.ooofc.com,系统设置,用户中心设置,就可以看到了.要是看到见,请睁大眼睛噢. 账目号到期模板(用户到期,被限制上网的通告): 本页面使用红色和粉色搭配,让用户有较大的视角感受,同时同供二维码标识,您可以放

从仿QQ消息提示框来谈弹出式对话框

<代码里的世界> -UI篇 用文字札记描绘自己 android学习之路 转载请保留出处 by Qiao http://blog.csdn.net/qiaoidea/article/details/45896477 [导航] - 自定义弹出式对话框的简单用法 列举各种常见的对话框实现方案 1.概述 android原生控件向来以丑著称(新推出的Material Design当另说),因此几乎所有的应用都会特殊定制自己的UI样式.而其中弹出式提示框的定制尤为常见,本篇我们将从模仿QQ退出提示框来看一

c#桌面应用程序如何添加弹出式广告

c#写的软件很多,如何添加诸如像搜狗输入法软件与灵格斯翻译软件的屏幕右下角弹出式广告呢. c#代码如下: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.

Operating System-Thread(5)弹出式线程&amp;&amp;使单线程代码多线程化会产生那些问题

本文主要内容 弹出式线程(Pop-up threads) 使单线程代码多线程化会产生那些问题 一.弹出式线程(Pop-up threads) 以在一个http到达之后一个Service的处理为例子来介绍弹出式线程. 上面的例子中传统的做法有可能是在Service中有一个线程一直在等待request的到达,等request到达后这个线程会开始检查请求最后在进行处理.当这个线程在处理request的时候,后面来的request会被block,一直到线程处理完当前request为止.如下图所示. 弹出

导航条——弹出式悬浮菜单

1.概述 采用弹出式悬浮菜单,不但可以使网站的导航内容更加清晰,而且不影响页面的整体效果.运行本实例,如图1所示,当鼠标移动到一级导航菜单的标题上时,将弹出悬浮菜单显示该菜单对应的子菜单,鼠标移出时,将隐藏悬浮菜单. 2.技术要点 本实例主要是在JavaScript中,动态改变<div>标签对象的style属性的display属性值来实现动态显示和隐藏二级导航菜单.其实,每一个一级菜单下的二级菜单内容是已经添加在网页的<div>标签中,只是此时设置了<div>不显示.所

JS框架_(jQuery.js)Tooltip弹出式按钮插件

弹出式按钮效果 <!DOCTYPE html> <html > <head> <meta charset="UTF-8"> <title>jQuery实现Tooltip弹出样式的分享按钮DEMO演示</title> <link rel="stylesheet" href="css/style.css"> </head> <body><

c#应用程序如何添加弹出式广告功能

使用c#语言,如何实现像搜狗输入法以及灵格斯翻译软件的屏幕右下角弹出式广告呢? c#code如下: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Run