如何用VC++实现作图(做一个类),主要是圆圈和方形,并能用箭头线将他们连起来,且要能识别箭头线的两端,即哪个图在箭头线的起始端,哪个在末端,其实就是要识别图形间代表的数据关系.做的图还要能保存及修改,且修改后图形代表的新的数据关系要能识别.

解决方案 »

  1.   

    我的建议:
    1。采用SDI程序
    2。定义圆圈类,方形类,箭头类,这三个都从基类如CShapeObj派生。圆圈类和方形类元素包括位置属性,箭头类除了首末位置属性,还用于存储箭头线连接的是那两个对象指针。每个类自己实现Serialize函数。
    3。定义指针链表对象存储的是CShapeObj对象指针如CTypedefPtrList<CPtrList,CShapeObj*> m_shapeObjList;由于圆圈类,方形类由CShapeObj派生,所以这些对象指针都可以存储到这个链表。所有操作包括增加、删除都对这个链表操作。显示的内容都从这个链表获得。
    4。专门定义一个指针链表,用于存储箭头类对象,箭头类中的元素标明箭头的的起始端(连接的对象和坐标)、末端。
      

  2.   

    如基类的定义
    class CShapeObj : public CObject  
    {
    protected:
    DECLARE_SERIAL(CShapeObj)
    public:
    CShapeObj();
    virtual ~CShapeObj();
    void Serialize(CArchive &ar);
    BOOL IsPointInObj(CPoint vpoint);
    public:
    virtual void DrawSelFrm(CDC *pDC);

    virtual void Draw(CDC* pDC);
    CDrawRect Pos;
    int nType;
    int nId;
    short nRow;
    float xBias;
    };//以画单选框为例draw Button Control
    class CRadioShape : public CShapeObj
    {
    public:
    CRadioShape();
    virtual ~CRadioShape();
    public: virtual void Draw(CDC *pDC);
    void Serialize(CArchive &ar);
    };class CDrawIconView : public CView
    {
    public:
          CTypedPtrList<CPtrList,CShapeObj *> SelShapeObjList;
          CTypedPtrList<CPtrList,CShapeObj *> ShapeObjList;
    }
    void CDrawIconDoc::Serialize(CArchive& ar)
    {
    int m_nCount;
    CShapeObj *m_pShapeObj;
    POSITION pos=this->GetFirstViewPosition();
    CDrawIconView *pView=(CDrawIconView *)this->GetNextView(pos);
    if (ar.IsStoring())
    {for(int i=0;i<m_nCount;i++){
    m_pShapeObj=pView->ShapeObjList.GetAt(pView->ShapeObjList.FindIndex(i));
    m_pShapeObj->Serialize(ar);
    }
      

  3.   

    //创建的例子我的代码通过托拽实现,在此为例子,供参考
    BOOL CDrawIconView::OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point) 
    {
    int m_nDataType;
    if(pDataObject->IsDataAvailable( CF_TEXT ))
    {
    HGLOBAL hMem = pDataObject->GetGlobalData( CF_TEXT );
    char* lp = (char *)GlobalLock((HGLOBAL) hMem);//lock source
    if (lp != NULL)
    {
    memcpy(&m_nDataType,lp,sizeof(int));

    }
    GlobalUnlock( hMem );//unlock source
    }
    CDrawIconDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    switch(m_nDataType)
    {
    case 0:
    {
    CEditShape *m_pEditShape=new CEditShape;
    m_pEditShape->nId=pDoc->nMaxId;
    m_pEditShape->nRow=m_nCurRow;
    m_pEditShape->Pos.width=TEXT_CONTROL_WIDTH;
    m_pEditShape->Pos.height=TEXT_CONTROL_HEIGHT;

    m_nCurRow++;
    pDoc->nMaxId++;
    ShapeObjList.AddTail(((CEditShape *)m_pEditShape));
    Invalidate(FALSE);
    }
    break;
    case 1:
    {//略
    }
    break;
    case 2:
    {
    CButtonShape *m_pButtonShape=new CButtonShape;
    //略
    ShapeObjList.AddTail(((CButtonShape *)m_pButtonShape));
    Invalidate(FALSE);
    }
    break;
             default:
    break;
    return CView::OnDrop(pDataObject, dropEffect, point);
    }
      

  4.   

    mousefj(冯杰),谢谢,你能否将你实现的这一部分的完整代码给我Email一下,我想仔细验证一下.再一个关键我还要能使用户下次能调出这个图形进行修改,就是要能象Visio那样.
      

  5.   

    1。每个对象均保存到文件中,打开时读入即可。在文档类的序列化实现,我上边的代码Serialize里只是存储,读入你可参考写入。
    2。请给我发短信告诉我你的邮箱。
      

  6.   

    楼上的好心给我一份呀!
    [email protected]
      

  7.   

    我也想要一份,我正要做一个与图形有关的程序,正需要类似得资料。
    [email protected] 
    thank you very much!
      

  8.   

    mousefj(冯杰),看完你写的代码.我想需要给各动态生成对象加上加上鼠标感应事件,以便进行位置的
    拖曳及箭头连接时对箭头线起始端和箭头端的感应,从而能很好地图表示的数据间的关系.
      

  9.   

    我的代码初步实现了鼠标拖动对象的功能(在CDrawIconView::OnMouseMove注释掉的就是拖动功能),因为功能不同,我的对象要求不是任意放置,必须放在客户区的左边或另一个对象的右边。你可以修改将void CDrawIconView::OnMouseMove(UINT nFlags, CPoint point)注释部分还原,自己修改代码实现你的要求。
      

  10.   

    看一下drawcli例子(微软msdn的例子),经典啊,看明白了你就会了