美文网首页
VC++(十一)图形的保存和重绘

VC++(十一)图形的保存和重绘

作者: 侧漏的少年 | 来源:发表于2016-11-17 16:59 被阅读0次
  • Invalidate使整个窗口客户区无效。
    窗口的客户区无效意味着需要重绘。Windows会在应用程序的消息队列里放置WM_PAINT消息。

  • UpdateWindow()的作用是使窗口立即重绘,可使WM_PAINT消息被直接发送到目标窗口,从而导致窗口立即重绘。

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

  • 如果该应用程序调用了SetWorldTransform函数,那么映射就从应用程序的世界坐标系空间开始;否则,映射在页面空间中进行。实际编程中,主要处理的是从页面空间到设备空间的转换。

  • 逻辑坐标和设备坐标
    几乎在所有的GDI函数中使用的坐标值都是采用的逻辑单位。Windows必须将逻辑单位转换为“设备单位”,即像素。这种转换是由映射方式、窗口和视口的原点以及窗口和视口的范围所控制的。
    Windows对所有的消息(如WM_SIZE、WM_MOUSEMOVE、WM_LBUTTONDOWN、WM_LBUTTONUP),所有的非GDI函数和一些GDI函数(例如GetDeviceCaps函数),永远使用设备坐标。

  • 窗口和视口
    窗口是基于逻辑坐标的,逻辑坐标以cm mm为单位
    视口是基于设备坐标的,设备坐标以像素为单位

  • 两个原则:
    1.总是由窗口原点映射为视口原点。即无论你窗口的原点和视口的原点怎么变,窗口的原点总是映射到视口的原点。(记住:映射方向是窗口到视口,而不是视口向窗口映射)
    2.不管利用函数(如:SetViewportOrgExt和SetWindowOrgEx)对窗口和视口的原点做怎么改变,设备点(0,0)始终是客户区的左上角。

  • 移动窗口和视口的原点
    SetWindowOrg(100, -300)则逻辑点(100,-300)映射为设备点(0,0)
    SetViewportOrg(100, -300)则逻辑点(0,00)映射为设备点(100,-300)
    不管原点怎么变化,永远都是原点映射到原点。

  • CPtrArray对象存储多个对象的地址。

  • OnPaint 和 OnDraw
    窗口重绘时会发送一个WM_PAINT消息:消息响应函数OnPaint().
    CView类派生自CWnd类。
    OnPaint()是CWnd的类成员,同时负责响应WM_PAINT消息。
    OnDraw()是CVIEW的成员函数,并且没有响应消息的功能。这就是为什么你用VC成的程序代码时,在视图类只有 OnDraw没有OnPaint的原因。

  • 要想在屏幕上绘图或显示图形,首先需要建立设备环境DC。其实DC是一个数据结构,它包含输出设备的绘图属性的描述。MFC提供了CPaintDC类和CWindwoDC类来实时的响应,而CPaintDC支持重画。

  • 当视图变得无效时(包括大小的改变,移动,被遮盖等等),Windows 将 WM_PAINT 消息发送给它。该视图的 OnPaint 处理函数通过创建 CPaintDC 类的DC对象来响应该消息并调用视图的 OnDraw 成员函数。通常我们不必编写重写的 OnPaint 处理成员函数。

//CView默认的标准的重画函数
void CView::OnPaint()
{
    CPaintDC dc(this);
    OnPreparDC(&dc);
    OnDraw(&dc); //调用了OnDraw
}

既然OnPaint最后也要调用OnDraw,因此我们一般会在OnDraw函数中进行绘制。下面是一个典型的程序

///视图中的绘图代码首先检索指向文档的指针,然后通过DC进行绘图调用。
void CMyView::OnDraw( CDC* pDC )
{ 
    CMyDoc* pDoc = GetDocument(); 
    CString s = pDoc->GetData(); // Returns a CString
    CRect rect;
    GetClientRect( &rect ); 
    pDC->SetTextAlign( TA_BASELINE | TA_CENTER ); 
    pDC->TextOut( rect.right / 2, rect.bottom / 2, s, s.GetLength() );
}

  • 设备环境(Device Context)(设备上下文)

  • 设备上下文DC是一个Windows数据结构,它包含了某个设备的绘制属性。通常,绘制调用都是借助于上下文对象,而这些设备上下文对象封装了用于画线、形状、文本等的Windows API。设备上下文是设备无关的,所以它既可以用于绘制屏幕,也可以用于绘制打印机甚至元文件。设备上下文在内存中创建,而内存经常受到扰动,所以它的地址是不固定的。因此,一个设备上下文句柄不是直接指向设备上下文对象,而是指向另外一个跟踪设备上下文地址的指针。

  • 我个人认为设备上下文相当于画图过程中的画布(画纸),在VC中,这个画布可以是显示器,也可以使打印机,设备上下文决定了画布的属性,而且封装了在画布上画画的方法,比如画线,画点,等等,例如: pDc->LineTo(512,0); //从左下角到右上角的一条红色直线 。我们在VC中画图时,首先要得到这块画布才可以画画,所以要进行获取设备环境。

常见设备上下文及区别:

  • CClientDC,CPaintDC,CWindowDC

  • CClientDC:(客户区设备上下文)用于客户区的输出,与特定窗口关联,可以让开发者访问目标窗口中客户区,其构造函数中包含了GetDC,析构函数中包含了ReleaseDC。只能在客户区绘制图形。

  • CPaintDC:只能在客户区绘制图形。
    (1)CPaintDC类是CDC类的一个派生类,该类一般用在响应WM_PAINT消息的函数OnPaint()中。
    (2)WM_PAINT消息是当窗口的某个区域需要重画时激发的窗口消息。当程序中的消息循环接到WM_PAINT消息时就自动调用消息处理函数OnPaint(),如果在OnPaint函数内定义了CPaintDC类的对象,通过这个类对象就可以使用CDC类的成员函数完成视图客户区中的图形绘制操作。
    (3)CPaintDC用于响应窗口重绘消息(WM_PAINT)时的绘图输出。CPaintDC在构造函数中调用BeginPaint()取得设备上下文,在析构函数中调用EndPaint()释放设备上下文。EndPaint()除了释放设备上下文外,还负责从消息队列中清除WM_PAINT消息。因此,在处理窗口重画时,必须使用CPaintDC,否则WM_PAINT消息无法从消息队列中清除,将引起不断的窗口重画。CPaintDC也只能用在WM_PAINT消息处理之中。

  • CWindowsDC:
    (1)可在非客户区绘制图形,而CClientDC,CPaintDC只能在窗口的客户区绘制图形。
    (2)坐标原点是在窗口的左上角,CClientDC,CPaintDC下坐标原点是在客户区的左上角。

CDC:GetDC,ReleaseDC
CClientDC:GetDC,ReleaseDC封装起来,只能访问客户区
CWindowDC:GetDC,ReleaseDC封装起来,不仅仅可以访问客户区 
CPaintDC:窗口重绘时会发送一个WM_PAINT消息:消息响应函数OnPaint,调用CPaintDC

下面介绍一下获得这块画布的方法,即获取设备上下文的方法:

1、通过OnDraw()函数获得CPaintDC:在OnDraw()函数中入口参数CDC *pDC,传入操作的设备上下文,这个上下文是CPaintDC。
他是通过OnPaint()构建,并传入OnDraw(),View类如果没有重载OnPaint(),则窗口刷新时自动调用MFC底层代码的OnPaint()函数,
从而调用OnDraw()。我们就可以通过OnDraw()在客户区进行初始化的绘制。
2、通过CClientDC,CPaintDC,CWindowDC定义一个DC。
例如:CClientDC dc(this);创建一个dc,
在当前对象的客户区。创建一个CWindowDC类的对象:CWindowDC dc(this);
3、通过HDC GetDC(HWND hWnd);hWnd:设备上下文环境被检索的窗口的句柄,如果该值为NULL,
GetDC则检索整个屏幕的设备上下文环境,返回值是hdc,
即一个DC描述符,入口参数是一个窗口类型的句柄。

例如: pWnd=GetDlgItem(IDC_STATIC_PIC); //IDC_STATIC_PIC是对话框图片空间的一个标识号

pWnd->SetWindowPos(NULL,0,0,512,120,SWP_NOZORDER|SWP_NOMOVE); //调整长宽为(512,120)
pDc=pWnd->GetDC();
GDI及GDI函数
GDI对象就是绘画时用的工具,比如画笔,画刷,字体,位图,调色板。
如果绘图的时候,需要先把相应的GDI设备选入设备环境,就是为画图选个画笔,工具。
注意MFC中,GDI和CDC是两个独立的类
  • 窗口滚动功能的实现
    OnInitialUpdate
    视图窗口完全建立后第一个被框架调用的函数。框架在第一次调用OnDraw前会调用OnInitialUpdate,因此OnInitialUpdate是设置滚动视图的逻辑尺寸和映射模式的最合适的地方。

OnCreate()后窗口产生, 然后才是视图的OnInitialUpDate,一般在这里对视图的显示做初始化。

一、OnCreate和OnInitialUpDate

  • OnCreate()只是产生VIEW的基本结构和变量.OnCreate()不产生窗口,只是在窗口显示前设置窗口的属性如风格位置等。create负责注册并产生窗口。
    OnInitialUpDate()中,主要初始化视图中控件等。对各个变量进行初始化操作。

  • OnCreate()是生成结构的
    OnInitialUpDate()是对结构进行初始化。
    两个一个相当于硬件一个相当于软件,功能和作用完全不同。

  • OnCreate
    oncreate 消息响应函数,是用来“表示一个窗口正在生成”。
    在CWnd::Create中,又会调用OnCreate函数,但是实际上这个时候Create函数还没有退出,CWnd的某些部分还没有创建好。

  • create()不是对应于消息wm_create的,oncreate()才是。
    create()只用于产生窗口,像动态创建控件中的create()一样。

  • 设备坐标(0,0)点始终位于窗口客户区的左上角。

  • 两种保存图形和重绘图形的方式:元文件和兼容设备描述表
    元文件
    元文件设备上下文类:CMetaFileDC
    元文件并没有包含所绘图形的图形数据,它包含的是图形的绘制命令。

相关文章

  • VC++(十一)图形的保存和重绘

    Invalidate使整个窗口客户区无效。窗口的客户区无效意味着需要重绘。Windows会在应用程序的消息队列里放...

  • R语言实战04-图形初阶

    今天我们来的学习创建和保存图形以及图形参数; 1、创建和保存图形 附图 除了pdf(), 还有win.metafi...

  • 2019-10-12 刷新echarts图形数据的方式

    第一种方式:像这样完全重绘一下echarts图形 drawZjymqkChart () { let myCh...

  • R语言实战—03图形初阶

    3.1 使用图形 使用代码保存图形:保存为PDF—pdf(filename),其它格式:win.metafile(...

  • CAD_学习_01

    AutoCAD与绘图 熟悉AUTOCAD软件,了解其主要功能 掌握图形文件的保存与打开 掌握直线、圆等基本图元的绘...

  • 22,重绘、回流

    1,浏览器渲染机制 2,重绘 3,回流 > 重绘。 4,浏览器优化 5,减少重绘和回流

  • View绘制

    save restore Canvas保存和还原 drawLine drawColor 绘制图形 tran...

  • 面经 之 Browser浏览器读后感

    浏览器,原文请移步Browser | InterviewMap 回流和重绘 回流和重绘 - 掘金 存储 cooki...

  • 前端总结(后续继续更新)

    1,reflow和repaint:回流和重绘。回流:renderTree 重建。重绘:外观样式风格进行更新。(co...

  • 前端一些细节

    1,reflow和repaint:回流和重绘。回流:renderTree 重建。重绘:外观样式风格进行更新。(co...

网友评论

      本文标题:VC++(十一)图形的保存和重绘

      本文链接:https://www.haomeiwen.com/subject/bbndpttx.html