



















其中,hovered表示鼠标是否悬浮在图形上.site表示该图形所在的GraphControl(可以把他理解为一个图形设计器).isSelected表示这个图形是否被选中.这个抽象类包括四个抽象方法:public abstract class Entity {
... protected internal bool hovered = false; protected GraphControl site; protected bool isSelected = false;
[Browsable(false)] public bool IsSelected { get{return isSelected;} set{isSelected = value;} } [Browsable(false)] public GraphControl Site { get{return site;} set{site = value;} } public abstract void Paint(Graphics g); public abstract bool Hit(Point p); public abstract void Invalidate(); public abstract void Move(Point p); }
接下来,我们看看所有具体图形对象的直接父类ShapeBase(继承自Entity)中,关于图形移动的核心内容
其中rectangle是具体图形所在的矩型区域.public class ShapeBase : Entity { ...... protected Rectangle rectangle; public int X { get{return rectangle.X;} set{ Point p = new Point(value - rectangle.X, rectangle.Y); this.Move(p); Site.Invalidate(); //note that 'this.Invalidate()' will not be enough } } public int Y { get{return rectangle.Y;} set{ Point p = new Point(rectangle.X, value - rectangle.Y); this.Move(p); Site.Invalidate(); } } public Point Location { get{return new Point(this.rectangle.X,this.rectangle.Y);} set{ //we use the move method but it requires the delta value, not an absolute position! Point p = new Point(value.X-rectangle.X,value.Y-rectangle.Y); //if you'd use this it would indeed move the shape but not the connector s of the shape //this.rectangle.X = value.X; this.rectangle.Y = value.Y; Invalidate(); this.Move(p); } } public override void Paint(System.Drawing.Graphics g) { return; } public override bool Hit(System.Drawing.Point p) { return false; } public override void Invalidate() { site.Invalidate(rectangle); } public override void Move(Point p) { this.rectangle.X += p.X; this.rectangle.Y += p.Y; for(int k=0;k<this.connectors.Count;k++) { connectors[k].Move(p); } this.Invalidate(); } ...... }
下面,我将用一个具体的图形元素:SimpleRectangle来说明下各个具体图形是怎么进行和移动有关的处理的.SimpleRectangle类的核心内容如下:
其中,Hit方法判断该矩行是否被鼠标点中,他通过定义一个Size为5,5的小矩行,该小矩型左上角的坐标是鼠标点击的点,看这个小矩行是否完全包含在图形矩行中.public class SimpleRectangle : ShapeBase { public override bool Hit(System.Drawing.Point p) { Rectangle r= new Rectangle(p, new Size(5,5)); return rectangle.Contains(r); } public override void Paint(System.Drawing.Graphics g) { g.FillRectangle(shapeBrush,rectangle); if(hovered || isSelected) g.DrawRectangle(new Pen(Color.Red,2F),rectangle); else g.DrawRectangle(blackPen,rectangle); for(int k=0;k<connectors.Count;k++) { connectors[k].Paint(g); } //well, a lot should be said here like //the fact that one should measure the text before drawing it, //resize the width and height if the text if bigger than the rectangle, //alignment can be set and changes the drawing as well... //here we keep it really simple: if(text !=string.Empty) g.DrawString(text,font,Brushes.Black, rectangle.X+10,rectangle.Y+10); }
public override void Invalidate() { Rectangle r = rectangle; r.Offset(-5,-5); r.Inflate(20,20); site.Invalidate(r); } }
现在,各个图形子元素已经具有了移动的行为,接下来看一看图形设计器GraphControl类是怎么控制各个图形元素的移动的.GraphControl类控制图形移动的关键内容如下:
首先,是在图形设计器上单击,响应单击事件的代码如下:
首先得到鼠标点击的X,Y坐标,GraphControl中的shapes前一篇随笔提到过,是一个ShapeCollection对象,保存所有的图形元素.然后通过这个图形元素自身的Hit方法判断是否选中了某一个图形元素.如果选中了一个图形元素,则将tracking置为true(为移动做准备).并将该图形元素定了唯一的选中图形.接下来是显示该图形的属性(这不是本随笔的重点,暂不说明).protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown (e); Point p = new Point(e.X,e.Y);
...... //test for shapes for(int k=0; k<shapes.Count; k++) { if(shapes[k].Hit(p)) { //shapes[k].ShapeColor = Color.WhiteSmoke; tracking = true; if(selectedEntity!=null) selectedEntity.IsSelected=false; selectedEntity = shapes[k]; selectedEntity.IsSelected = true; refp=p; if(OnShowProps!=null) OnShowProps(this.shapes[k]); if(e.Button==MouseButtons.Right) { if(OnShowProps!=null) OnShowProps(this); } return; } } if(selectedEntity!=null) selectedEntity.IsSelected=false; selectedEntity = null; Invalidate(); refp = p; //useful for all kind of things //nothing was selected but we'll show the props of the control in this case if(OnShowProps!=null) OnShowProps(this.proxy); }
确定了选中的图形元素后,在鼠标移动的时候,响应鼠标的OnMouseMove事件,如果tracking是true的话,则将唯一选中的图形元素进行移动(移动的实现是在各个图形元素中的).最后,在OnMouseUp时间中将tracking置为false,至此,完成了整个图形移动的任务.
(发现代码贴得太多了,"联通篇"还是重起一篇随笔分析吧)
----2005.12.25 15:59 星期日
文章来源:http://www.agilelabs.cn/blogs/woody/archive/2005/12/25/310.aspx
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。