最近做一个图象的采集,需要一个图形的选择控件,但是在.net下没有类似vb中的shape控件,所以考虑了自己写一个控件。
下面我将从头创建控件,这个控件主要是用来选择图形的Rectangle,有一下几个属性Color BorderColor:边框颜色,Color BackColor:背景颜色,bool ReSizeble:是否可移动, Rectangle SelectRectangle:选择区域。
打开vs2003(我用的这个版本),新建一个c#控件库,ok,拷贝如下代码到你的代码里。
using System; using System.Collections; using System.ComponentModel; using System.Drawing; using System.Data; using System.Windows.Forms; namespace WindowsExtendedControls { /// <summary> /// 控件 /// </summary> public class ShapeEx : System.Windows.Forms.Control { /// <summary> /// 必需的设计器变量。 /// </summary> /// private Color _BorderColor=new Color(,',','); private Color _BackColor=new Color(,',','); private bool _ReSizeble; private Point _SelfLocation=new Point(,',','); private Point _MouseLocation=new Point(,',','); private int _SelfWidth; private int _SelfHeight; private int _SelectSelctedIndex;//0-8,0:SizeAll private Rectangle _rectLeftSelector=new Rectangle(,',','); private Rectangle _rectTopSelector=new Rectangle(,',','); private Rectangle _rectRightSelector=new Rectangle(,',','); private Rectangle _rectBottomSelector=new Rectangle(,',','); private Rectangle _rectLeftTopSelector=new Rectangle(,',','); private Rectangle _rectRightTopSelector=new Rectangle(,',','); private Rectangle _rectRightBottomSelector=new Rectangle(,',','); private Rectangle _rectLeftBottomSelector=new Rectangle(,',','); private System.ComponentModel.Container components = null; public ShapeEx() { // 该调用是 Windows.Forms 窗体设计器所必需的。 InitializeComponent(,',','); // TODO: 在 InitComponent 调用后添加任何初始化 } [DefaultValue("Black"),Description("边框颜色"),Category("Appearance")] public Color BorderColor { get { // Insert code here. return _BorderColor; } set { _BorderColor=value; this.Invalidate(,',','); } } [DefaultValue("Control"),Description("背景颜色"),Category("Appearance")] public override Color BackColor { get { // Insert code here. return _BackColor; } set { _BackColor=value; this.Invalidate(,',','); } } [DefaultValue(false),Description("运行中控件大小是否可拖拽编辑"),Category("Behavior")] public bool ReSizeble { get { // Insert code here. return _ReSizeble; } set { _ReSizeble=value; this.Invalidate(,',','); } } [Description("控件选择区域"),Category("Behavior")] public Rectangle SelectRectangle { get { Rectangle selectRectangler=new Rectangle(,',','); selectRectangler.X = this.Location.X+7; selectRectangler.Y = this.Location.Y+7; selectRectangler.Height = this.Height-15; selectRectangler.Width = this.Width-15; return selectRectangler; } } protected override void OnPaint(PaintEventArgs pe) { // Calling the base class OnPaint base.OnPaint(pe,',','); ReDrawControl(pe.Graphics,',','); } private void DrawSelector(Graphics graphics) { SolidBrush SelectorPen=new SolidBrush(Color.White,',','); Pen borderPen=new Pen(this._BorderColor,1,',','); try { //实心 PointF[] LeftPoints=getPointF(0,this.Height/2-3,6,6,',','); graphics.FillClosedCurve(SelectorPen, LeftPoints,',','); PointF[] TopPoints=getPointF(this.Width/2-3,0,6,6,',','); graphics.FillClosedCurve(SelectorPen, TopPoints,',','); PointF[] RightPoints=getPointF(this.Width-7,this.Height/2-3,6,6,',','); graphics.FillClosedCurve(SelectorPen, RightPoints,',','); PointF[] BottomPoints=getPointF(this.Width/2-3,this.Height-7,6,6,',','); graphics.FillClosedCurve(SelectorPen, BottomPoints,',','); PointF[] LeftTopPoints=getPointF(0,0,6,6,',','); graphics.FillClosedCurve(SelectorPen, LeftTopPoints,',','); PointF[] RightTopPoints=getPointF(this.Width-7,0,6,6,',','); graphics.FillClosedCurve(SelectorPen, RightTopPoints,',','); PointF[] RightBottomPoints=getPointF(this.Width-7,this.Height-7,6,6,',','); graphics.FillClosedCurve(SelectorPen, RightBottomPoints,',','); PointF[] LeftBottomPoints=getPointF(0,this.Height-7,6,6,',','); graphics.FillClosedCurve(SelectorPen, LeftBottomPoints,',','); //边框 _rectLeftSelector.X = 0; _rectLeftSelector.Y = this.Height/2-3; _rectLeftSelector.Height = 6; _rectLeftSelector.Width = 6; graphics.DrawRectangle(borderPen, _rectLeftSelector,',','); _rectTopSelector.X = this.Width/2-3; _rectTopSelector.Y = 0; _rectTopSelector.Height = 6; _rectTopSelector.Width = 6; graphics.DrawRectangle(borderPen, _rectTopSelector,',','); _rectRightSelector.X = this.Width-7; _rectRightSelector.Y = this.Height/2-3; _rectRightSelector.Height = 6; _rectRightSelector.Width = 6; graphics.DrawRectangle(borderPen, _rectRightSelector,',','); _rectBottomSelector.X = this.Width/2-3; _rectBottomSelector.Y = this.Height-7; _rectBottomSelector.Height = 6; _rectBottomSelector.Width = 6; graphics.DrawRectangle(borderPen, _rectBottomSelector,',','); _rectLeftTopSelector.X=0; _rectLeftTopSelector.Y=0; _rectLeftTopSelector.Width=6; _rectLeftTopSelector.Height=6; graphics.DrawRectangle(borderPen, _rectLeftTopSelector,',','); _rectRightTopSelector.X=this.Width-7; _rectRightTopSelector.Y=0; _rectRightTopSelector.Width=6; _rectRightTopSelector.Height=6; graphics.DrawRectangle(borderPen, _rectRightTopSelector,',','); _rectRightBottomSelector.X=this.Width-7; _rectRightBottomSelector.Y=this.Height-7; _rectRightBottomSelector.Width=6; _rectRightBottomSelector.Height=6; graphics.DrawRectangle(borderPen, _rectRightBottomSelector,',','); _rectLeftBottomSelector.X=0; _rectLeftBottomSelector.Y=this.Height-7; _rectLeftBottomSelector.Width=6; _rectLeftBottomSelector.Height=6; graphics.DrawRectangle(borderPen, _rectLeftBottomSelector,',','); } catch(Exception E) { throw E; } finally { SelectorPen.Dispose(,',','); borderPen.Dispose(,',','); } } private void ReDrawControl(Graphics graphics) { try { //绘制背景 /* graphics.Clear(this._BackColor,',','); SolidBrush backPen=new SolidBrush(this._BackColor,',','); PointF point1 = new PointF(1,1,',','); PointF point2 = new PointF(this.Width-2,1,',','); PointF point3 = new PointF(this.Width-2,this.Height-2,',','); PointF point4 = new PointF(1,this.Height-2,',','); PointF[] points = {point1, point2, point3, point4}; graphics.FillClosedCurve(backPen, points,',','); */ //绘制边框 Rectangle rectBorder=new Rectangle(,',','); Pen borderPen=new Pen(this._BorderColor,1,',','); rectBorder.X = 7; rectBorder.Y = 7; rectBorder.Height = this.Height-15; rectBorder.Width = this.Width-15; graphics.DrawRectangle(borderPen, rectBorder,',','); //绘制编辑框 if (_ReSizeble) { DrawSelector(graphics,',','); } } catch(Exception E) { throw E; } finally { graphics.Dispose(,',','); } } /// <summary> /// 清理所有正在使用的资源。 /// </summary> private PointF[] getPointF(int x,int y,int Width,int Height){ PointF point1 = new PointF(x,y,',','); PointF point2 = new PointF(x+Width,y,',','); PointF point3 = new PointF(x+Width,y+Height,',','); PointF point4 = new PointF(x,y+Height,',','); PointF[] points = {point1, point2, point3, point4}; return points; } protected override void Dispose( bool disposing ) { if( disposing ) { if( components != null ) components.Dispose(,',','); } base.Dispose( disposing ,',','); } #region 组件设计器生成的代码 /// <summary> /// 设计器支持所需的方法 - 不要使用代码编辑器 /// 修改此方法的内容。 /// </summary> private void InitializeComponent() { components = new System.ComponentModel.Container(,',','); this.Resize+=new EventHandler(ShapeEx_Resize,',','); this.MouseDown+=new MouseEventHandler(ShapeEx_MouseDown,',','); this.MouseMove+=new MouseEventHandler(ShapeEx_MouseMove,',','); this.MouseLeave+=new EventHandler(ShapeEx_MouseLeave,',','); this.MouseUp+=new MouseEventHandler(ShapeEx_MouseUp,',','); this._BorderColor=Color.Black; this._BackColor=Color.FromName("Control",',','); this._ReSizeble=false; this._SelectSelctedIndex=-1; SetStyle(ControlStyles.SupportsTransparentBackColor, true,',','); } #endregion private void ShapeEx_Resize(object sender, EventArgs e) { if (this.Width<16 || this.Height<16) { this.Width=16; this.Height=16; } this.Invalidate(,',','); } private void ShapeEx_MouseDown(object sender, MouseEventArgs e) { 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) ) { this.Cursor=Cursors.SizeNWSE; this._SelectSelctedIndex=1; } if (_rectTopSelector.Contains(e.X,e.Y) ) { this.Cursor=Cursors.SizeNS; this._SelectSelctedIndex=2; } if (_rectRightTopSelector.Contains(e.X,e.Y) ) { this.Cursor=Cursors.SizeNESW; this._SelectSelctedIndex=3; } if (_rectRightSelector.Contains(e.X,e.Y) ) { this.Cursor=Cursors.SizeWE; this._SelectSelctedIndex=4; } if (_rectRightBottomSelector.Contains(e.X,e.Y) ) { this.Cursor=Cursors.SizeNWSE; this._SelectSelctedIndex=5; } if (_rectBottomSelector.Contains(e.X,e.Y)) { this.Cursor=Cursors.SizeNS; this._SelectSelctedIndex=6; } if (_rectLeftBottomSelector.Contains(e.X,e.Y) ) { this.Cursor=Cursors.SizeNESW; this._SelectSelctedIndex=7; } if (_rectLeftSelector.Contains(e.X,e.Y)) { this.Cursor=Cursors.SizeWE; this._SelectSelctedIndex=8; } } else { this.Cursor=Cursors.SizeAll; this._SelectSelctedIndex=0; } this._SelfLocation.X=this.Location.X; this._SelfLocation.Y=this.Location.Y; this._MouseLocation.X=Cursor.Position.X; this._MouseLocation.Y=Cursor.Position.Y; this._SelfWidth=this.Width; this._SelfHeight=this.Height; } } private void ShapeEx_MouseMove(object sender, MouseEventArgs e) { //move and resize switch (this._SelectSelctedIndex) { case 0: this.Location=new Point(Cursor.Position.X-(_MouseLocation.X-_SelfLocation.X),Cursor.Position.Y-(_MouseLocation.Y-_SelfLocation.Y),',','); break; case 1: this.Height=this._SelfHeight-(Cursor.Position.Y-_MouseLocation.Y,',','); this.Width=this._SelfWidth-(Cursor.Position.X-_MouseLocation.X,',','); this.Location=new Point(Cursor.Position.X-_MouseLocation.X+_SelfLocation.X,Cursor.Position.Y-_MouseLocation.Y+_SelfLocation.Y,',','); break; case 2: this.Height=this._SelfHeight-(Cursor.Position.Y-_MouseLocation.Y,',','); this.Location=new Point(_SelfLocation.X,Cursor.Position.Y-_MouseLocation.Y+_SelfLocation.Y,',','); break; case 3: this.Height=this._SelfHeight-(Cursor.Position.Y-_MouseLocation.Y,',','); this.Width=this._SelfWidth+(Cursor.Position.X-_MouseLocation.X,',','); this.Location=new Point(_SelfLocation.X,Cursor.Position.Y-(_MouseLocation.Y-_SelfLocation.Y),',','); break; case 4: this.Width=this._SelfWidth+(Cursor.Position.X-_MouseLocation.X,',','); break; case 5: this.Height=this._SelfHeight+(Cursor.Position.Y-_MouseLocation.Y,',','); this.Width=this._SelfWidth+(Cursor.Position.X-_MouseLocation.X,',','); break; case 6: this.Height=this._SelfHeight+(Cursor.Position.Y-_MouseLocation.Y,',','); break; case 7: this.Height=this._SelfHeight+(Cursor.Position.Y-_MouseLocation.Y,',','); this.Width=this._SelfWidth-(Cursor.Position.X-_MouseLocation.X,',','); this.Location=new Point(Cursor.Position.X-_MouseLocation.X+_SelfLocation.X,_SelfLocation.Y,',','); break; case 8: this.Width=this._SelfWidth-(Cursor.Position.X-_MouseLocation.X,',','); this.Location=new Point(Cursor.Position.X-_MouseLocation.X+_SelfLocation.X,_SelfLocation.Y,',','); break; } } private void ShapeEx_MouseLeave(object sender, EventArgs e) { this.Cursor=Cursors.Default; this._SelectSelctedIndex=-1; } private void ShapeEx_MouseUp(object sender, MouseEventArgs e) { this.Cursor=Cursors.Default; this._SelectSelctedIndex=-1; } } }
下面讲一下控件具体如何工作,首先要写他的属性以及重写他的属性,
private Color _BorderColor=new Color(,',','); [DefaultValue("Black"),Description("边框颜色"),Category("Appearance")] public Color BorderColor { get { // Insert code here. return _BorderColor; } set { _BorderColor=value; this.Invalidate(,',','); } }
DefaultValue:设定默认值,Description:描述,就是属性下面的说明,Category:属性分类.其他的同理
设置好属性以后应该重写他的绘制过程,也就是
protected override void OnPaint(PaintEventArgs pe) { // Calling the base class OnPaint base.OnPaint(pe,',','); ReDrawControl(pe.Graphics,',','); } private void ReDrawControl(Graphics graphics) { try { //绘制边框 Rectangle rectBorder=new Rectangle(,',','); Pen borderPen=new Pen(this._BorderColor,1,',','); rectBorder.X = 7; rectBorder.Y = 7; rectBorder.Height = this.Height-15; rectBorder.Width = this.Width-15; graphics.DrawRectangle(borderPen, rectBorder,',','); //绘制编辑框 if (_ReSizeble) { DrawSelector(graphics,',','); } } catch(Exception E) { throw E; } finally { graphics.Dispose(,',','); } } [Description("控件选择区域"),Category("Behavior")] public Rectangle SelectRectangle { get { Rectangle selectRectangler=new Rectangle(,',','); selectRectangler.X = this.Location.X+7; selectRectangler.Y = this.Location.Y+7; selectRectangler.Height = this.Height-15; selectRectangler.Width = this.Width-15; return selectRectangler; } }
ReDrawControl中定义了Rectangle (矩形),让后填充改矩形的边框:graphics.DrawRectangle(borderPen, rectBorder,',',');,这里要说明的是边框外面还有编辑框,所以大小不是控件的大小。DrawSelector就是绘制8个选择框的,基本和绘制边框差不多,即使定义好坐标就可以了。干好了之后不要忘了释放资源:graphics.Dispose(,',',');
SelectRectangle:控件所选择的Rectangle,最终要得就是它了
ok,这样一个基本的东西出来了,下面我们要写他的move和resize函数了,先添加事件:
this.Resize += new System.EventHandler(this.ShapeEx_Resize,',','); this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.ShapeEx_MouseUp,',','); this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.ShapeEx_MouseMove,',','); this.MouseLeave += new System.EventHandler(this.ShapeEx_MouseLeave,',','); this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ShapeEx_MouseDown,',',');
原理:当鼠标点击的时候this.MouseDown,记录鼠标的位置,控件的原始位置和大小,判断位置:_rectLeftBottomSelector.Contains(e.X,e.Y):表示点击的是左下,设置鼠标,记录状态this._SelectSelctedIndex:判断点击了那个选择框,取值0-8:0代表移动整个控件,1是右上移动,2-8顺时针索引选择框。this.MouseMove处理如何改变控件的大小和位置
case 0://只移动位置
this.Location=new Point(Cursor.Position.X-(_MouseLocation.X-_SelfLocation.X),Cursor.Position.Y-(_MouseLocation.Y-_SelfLocation.Y),',',');
break;
1,5不仅移动位置,还改变大小,2,3,4,6,7,8只改变大小
其他则是清理工作。
好了,那么赶紧编译。生成就可以了。