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
- 这是第一个公开版本


