国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

利用MFC Document/View框架完成圖形顯示和保存功能

2019-11-08 02:24:13
字體:
來源:轉載
供稿:網友

Document/View結構

首先總結下MFC的Document/View結構相關的知識點:

(1)在MFC中,文檔類負責管理數據,提供保存和加載數據的功能;視類負責數據的顯示,以及提供給用戶對數據編輯和修改功能。

(2)有關文件的讀寫操作在CDocument的Serialize函數中進行,有關數據和圖形顯示的操作在CView的OnDraw函數中進行,相關的函數都是虛函數,我們只需要在派生類中重寫這些函數即可。

(3)在單擊“文件/打開”菜單命令后,應用程序框架會激活“文件打開”對話框,讓用戶指定將要打開的文件名。然后程序自動調用文檔類的Serialize函數,完成數據的加載,同時還會調用視類的OnDraw函數,提供窗口重繪的機會。

(4)在應用程序啟動會創建文檔類對象,同時還創建了框架類對象和視類對象。這是MFC Doc/View的特定,即每當有一個文檔產生,總是會產生一個文檔類對象、框架類對象、視類對象,它們三位一個為這份文檔服務。

(5)對于一個文檔類對象來說,可以有多個視類對象與之相關;對一個視類對象來說,只有一個文檔類對象相關。

(6)若需要保存類對象數據,我們需要設計可串行化的類,數據的保存和加載實際上都是在可串行化的類對象中進行。

(7)可串行化的類均是派生于CObject類,在該類中有Serialize函數,我們可利用該函數做為串行化的入口。

(8)在可串行化的類中,我們“IMPLEMENT_SERIAL宏”會幫助我們在堆上申請對象,因此我們在提取類對象數據時,我們不用分配類對象空間,我們傳入該類的指針即可。

(9)在堆上申請的內存,需要我們手動去釋放,文檔類提供了DeleteContents虛函數,用于文檔對象數據的銷毀。在新建文件和打開文件都會調用這個DeleteContents函數。

(10)MFC為我們提供的文檔/視類/框架結構中,已經為我們設計好了CDoucment類,CView類,CMainFrame類這三個類的相互調用接口。

實例

根據以上特點,我們將繪圖三要素作為數據,保存在文檔類中,在視類中完成圖形的顯示,這個功能基于“圖形重繪”這篇文件進行修改的,部分關鍵代碼如下:

Graph.h 中是圖形類的數據和操作方法

//(1)派生于CObject類class CGraph:public CObject{public:    //(3)聲明中使用DECLARE_SERIAL宏    DECLARE_SERIAL(CGraph)    //(4)定義無參的構造函數    CGraph(void);    CGraph(CPoint ptBegin, CPoint ptEnd, int DrawType);    ~CGraph(void);    //(2)重寫Serialize成員函數    virtual void Serialize(CArchive& ar);public:    enum    {        EN_RECT = 0,        EN_ELLipSE,        EN_LINE,    };    void SetDrawType(int nType);    void SetBeginPoint(CPoint ptBegin);    void SetEndPont(CPoint ptEnd);    CPoint GetBeginPoint();    CPoint GetEndPont();    int GetDrawType();    //new CGraph對象    CGraph* CreateGraphObj();    //完成畫圖功能    void  DrawItem(CDC *pDC);PRivate:    CPoint m_ptBegin;    CPoint m_ptEnd;    int   m_DrawType;};   //Graph.cpp是實現部分

#include "StdAfx.h"#include "Graph.h"//(5)實現文件中使用“IMPLEMENT_SERIAL”宏IMPLEMENT_SERIAL(CGraph, CObject, 1)CGraph::CGraph(void){    m_DrawType = 0;}CGraph::CGraph(CPoint ptBegin, CPoint ptEnd, int DrawType){    this->m_ptBegin = ptBegin;    this->m_ptEnd = ptEnd;    this->m_DrawType = DrawType;}CGraph::~CGraph(void){}//Call your base class version of Serialize to make sure that the inherited portion of the object is serialized. //Insert or extract the member variables specific to your class. void CGraph::Serialize(CArchive& ar){    // call base class function first    // base class is CObject in this case    CObject::Serialize(ar);    // now do the stuff for our specific class    if (ar.IsStoring())    {        ar << m_DrawType << m_ptBegin << m_ptEnd;    }     else    {        ar >> m_DrawType >> m_ptBegin >> m_ptEnd;    }}void CGraph::SetDrawType(int nType){    m_DrawType = nType;}void CGraph::SetBeginPoint(CPoint ptBegin){   m_ptBegin = ptBegin;}void CGraph::SetEndPont(CPoint ptEnd){    m_ptEnd = ptEnd;}  CPoint CGraph::GetBeginPoint(){    return m_ptBegin;}CPoint CGraph::GetEndPont(){    return m_ptEnd;}int CGraph::GetDrawType(){    return m_DrawType;}CGraph* CGraph::CreateGraphObj(){    CGraph *pObj = NULL;    try    {        pObj = new CGraph(m_ptBegin, m_ptEnd, m_DrawType);    }    catch (...)    {       return NULL;    }    return pObj;}//圖形繪制顯示功能void CGraph::DrawItem(CDC *pDC){    //開始繪圖操作流程    CBrush* pBrush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));    CBrush* pOldBrush = pDC->SelectObject(pBrush);    //畫圖選擇    switch (m_DrawType)    {    case CGraph::EN_RECT :        {            pDC->Rectangle(CRect(m_ptBegin, m_ptEnd));            break;        }    case CGraph::EN_LINE :        {            pDC->MoveTo(m_ptBegin);            pDC->LineTo(m_ptEnd);            break;        }    case CGraph::EN_ELLIPSE :        {            pDC->Ellipse(CRect(m_ptBegin, m_ptEnd));            break;        }    default:        break;    }    pDC->SelectObject(pOldBrush);}

//CGraphicview.cpp 主要是圖形數據保存和顯示 m_obArray是CObject類型,是文檔類的成員數據

/*****************************************************************函數名稱: *功    能:畫圖顯示到屏幕*作    者:Jin*日    期:2017年2月12日****************************************************************/void CGraphicView::OnDraw(CDC* pDC){    CGraphicDoc* pDoc = GetDocument();    ASSERT_VALID(pDoc);    if (!pDoc)        return;    //窗口變化或者窗口生成時開始繪制歷史圖形    int nCount = pDoc->m_obArray.GetCount();    for (int i = 0; i < nCount; i++)    {        ((CGraph*)pDoc->m_obArray.GetAt(i))->DrawItem(pDC);    }}/*****************************************************************函數名稱: 主要完成數據保存和顯示*功    能:*作    者:Jin*日    期:2017年2月12日****************************************************************/void CGraphicView::OnLButtonUp(UINT nFlags, CPoint point){    // TODO: 在此添加消息處理程序代碼和/或調用默認值    m_GrahpInfo.SetEndPont(point);         //顯示本次圖形,但是存在延遲效果不佳    //CClientDC dc(this);    //m_GrahpInfo.DrawItem(&dc);    //記錄本次畫圖數據    CGraph *pNewGraph = m_GrahpInfo.CreateGraphObj();    if (pNewGraph != NULL)    {        CGraphicDoc* pDoc = GetDocument();        if (pDoc!= NULL)        {            pDoc->m_obArray.Add(pNewGraph);        }    }    //引發客戶窗口無效,發生重繪,    //圖形能立即顯示,但大量數據情況下頻繁重繪效率下    Invalidate(TRUE);    CView::OnLButtonUp(nFlags, point);}GraphicDoc.cpp主要是完成文檔數據的銷毀、數據加載和保存功能

//重新新建或者打開文檔對象之前需要數據銷毀,防止堆溢出void CGraphicDoc::DeleteContents(){    int nCount = m_obArray.GetCount();    for (int i = 0; i < nCount; i++)    {        if (NULL != m_obArray.GetAt(i))        {            //刪除指針對象的所指的內存            delete m_obArray.GetAt(i);            m_obArray.SetAt(i, NULL);        }    }    //清空數據    m_obArray.RemoveAll();}// CGraphicDoc 序列化void CGraphicDoc::Serialize(CArchive& ar){    CGraphicView *pView = NULL;    CGraph *pGraph = NULL;    POSITION pos = GetFirstViewPosition();    if (pos != NULL)    {        pView = (CGraphicView*)GetNextView(pos);    }    if (ar.IsStoring())	{	}	else	{	}    //使用這種方式更加簡便    m_obArray.Serialize(ar);}

運行結果:

我們繪制一些圖案后,然后點擊保存,會有“文件保存”提示框,我們命名為GraphData.txt,關閉應用程序后;使用打擊工具欄的“打開”后,會有“文件打開對話”,我們選中GraphData.txt,界面上就會顯示我們之前繪制的圖案了,如下所示:

以上我們是使用MFC的文檔/視類結構以及串行化完成圖形重繪和保存功能。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 哈巴河县| 南溪县| 武安市| 长葛市| 修水县| 江阴市| 噶尔县| 赤城县| 新蔡县| 兴仁县| 吴江市| 互助| 汝城县| 南郑县| 房产| 嘉义县| 德阳市| 沙洋县| 察雅县| 平阳县| 盐津县| 芜湖市| 中宁县| 海伦市| 柳江县| 仁布县| 南岸区| 乌兰县| 太谷县| 广东省| 荔波县| 永福县| 宁津县| 苏尼特右旗| 遂昌县| 沈丘县| 济宁市| 绿春县| 台前县| 潍坊市| 安庆市|