孙鑫11课 图形的保存和重绘_第1页
孙鑫11课 图形的保存和重绘_第2页
孙鑫11课 图形的保存和重绘_第3页
孙鑫11课 图形的保存和重绘_第4页
孙鑫11课 图形的保存和重绘_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、坐标空间n Win32应用程序设计接口(API)使用四种坐标空间:世界坐标系空间、页面空间、设备空间、和物理设备空间。应用程序运用世界坐标系空间对图形输出进行旋转、斜切或者反射。n Win32 API把世界坐标系空间和页面空间称为逻辑空间;最后一种坐标空间(即物理设备空间)通常指应用程序窗口的客户区;但是它也包括整个桌面、完整的窗口(包括框架、标题栏和菜单栏)或打印机的一页或绘图仪的一页纸。物理设备的尺寸随显示器、打印机或绘图仪所设置的尺寸而变化。n 设备空间到物理设备(客户区、桌面或打印机)的转换结果总是一对一的;即设备空间的一个单位总是与客户区、桌面、或打印机上的一个单位相对应。这一转换的

2、唯一用途是平移。无论窗口移到桌面的什么位置,它永远确保输出能够正确无误地出现在窗口上。n 默认转换的一个独特之处是设备空间和应用程序窗口的y轴方向。在默认的状态下,y轴正向朝下,负y方向朝上。n 页面空间(逻辑空间)(窗口 逻辑坐标)到设备空间(视口,客户区设备坐标)的转换所用的是两个矩形的宽与高的比率,其中页面空间中的矩形被称为窗口,设备空间中的矩形被称为视口,Windows把窗口原点映射到视口原点,把窗口范围映射到视口范围,就完成了这种转换n 一旦应用程序建立了设备描述表,并立即开始调用GDI绘图或输出函数,则运用默认页面空间到设备空间的转换和设备空间到客户区的转换(在应用程序调用SetW

3、orldTransform函数之前,不会出现世界坐标空间到页面空间的转换)。n 默认页面空间到设备空间的转换结果是一对一的映射;即页面空间上给出的一点映射到设备空间的一个点。正如前文讲到的,这种转换没有以矩阵指定,而是通过把视口宽除以窗口宽,把视口高除以窗口高而得出的。在默认的情况下,视口尺寸为1x1个象素,窗口尺寸为1x1页单位。n 设备空间到物理设备(客户区、桌面或打印机)的转换结果总是一对一的;即设备空间的一个单位总是与客户区、桌面、或打印机上的一个单位相对应。这一转换的唯一用途是平移。无论窗口移到桌面的什么位置,它永远确保输出能够正确无误地出现在窗口上。n 默认转换的一个独特之处是设备

4、空间和应用程序窗口的y轴方向。在默认的状态下,y轴正向朝下,负y方向朝上。n 几乎在所有的GDI函数中使用的坐标值都是采用的逻辑单位。Windows必须将逻辑单位转换为“设备单位”,即像素。这种转换是由映射方式、窗口和视口的原点以及窗口和视口的范围所控制的。n Windows对所有的消息(如WM_SIZE、WM_MOUSEMOVE、WM_LBUTTONDOWN、WM_LBUTTONUP),所有的非GDI函数和一些GDI函数(例如GetDeviceCaps函数),永远使用设备坐标。n “窗口”是基于逻辑坐标的,逻辑坐标可以是象素、毫米、英寸等单位;“视口”是基于设备坐标(象素)的。通常,视口和客

5、户区是相同的。n 缺省的映射模式为MM_TEXT。在这种映射模式下,逻辑单位和设备单位相同。n 不管对窗口和视口原点作什么改变,设备点(0,0)始终是客户区的左上角。n 关于解决方法的说明n 首先我们在绘制图形之后,在保存坐标点之前,调用OnPrepareDC函数,调整显示上下文的属性,将视口的原点设置为(0,-150),这样的话,窗口的原点,也就是逻辑坐标(0,0)将被映射为设备坐标(0,-150),然后我们调用DPtoLP函数将设备坐标(680,390)转换为逻辑坐标,根据设备坐标转换为逻辑坐标的公式:n xWindow = xViewport-xViewOrg+xWinOrg,n yWi

6、ndow = yViewport-yViewOrg+yWinOrg,得到逻辑点的x坐标为680-0+0=680,y坐标为390-(-150)+0=540,将逻辑坐标(680,540)保存起来,在窗口重绘时,会先调用OnPrepareDC函数,调整显示上下文的属性,将视口的原点设置为了(0,-150),然后GDI函数用逻辑坐标点(680,540)绘制图形,被Windows转换为设备坐标点(680,390),和原先显示图形时的设备点是一样的,当然图形就还在原先的地方显示出来。n逻辑坐标和设备坐标n 几乎在所有的GDI函数中使用的坐标值都是采用的逻辑单位。Windows必须将逻辑单位转换为“设备单位

7、”,即像素。这种转换是由映射方式、窗口和视口的原点以及窗口和视口的范围所控制的。n Windows对所有的消息(如WM_SIZE、WM_MOUSEMOVE、WM_LBUTTONDOWN、WM_LBUTTONUP),所有的非GDI函数和一些GDI函数(例如GetDeviceCaps函数),永远使用设备坐标。n “窗口”是基于逻辑坐标的,逻辑坐标可以是象素、毫米、英寸等单位;“视口”是基于设备坐标(象素)的。通常,视口和客户区是相同的。n 缺省的映射模式为MM_TEXT。在这种映射模式下,逻辑单位和设备单位相同。视口和窗口原点的改变n CDC中提供了两个成员函数函数SetViewportOrg和S

8、etWindowOrg,用来改变视口和窗口的原点。n 如果将视口原点设置为(xViewOrg,yViewOrg),则逻辑点(0,0)就会被映射为设备点(xViewOrg,yViewOrg)。如果将窗口原点改变为(xWinOrg,yWinOrg),则逻辑点(xWinOrg,yWinOrg)将会被映射为设备点(0,0),即左上角。n 不管对窗口和视口原点作什么改变,设备点(0,0)始终是客户区的左上角。OnPrepareDC会随时根据滚动窗口的位置来调整视口的原点。CreateCompatibleBitmap返回的位图对象只包含相应设备描述表中的位图的位图信息头,不包含颜色表和象素数据块。因此,选

9、入该位图对象的设备描述表不能像选入普通位图对象的设备描述表一样应用,必须在SelectObject函数之后,调用BitBlt将原始设备描述表的颜色表及象素数据块拷贝到兼容设备描述表。建立一个MFC的单文档程序,加上点,线,矩形,椭圆按钮。并在VIEW类中增加消息响应函数。private:UINT m_dwstyle;CPoint m_dnpt;CGraphicView:CGraphicView()/ TODO: add construction code here m_dwstyle=0;m_dnpt=0;void CGraphicView:OnDot() / TODO: Add your c

10、ommand handler code herem_dwstyle=1;void CGraphicView:OnLine() / TODO: Add your command handler code herem_dwstyle=2;void CGraphicView:OnRect() / TODO: Add your command handler code herem_dwstyle=3;void CGraphicView:OnEllipse() / TODO: Add your command handler code herem_dwstyle=4;void CGraphicView:

11、OnLButtonDown(UINT nFlags, CPoint point) / TODO: Add your message handler code here and/or call defaultm_dnpt=point;CView:OnLButtonDown(nFlags, point);void CGraphicView:OnLButtonUp(UINT nFlags, CPoint point) / TODO: Add your message handler code here and/or call defaultCClientDC dc(this);CBrush *pbr

12、ush=(CBrush*)dc.SelectStockObject(NULL_BRUSH);switch (m_dwstyle)case 1:dc.SetPixel(point,RGB(255,0,0);break;case 2:dc.MoveTo(m_dnpt);dc.LineTo(point);break;case 3:dc.Rectangle(CRect(m_dnpt,point);break;case 4:dc.Ellipse(CRect(m_dnpt,point);break;default:break;dc.SelectObject(pbrush);CView:OnLButtonU

13、p(nFlags, point);此时当窗口尺寸发生变化时,画的图形不见了。先擦除背景,再重绘。窗口重绘 的时候要调用OnDraw(CDC* pDC)。新增一个通用类:CGraph。其头文件和源文件如下:头文件:class CGraph public:UINT m_dwsytle;CPoint m_dnpt;CPoint m_uppt;CGraph();CGraph(UINT style,CPoint dnpt,CPoint uppt);virtual CGraph();源文件中:CGraph:CGraph(UINT style,CPoint dnpt,CPoint uppt)m_dwsytl

14、e=style;m_dnpt=dnpt;m_uppt=uppt;为VIEW类增加:CPtrArray m_ptrArray;void CGraphicView:OnLButtonUp(UINT nFlags, CPoint point)中的代码增加下面代码:CGraph *pgraph=new CGraph(m_dwstyle,m_dnpt,point);m_ptrArray.Add(pgraph);void CGraphicView:OnDraw(CDC* pDC)CGraphicDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);CClientDC d

15、c(this);CBrush *pBrush=(CBrush*)dc.SelectStockObject(NULL_BRUSH);int count=m_ptrArray.GetSize();for (int i=0;im_dwsytle)case 1:dc.SetPixel(CGraph*)m_ptrArray.GetAt(i)-m_dnpt,RGB(255,0,0);break;case 2:dc.MoveTo(CGraph*)m_ptrArray.GetAt(i)-m_dnpt);dc.LineTo(CGraph*)m_ptrArray.GetAt(i)-m_uppt);break;ca

16、se 3:dc.Rectangle(CRect(CGraph*)m_ptrArray.GetAt(i)-m_dnpt,(CGraph*)m_ptrArray.GetAt(i)-m_uppt);break;case 4:dc.Ellipse(CRect(CGraph*)m_ptrArray.GetAt(i)-m_dnpt,(CGraph*)m_ptrArray.GetAt(i)-m_uppt);break;default:break;dc.SelectObject(pBrush);/ TODO: add draw code for native data here此时发现窗口重绘的时候,图形仍在

17、。OnDraw是一个虚函数,当窗口重绘 的时候会被调用。窗口重绘 的时候会发送WM_PAINT消息。如果想让一个图形在窗口中始终都能看到,应该放到响应WM_PAINT的函数中。在查询VC的源代码的时候发现:void CView:OnPaint() /响应WM_PAINT消息/ standard paint routineCPaintDC dc(this);OnPrepareDC(&dc);OnDraw(&dc);如果void CGraphicView:OnPaint()有了这个消息,就不会调用OnDraw函数。(当然可以在这个里面调用OnDraw函数);void CGraphicView:On

18、Paint() CPaintDC dc(this); / device context for painting/ TODO: Add your message handler code hereOnPrepareDC(&dc);/后面介绍为什么调用这个函数。OnDraw(&dc);/ Do not call CView:OnPaint() for painting messages下面让窗口具有滚动的能力:将头文件和源文件中的VIEW换成SCROLLVIEW类。void CGraphicView:OnPaint() CPaintDC dc(this); / device context fo

19、r painting/ TODO: Add your message handler code hereOnPrepareDC(&dc);OnDraw(&dc);/ Do not call CScrollView:OnPaint() for painting messages/窗口创建完成之后第一个要调用的函数。在OnDraw函数调用之前.void CGraphicView:OnInitialUpdate() CScrollView:OnInitialUpdate();/ TODO: Add your specialized code here and/or call the base cla

20、ss CSize(100, 100)SetScrollSizes( MM_TEXT, CSize(1000, 1000)/* GetDocument( )-GetDocSize( )*/ );CClientDC dc(this);OnPrepareDC(&dc);这时在OnDraw中添加如下代码:OnPrepareDC(&dc);dc.DPtoLP(&m_dnpt);dc.DPtoLP(&point);此操作在保存点之前做的。设备坐标点的(0,0)始终是客户区的左上角。下面再介绍两种保存图形和重绘图形的方式:第一种:CMetaFileDC包含了一系列的图形绘制命令(源文件,内存中),(绘制图形

21、函数),在METAFILEDC里面做图,想看的时候再次打开。private:CMetaFileDC m_metafl;CTestView:CTestView()/ TODO: add construction code here m_dwstyle=0; m_dnpt=0; m_metafl.Create();void CGraphicView:OnLButtonUp(UINT nFlags, CPoint point) / TODO: Add your message handler code here and/or call default/CClientDC dc(this);CBrus

22、h *pbrush=(CBrush*)m_metafl.SelectStockObject(NULL_BRUSH);switch (m_dwstyle)case 1:m_metafl.SetPixel(point,RGB(255,0,0);break;case 2:m_metafl.MoveTo(m_dnpt);m_metafl.LineTo(point);break;case 3:m_metafl.Rectangle(CRect(m_dnpt,point);break;case 4:m_metafl.Ellipse(CRect(m_dnpt,point);break;default:brea

23、k;m_metafl.SelectObject(pbrush);CScrollView:OnLButtonUp(nFlags, point);void CGraphicView:OnDraw(CDC* pDC)CGraphicDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);/CClientDC dc(this);CBrush *pBrush=(CBrush*)m_metafl.SelectStockObject(NULL_BRUSH);HMETAFILE hmetal=m_metafl.Close( );pDC-PlayMetaFile( hmetal

24、 );m_metafl.Create();/为再次绘制时做准备。 DeleteMetaFile(hmetal);m_metafl.SelectObject(pBrush);/ TODO: add draw code for native data here注意此时窗口重绘的时候图形出现,但是先前保存的图形不见了。void CGraphicView:OnDraw(CDC* pDC)CGraphicDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);/CClientDC dc(this);CBrush *pBrush=(CBrush*)m_metafl.Sel

25、ectStockObject(NULL_BRUSH);HMETAFILE hmetal=m_metafl.Close( );pDC-PlayMetaFile( hmetal );/将图形在当头窗口输出。m_metafl.Create();/为再次绘制时做准备。m_metafl.PlayMetaFile(hmetal);/在源文件中绘制。 DeleteMetaFile(hmetal);m_metafl.SelectObject(pBrush);/ TODO: add draw code for native data here此时在重绘的时候能重新看到图形了。下面对图形进行保存和打开。为文件下面

26、的打开和保存添加VIEW类中的响应函数。void CGraphicView:OnFileSave() / TODO: Add your command handler code hereHMETAFILE hmeta=m_metafl.Close();CopyMetaFile(hmeta,1.wmf);/.wmf是源文件扩展名m_metafl.Create();DeleteMetaFile(hmeta);void CGraphicView:OnFileOpen() / TODO: Add your command handler code hereHMETAFILE hmeta=GetMetaFile(1.wmf);m_metafl.PlayMetaFile(hmeta);/m_metafl.Create();DeleteMetaFile(hmeta);Invalidate();利用兼容DC:在内存中准备一幅图像,在ONDRAW函数中,COPY到目的DC中。private: CDC m_cmpdc;当兼容DC创建时,会选择一个单色的位图,这个位图是一个像素大小的。为VIEW类增加:CDC m_cmpdc;此时:void CGraphicView:OnLButtonUp(UINT nFlags, CPoint point) / TODO: Add your

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论