AGE,.NET 中的另一个图形引擎






4.96/5 (32投票s)
一个允许在运行时以简单方式进行 GDI+ 操作的库。
引言
这个库允许您在运行时在应用程序中操作图形对象。

背景
前段时间,我看到有人问是否有一种方法可以将项拖放到面板上。我也有同样的问题(所有这些都始于 MyNeoReport 项目的设计器),所以我试图以一种通用的方式解决这个问题,以便该系统可以毫不费力地用于不同的应用程序。
AGE 支持项拖动、吸附到网格、多选、图层等。
AGE 发展迅速;如果我是你,我会密切关注这个项目。
主要主题
GraphicItem
:要绘制的项Painter
:负责“脏活”绘制的类GraphicDocument
:收集所有要在单个表面上绘制的项的类Canvas
:显示绘图的控件
为什么要设置这个类?
问:为什么我需要一个 RendererBase
,为什么我不能将 Render()
方法直接放在 GraphicItem
类中?
答:因为我需要更多的抽象。
这样我就可以将逻辑项与渲染的执行者分开。
我可以为不同的项使用相同的渲染器,或者为单个项选择不同的渲染器。
问:为什么 GraphicDocument
是一个与 Canvas
分开的类?我可以将所有要绘制的项直接添加到 Canvas
中。
答:原因与第一个问题相同:GraphicDocument
是逻辑项的集合,它是文档,而 Canvas
是绘制文档的表面。
同样,这样我就可以将同一个文档打开到多个画布上。
好的,开始吧……它是如何工作的?
问:我如何创建自己的图形文档?
答:好的,让我们定义一个全新的自定义文档
class CustomDocument : GraphicDocument
{
// define here your document properties
}
// define a custom item: an ellipse.
class Ellipse : GraphicItem
{
Color _foreColor = Color.Blue;
public Ellipse()
{
Painter = new EllipsePainter();
}
public Color ForeColor
{
get{ return _foreColor; }
set{ _foreColor = value; }
}
}
// define the ellipse painter
class EllipsePainter : Painter
{
// how the ellipse is painted...
protected override void Paint(Graphics g)
{
Ellipse ellipse = (Ellipse)Item;
Pen pen = new Pen(ellipse.ForeColor);
g.DrawEllipse(pen, Item.Bounds);
pen.Dispose();
}
}
...
canvas1.Document = new CustomDocument();
// add a new ellipse to the default layer
canvas1.Document.AddItem(new Ellipse());
从 1.4.0.0 版本开始,您还可以使用 ScriptAge 在运行时定义自定义图形项
ScriptedItem triangle = new ScriptedItem();
// Of course: it doesn't make much sense to hard code the script :)
// Rather you would load it from a separate text file or a string resource.
triangle.Script = "stroke: Polygon\n",
"pen: #7070ff, 2!\n",
"brush: gradient, #0000ff, #000000ff, (0; 0.5) (1; 1)\n",
"points: (0; 0.5) (1; 0.0) (1; 1)\n"
有关更多详细信息,请参阅下面的“参考文献”部分。
绘制项的限制
- 您的 GDI+ 想象力
您如何贡献?
如果您认为本文和发布的项目有趣和/或有用,您可以通过多种方式帮助我维护它
- 提供新想法
- 通知/修复错误
- 实现新功能
- 传播项目
- 在您应用程序的“关于”框中注明本项目
- 为本文投票
- 访问我的网站及其论坛
- 访问我的网站并做出一些小贡献(这将是巨大的鼓励)
致谢
感谢Itai Bar-Haim提供的帮助和改进。
愿望清单
- [1.5.0.0] 缩放(感谢 Itai Bar-Haim)
- [1.4.0.0 D] 移植到 Linux+Mono
- [1.4.0.0 B]
ItemEnter
/ItemLeave
事件 - [1.3.0.0] 加载
items
库的能力 - [1.3.0.0]
GraphicItem [Browsable(false)]Min/MaxSize
- [1.3.0.0]
SelectionPainter
自定义所选项的选中“边框”的渲染 - [1.3.0.0]
LoadFrom()
和SaveTo()
在Stream
上工作,因此您可以将文档作为程序集资源包含在内 - [1.2.0.0] 图层
- [1.1.0.0] 保存图形文档的良好序列化方式
- [1.1.0.0] 将绘图保存为图像文件的能力
- [1.1.0.0] 工具栏图标
- 打印绘图的能力
- 撤销/重做
- 选中项的剪贴板复制/粘贴
- 管理屏幕和其他设备(如打印机)上的物理单位度量(厘米、毫米、米、英寸……)
- ……还有其他吗?
我需要一些帮助……有什么建议吗?
参考文献
历史
如有任何疑问或建议,请前往我的网站论坛。
1.5.0.0
抱歉,此版本与 1.4.0.0 C 不完全兼容,但您应该不会遇到问题。我更改了一些属性名称,因此我选择更改版本号,并且需要重新编译使用 AGE 引擎的应用程序。
如果您有需要加载的文档,则必须使用记事本编辑它们,并替换重命名的属性(如下所列)。

- Added
GraphicItem.RotationCenter
、GraphicItem.RotationCenterRelativeTo
,它们允许您定义旋转角度的中心Stroke.RotationCenter
,使用 ScriptAGE,您可以为每个单独的笔触定义旋转点Canvas QueryCursor
事件允许您了解光标状态并设置自定义光标- 图像笔触
- 文本脚本笔触 beta(尚未完全正常工作)
Theme
和DefaultTheme
类允许您定义画布外观(感谢 Itai Bar-Haim)Canvas.Zoom
属性(感谢 Itai Bar-Haim)- 选中项各侧的拖动句柄(感谢 Itai Bar-Haim)
- 固定
Canvas.Cursor
现在是只读的,并反映运行时中的光标状态- 仅允许使用鼠标左键拖动(右键和中键可用于其他目的)
GraphicItem.Angle
已重命名为GraphicItem.RotationAngle
Stroke.Angle
已重命名为Stroke.RotationAngle
Canvas.GridSize
已重命名为Canvas.SnapGridSize
,以避免与 Visual Studio 设计器GridSize
属性冲突- ScriptAGE 已修复笔触和项属性
- 还有许多其他 bug
- 在 Linux Ubuntu 7.4 + Mono 1.2.3.1 上测试:引擎运行良好,设计器需要一些变通方法,因为 Mono 不完全支持
TreeView
(未实现TreeView.Sort()
、TreeView.NodeMouseDoubleClick
事件、TreeView.NodeMouseClick()
事件)
1.4.0.0 版本 C
在此版本中,我再次增强了 ScriptAge。
ScriptAge 与 1.4.0.0 版本 100% 兼容。

- 现在 ScriptAge 可以定义由多个图形组成的笔触
- 这允许您创建由曲线和线条组成的笔触
- 添加了
path
、radial
、elliptic
笔刷类型 - 笔刷现在可以有 2 种以上颜色
- Scriptage 现在可扩展:您可以定义自己的
PaintStroke
类 - 您的自定义笔触可以通过覆盖
PaintStroke.ParseToken()
方法来定义其接受的标记 - 添加了
PathStroke
类
1.4.0.0 版本 B
从现在开始,我将使用 AssemblyDescriptionAttribute
标记 AGE 引擎,以指示子版本。这是因为从 1.4.0.0 开始,我使用强名称签名了程序集,出于兼容性原因,我无法再修改版本号。
在此版本中,我增强了 ScriptAge(请参阅“参考文献”部分)。
ScriptAge 与 1.4.0.0 版本 100% 兼容。
- 现在 ScriptAge 支持注释、图像标记、多行标记等
- 一些次要的 ScriptAge 和
Canvas
修复 - 添加了
Canvas ItemMouseEnter
和ItemMouseExit
事件 - 修复了设计时在
Canvas
上拖放控件的错误
1.4.0.0
此版本使我能够对库的灵活性进行重大改进,允许您在运行时直接定义项。
- 添加了
ScriptedItem
类,允许您使用少量脚本定义图形 - 进行了大量代码清理
1.3.0.0
这次,主要的改变是能够将自定义项写入单独的库中,这些库可以在运行时被文档加载。

- Added
virtual GraphicItem.PointIsOverMe()
,它允许您定义一个点是否在项之上Size GraphicItem.MinSize
,它允许您定义项的最小尺寸class SelectionPainter
和GraphicItem.SelectionPainter
,它们允许您自定义项的选中边框virtual Document.LoadLibrary()
,它允许您从外部 DLL 导入GraphicItems
GraphicLayer Canvas.ActiveLayer
bool Canvas.AllowUserEditItems
和bool Canvas.AllowUserScrollCanvas
,允许您决定用户是否可以操作画布content
以及如何操作Painter.GetPoint()
、Painter.GetSize()
、Painter.FlipPoint()
和Painter.FlipRectangle()
Painter.OnItemBoundsChanged()
- 我记不清的其他一些内容
- 测试项目开始成为一个真正的设计器
1.2.0.0
此版本侧重于图层功能。这是一项真正的挑战,目前仍处于 beta 阶段(它奏效了!我正在考虑一个更面向对象的解决方案)。

- 添加了
Document.Groups
来定义项组和包装器GraphicDocument.Layers
- 从
canvas
中移除了ContextMenuStrip
,因为它对实现canvas
的应用程序来说不是灵活的解决方案,并且 Mono 不支持它 Canvas.OffsetX
和Canvas.OffsetY
现在是Point Canvas.Offset
RendererBase
已重命名为Painter
,使其更类似于框架命名- 常规修复和次要更改
1.1.0.0
此版本侧重于将文档保存到磁盘的功能,但在此过程中进行了数十项附带的改进
- 我对类基础设施进行了重大审查。现在我引入了这些通用基类
文档
DocumentItem
这允许您派生您想要的文档类型,并允许您将其保存到磁盘而无需额外的代码。
GraphicDocument
现在继承自Document
,GraphicItem
继承自DocumentItem
- 序列化由一些类完成,我不会在本文中进行描述,因为它们不完整并且可能很快会更改
- 增强并修复了
canvas
上的光标和选择方式 - 提高了刷新速度
- 添加了虚拟方法,让您可以决定接受或取消对项或文档的操作
Document.OnAddingToDocument(DocumentActionEventArgs e)
Document.OnRemovingFromDocument(DocumentActionEventArgs e)
Document.OnAddedToDocument(DocumentActionEventArgs e)
Document.OnRemovedFromDocument(DocumentActionEventArgs e)
DocumentItem.OnAddingToDocument(DocumentActionEventArgs e)
DocumentItem.OnAddedToDocument(DocumentActionEventArgs e)
DocumentItem.OnRemovingFromDocument(DocumentActionEventArgs e)
DocumentItem.OnRemovedFromDocument(DocumentActionEventArgs e)
- Added
GraphicDocument.SaveImage(string fileName, ImageFormat format)
GraphicDocument.GetBounds()
GraphicDocument.GraphicItems // this is a subset of Document.Items
Document.SaveTo(string fileName)
Document.LoadFrom(string fileName)
Document.OnLoadingDocument()
Document.OnSavingDocument()
Document.OnDocumentLoaded()
Document.OnDocumentSaved()
- 移除了
Renderer.RenderType enum
:现在由Canvas
决定如何以及渲染什么 - 添加了属性
Canvas.DrawInvisibleItems
Canvas.DrawDocumentBounds
Document.Items
现在是GraphicItemCollection
Canvas.SelectedItems
现在是GraphicItemCollection
Canvas.ItemMouseDoubleClick
事件现在是Canvas.ItemDoubleClick
- 添加了
Canvas.ItemClick
事件 - 各种次要修改和修复,我记不清了
1.0.0.0
- 这是第一个公开版本