实现重绘

来源:互联网 发布:淘宝的中药材 编辑:程序博客网 时间:2024/04/28 22:32

       我们在上一章“简单绘制擦除”里面讲解了如何绘制和擦除图形,但是只要文档刷新前面所绘制的图形就会消失。绘图程序就是要保存所绘制的线条等,所以这次给大家讲解图形的重绘。

大家都知道MFC程序的Document-View结构,在Document类中保存数据,在View类中显示数据。所以只要在绘制图形时,只要把绘制的图形在Document类中保存起来,并且在View类中重绘出来就是了。

上章我们新建了一个myGraphic程序,这里接着修改此程序,要保存绘制的图形,需要用到数组来保存数据,以便访问。MFC提供了很多动态的数组,这里使用一个简单的支持类型检查的类CArray,在使用这个类时要包含头文件#include <afxtempl.h>。类的具体用法参看MSDN,这里直接用之。

此程序没有使用类,只是简单的绘制图形,要保存绘制的图形需要保存图形的起始点和终止点,还需要一个分辨图形类型的参数。一共需要三个变量,这里新建一个数据结构来包含这三个变量。定义如下:

struct SAVE_GRAPHIC

{

    int nDrawType;      // 图形的类型

    CPoint ptOrigin;    // 图形的起始点

    CPoint ptEnd;       // 图形的终止点

};

此时需要定义一个数组来保存定义的结构,数组的定义如下:CArray<SAVE_GRAPHIC*, SAVE_GRAPHIC*> m_arrGraphic;。这条语句主要意思是在变量m_arrGraphic中保存的是SAVE_GRAPHIC结构的指针(第二个参数),从m_arrGraphic中得到的是SAVE_GRAPHIC结构的指针(第一个参数)。

至此需做的准备都已做完,只剩下在绘制完图形后保存图形,在窗口重绘时绘制图形。要保存图形就在OnLButtonUp函数中实现,重绘图形就在OnDraw函数中实现(因为窗口重绘时会激活WM_PAINT消息,调用OnDraw函数)。

OnLButtonUp函数修改如下:

void CMyGraphicView::OnLButtonUp(UINT nFlags, CPoint point)

{

    // TODO: Add your message handler code here and/or call default

    ASSERT(m_nDrawType >= DRAW_NONE);

    if (m_nDrawType < DRAW_NONE)

    {

        CView::OnLButtonUp(nFlags, point);

        return;

    }

    if (0 == m_nStep)

    {

        m_ptOrigin = point;

        m_ptPreMoving = point;

        m_nStep = 1;

    }

    else if (1 == m_nStep)

    {

        CClientDC dc(this);

        int nOldMode = dc.SetROP2(R2_NOTXORPEN);

        switch (m_nDrawType)

        {

        case DRAW_NONE:

            break;

        case DRAW_LINE:

            dc.MoveTo(m_ptOrigin);

            dc.LineTo(m_ptPreMoving);

            dc.MoveTo(m_ptOrigin);

            dc.LineTo(point);

            break;

        case DRAW_RECT:

            dc.SelectStockObject(NULL_BRUSH);

            dc.Rectangle(CRect(m_ptOrigin, m_ptPreMoving));

            dc.Rectangle(CRect(m_ptOrigin, point));

            break;

        default:

            break;

        }

        if (m_nDrawType > DRAW_NONE && m_nDrawType <= DRAW_RECT)

        {// 新增加的,保存绘制的图形

            SAVE_GRAPHIC *pSaveGraphic = new SAVE_GRAPHIC;

            pSaveGraphic->nDrawType = m_nDrawType;

            pSaveGraphic->ptOrigin = m_ptOrigin;

            pSaveGraphic->ptEnd = point;

            CMyGraphicDoc *pDoc = GetDocument();

            pDoc->m_arrGraphic.Add(pSaveGraphic);

        }

        m_nStep = 0;

        dc.SetROP2(nOldMode);

    }

    CView::OnLButtonUp(nFlags, point);

}

OnDraw函数中重绘图形也很简单,只需要从Document类中读取数据,在分类绘制图形即可。

void CMyGraphicView::OnDraw(CDC* pDC)

{

    CMyGraphicDoc* pDoc = GetDocument();

    ASSERT_VALID(pDoc);

    // TODO: add draw code for native data here

    pDC->SelectStockObject(NULL_BRUSH);

    for (int i = 0; i < pDoc->m_arrGraphic.GetSize(); ++i)

    {

        SAVE_GRAPHIC *pSaveGraphic = pDoc->m_arrGraphic.GetAt(i);

        ASSERT(pSaveGraphic);

        if (!pSaveGraphic)

            continue;

        switch (pSaveGraphic->nDrawType)

        {

        case DRAW_NONE:

            break;

        case DRAW_LINE:

            pDC->MoveTo(pSaveGraphic->ptOrigin);

            pDC->LineTo(pSaveGraphic->ptEnd);

            break;

        case DRAW_RECT:

            pDC->Rectangle(CRect(pSaveGraphic->ptOrigin, pSaveGraphic->ptEnd));

            break;

        default:

            break;

        }

    }

}

至此图形的重绘已经完成。

O(_)O~,别忘了,上面保存图形用的是new出来的指针,在堆上,所以在程序退出时一定要delete掉。在Document类释放资源可以重载虚函数virtual void DeleteContents();具体实现如下:

void CMyGraphicDoc::DeleteContents()

{

    // TODO: Add your specialized code here and/or call the base class

    for (int i = 0; i < m_arrGraphic.GetSize(); ++i)

        delete m_arrGraphic.GetAt(i);

    m_arrGraphic.RemoveAll();

    CDocument::DeleteContents();

}

是不是很简单……

又听到一首好听的歌刘若英的《当爱在靠近》,这首歌的每一句歌词都是如此的温柔!

 

原创粉丝点击