1、InvalidateRect 只是增加重绘区域,在下次 WM_PAINT 的时候才生效InvalidateRect 函数中的参数 TRUE 表示系统会在你画之前用背景色将所选区域覆盖一次,默认背景色为白色,可以通过设置 BRUSH 来改变背景色。Invalidate()之后:(MFC 的,顺便了)OnPaint()-OnPrepareDC()-OnDraw()所以只是刷新在 OnPaint()和 OnDraw()函数中的绘图语句。其它地方没有影响。Invalidate 标记一个需要重绘的无效区域,并不意味着调用该函数后就立刻进行重绘。类似于 PostMessage(WM_PAINT),需要处理
2、到 WM_PAINT 消息时才真正重绘。以为您 Invalidate 之后还有其他的语句正在执行,程序没有机会去处理WM_PAINT 消息,但当函数执行完毕后,消息处理才得以进行。Invalidate 只是放一个 WM_PAINT 消息在队列里,不做别的,所以只有当当前函数返回后,进入消息循环,取出 WM_PAINT,才执行 PAINT,所以不管Invalidate 放哪里,都是最后的。InvalidateRect(hWnd,向 hWnd 窗体发出 WM_PAINT 的消息,强制客户区域重绘制,rect 是你指定要刷新的区域,此区域外的客户区域不被重绘,这样防止客户区域的一个局部的改动,而导致
3、整个客户区域重绘而导致闪烁,如果最后的参数为 TRUE,则还向窗体发送 WM_ERASEBKGND 消息,使背景重绘,当然在客户区域重绘之前。UpdateWindow 只向窗体发送 WM_PAINT 消息,在发送之前判断GetUpdateRect(hWnd,NULL,TRUE)看有无可绘制的客户区域,如果没有,则不发送 WM_PAINT如果希望立即刷新无效区域,可以在调用 InvalidateRect 之后调用UpdateWindow,如果客户区的任一部分无效,则 UpdateWindow 将导致 Windows用 WM_PAINT 消息调用窗口过程(如果整个客户区有效,则不调用窗口过程)。这
4、一 WM_PAINT 消息不进入消息队列,直接由 WINDOWS 调用窗口过程。窗口过程完成刷新以后立刻退出,WINDOWS 将控制返回给程序中 UpdateWindow 调用之后的语句。(windows 程序设计第 5 版 P98)UpdateData()顺便说下,这个函数不是刷新界面用的。UpdateData();参数为 FALSE 时,将界面上控件绑定的变量的数据导到控件内,参数为 TRUE 时,导入方向则相反Invalidate 与 WM_PAINT 之间的关系 系统会在多个不同的时机发送 WM_PAINT 消息:当第一次创建一个窗口时,当改变窗口的大小时,当把窗口从另一个窗口背后移出
5、时,当最大化或最小化窗口时,等等,这些动作都是由系统管理的,应用只是被动地接收该消息,在消息处理函数中进行绘制操作;大多数的时候应用也需要能够主动引发窗口中的绘制操作,比如当窗口显示的数据改变的时候,这一般是通过 InvalidateRect和 InvalidateRgn 函数来完成的。InvalidateRect 和 InvalidateRgn 把指定的区域加到窗口的 Update Region 中,当应用的消息队列没有其他消息时,如果窗口的 Update Region 不为空时,系统就会自动产生 WM_PAINT 消息。 系统为什么不在调用 Invalidate 时发送 WM_PAINT
6、消息呢?又为什么非要等应用消息队列为空时才发送 WM_PAINT 消息呢?这是因为系统把在窗口中的绘制操作当作一种低优先级的操作,于是尽可能地推后做,这样有利于提高绘制的效率:在两个 WM_PAINT 消息之间多个 Invalidate 调用使之失效的区域就会被累加起来,然后在一个 WM_PAINT 消息中一次得到更新,不仅能避免多次重复地更新同一区域,也优化了应用的更新操作。像这种通过 InvalidateRect 和InvalidateRgn 来使窗口区域无效,依赖于系统在合适的时机发送 WM_PAINT 消息的机 制实际上是一种异步工作方式,也就是说,在无效化窗口区域和发送WM_PAIN
7、T 消息之间是有延迟的;有时候这种延迟并不是我们希望的,这时我们当然可以在无效化窗口区域后利用 SendMessage 发送一条 WM_PAINT 消息来强制立即重画,但不如使用 Windows GDI 为我们提供的更方便和强大的函数:UpdateWindow 和 RedrawWindow。UpdateWindow 会检查窗口的 Update Region,当其不为空时才发送 WM_PAINT 消息;RedrawWindow 则给我们更多的控制:是否重画非客户区和背景,是否总是发送 WM_PAINT 消息而不管 Update Region 是否为空等CClientDC、CPaintDC、CWi
8、ndowDC 类、WM_PAINT 消息首先说一下什么是 DC(设备描述表) 解:Windows 应用程序通过为指定设备(屏幕,打印机等)创建一个设备描述表(Device Context, DC)在 DC 表示的逻辑意义的 “画布”上进行图形的绘制。DC 是一种包含设备信息的数据结构,它包含了物理设备所需的各种状态信息。Win32 程序在绘制图形之前需要获取 DC 的句柄 HDC,并在不继续使用时释放掉。 在 c+ 编程中常会见到 HDC,CDC,CClientDC,CPaintDC,CWindowDC 这样的类 HDC 是 DC 的句柄,API 中的一个类似指针的数据类型. CDC 是 MF
9、C 的 DC 的一个类 CDC 等设备上下分类 ,都含有一个类的成员变量 :m_Hdc;即 HDC 类型的句柄. 下面说下一些细点的知识点 CClientDC,CWindowDC 区别不大, 可以说 CWindowDC 包含了 CClientDC 就拿记事本来说 CClientDC 就只是白白的我们可以编辑文字的那个区域是 客户区 CWindowDC 除了上面说的白白区域, 还包括菜单栏和工具栏等 CClientDC 和 CWindowDC 与 CPaintDC 的区别大点 在 DC 的获取方面 CClientDC 和 CWindowDC 使用的是并只能是 GetDC 和 ReleaseDC
10、CPaintDC 使用的是并只能是 BeginPaint 和 EndPaint CPaintDC 只能用在响应 WM_PAINT 事件 CClientDC,CWindowDC 只能用在响应 非 WM_PAINT 事件 关于 WM_PAINT 事件 系统会在多个不同的时机发送 WM_PAINT 消息:当第一次创建一个窗口时,当改变窗口的大小时,当把窗口从另一个窗口背后移出时,当最大化或最小化窗口时,等等,这些动作都是由系统管理的,应用只是被动地接收该消息,在消息处理函数中进行绘制操作;大多数的时候应用也需要能够主动引发窗口中的绘制操作,比如当窗口显示的数据改变的时候,这一般是通过 Invalid
11、ateRect和 InvalidateRgn 函数来完成的。 InvalidateRect 和 InvalidateRgn 把指定的区域加到窗口的 Update Region 中,当应用的消息队列没有其他消息时,如果窗口的Update Region 不为空时,系统就会自动产生 WM_PAINT 消息。 系统为什么不在调用 Invalidate 时发送 WM_PAINT 消息呢?又为什么非要等应用消息队列为空时才发送 WM_PAINT 消息呢?这是因为系统把在窗口中的绘制操作当作一种低优先级的操作,于是尽可能地推后做。不过这样也有利于提高绘制的效率:两个 WM_PAINT 消息之间通过 Inva
12、lidateRect 和 InvaliateRgn使之失效的区域就会被累加起来,然后在一个 WM_PAINT 消息中一次得到更新,不仅能避免多次重复地更新同一区域,也优化了应用的更新操作。像这种通过 InvalidateRect 和 InvalidateRgn 来使窗口区域无效,依赖于系统在合适的时机发送 WM_PAINT 消息的机制实际上是一种异步工作方式,也就是说,在无效化窗口区域和发送 WM_PAINT 消息之间是有延迟的;有时候这种延迟并不是我们希望的,这时我们当然可以在无效化窗口区域后利用 SendMessage 发送一条 WM_PAINT 消息来强制立即重画,但不如使用 Windo
13、ws GDI 为我们提供的更方便和强大的函数:UpdateWindow 和 RedrawWindow。UpdateWindow 会检查窗口的 Update Region,当其不为空时才发送 WM_PAINT 消息;RedrawWindow 则给我们更多的控制:是否重画非客户区和背景,是否总是发送 WM_PAINT 消息而不管 Update Region 是否为空等。CDC 及其派生类的继承视图: CObject public |-CDC public |-|-CClientDC public |-|-CPaintDC public |-|-CWindowDC public |-|-CMetaF
14、ileDC (注意: 除 CMetaFileDC 以外的三个派生类用于图形绘制.) CDC 类定义了一个设备描述表相关的类,其对象提供成员函数操作设备描述表进行工作,如显示器,打印机,以及显示器描述表相关的窗口客户区域。 通过 CDC 的成员函数可进行一切绘图操作。CDC 提供成员函数进行设备描述表的基本操作,使用绘图工具, 选择类型安全的图形设备结构(GDI) ,以及色彩,调色板。除此之外还提供成员函数获取和设置绘图属性,映射,控制视口,窗体范围,转换坐标,区域操作,裁减,划线以及绘制简单图形(椭圆,多边形等) 。成员函数也提供绘制文本,设置字体,打印机换码,滚动, 处理元文件。 其派生类:
15、 1.PaintDC: 封装 BeginPaint 和 EndPaint 两个 API 的调用。 (1)用于响应窗口重绘消息(WM_PAINT)是的绘图输出。 (2)CPaintDC 在构造函数中调用 BeginPaint()取得设备上下文,在析构函数中调用 EndPaint()释放设备上下文。 EndPaint()除了释放设备上下文外,还负责从消息队列中清除 WM_PAINT 消息。因此,在处理窗口重画时,必须使用CPaintDC,否则 WM_PAINT 消息无法从消息队列中清除,将引起不断的窗口重画。 (3)CPaintDC 也只能用在 WM_PAINT 消息处理之中。2.CClientD
16、C(客户区设备上下文): 处理显示器描述表的相关的窗体客户区域。用于客户区的输出,与特定窗口关联,可以让开发者访问目标窗口中客户区,其构造函数中包含了 GetDC,析构函数中包含了 ReleaseDC。 3.CWindowDC: 处理显示器描述表相关的整个窗体区域,包括了框架和控 件(子窗体) 。 (1)可在非客户区绘制图形,而 CClientDC,CPaintDC 只能在客户区绘制图形。 (2)坐标原点是在屏幕的左上角,CClientDC,CPaintDC 下坐标原点是在客户区的左上角。 (3)关联一特定窗口,允许开发者在目标窗口的任何一部分进行绘图,包含边界与标题,这种 DC 同 WM_NCPAINT 消息一起发送。 4.CMetaFileDC: 与元文件相关的设备描述表关联。