孙鑫11课 图形的保存和重绘Word格式.docx
- 文档编号:18803544
- 上传时间:2023-01-01
- 格式:DOCX
- 页数:13
- 大小:19.27KB
孙鑫11课 图形的保存和重绘Word格式.docx
《孙鑫11课 图形的保存和重绘Word格式.docx》由会员分享,可在线阅读,更多相关《孙鑫11课 图形的保存和重绘Word格式.docx(13页珍藏版)》请在冰豆网上搜索。
⏹“窗口”是基于逻辑坐标的,逻辑坐标可以是象素、毫米、英寸等单位;
“视口”是基于设备坐标(象素)的。
通常,视口和客户区是相同的。
⏹缺省的映射模式为MM_TEXT。
在这种映射模式下,逻辑单位和设备单位相同。
⏹不管对窗口和视口原点作什么改变,设备点(0,0)始终是客户区的左上角。
⏹关于解决方法的说明
⏹首先我们在绘制图形之后,在保存坐标点之前,调用OnPrepareDC函数,调整显示上下文的属性,将视口的原点设置为(0,-150),这样的话,窗口的原点,也就是逻辑坐标(0,0)将被映射为设备坐标(0,-150),然后我们调用DPtoLP函数将设备坐标(680,390)转换为逻辑坐标,根据设备坐标转换为逻辑坐标的公式:
⏹xWindow=xViewport-xViewOrg+xWinOrg,
⏹yWindow=yViewport-yViewOrg+yWinOrg,得到逻辑点的x坐标为680-0+0=680,y坐标为390-(-150)+0=540,将逻辑坐标(680,540)保存起来,在窗口重绘时,会先调用OnPrepareDC函数,调整显示上下文的属性,将视口的原点设置为了(0,-150),然后GDI函数用逻辑坐标点(680,540)绘制图形,被Windows转换为设备坐标点(680,390),和原先显示图形时的设备点是一样的,当然图形就还在原先的地方显示出来。
⏹
逻辑坐标和设备坐标
视口和窗口原点的改变
⏹CDC中提供了两个成员函数函数SetViewportOrg和SetWindowOrg,用来改变视口和窗口的原点。
⏹如果将视口原点设置为(xViewOrg,yViewOrg),则逻辑点(0,0)就会被映射为设备点(xViewOrg,yViewOrg)。
如果将窗口原点改变为(xWinOrg,yWinOrg),则逻辑点(xWinOrg,yWinOrg)将会被映射为设备点(0,0),即左上角。
OnPrepareDC会随时根据滚动窗口的位置来调整视口的原点。
CreateCompatibleBitmap返回的位图对象只包含相应设备描述表中的位图的位图信息头,不包含颜色表和象素数据块。
因此,选入该位图对象的设备描述表不能像选入普通位图对象的设备描述表一样应用,必须在SelectObject函数之后,调用BitBlt将原始设备描述表的颜色表及象素数据块拷贝到兼容设备描述表。
建立一个MFC的单文档程序,加上点,线,矩形,椭圆按钮。
并在VIEW类中增加消息响应函数。
private:
UINTm_dwstyle;
CPointm_dnpt;
CGraphicView:
:
CGraphicView()
{
//TODO:
addconstructioncodehere
m_dwstyle=0;
m_dnpt=0;
}
voidCGraphicView:
OnDot()
Addyourcommandhandlercodehere
m_dwstyle=1;
OnLine()
m_dwstyle=2;
OnRect()
m_dwstyle=3;
OnEllipse()
m_dwstyle=4;
OnLButtonDown(UINTnFlags,CPointpoint)
Addyourmessagehandlercodehereand/orcalldefault
m_dnpt=point;
CView:
OnLButtonDown(nFlags,point);
OnLButtonUp(UINTnFlags,CPointpoint)
CClientDCdc(this);
CBrush*pbrush=(CBrush*)dc.SelectStockObject(NULL_BRUSH);
switch(m_dwstyle)
{
case1:
dc.SetPixel(point,RGB(255,0,0));
break;
case2:
dc.MoveTo(m_dnpt);
dc.LineTo(point);
case3:
dc.Rectangle(CRect(m_dnpt,point));
case4:
dc.Ellipse(CRect(m_dnpt,point));
default:
}
dc.SelectObject(pbrush);
OnLButtonUp(nFlags,point);
此时当窗口尺寸发生变化时,画的图形不见了。
先擦除背景,再重绘。
窗口重绘的时候要调用OnDraw(CDC*pDC)。
新增一个通用类:
CGraph。
其头文件和源文件如下:
头文件:
classCGraph
public:
UINTm_dwsytle;
CPointm_uppt;
CGraph();
CGraph(UINTstyle,CPointdnpt,CPointuppt);
virtual~CGraph();
};
源文件中:
CGraph:
CGraph(UINTstyle,CPointdnpt,CPointuppt)
m_dwsytle=style;
m_dnpt=dnpt;
m_uppt=uppt;
为VIEW类增加:
CPtrArraym_ptrArray;
OnLButtonUp(UINTnFlags,CPointpoint)中的代码增加下面代码:
CGraph*pgraph=newCGraph(m_dwstyle,m_dnpt,point);
m_ptrArray.Add(pgraph);
OnDraw(CDC*pDC)
CGraphicDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
CBrush*pBrush=(CBrush*)dc.SelectStockObject(NULL_BRUSH);
intcount=m_ptrArray.GetSize();
for(inti=0;
i<
count;
i++)
switch(((CGraph*)m_ptrArray.GetAt(i))->
m_dwsytle)
{
case1:
dc.SetPixel(((CGraph*)m_ptrArray.GetAt(i))->
m_dnpt,RGB(255,0,0));
break;
case2:
dc.MoveTo(((CGraph*)m_ptrArray.GetAt(i))->
m_dnpt);
dc.LineTo(((CGraph*)m_ptrArray.GetAt(i))->
m_uppt);
case3:
dc.Rectangle(CRect(((CGraph*)m_ptrArray.GetAt(i))->
m_dnpt,
((CGraph*)m_ptrArray.GetAt(i))->
m_uppt));
case4:
dc.Ellipse(CRect(((CGraph*)m_ptrArray.GetAt(i))->
default:
}
dc.SelectObject(pBrush);
adddrawcodefornativedatahere
此时发现窗口重绘的时候,图形仍在。
OnDraw是一个虚函数,当窗口重绘的时候会被调用。
窗口重绘的时候会发送WM_PAINT消息。
如果想让一个图形在窗口中始终都能看到,应该放到响应WM_PAINT的函数中。
在查询VC的源代码的时候发现:
voidCView:
OnPaint()//响应WM_PAINT消息
//standardpaintroutine
CPaintDCdc(this);
OnPrepareDC(&
dc);
OnDraw(&
如果voidCGraphicView:
OnPaint()有了这个消息,就不会调用OnDraw函数。
(当然可以在这个里面调用OnDraw函数);
OnPaint()
//devicecontextforpainting
Addyourmessagehandlercodehere
//后面介绍为什么调用这个函数。
//DonotcallCView:
OnPaint()forpaintingmessages
下面让窗口具有滚动的能力:
将头文件和源文件中的VIEW换成SCROLLVIEW类。
//DonotcallCScrollView:
//窗口创建完成之后第一个要调用的函数。
在OnDraw函数调用之前.
OnInitialUpdate()
CScrollView:
OnInitialUpdate();
Addyourspecializedcodehereand/orcallthebaseclassCSize(100,100)
SetScrollSizes(MM_TEXT,CSize(1000,1000)/*GetDocument()->
GetDocSize()*/);
这时在OnDraw中添加如下代码:
dc.DPtoLP(&
point);
此操作在保存点之前做的。
设备坐标点的(0,0)始终是客户区的左上角。
下面再介绍两种保存图形和重绘图形的方式:
第一种:
CMetaFileDC包含了一系列的图形绘制命令(源文件,内存中),(绘制图形函数),在METAFILEDC里面做图,想看的时候再次打开。
CMetaFileDCm_metafl;
//CClientDCdc(this);
CBrush*pbrush=(CBrush*)m_metafl.SelectStockObject(NULL_BRUSH);
m_metafl.SetPixel(point,RGB(255,0,0));
m_metafl.MoveTo(m_dnpt);
m_metafl.LineTo(point);
m_metafl.Rectangle(CRect(m_dnpt,point));
m_metafl.Ellipse(CRect(m_dnpt,point));
//OnPrepareDC(&
//dc.DPtoLP(&
//CGraph*pgraph=newCGraph(m_dwstyle,m_dnpt,point);
//m_ptrArray.Add(pgraph);
m_metafl.SelectObject(pbrush);
//CClientDCdc(this);
CBrush*pBrush=(CBrush*)m_metafl.SelectStockObject(NULL_BRUSH);
HMETAFILEhmetal=m_metafl.Close();
pDC->
PlayMetaFile(hmetal);
m_metafl.Create();
//为再次绘制时做准备。
DeleteMetaFile(hmetal);
m_metafl.SelectObject(pBrush);
注意此时窗口重绘的时候图形出现,但是先前保存的图形不见了。
//将图形在当头窗口输出。
m_metafl.PlayMetaFile(hmetal);
//在源文件中绘制。
此时在重绘的时候能重新看到图形了。
下面对图形进行保存和打开。
为文件下面的打开和保存添加VIEW类中的响应函数。
OnFileSave()
HMETAFILEhmeta=m_metafl.Close();
CopyMetaFile(hmeta,"
1.wmf"
);
//.wmf是源文件扩展名
DeleteMetaFile(hmeta);
OnFileOpen()
HMETAFILEhmeta=GetMetaFile("
m_metafl.PlayMetaFile(hmeta);
//m_metafl.Create();
Invalidate();
利用兼容DC:
在内存中准备一幅图像,在ONDRAW函数中,COPY到目的DC中。
CDCm_cmpdc;
当兼容DC创建时,会选择一个单色的位图,这个位图是一个像素大小的。
(2:
14)
CDCm_cmpdc;
此时:
if(!
m_cmpdc.m_hDC)
m_cmpdc.CreateCompatibleDC(&
CRectrect;
GetClientRect(&
rect);
CBitmapbp;
bp.CreateCompatibleBitmap(&
dc,rect.Width(),rect.Height());
//将兼容位图选到兼容DC中,从而确定兼容DC的大小。
兼容DC必须要选择一幅位图。
是一个内存DC
//兼容DC做的图,在窗口当中是看不到的。
m_cmpdc.SelectObject(&
bp);
m_cmpdc.BitBlt(0,0,rect.Width(),rect.Height(),&
dc,0,0,SRCCOPY);
CBrush*pbrush=(CBrush*)m_cmpdc.SelectStockObject(NULL_BRUSH);
m_cmpdc.SetPixel(point,RGB(255,0,0));
m_cmpdc.MoveTo(m_dnpt);
m_cmpdc.LineTo(point);
m_cmpdc.Rectangle(CRect(m_dnpt,point));
m_cmpdc.Ellipse(CRect(m_dnpt,point));
//m_cmpdc.SelectObject(pbrush);
CS
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 孙鑫11课 图形的保存和重绘 孙鑫 11 图形 保存
![提示](https://static.bdocx.com/images/bang_tan.gif)