网站布局用什么代码,个人网站的网页,对网络推广的理解,做网站找华企双缓冲
双缓冲在之前写字符雨的时候#xff0c;已经简单介绍过#xff0c;今天我们来写一个简单的程序来体会双缓冲机制
我们实现一个在屏幕上画直线的功能#xff1a;
在类中添加变量#xff0c;保存起点坐标和终点坐标#xff1a;
//定义一个容器#xff0c;保存每…双缓冲
双缓冲在之前写字符雨的时候已经简单介绍过今天我们来写一个简单的程序来体会双缓冲机制
我们实现一个在屏幕上画直线的功能
在类中添加变量保存起点坐标和终点坐标
//定义一个容器保存每次画的直线
using Lint std::pair(CPoint,CPoint);
CListm_List;CPoint m_begin;
CPoint m_end;在对话框上添加WM_MOUSEMOVEWM_LBUTTONDOWMWM_LBUTTONUP消息处理函数
void C双缓冲View::OnDraw(UINT nFlags,CPoint point){C双缓冲View* pDoc GetDocument();ASSERT_CALID(pDoc);if(!pFoc)return;//画直线pDC-MoveTo(m_begin);pDC-LineTo(m_end);CVIew::OnMouseMove(nFlags,point);
}void C双缓冲::OnMouseMove(UINT nFlags,CPoint point){if(nFlagsMK_LBUTTON){m_end point;IncalidateRect(NULL,TRUE);}CView::OnMouseMoce(nFlags,point);
}void C双缓冲View::OnLButtonDown(UINT nFlags,CPoint point){//记录开始坐标CVIew::OnLButtonDown(nFlags,point);m_begin point;
}void C双缓冲View::OnLButtonUp(UINT nFlags,CPoint point){//记录终点坐标m_end point;CVIew::OnLButtonUp(nFlags,point);ReleaseCapture();
}这样写完之后没有反应这是因为没有无效区域我们将OnLButtonUp函数中添加无效区域就可以了
void C双缓冲View::OnLButtonUp(UINT nFlags,CPoint point){//记录终点坐标m_end point;CVIew::OnLButtonUp(nFlags,point);InvalidateRect(NULL,TRUE);
}只有有了无效区域绘图消息才会产生
然后我们完善
//定义一个容器保存每次画的直线
using Lint std::pair(CPoint,CPoint);
CListm_List;void C双缓冲View::OnDraw(UINT nFlags,CPoint point){C双缓冲View* pDoc GetDocument();ASSERT_CALID(pDoc);if(!pFoc)return;pDC-MoveTo(m_begin);pDC-LineTo(m_end);auto pos m_list.GetHeadPossition();while(pos){auto Lint m_list.GetNext(pos);//画直线pDC-MoveTo(Line.first);pDC-LineTo(line.second);}CVIew::OnMouseMove(nFlags,point);
}void C双缓冲::OnMouseMove(UINT nFlags,CPoint point){if(nFlagsMK_LBUTTON){m_end point;IncalidateRect(NULL,TRUE);}CView::OnMouseMoce(nFlags,point);
}void C双缓冲View::OnLButtonDown(UINT nFlags,CPoint point){//记录开始坐标CVIew::OnLButtonDown(nFlags,point);m_begin point;//捕捉客户区外鼠标消息SetCapture();
}void C双缓冲View::OnLButtonUp(UINT nFlags,CPoint point){//记录终点坐标m_end point;m_list.AddTail(Line(m_begin,m_end));CVIew::OnLButtonUp(nFlags,point);InvalidateRect(NULL,TRUE);ReleaseCapture();
}这样写完了之后确实可以画出来直线但是这是我们直接操作外设的所以会出现闪屏的情况
这时候就需要我们的双缓冲了
双缓冲就是我们操作内存将直线画在内存上然后将内存完整拷贝到外设上这样就可以避免操作慢闪屏的问题
Win32中能操作设备的只有设备句柄hdc
而在MFC中封装了
CDC-------对应Win32GetDC
CMetaFileDC 矢量图位图了解一下就行了
CPainDCWM_PAINT::BEGINPAINT
CWindowDC桌面窗口的HDC 这几种对象能代表他们各自的东西肯定是内部有绑定机制Attah()
双缓冲内存DC这里的CDC就代表了内存DC
然后我们修改代码
void C双缓冲View::OnDraw(UINT nFlags,CPoint point){C双缓冲View* pDoc GetDocument();ASSERT_CALID(pDoc);if(!pFoc)return;//双缓冲绘图//1.创建内存DCCDC dcMem;dcMem.CreateCompatibleDC(pDC);CRect rect;GetClintRect(rect);//2.创建一张屏幕DC一样的位图CBitmap bitmap;bitmap.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());//3.送到内存DC中dcMem.SeleObject(bitmap);dcMem.FillSolidRect(rect,RGB(255,255,255));//然后我们使用内存DC绘图dcMem-MoveTo(m_begin);dcMem-LineTo(m_end);auto pos m_list.GetHeadPossition();while(pos){auto Lint m_list.GetNext(pos);//画直线dcMem-MoveTo(Line.first);dcMem-LineTo(line.second);}//4.拷贝到设备pDC.BitBit(0,0,rect.Width(),rect.Height(),dcMem,0,DRCCOPY);CVIew::OnMouseMove(nFlags,point);
}修改完这个函数后将绘制无效区域的函数不再擦除背景 画壁画刷位图 在Win32中都是GDI句柄 MFC封装了GDI对象 Win32什么流程 MFC就还是什么流程 void C双缓冲View::OnDraw(UINT nFlags,CPoint point){C双缓冲View* pDoc GetDocument();ASSERT_CALID(pDoc);if(!pFoc)return;//双缓冲绘图//1.创建内存DCCDC dcMem;dcMem.CreateCompatibleDC(pDC);CRect rect;GetClintRect(rect);//2.创建一张屏幕DC一样的位图CBitmap bitmap;bitmap.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());CPen pen;pen.CreatePen(PS_DOT,55,RGB(0,255,255));//把画笔送到内存DCdeMem.SelectObject(pen);//3.送到内存DC中dcMem.SeleObject(bitmap);dcMem.FillSolidRect(rect,RGB(255,255,255));//然后我们使用内存DC绘图dcMem-MoveTo(m_begin);dcMem-LineTo(m_end);auto pos m_list.GetHeadPossition();while(pos){auto Lint m_list.GetNext(pos);//画直线dcMem-MoveTo(Line.first);dcMem-LineTo(line.second);}//4.拷贝到设备pDC.BitBit(0,0,rect.Width(),rect.Height(),dcMem,0,DRCCOPY);CVIew::OnMouseMove(nFlags,point);
}序列化 为什么要有序列化 我们在绘图应用程序上绘制的图形可以保存起来我们之后还可以打开 而我们上面写的程序是不能保存的这就是序列化的基本功能 简单使用以下序列化 首先继承于CObject类内添加声明宏DECLARE_SERTAL类外实现宏IMPLEMENT_SERIAL //直线类
class Cline:public Cobject{
public:CLine(){};CLine(int x,int y,CString type):x(x),y(y),str(type){};virtual coid Setialize(CArchice* ar){if(ar,IsLoading()){//加载arxystr;}else{//保存arxystr;}}int x;int y;int color;CString str;DECLARE_SERTAL(CLine)
}
IMPLEMENT_SERIAL(CLine,Cobject,1)int main(){int nRetCode 0;HMODULE hModule ::GEtModuleHandle(nullptr);AfxWinInit(hModule,nullptr,::GetCommandLine(),0);CLine line(40,40,直线);CFile file;file.Open(R(文件路径\文件名),CFile::modeCreate|CFile::modeWrite);CArchive ar(file,CArchice::store,4096);arline;ar.Close();file.Close();return nRetCode;
}我们这样实现后发现我们只写了三个成员但是文件中有很多我们来简单追踪有一下序列化是如何实现的
序列化过程 CArchive 归档类对象
CArchive AFXAPI operator(CArchive ar, CLine* pOb)
{pOb (CLine*) ar.ReadObject(RUNTIME_CLASS(CLine)); return ar;
}CArchive ar(file, CArchive::store,4096)
{m_nMode nMode;//模式m_pFile pFile;//文件句柄m_nBufSize nBufSize //缓冲区大小this-m_lpBufStart new BYTE[m_nBufSize]; //申请了缓冲区大小m_lpBufMax m_lpBufStart nBufSize;//缓冲区的尾地址m_lpBufCur (IsLoading()) ? m_lpBufMax : m_lpBufStart;
}struct
{类版本类大小x
}void CArchive::WriteObject(const CObject* line)
{//获取类信息地址CRuntimeClass* pClassRef pOb-GetRuntimeClass();//写类信息WriteClass(pClassRef);((CObject*)pOb)-Serialize(ar对象/*归档类对象*/);{ar x{return CArchive::operator((char)x); {if (m_lpBufCur sizeof(LONG) m_lpBufMax) Flush();*(UNALIGNED LONG*)m_lpBufCur x;m_lpBufCur sizeof(LONG);return *this; }}AfxWriteStringLength(*this, 长度, 判断字符串是否是多字节{ar(BYTE)nLength;}:memcpy_s(m_lpBufCur, (size_t)(m_lpBufMax - m_lpBufCur), lpBuf, nTemp)}
}ar,close
{Flush();{ m_pFile-Write(m_lpBufStart, ULONG(m_lpBufCur - m_lpBufStart){//写文件::WriteFile(m_hFile, lpBuf, nCount, nWritten, NULL)m_lpBufCur m_lpBufStart;}}
}反序列化
int main(){int nRetCode 0;HMODULE hModule ::GEtModuleHandle(nullptr);AfxWinInit(hModule,nullptr,::GetCommandLine(),0);CLine* line;CFile file;file.Open(R(文件路径\文件名),CFile::modeCreate|CFile::modeRead);CArchive ar(file,CArchice::store,4096);ar line;ar.Close();file.Close();std::coutline-str;std::coutdline-x;std::coutline-y;return nRetCode;
}CArchive ar(file, CArchive::store,4096)
{m_nMode nMode;//模式 读m_pFile pFile;//文件句柄m_nBufSize nBufSize //缓冲区大小this-m_lpBufStart new BYTE[m_nBufSize]; //申请了缓冲区大小m_lpBufMax m_lpBufStart nBufSize;//缓冲区的尾地址m_lpBufCur (IsLoading()) ? m_lpBufMax : m_lpBufStart;
}ar.ReadObject(直线类信息)
{//读类信息CRuntimeClass* pClassRef ReadClass(pClassRefRequested, nSchema, obTag);{BYTE* lpTemp m_lpBufStart nPreviouslyFilled;do{//读文件 全部读上来nBytesRead m_pFile-Read(lpTemp, nLeftToRead);lpTemp lpTemp nBytesRead;nTotalInBuffer nBytesRead;nLeftToRead - nBytesRead;}while (nBytesRead 0 nLeftToRead 0 nTotalInBuffer nTotalSizeWanted);m_lpBufCur m_lpBufStart;m_lpBufMax m_lpBufStart nTotalInBuffer;}//动态创建对象pOb pClassRef-CreateObject();//回到我们代码pOb-Serialize(*this){CArchive::operator((LONG)x);{if (m_lpBufCur sizeof(LONG) m_lpBufMax)FillBuffer(UINT(sizeof(LONG) - (m_lpBufMax - m_lpBufCur)));i *(UNALIGNED LONG*)m_lpBufCur;m_lpBufCur sizeof(LONG);return *this; }}
}了解了序列化和反序列化过程我们就可以将我们画的图保存起来了
添加一个直线类#pragma once
#include afx.h
class Cline:public CObject{
public:DECLARE_SERTAL(CLine)virtual void Serialize(CArchive ar);CPoint m_begin;CPoint m_end;
};//在cpp中实现
#include pch.h
#include CLine.hIMPLEMENT_SERIAL(CLine,CObject,1)void Serialize(CArchive ar){CObject::Serialize(ae);if(ar.IsLoading()){arm_begin.xm_begin.y;arm_end.xm_end.y;}else{arm_begin.xm_begin.y;arm_end.xm_end.y;}
}我们还需要将直线的链表存储到文档中
在文档类.cpp中
#include CLine.h为文档类添加变量
CListCLinem_list;我们将OnDraw消息稍作修改就是直线的数据获取位置不一样了我们需要修改 auto pos pDoc-m_list.GetHeadPossition();while(pos){auto Lint pDoc-m_list.GetNext(pos);//画直线dcMem-MoveTo(Line.m_begin);dcMem-LineTo(line.m_end);}这样修改之后我们还需要将直线类的拷贝构造函数修改因为默认是浅拷贝我们在OnDraw函数中使用的时候显示已经释放
#pragma once
#include afx.h
class Cline:public CObject{
public:CLine(){};CLine operator_(const line){this-m_begin line.m_begin;this-m_end list.m_red;return *this;}CLine(const CLine line){this-m_begin line.m_begin;this-m_end list.m_red;}CLine(CPoint begin,CPoint end){this-m_begin begin;this-m_end end;}DECLARE_SERTAL(CLine)virtual void Serialize(CArchive ar);CPoint m_begin;CPoint m_end;
};然后我们去文档类中处理
void C...DOC::Serialize(CArchive ar){if(ar.IsStoring()){arm_list.getSize();auto pos m_list.GetHeadPosition();while(pos){//arm_list.GetNext(pos);CLine*p m_listl.GetNext(pos);arp;//这里第二种方式看似跟上面的方式没有什么区别但是运行发现只保存了一条直线//这是因为每一次p都是一个地址}else{int nSize;arnSize;CObject* shape;while(nSize--){arshape;m_list.AddTail(*(CLine*)shape);}}}
}双缓冲
双缓冲在之前写字符雨的时候已经简单介绍过今天我们来写一个简单的程序来体会双缓冲机制
我们实现一个在屏幕上画直线的功能
在类中添加变量保存起点坐标和终点坐标
//定义一个容器保存每次画的直线
using Lint std::pair(CPoint,CPoint);
CListm_List;CPoint m_begin;
CPoint m_end;在对话框上添加WM_MOUSEMOVEWM_LBUTTONDOWMWM_LBUTTONUP消息处理函数
void C双缓冲View::OnDraw(UINT nFlags,CPoint point){C双缓冲View* pDoc GetDocument();ASSERT_CALID(pDoc);if(!pFoc)return;//画直线pDC-MoveTo(m_begin);pDC-LineTo(m_end);CVIew::OnMouseMove(nFlags,point);
}void C双缓冲::OnMouseMove(UINT nFlags,CPoint point){if(nFlagsMK_LBUTTON){m_end point;IncalidateRect(NULL,TRUE);}CView::OnMouseMoce(nFlags,point);
}void C双缓冲View::OnLButtonDown(UINT nFlags,CPoint point){//记录开始坐标CVIew::OnLButtonDown(nFlags,point);m_begin point;
}void C双缓冲View::OnLButtonUp(UINT nFlags,CPoint point){//记录终点坐标m_end point;CVIew::OnLButtonUp(nFlags,point);ReleaseCapture();
}这样写完之后没有反应这是因为没有无效区域我们将OnLButtonUp函数中添加无效区域就可以了
void C双缓冲View::OnLButtonUp(UINT nFlags,CPoint point){//记录终点坐标m_end point;CVIew::OnLButtonUp(nFlags,point);InvalidateRect(NULL,TRUE);
}只有有了无效区域绘图消息才会产生
然后我们完善
//定义一个容器保存每次画的直线
using Lint std::pair(CPoint,CPoint);
CListm_List;void C双缓冲View::OnDraw(UINT nFlags,CPoint point){C双缓冲View* pDoc GetDocument();ASSERT_CALID(pDoc);if(!pFoc)return;pDC-MoveTo(m_begin);pDC-LineTo(m_end);auto pos m_list.GetHeadPossition();while(pos){auto Lint m_list.GetNext(pos);//画直线pDC-MoveTo(Line.first);pDC-LineTo(line.second);}CVIew::OnMouseMove(nFlags,point);
}void C双缓冲::OnMouseMove(UINT nFlags,CPoint point){if(nFlagsMK_LBUTTON){m_end point;IncalidateRect(NULL,TRUE);}CView::OnMouseMoce(nFlags,point);
}void C双缓冲View::OnLButtonDown(UINT nFlags,CPoint point){//记录开始坐标CVIew::OnLButtonDown(nFlags,point);m_begin point;//捕捉客户区外鼠标消息SetCapture();
}void C双缓冲View::OnLButtonUp(UINT nFlags,CPoint point){//记录终点坐标m_end point;m_list.AddTail(Line(m_begin,m_end));CVIew::OnLButtonUp(nFlags,point);InvalidateRect(NULL,TRUE);ReleaseCapture();
}这样写完了之后确实可以画出来直线但是这是我们直接操作外设的所以会出现闪屏的情况
这时候就需要我们的双缓冲了
双缓冲就是我们操作内存将直线画在内存上然后将内存完整拷贝到外设上这样就可以避免操作慢闪屏的问题
Win32中能操作设备的只有设备句柄hdc
而在MFC中封装了
CDC-------对应Win32GetDC
CMetaFileDC 矢量图位图了解一下就行了
CPainDCWM_PAINT::BEGINPAINT
CWindowDC桌面窗口的HDC 这几种对象能代表他们各自的东西肯定是内部有绑定机制Attah()
双缓冲内存DC这里的CDC就代表了内存DC
然后我们修改代码
void C双缓冲View::OnDraw(UINT nFlags,CPoint point){C双缓冲View* pDoc GetDocument();ASSERT_CALID(pDoc);if(!pFoc)return;//双缓冲绘图//1.创建内存DCCDC dcMem;dcMem.CreateCompatibleDC(pDC);CRect rect;GetClintRect(rect);//2.创建一张屏幕DC一样的位图CBitmap bitmap;bitmap.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());//3.送到内存DC中dcMem.SeleObject(bitmap);dcMem.FillSolidRect(rect,RGB(255,255,255));//然后我们使用内存DC绘图dcMem-MoveTo(m_begin);dcMem-LineTo(m_end);auto pos m_list.GetHeadPossition();while(pos){auto Lint m_list.GetNext(pos);//画直线dcMem-MoveTo(Line.first);dcMem-LineTo(line.second);}//4.拷贝到设备pDC.BitBit(0,0,rect.Width(),rect.Height(),dcMem,0,DRCCOPY);CVIew::OnMouseMove(nFlags,point);
}修改完这个函数后将绘制无效区域的函数不再擦除背景 画壁画刷位图 在Win32中都是GDI句柄 MFC封装了GDI对象 Win32什么流程 MFC就还是什么流程 void C双缓冲View::OnDraw(UINT nFlags,CPoint point){C双缓冲View* pDoc GetDocument();ASSERT_CALID(pDoc);if(!pFoc)return;//双缓冲绘图//1.创建内存DCCDC dcMem;dcMem.CreateCompatibleDC(pDC);CRect rect;GetClintRect(rect);//2.创建一张屏幕DC一样的位图CBitmap bitmap;bitmap.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());CPen pen;pen.CreatePen(PS_DOT,55,RGB(0,255,255));//把画笔送到内存DCdeMem.SelectObject(pen);//3.送到内存DC中dcMem.SeleObject(bitmap);dcMem.FillSolidRect(rect,RGB(255,255,255));//然后我们使用内存DC绘图dcMem-MoveTo(m_begin);dcMem-LineTo(m_end);auto pos m_list.GetHeadPossition();while(pos){auto Lint m_list.GetNext(pos);//画直线dcMem-MoveTo(Line.first);dcMem-LineTo(line.second);}//4.拷贝到设备pDC.BitBit(0,0,rect.Width(),rect.Height(),dcMem,0,DRCCOPY);CVIew::OnMouseMove(nFlags,point);
}序列化 为什么要有序列化 我们在绘图应用程序上绘制的图形可以保存起来我们之后还可以打开 而我们上面写的程序是不能保存的这就是序列化的基本功能 简单使用以下序列化 首先继承于CObject类内添加声明宏DECLARE_SERTAL类外实现宏IMPLEMENT_SERIAL cpp //直线类 class Cline:public Cobject{ public: CLine(){}; CLine(int x,int y,CString type):x(x),y(y),str(type){}; virtual coid Setialize(CArchice* ar){ if(ar,IsLoading()){ //加载 arxystr; }else{ //保存 ar
我们这样实现后发现我们只写了三个成员但是文件中有很多我们来简单追踪有一下序列化是如何实现的
序列化过程 CArchive 归档类对象
CArchive AFXAPI operator(CArchive ar, CLine* pOb)
{pOb (CLine*) ar.ReadObject(RUNTIME_CLASS(CLine)); return ar;
}CArchive ar(file, CArchive::store,4096)
{m_nMode nMode;//模式m_pFile pFile;//文件句柄m_nBufSize nBufSize //缓冲区大小this-m_lpBufStart new BYTE[m_nBufSize]; //申请了缓冲区大小m_lpBufMax m_lpBufStart nBufSize;//缓冲区的尾地址m_lpBufCur (IsLoading()) ? m_lpBufMax : m_lpBufStart;
}struct
{类版本类大小x
}void CArchive::WriteObject(const CObject* line)
{//获取类信息地址CRuntimeClass* pClassRef pOb-GetRuntimeClass();//写类信息WriteClass(pClassRef);((CObject*)pOb)-Serialize(ar对象/*归档类对象*/);{ar x{return CArchive::operator((char)x); {if (m_lpBufCur sizeof(LONG) m_lpBufMax) Flush();*(UNALIGNED LONG*)m_lpBufCur x;m_lpBufCur sizeof(LONG);return *this; }}AfxWriteStringLength(*this, 长度, 判断字符串是否是多字节{ar(BYTE)nLength;}:memcpy_s(m_lpBufCur, (size_t)(m_lpBufMax - m_lpBufCur), lpBuf, nTemp)}
}ar,close
{Flush();{ m_pFile-Write(m_lpBufStart, ULONG(m_lpBufCur - m_lpBufStart){//写文件::WriteFile(m_hFile, lpBuf, nCount, nWritten, NULL)m_lpBufCur m_lpBufStart;}}
}反序列化
int main(){int nRetCode 0;HMODULE hModule ::GEtModuleHandle(nullptr);AfxWinInit(hModule,nullptr,::GetCommandLine(),0);CLine* line;CFile file;file.Open(R(文件路径\文件名),CFile::modeCreate|CFile::modeRead);CArchive ar(file,CArchice::store,4096);ar line;ar.Close();file.Close();std::coutline-str;std::coutdline-x;std::coutline-y;return nRetCode;
}CArchive ar(file, CArchive::store,4096)
{m_nMode nMode;//模式 读m_pFile pFile;//文件句柄m_nBufSize nBufSize //缓冲区大小this-m_lpBufStart new BYTE[m_nBufSize]; //申请了缓冲区大小m_lpBufMax m_lpBufStart nBufSize;//缓冲区的尾地址m_lpBufCur (IsLoading()) ? m_lpBufMax : m_lpBufStart;
}ar.ReadObject(直线类信息)
{//读类信息CRuntimeClass* pClassRef ReadClass(pClassRefRequested, nSchema, obTag);{BYTE* lpTemp m_lpBufStart nPreviouslyFilled;do{//读文件 全部读上来nBytesRead m_pFile-Read(lpTemp, nLeftToRead);lpTemp lpTemp nBytesRead;nTotalInBuffer nBytesRead;nLeftToRead - nBytesRead;}while (nBytesRead 0 nLeftToRead 0 nTotalInBuffer nTotalSizeWanted);m_lpBufCur m_lpBufStart;m_lpBufMax m_lpBufStart nTotalInBuffer;}//动态创建对象pOb pClassRef-CreateObject();//回到我们代码pOb-Serialize(*this){CArchive::operator((LONG)x);{if (m_lpBufCur sizeof(LONG) m_lpBufMax)FillBuffer(UINT(sizeof(LONG) - (m_lpBufMax - m_lpBufCur)));i *(UNALIGNED LONG*)m_lpBufCur;m_lpBufCur sizeof(LONG);return *this; }}
}了解了序列化和反序列化过程我们就可以将我们画的图保存起来了
添加一个直线类#pragma once
#include afx.h
class Cline:public CObject{
public:DECLARE_SERTAL(CLine)virtual void Serialize(CArchive ar);CPoint m_begin;CPoint m_end;
};//在cpp中实现
#include pch.h
#include CLine.hIMPLEMENT_SERIAL(CLine,CObject,1)void Serialize(CArchive ar){CObject::Serialize(ae);if(ar.IsLoading()){arm_begin.xm_begin.y;arm_end.xm_end.y;}else{arm_begin.xm_begin.y;arm_end.xm_end.y;}
}我们还需要将直线的链表存储到文档中
在文档类.cpp中
#include CLine.h为文档类添加变量
CListCLinem_list;我们将OnDraw消息稍作修改就是直线的数据获取位置不一样了我们需要修改 auto pos pDoc-m_list.GetHeadPossition();while(pos){auto Lint pDoc-m_list.GetNext(pos);//画直线dcMem-MoveTo(Line.m_begin);dcMem-LineTo(line.m_end);}这样修改之后我们还需要将直线类的拷贝构造函数修改因为默认是浅拷贝我们在OnDraw函数中使用的时候显示已经释放
#pragma once
#include afx.h
class Cline:public CObject{
public:CLine(){};CLine operator_(const line){this-m_begin line.m_begin;this-m_end list.m_red;return *this;}CLine(const CLine line){this-m_begin line.m_begin;this-m_end list.m_red;}CLine(CPoint begin,CPoint end){this-m_begin begin;this-m_end end;}DECLARE_SERTAL(CLine)virtual void Serialize(CArchive ar);CPoint m_begin;CPoint m_end;
};然后我们去文档类中处理
void C...DOC::Serialize(CArchive ar){if(ar.IsStoring()){arm_list.getSize();auto pos m_list.GetHeadPosition();while(pos){//arm_list.GetNext(pos);CLine*p m_listl.GetNext(pos);arp;//这里第二种方式看似跟上面的方式没有什么区别但是运行发现只保存了一条直线//这是因为每一次p都是一个地址}else{int nSize;arnSize;CObject* shape;while(nSize--){arshape;m_list.AddTail(*(CLine*)shape);}}}
}