新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 中文XML论坛 - 专业的XML技术讨论区计算机技术与应用『 C/C++编程思想 』 → 用VC实现小型矢量图形系统的开发 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 8096 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 用VC实现小型矢量图形系统的开发 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客楼主
    发贴心情 用VC实现小型矢量图形系统的开发

    大家学习了VC的MFC的一些基础知识后,如果能用VC开发一个比较实用的软件,对熟悉VC各方面编程和面向对象的软件设计和开发都是很有帮助的。

      本文旨在通过对一个作者自己开发的小型矢量图形系统全面讲述而达到让读者了解一个小软件从设计到实现的阶段的解决的问题。同时也从界面和功能上对MFC和Windows系统功能的挖掘,同样,对于学习计算机图形学的读者,也可以看到本文有很多对图形学算法和实现的有益探讨。

      一. 功能和界面设计

      首先,让大家对一个本软件功能的大概了解。当你着手开发一个软件时,首先要解决的当然是本软件的功能(软件工程常称作用例,具体概念可以参考有关资料,不妨简单理解为用户使用它能完成哪些工作)。由于写这篇文章时,本软件已经具有比较完整的原型。我们可以结合它的界面(图1)来介绍软件设计的过程。
    按此在新窗口浏览图片
    图 1 软件界面  

      可以看到,本软件是实现了一个绘图功能的子集。最初就确定了开发环境为VC6.0,界面采用IE风格。在使用上为了给用户最大的便利,采用了三种工具条(普通文件、打印操作等标准工具,对图形对象属性设置的工具条式对话框,带文字说明的大按钮式可浮动或任意船坞- Dock定位的绘图工具条)。

      操作上采用左键点击建立图形对象起始点,移动动态调整图形大小和位置(随手画采用按住左键拖动的方式,再次点击左键确定位置,右键取消操作,双击确定(结束)多步图形对象(如多边形)的绘制。在功能设计方面基本符合一般图形软件的惯例,但出于作者的便利和保护鼠标的考虑,整个功能体现了基本无需按住左键拖动的思想。这也是很容易让人接受的,因为即便习惯拖动的用户拖动时也会产生位置调整,只是释放后还是出于拖动状态,再次点击或双击才最终确定。

      功能上选择了画线、框、圆、多边形、立体、文字、曲线、填充以及删除的功能,根据是否填充和光照又增加了几个类别,填充方式根据图形学的概念提供了两种方式(以后介绍)。根据对图形属性取了线宽、线型(很容易实现简单的线型,由于想加入更多的特性,作者先没有具体实现它,以后作者会提到它的实现,读者有兴趣可以试着实现)、边框色、填充色和字体几个属性。当然,这些功能在面向对象的方法中都是可以很方便扩展的(如画椭圆,选取对象,对象的位移和旋转操作,根据填充算法实现同色选取,即Photoshop等软件的魔棒功能等),对于橡皮擦功能可以很简单的实现特定工具或告诉用户如何实现此功能(即用背景色利用已有功能绘图)。

      内部实现上,要求单独记录各图形的关键属性(如位置、色彩等,这些是矢量图区别于位图的特点)。由于各对象可以形成对象链表,因此,也要求实现多步撤消(Undo)和重做(Redo)的功能,这往往是用户所十分期待的功能(Window自带的画笔附件程序在这点上就很欠缺)。


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/4/10 15:59:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客2
    发贴心情 
    二. 对象设计

      面向对象的程序设计方法都支持三种基本的活动:识别对象和类,描述对象和类之间的关系,以及通过描述每个类的功能定义对象的行为。

      首先介绍一下对象(Object)和类(Class)的区别,类是同类对象数据和功能的描述和实现(C++中用Class关键字定义的是类),对象是类的在内存中的具体形态(用类名声明或用new操作生成的是对象变量),一般称对象为类的实例(Instance)。

      对于图形对象的对象设计由于它们的较强的相关性,往往在很多面向对象编程书都提到过,故相信读者识别对象和类不会很困难。但是,要充分利用继承和多态的特性来描述对象和类之间的关系,以及通过描述每个类的功能定义还是要具体问题具体分析的。

      下面还是以一副图来说明。图2是采用北航软件所的软件分析与测试工具——SafePro生成的本软件的类图局部。

      由图2中可以清晰看到,我们的绘图子系统实现部分主要利用了几个从MFC可序列化的基类CObject继承的四个类:MFC已有类CArray,CObList,CDC以及我们自己需要实现的类CGraph。CDC对象封装了我们可以利用Windows系统绘图功能的设备无关的几乎全部绘图功能。CArray类和CObList 类用于实现基于CObject类的对象的数组和链表存储的辅助类。CGraph是抽象类,所有图形对象都由它继承而来。值得注意的是,由于多边形和框都是直线的组合,本软件采用了从CLine继承的方法,可以充分利用它的功能。

      现在并不想把所有类的功能定义(以后会逐步介绍大部分)。下面介绍一些关系全局的类的设计。
    按此在新窗口浏览图片

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/4/10 16:00:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客3
    发贴心情 
    1. 基于文档-视图结构的类

      在图1可以看到,本软件是基于多文档界面(MDI)的。由AppWizard选取多文档界面后,它会帮助我们生成基本的基于文档-视图结构的类。本软件使用DrawGraph为应用程序名,故有以下类:CMainFrame,CChildFrame,CDrawGraphApp,CDrawGraphDoc ,CDrawGraphView。

    按此在新窗口浏览图片
    按此在新窗口浏览图片
    按此在新窗口浏览图片

      其中:CDrawGraphApp(以后我用是应用程序类,支持应用程序的建立和基本交互,我们可以不必改它。CChildFrame类是视图文档的容器,除了在显示图标上的定制外,我们也可以不修改它。

      CMainFrame,CDrawGraphDoc ,CDrawGraphView用于分别实现主窗口、文档、视图的功能。

      1). 主窗口(CMainFrame)主要需要定制图标、工具条的建立、显示和交互。下面是类的定义,阴影部分是自己定制的(非AppWizard自动生成)

    class CMainFrame : public CMDIFrameWnd

    {

     DECLARE_DYNAMIC(CMainFrame)//支持动态建立

     public:

     CMainFrame();

     // Attributes

     public:

      // Operations

     public:

      // Overrides

      // ClassWizard generated virtual function overrides

      //{{AFX_VIRTUAL(CMainFrame)

     public:

      virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

    //}}AFX_VIRTUAL

    // Implementation

    public:

    int m_Depth;//立体深度

    COLORREF m_fillcolor;//填充色

    COLORREF m_pencolor;//边框色

    LOGFONT m_font;//字体

    int m_penstyle;//线型

    UINT m_penwidth;//笔宽

    void SaveToReg();//记录退出前的窗口状态

    void ReadFromReg();//读取退出前的窗口状态

    objecttype GetDrawType();//返回当前选中的绘图工具类别

    virtual ~CMainFrame();

    #ifdef _DEBUG

    virtual void AssertValid() const;

    virtual void Dump(CDumpContext& dc) const;

    #endif

    protected: // control bar embedded members
     
     CStatusBar m_wndStatusBar;//状态栏

     CReBar m_wndReBar;//标准栏和属性栏的容器工具条

     CDialogBar m_wndDlgBar;//属性栏

     CToolBar m_wndToolBar;//标准栏

     CToolBar m_wndDrawTool;//绘图工具条

     UINT objtype;//选中工具的ID号

     // Generated message map functions

     protected:

      afx_msg void OnDropDown(NMHDR* pNotifyStruct,LRESULT* result);

      //{{AFX_MSG(CMainFrame)

      afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

      afx_msg void OnShowdrawtool();//显隐工具条

      afx_msg void OnUpdateShowdrawtool(CCmdUI* pCmdUI);

      afx_msg void OnFont();

      afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);

      afx_msg void OnColor();

      afx_msg void OnUpdateColor(CCmdUI* pCmdUI);

      afx_msg void OnFillcolor();

      afx_msg void OnUpdateFillcolor(CCmdUI* pCmdUI);

     //}}AFX_MSG

     afx_msg void OnSelectTool(UINT ID);//选中工具

     afx_msg void OnUpdateButtons(CCmdUI* pCmdUI);//处理按钮按下状态

     afx_msg void onchangedpenwidth();

     DECLARE_MESSAGE_MAP()

    };

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/4/10 16:01:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客4
    发贴心情 
    2). 文档(CDrawGraphDoc)用于实现矢量图形对象的建立、存储和读取(即序列化)。

    class CDrawGraphDoc : public CDocument

    {

     protected: // create from serialization only

     CDrawGraphDoc();

     DECLARE_DYNCREATE(CDrawGraphDoc)

      // Attributes

     public:

      // Operations

     public:

      // Overrides

      // ClassWizard generated virtual function overrides

      //{{AFX_VIRTUAL(CDrawGraphDoc)

     public:

      virtual BOOL OnNewDocument();

      virtual void Serialize(CArchive& ar);

      virtual BOOL OnOpenDocument(LPCTSTR lpszPathName);

      virtual void DeleteContents();

     //}}AFX_VIRTUAL

     // Implementation

     public:

      CMainFrame* GetMainFrame();//获得对主框架窗口的指针

      BOOLEAN m_fillmode;//两种填充方式

      void Cancel();//删除当前正在建立的绘图对象

      COLORREF m_color;

      COLORREF m_filledcolor;

      UINT m_PenWidth;

      CGraph* NewDrawing();

      CObList m_graphoblist;//绘图对象列表

      CObList m_redolist;//为redo功能提供的历史记录对象列表

      //以后可以添加下面的功能,把图形存储为流行的图形交互格式。

      //SaveAsBitmap();

      //SaveAsWMF();

      //SaveAsJPEG();

      //SaveAsGIF();

      virtual ~CDrawGraphDoc();

      #ifdef _DEBUG

      virtual void AssertValid() const;

      virtual void Dump(CDumpContext& dc) const;

      #endif

      protected:

       // Generated message map functions

       protected:

        void Refresh();//用于更新视图

        void InitDocument();

        //{{AFX_MSG(CDrawGraphDoc)

         afx_msg void OnFillinborder();

         afx_msg void OnUpdateFillinborder(CCmdUI* pCmdUI);

         afx_msg void OnFilloncolor();

         afx_msg void OnUpdateFilloncolor(CCmdUI* pCmdUI);

         afx_msg void OnPenwidth();

         afx_msg void OnEditUndo();

         afx_msg void OnUpdateEditUndo(CCmdUI* pCmdUI);

         afx_msg void OnClear();

         afx_msg void OnUpdateClear(CCmdUI* pCmdUI);

         afx_msg void OnEditRedo();

         afx_msg void OnUpdateEditRedo(CCmdUI* pCmdUI);

        //}}AFX_MSG

      DECLARE_MESSAGE_MAP()

      };

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/4/10 16:02:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客5
    发贴心情 
    3). 视图(CDrawGraphView)接收用户的对特定图形对象的操作并绘制图形对象。

    class CDrawGraphView : public CView

    {

     protected: // create from serialization only

      CDrawGraphView();

      DECLARE_DYNCREATE(CDrawGraphView)

      // Attributes

     public:

      CDrawGraphDoc* GetDocument();

      // Operations

      public:

       // Overrides

       // ClassWizard generated virtual function overrides

       //{{AFX_VIRTUAL(CDrawGraphView)

      public:

       virtual void OnDraw(CDC* pDC); // overridden to draw this view

       virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

      protected:

       virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);

       virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
     
       virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);

      //}}AFX_VIRTUAL

      // Implementation

      public:

       virtual ~CDrawGraphView();

       #ifdef _DEBUG

        virtual void AssertValid() const;

        virtual void Dump(CDumpContext& dc) const;

       #endif

      protected:

       // Generated message map functions

      protected:

       CPoint m_ptPrev;//前面一次点击的位置

       CGraph* m_curGraph;//当前正在绘制的图形对象

       state bdrawbegin;//绘制状态

       //{{AFX_MSG(CDrawGraphView)

       afx_msg void OnLButtonDown(UINT nFlags, CPoint point);

       afx_msg void OnMouseMove(UINT nFlags, CPoint point);

       afx_msg void OnRButtonDown(UINT nFlags, CPoint point);

       afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);

       afx_msg void OnLButtonUp(UINT nFlags, CPoint point);

      //}}AFX_MSG

      DECLARE_MESSAGE_MAP()

    };

      视图类在界面上改得少,主要是处理鼠标事件和调用各图形对象的绘制方法,实现上也尽量统一,充分利用图形对象的多态性。

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/4/10 16:02:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客6
    发贴心情 
    4). 各图形对象的基类CGraph的考虑是关键,所以是需要关注的。

      它定义了绘图类别和绘制状态两个枚举类型。当你把它定义好后,可以在stdafx.h加上#include “graph.h”来使得所有文件都能自由引用它,并且获得预编译。

    enum state{notstart=0,startstroke,continuedrag,enddraw};

    typedef enum {line ,bezier,solid,light,stroke,circle,rectangle,filledrectangle,&
    polyline,filledcircle,filledpolygon,ellipse,fill,text} objecttype;

    class CGraph : public CObject

    {protected:

    CGraph( ){};

    DECLARE_DYNAMIC( CGraph )

    // Attributes

    protected:

    COLORREF m_color;//所有图形对象都有颜色

    public:

    // Operations

    public:

    virtual state SetNext(CPoint pt)=0;//再次点击,由返回值确定是否结束绘制

    virtual void SetStart(CPoint pt)=0;//一次点击,产生第一点的位置

    virtual void Draw( CDC* pDC )=0;//图形对象绘制自己的方法

    inline void SetColor(COLORREF color){m_color=color;};//设置图形对象颜色

    virtual void DrawXOR(CDC*pDC,CPoint pt)=0;//在拖动状态,图形对象绘制自己的方法

    virtual void Serialize( CArchive& ar );//图形对象序列化的方法

    //以后可以扩展以下功能

    // virtual void IsHit(CPoint pt);//确定对象是否被点击

    // virtual void Highlight();//被点击后突出显示

    // virtual CRect GetBoundRect();//获得图形矩阵,可以用线索的方法局部更新视图,免除闪烁和时延等。

    // virtual void Move(CPoint shift);//移动

    // virtual void Rotate(int Degree);//旋转

    // virtual void Scale(int scalecoef);//缩放

    // virtual void Copy();//拷贝、粘贴、剪切功能

    // virtual void Paste();

    // virtual void Cut();

    };

      虽然是个小软件,“开发过程”还是可以和“软件工程”的步骤基本对应的。

      本软件的“需求分析”是人们需要一个比Windows画笔功能强大,但十分小巧易用的小而精的基于矢量的(易于编辑)的图形工具。而且,另一方面,这个小软件的开发是一个典型的基于VC的面向对象软件开发的尝试,很有教学意义。

      至此,基本完成了“概要设计”。以后将把“详细设计”和“编码”结合起来讲。至于“测试”和“维护”(改错、升级)有兴趣的读者可以自己完成。

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/4/10 16:03:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/9/21 13:54:07

    本主题贴数6,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    121.094ms