惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Threatpost
V
Vulnerabilities – Threatpost
TaoSecurity Blog
TaoSecurity Blog
C
Cybersecurity and Infrastructure Security Agency CISA
P
Proofpoint News Feed
G
GRAHAM CLULEY
S
Securelist
P
Palo Alto Networks Blog
MongoDB | Blog
MongoDB | Blog
A
Arctic Wolf
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
WordPress大学
WordPress大学
Project Zero
Project Zero
T
Threat Research - Cisco Blogs
L
Lohrmann on Cybersecurity
C
Cyber Attacks, Cyber Crime and Cyber Security
F
Fortinet All Blogs
博客园 - 叶小钗
B
Blog RSS Feed
C
Cisco Blogs
Google DeepMind News
Google DeepMind News
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Apple Machine Learning Research
Apple Machine Learning Research
G
Google Developers Blog
K
Kaspersky official blog
D
Docker
Latest news
Latest news
Cisco Talos Blog
Cisco Talos Blog
T
Tor Project blog
Cyberwarzone
Cyberwarzone
Security Latest
Security Latest
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Spread Privacy
Spread Privacy
Microsoft Azure Blog
Microsoft Azure Blog
C
Check Point Blog
J
Java Code Geeks
Simon Willison's Weblog
Simon Willison's Weblog
T
Tenable Blog
Recent Announcements
Recent Announcements
T
Tailwind CSS Blog
H
Help Net Security
L
LINUX DO - 热门话题
T
The Exploit Database - CXSecurity.com
Jina AI
Jina AI
S
SegmentFault 最新的问题
MyScale Blog
MyScale Blog
NISL@THU
NISL@THU
美团技术团队
腾讯CDC

博客园 - 太白飞仙

.Net网络资源 CI创意的方法与技巧 可控人生核聚变 用c#备份和还原sql server 2000数据库 论文先睹:关于科学的生命哲学的思考 蚂蚁造山的思考 语言争霸VS魔兽争霸 :: IT世界VS魔兽世界 第九章 SQL Server的简单应用 [导入]类型MSN窗体行为的实现(.NET 2.0) - 太白飞仙 - 博客园 [导入]文章藏金阁 [导入]敏捷实验室的一次争论 [导入]Netron研究(四)----"移动和联通"之联通篇 [导入]Netron研究(二)----"容器"登场 [导入]Netron研究(一)----初识 [导入]Agile Framework的日志服务 [导入]Agile Framework工作流服务的设计思路 [导入]KISS原则 [导入]WWF工作流引擎的一个奇怪现象 - 太白飞仙 - 博客园 [导入]时刻提防过度设计
[导入]Netron研究(三)----"移动和联通"之移动篇
太白飞仙 · 2006-01-16 · via 博客园 - 太白飞仙
  • 序:    在这里,我可不是要讨论中国移动和中国联通谁的信号好,收费低,而是针对Netron中的两大重要操作:图形的移动和图形的联接进行分析.:)
  • 移动篇
    对于图形设计器来讲,图形的移动应该是其中非常核心的一部分.接下来,就来分析下Netron是怎么实现这个核心功能的.
    关于这点,要首先回顾下前面随笔提到的一些东西.Netron中所有的具体图形对象(椭圆,矩行...)都继承自ShapeBase这个基类,而ShapeBase又是继承自Entity这个抽象类的.下面,我们就先深入Entity内部,看看他的五脏六腹到底是怎么样的.Entity类的核心内容如下:

    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); }

     其中,hovered表示鼠标是否悬浮在图形上.site表示该图形所在的GraphControl(可以把他理解为一个图形设计器).isSelected表示这个图形是否被选中.这个抽象类包括四个抽象方法:
    Paint方法指定各种不同的图形元素应该怎么在窗体上画出他自身.
    Hit方法判断图形是否被鼠标点中.
    Invalidate方法使图形元素失效,由此产生OnPaint消息,进行窗体的刷新.
    Move方法是图形移动控制的方法.

    接下来,我们看看所有具体图形对象的直接父类ShapeBase(继承自Entity)中,关于图形移动的核心内容

    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(); } ...... }

     其中rectangle是具体图形所在的矩型区域.
    X,Y,Location是该矩型所在的位置.
    ShapeBase类没有具体实现抽象类Entity中的抽象方法,Paint,Hit.因为这两个具体的操作应该交给具体的子类来实现.(比如,矩行图形和椭圆图形的Paint的具体实现就不相同.剩下的两个方法Invalidate和Move,这都是所有图形共用的方法,很简单吧?

    下面,我将用一个具体的图形元素:SimpleRectangle来说明下各个具体图形是怎么进行和移动有关的处理的.SimpleRectangle类的核心内容如下:

    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); } }

     其中,Hit方法判断该矩行是否被鼠标点中,他通过定义一个Size为5,5的小矩行,该小矩型左上角的坐标是鼠标点击的点,看这个小矩行是否完全包含在图形矩行中.
    Paint方法是矩形图形将自身绘制出来的方法.其中有进行Connector和矩行中的文本的处理,在移动篇里暂时不对他们进行说明.不过也相当简单.
    Invalidate方法使该矩行失效,然后对窗体进行重新绘制.

    现在,各个图形子元素已经具有了移动的行为,接下来看一看图形设计器GraphControl类是怎么控制各个图形元素的移动的.GraphControl类控制图形移动的关键内容如下:
    首先,是在图形设计器上单击,响应单击事件的代码如下:

    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); }

     首先得到鼠标点击的X,Y坐标,GraphControl中的shapes前一篇随笔提到过,是一个ShapeCollection对象,保存所有的图形元素.然后通过这个图形元素自身的Hit方法判断是否选中了某一个图形元素.如果选中了一个图形元素,则将tracking置为true(为移动做准备).并将该图形元素定了唯一的选中图形.接下来是显示该图形的属性(这不是本随笔的重点,暂不说明).

    确定了选中的图形元素后,在鼠标移动的时候,响应鼠标的OnMouseMove事件,如果tracking是true的话,则将唯一选中的图形元素进行移动(移动的实现是在各个图形元素中的).最后,在OnMouseUp时间中将tracking置为false,至此,完成了整个图形移动的任务.
    (发现代码贴得太多了,"联通篇"还是重起一篇随笔分析吧)

----2005.12.25 15:59 星期日


文章来源:http://www.agilelabs.cn/blogs/woody/archive/2005/12/25/310.aspx