最近做一个图象的采集,需要一个图形的选择控件,但是在.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新闻热点
疑难解答