以下代码为VC++编写
主要有四个大类,分别是图元类,命令类,工具管理类和历史记录类
// 图元基类
class CFormObject
{
public:
CFormObject();
~CFormObject();
// 图元迭代器
typedef vector Objects;
// 鼠标事件
virtual void OnLButtonDown(UINT nFlags,CPoint point);
virtual void OnLButtonUp(UINT nFlags,CPoint point);
virtual void OnLButtonDblClk(UINT nFlags, CPoint point);
virtual void OnMouseMove(UINT nFlags,CPoint point);
virtual void OnRButtonDown(UINT nFlags,CPoint point);
virtual void OnRButtonUp(UINT nFlags,CPoint point);
// 鼠标测试(返回鼠标在图元上的位置,各顶点处和图元主体上都返回不同的值)
virtual UINT hitTest(CFormObject *obj);
// 键盘事件
virtual void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
// 重画
virtual void draw();
// 选中
virtual void selected();
// 拷贝
virtual BOOL copy();
CFormObject *GetParent();
void SetParent();
void init(CFormObject *m_parent,...);
CDC *GetDC();
CPen *GetPen();
CBrush *GetBrush();
.......
private:
// 当前工具(可以先将要用到的工具,如线,框等做个枚举,不同类型的工具指向不同的图元类)
CString m_CurTool;
// 当前选中的图元
CFormObject *m_CurSelected;
// 子图元集合
Objects m_ChildrenObj;
// 图元的父图元
CFormObject * m_parent;
// 画布
CDC * pDC;
// 填充笔刷
CBrush m_brush;
// 描绘笔
CPen m_pen;
.......
CHistory m_history;
}
// 命令基类
class CCommand
{
...
virtual void execute();
virtual void unexecute();
}
// 历史记录类
class CHistory
{
public:
typedef vector TCommandList;
/** 增加一个新的命令并执行,
* 如当前命令不是最后一条命令,要清除后面的命令
* @return 如果命令执行失败,返回false,否则true
*/
bool pushCommand(CCommand* cmd);
/// 清空历史命令记录
void clearCommand();
private:
// 历史记录列表
TCommandList m_History;
}
// 工具管理类
class CToolMgr
{
typedef map TOOLS;
/// 工具集合
TOOLS m_tools;
/// 活动工具名称
string m_active;
/// 根据名称得到工具对应的图元对象
CFormObject* getTool(string toolname);
/// 得到当前活动的图元对象
CFormObject* getActiveTool();
/// 得到活动工具名称
string getActiveToolName();
/// 设定活动工具
bool setActiveToolName(string toolname);
/// 登记工具对象
bool registerTool(string toolname, CFormObject* tool);
}
图元类派生子类:
CFromObject : public CObject
CQLine
CQRectangle
CQCircle
.........
命令类派生子类:
CCommand
CCreateCmd // 创建图元命令
CCopyCmd
CCutCmd
CPasteCmd
CUndoCmd // 撤消命令
CRedoCmd
CMoveCmd
CRotateCmd // 旋转命令
CReMoveCmd
CSelectCmd // 选择命令
.......
大概思路:
view中声明两个CFormObject和CToolMgr的对象m_Object和m_Toolmgr;
在程序运行时,在View初始化或创建的函数中先注册工具registerTool,然后当选中一个工具时
,调用setActiveToolName,设定当前的图元对象,然后View的各事件中直接转给CFormObject,在
CFormObject的派生类中也重载这些鼠标事件.
注册方法:
Toolmgr.registerTool("line",new CQLine());
调用事件的方法:
Toolmgr.getActiveTool()->OnLButtonDown(nFlag,point);
.............