|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
就安全性而言,net网页编程已经远远低于VB.NET,更无法与安全性著称的C#相比。合用于:MicrosoftWindowsCE.NET/SmartDeviceExtensionsforMicrosoftVisualStudio.NET
简介
SmartDeviceExtensionsforMicrosoftVisualStudio.NET(SDE)供应了一种能够在使用程序中利用的很好的基础控件。遗憾的是,嵌进式设备使用程序触及的局限十分广,这就使得开辟职员几近一定会在某些中央短少符合的控件,此时,基础上有两个选择:从头举行使用程序的布局计划以利用可用的控件,大概接纳您本人的自界说控件。
SDE的第一个版本不撑持计划时自界说控件,这意味着为了利用它们,必需手动编写将它们放进窗体并设置其巨细和属性的代码。它只需很少的分外事情量,而且只必要您承受没有可用于自界说控件的FormDesignSupport这一现实。
成绩
比来,我一向在为VisualStudio.NET创立类库,用于包装良多硬件的功效。经由过程利用一个能够为他们完成一切P/Invoking和资本办理事情的类库,托管代码开辟职员利用这个类库来会见机载微型把持器和MicrosoftWindowsCE端口就简单多了。我开辟用于GraphicsMaster设备的I/O的类库,以便供应对两个独自的头上的引脚的读取和写进功效。
我必要一个测试和示例使用程序,该程序可以利用户轻松地经由过程得当的图形接口设置或读取数字I/O形态并读取摹拟I/O。我但愿有某个工具看起来像表示图上的讨论或相似板上的物理插头。因为我要处置两个物理上分歧巨细的讨论,以是我必要多个控件,或最好是一个能够界说巨细的控件。很明显,SDE的工具箱中没有我想要的控件。
我原本可使用大批的Label、CheckBox、PictureBox和TextBox,可是我以为这类替换计划看起来很丢脸。让我们实验编写本人的控件。
C#自界说控件对象模子
第一个义务是决意全部对象模子。我们必要甚么样的构成部分,这些构成部分将怎样交融在一同,它们怎样互相交互,怎样与它们的情况交互?
.我的毗连器控件观点
我们将创立毗连器,用来包括巨细可变的引脚汇合,以便可以毗连分歧巨细的讨论。每一个引脚必需有能够放在被显现的"引脚"的左边或右边(取决于它是偶数仍是奇数引脚)的标识标签。每一个引脚还能够是数字的或摹拟的I/O,因而每一个引脚都必要有局限从零到0xFFFF的独自的值。最好可以一眼便可辨认每一个引脚的范例和值,以是将必要利用一些色彩。固然,并不是讨论上的一切引脚都可用于I/O,以是我们必要可以禁用它们中的一部分,别的,我们但愿引脚是交互的,如许当我们接通一个引脚时,它能够做某些操纵,好比变动形态。
是一个控件在屏幕上显现的表面的很好模子。
基于这些请求,我们提出了一个如所示的对象模子。
.控件对象模子
全体的思绪是,我们将有一个Connector基类,然后从它派生出其他几个自界说的Connector类。Connector将包括一个Pins类,这个类只是经由过程从CollectionBase派生,利用索引器来公然Pin对象的ListArray。
C#自界说控件:完成Pin对象
由于此控件的主干是Pin对象,以是我们起首先容它。Pin对象将处置控件的年夜多半显现属性,并处置用户交互。一旦我们能够乐成地在窗体上创立、显现单个引脚并与之交互,构建一个毗连器将它们组合在一同就十分复杂了。
Pin对象有四个在创立它时必需设置的属性。默许的机关函数会设置它们中的每个,但其他机关函数还能够用来同意创立者传送非默许的值。
最主要的属性是Alignment。这个属性断定了绘制对象时文本和引脚的地位,但更主要的是,设置属性时,它将创立和安排用于绘制引脚和文本的矩形。这些矩形的利用将在随后注释OnDraw时举行会商。
清单1显现了基础机关函数和Alignment属性的代码。为引脚子组件四周所界说的偏移量和边框利用了常量,但这些常量也很简单成为控件的其他属性。
清单1.引脚机关函数和Alignment属性- publicPin(){showValue=false;pinValue=0;type=PinType.Digital;Alignment=PinAlignment.PinOnRight;}publicPinAlignmentAlignment{//determineswherethepinrectangleisplacedset{align=value;if(value==PinAlignment.PinOnRight){this.pinBorder=newRectangle(this.ClientRectangle.Width-(pinSize.Width+10),1,pinSize.Width+9,this.ClientRectangle.Height-2);this.pinBounds=newRectangle(this.ClientRectangle.Width-(pinSize.Width+5),((this.ClientRectangle.Height-pinSize.Height)/2)+1,pinSize.Width,pinSize.Height);this.textBounds=newRectangle(5,5,this.ClientRectangle.Width-(pinSize.Width+10),20);}else{this.pinBorder=newRectangle(1,1,pinSize.Width+9,this.ClientRectangle.Height-2);this.pinBounds=newRectangle(6,this.ClientRectangle.Height-(pinSize.Height+4),pinSize.Width,pinSize.Height);this.textBounds=newRectangle(pinSize.Width+10,5,this.ClientRectangle.Width-(pinSize.Width+10),20);}this.Invalidate();}get{returnalign;}}
复制代码 因为Pin对象不会供应很好的用户交互或可自界说性,以是引脚的中心功效是我们将重写的画图例程OnDraw,重写该例程是为了能够由我们来绘制全部引脚。
每一个引脚将绘制三个部分:引剧本身将是一个圆(除非它是Pin1,这时候它将是一个方块),我们将环绕引脚绘制边框矩形,然后在引脚的左边或右边留出一个地区用来绘制引脚的文本。
要绘制引脚,我们起首断定暗示实践引脚的圆所利用的色彩。假如引脚被禁用,它的色彩是灰色。假如启用,则要断定它是甚么范例。摹拟引脚将是绿色,而数字引脚跟据情形而分歧,假如是低(关)则是蓝色,假如是高(开)则是橙色。
下一步,我们利用FillEllipse来绘制一切实践的引脚,但PinNumber=1时除外,这时候利用FillRectangle绘制引脚。经由过程绘制在矩形(pinBounds)中而不是控件的界限上,我们可以在创立引脚时设置引脚的地位(左边或右边),而且从这一点入手下手,我们能够在不必体贴引脚的地位的情形下举行绘制。
下一步我们绘制标签,它将是引脚的文本或引脚的值,这取决于ShowValue属性。
我们利用与绘制引脚时相似的战略来绘制文本,但此次我们必需盘算程度和垂直偏移量,由于在Microsoft.NET紧缩框架中,DrawText办法不同意有TextAlign参数。
终极,我们经由过程挪用Dispose办法清算我们手动利用的Brush对象。
清单2显现了完全的OnDraw例程。
清单2.OnDraw()办法- protectedoverridevoidOnPaint(PaintEventArgspe){Brushb;//determinethePincolorif(this.Enabled){if(type==PinType.Digital){//digitalpinshavedifferenton/offcolorb=newSystem.Drawing.SolidBrush(this.Value==0?(digitalOffColor):(digitalOnColor));}else{//analogpinb=newSystem.Drawing.SolidBrush(analogColor);}}else{//disabledpinb=newSystem.Drawing.SolidBrush(disabledColor);}//drawthepinif(this.PinNumber==1)pe.Graphics.FillRectangle(b,pinBounds);elsepe.Graphics.FillEllipse(b,pinBounds);//drawaborderRectanglearoundthepinpe.Graphics.DrawRectangle(newPen(Color.Black),pinBorder);//drawthetextcenteredinthetextboundstringdrawstring;//areweshowingtheTextorValue?if(showValue)drawstring=Convert.ToString(this.Value);elsedrawstring=this.Text;//determinetheactualstringsizeSizeFfs=pe.Graphics.MeasureString(drawstring,newFont(FontFamily.GenericMonospace,8f,FontStyle.Regular));//drawthestringpe.Graphics.DrawString(drawstring,newFont(FontFamily.GenericMonospace,8f,FontStyle.Regular),newSolidBrush((showValue?analogColor:Color.Black)),textBounds.X+(textBounds.Width-fs.ToSize().Width)/2,textBounds.Y+(textBounds.Height-fs.ToSize().Height)/2);//cleanuptheBrushb.Dispose();}}
复制代码 构建Pin类的最初一步是增加Click处置程序。关于我们的Pin类来讲,我们将利用自界说的EventArg,以即可以向事务处置程序传送引脚的文本和编号。要创立自界说的EventArg,我们只是创立了一个从EventArgs类派生的类:- publicclassPinClickEventArgs:EventArgs{//aPinClickpassesthePinNumberandthePinsTextpublicintnumber;publicstringtext;publicPinClickEventArgs(intPinNumber,stringPinText){number=PinNumber;text=PinText;}}
复制代码 下一步,我们将一个托付增加到定名空间中:- publicdelegatevoidPinClickHandler(Pinsource,PinClickEventArgsargs);
复制代码 如今,我们必要增加代码来断定甚么时分产生单击,然后激发事务。关于我们的Pin类,当引脚的边框矩形外部产生MouseDown和MouseUp事务时即为一个逻辑上的单击-如许,假如用户单击引脚的文本部分,则不会触发Click事务,但假如点击暗示实践引脚的地区,则触发该事务。
起首,我们必要一个大众PinClickHandler事务,其界说以下:- publiceventPinClickHandlerPinClick;
复制代码 我们还必要一个公有的布尔变量,我们将在MouseDown事务产生时设置该变量,用于唆使我们正在单击过程当中。然后,我们反省MouseUp事务的该变量,以断定事务是不是是按一连的按次产生的:下一步,我们必要为MouseDown和MouseUp增加两个事务处置程序,如清单3所示。
清单3.用于完成PinClick事务的事务处置程序- privatevoidPinMouseDown(objectsender,MouseEventArgse){if(!this.Enabled)return;//iftheuserclickedinthe"pin"rectangle,startaclickprocessmidClick=pinBorder.Contains(e.X,e.Y);}privatevoidPinMouseUp(objectsender,MouseEventArgse){//ifwehadamousedownandthenupinsidethe"pin"rectangle,//fireaclickif((midClick)&&(pinBorder.Contains(e.X,e.Y))){if(PinClick!=null)PinClick(this,newPinClickEventArgs(this.PinNumber,this.Text));}}
复制代码 最初,我们必要为每一个引脚完成事务处置程序。引脚的基础机关函数是增加这些挂钩的好中央,我们能够经由过程间接在机关函数中增加以下代码来完成:this.MouseDown+=newMouseEventHandler(PinMouseDown);this.MouseUp+=newMouseEventHandler(PinMouseUp);this.MouseDown+=newMouseEventHandler(PinMouseDown);
this.MouseUp+=newMouseEventHandler(PinMouseUp);完成Pins类一旦有了Pin类,就能够创立从CollectionBase派生的Pins类。该类的目标是供应索引器,如许我们就能够很简单在汇合内增加、删除和利用Pin类。
清单4.Pins类- publicclassPins:CollectionBase{publicvoidAdd(PinPinToAdd){List.Add(PinToAdd);}publicvoidRemove(PinPinToRemove){List.Remove(PinToRemove);}//IndexerforPinspublicPinthis[byteIndex]{get{return(Pin)List[Index];}set{List[Index]=value;}}publicPins(){}}
复制代码 完成Connector类既然我们已取得了Pins类,我们如今必要构建Connector类,该类将是一个复杂的包装类,这个包装类包括Pins类,并在每一个引脚和毗连器容器之间封送PinClick事务,并且它有一个暗示毗连器上的引脚数的机关函数。清单5显现了完全的Connector类。
清单5.Connector类- publicclassConnector:System.Windows.Forms.Control{publiceventPinClickHandlerPinClick;protectedPinspins;bytepincount;publicConnector(byteTotalPins){pins=newPins();pincount=TotalPins;InitializeComponent();}privatevoidInitializeComponent(){for(inti=0;i<pincount;i++){Pinp=newPin(PinType.Digital,(PinAlignment)((i+1)%2),0);p.PinClick+=newPinClickHandler(OnPinClick);p.PinNumber=i+1;p.Text=Convert.ToString(i);p.Top=(i/2)*p.Height;p.Left=(i%2)*p.Width;this.Pins.Add(p);this.Controls.Add(p);}this.Width=Pins[0].Width*2;this.Height=Pins[0].Height*this.Pins.Count/2;}publicPinsPins{set{pins=value;}get{returnpins;}}privatevoidOnPinClick(Pinsender,PinClickEventArgse){//passontheeventif(PinClick!=null){PinClick(sender,e);if(sender.Type==PinType.Digital)sender.Value=sender.Value==0?1:0;elsesender.DisplayValue=!sender.DisplayValue;}}protectedoverridevoidDispose(booldisposing){base.Dispose(disposing);}}
复制代码 Connector的InitializeComponent办法是创立一切被包括的Pin类并将其增加到毗连器的控件中的中央,而且是毗连器自己调剂巨细的中央。InitializeComponent也是终极被FormDesigner用来显现我们的毗连器的办法。
C#自界说控件:构建自界说毗连器
我也不知道,我原来理解的,NET就是C++编程,只是与net网页编程相对,呵呵。以为.ET就是高级C++编程。 |
|