GraphEditor
GraphEditor copied to clipboard
图形编辑器(MFC VC6.0)
以下涉及操作帮助和功能讲解。
============================= 一、功能概述 =============================
- 添加启动界面
- 文件可保存为位图(光栅化)和矢量图(序列化)
- 添加控制面板和工具栏
- 添加图形列表(双击定位)
- 图形信息显示(选中右键)
- 图形信息编辑(选中右键)
- 图形删除(选中右键)
- 图形拖拽与复制(按Ctrl键)
- 图形拉伸变形
- 图形位置微调(按方向键)
- 撤消和恢复功能
- Tab次序预览(Tab键)
- 右键直接进入选择状态
- 设置隐藏和显示隐藏(图形菜单)
- 响应鼠标滚动
- 画布动态响应窗口大小变化
============================= 二、使用帮助 =============================
- 图片只能保存为位图(*.bmp),且为无损压缩
- 控制栏可供选择的内容: (1)画笔颜色、风格、粗细 (2)画刷颜色、风格
- 在选择模式下可以进行的操作: (1)选中、拖动、拉伸变形、按CTRL键复制、按方向键进行微调 (2)右键菜单弹出信息(先选中):包括画布大小、图形操作、图形信息概况 (3)选中之后必须按住图形周围的圆点进行变形
- 在画图模式下可以进行的操作: (1)一般操作 (2)按SHIFT键画正形(正圆、正方形、斜45度直线)
- 附加功能: (1)Tab次序:控制显示在【图形】菜单中调整 (2)隐藏:图形设置隐藏,隐藏显示在【图形】菜单中调整 (3)自定义名称:图形设置中更改 (4)图形列表:双击可定位图形,选中图形也会定位列表
============================= 三、代码结构 =============================
-
概况 (1)代码行数:约3000行(View:~1000 Graphic:~1000) (2)主要类名:(带*的会有技术讲解) * CGraphic(子类:直线类CLine,椭圆类CEllipse,矩形类CRectangle,曲线类CCurve) CHelpDlg(模态帮助提示界面) * CStartupDlg(非模态启动界面) ConfigDlg(模态图形编辑界面) GraphicMember(通用图形数据转存类) * CGraphicLog(操作记录类,实现撤消和恢复)
-
类的讲解和技术解析(带的会详解) (1)CGraphic:图形基类 1) 基类及派生类数据成员(看名称,略) 2) 主要静态函数 CreateGraphic: 根据介质创建相应类并赋值 GetIdBySelection... : 存储画笔(刷)类型的一种方式,采用位运算 LineHitTest: 若点在直线上,那么短两边和等于第三边,以此判断 3) 主要成员函数 Serialize: 序列化(在子类中必须先调用父类的序列化) UpdateData: 类似于MFC中的UpdateData(GraphicMember充当交换介质) Draw: 画图 DrawSelectedEdge: 画选中后四周的点 * HitTest: 测试点是否在图形内部,若是,bResult为真 * HitSizingTest: 测试点是否在图形的四周变形点上,若是,bResult为真 GetRect: 返回图形的矩形坐标,便于重绘 4) 宏 选择误差:(->N:趋于N更精确) SELECT_MISS_LINE: 直线(->1) SELECT_MISS_ELLIPSE: 椭圆(->0) DRAG_INF_WIDTH: 拉伸圆点 其他: INF_WIDTH: 图形外边框厚度 LOG_MAX_SAVE: 最大撤消数 图形类的类型(LINE...) IF_NULL_PEN: 是否是透明画笔 IF_NULL_BRUSH: 是否是透明画刷 Convert_To_Graphic:转换为图形类 5) 带讲解 HitTest和HitSizingTest:其实就是个回调函数,用来判断点是否在图形内部 HitSizingTest有另外两个参数 PtX PtY,是int**类型(有原因的) 假如要让图形变形,就要改它坐标,有时要改它的A坐标的X,B坐标的Y 那么就要保存原坐标的LONG变量指针,再间接改变它 6) 其他内容 操作图形的界面很特殊。可以这么想,假如所有图形就不可拖动和更改,图形 内容变的丰富,可以响应许多消息,可以加载位图,那么这个程序就实现 了一般商业程序UI的功能。所以,可以用设计UI的思想来设计这些类。 一般的开源UI库有Duilib和XCGUI,涉及工厂模式,观察者模式等等模式,且 实现控件坐标非硬性编码,界面可由ZIP加载(通过解析XML和图片), 所以多读优秀的代码可以提升思想。 有兴趣可以看Java的《Head First设计模式》,语言不同,但思想是互通的。 MFC的思想不错,只是可重用性不足,安全性不足,所以现在的软件一般采用 开源的或自己开发的界面库。 掌握了思想,技术实现就不是问题(只是时间问题)。 (2)CGraphicLog 1) 枚举体: 代表操作类型,包括新增,更改,删除 2) 结构体: GraphicOperation 包括操作类型,保存的数据对象,对应下标 Trace函数便于调试 3) 单词解释: Undo - 撤消,Done - 恢复 4) 解释 本类的实现思想略为复杂(详见代码注释) 虽然有两个成员是CList,但实现的功能是堆栈(思考为什么) 因为删除了对象,不能真删了它,不然怎么恢复? 对象被更改了,得保存更改之前的备份,这是UPDATE操作(new操作) 我又画了东西,那么Done里的东西不复存在,记录记不下了,要删 可是会导致重复删除(思考?),怎么解决? “引用”思想 ——创建时维持引用计数为1,删除时减去1,如果计数为0则删除。 (3)CStartupDlg 运用工具:定时器,无模态对话框,线程 线程同步方法:事件(CEvent->HANDLE),WaitingForSingleObject
-
其他技术解析 (1)双缓冲位图和后台位图 直接在屏幕DC上操作,那么每画一次,就得更新一次界面,所以会闪屏 如果在缓冲上操作,然后BitBlt给屏幕,那只要更新一次 后台位图的功能是:当拖拽图形A的时候,除去这个图形之外的所有图形 全部画在X上,此时拖动A,只要将屏幕重设成X,再画改变坐标后的A, 再加上双缓冲,就可以有效避免闪屏 注:为了简便(累。。),有些细节没有处理,所以还是会有闪屏 注2: 在有些BitBlt操作之前,必须先调用UpdateWindow (2)保存为位图 位图:BITMAPFILEHEADER,BITMAPINFO,位图像素 函数实现详见XXXView::OnSaveAsBitmap,方法固定
============================= 四、总体评价 =============================
- 本人带有代码格式化的习惯(格式化直观体现美和便于阅读)
- 推荐格式化工具(Visual Assist X)
- 程序代码相对较长,因此会有未发现的BUG……
- 代码注释较少,故将解释写在帮助中
- 写此文也是为了总结MFC的主要内容
- 不熟悉的类和方法可以查询MSDN
- 尚未尝试的功能:多选(很复杂,相当于重新建构),旋转(像素级运算), (PS:尝试后倒地不起)
- 代码更新:三周