首页 > 开发 > 综合 > 正文

c#自定义控件开发实例

2024-07-21 02:27:14
字体:
来源:转载
供稿:网友

最近做一个图象的采集,需要一个图形的选择控件,但是在.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只改变大小

其他则是清理工作。

好了,那么赶紧编译。生成就可以了。

源文件:http://ded.nuaa.edu.cn/download/windows%20extended%20controls.rar
示例代码:http://ded.nuaa.edu.cn/download/windowsapplication6.rar
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表