zoukankan      html  css  js  c++  java
  • RedrawWindow, UpdateWindow,InvalidateRect 用法

    1. 系统何时发送WM_PAINT消息?

    系统会在多个不同的时机发送 WM_PAINT 消息:当第一次创建一个窗口时,当改变窗口的大小时,当把窗口从另一个

    窗口背后移出时,当最大化或最小化窗口时,等等,这些动作都是由系统管理的,应用只是被动地接收该消息,在消息处理

    函数中进行绘制操作;大多数的时候应用也需要能够主动引发窗口中的绘制操作,比如当窗口显示的数据改变的时候,这一

    般是通过 InvalidateRect 和 InvalidateRgn 函数来完成的。

    InvalidateRect 和 InvalidateRgn把指定的区域加到窗口的 Update Region 中,当应用的消息队列没有其他

    消息时,如果窗口的 Update Region 不为空时,系统就会自动产生 WM_PAINT 消息。

    系统为什么不在调用 Invalidate 时发送 WM_PAINT 消息呢?又为什么非要等应用消息队列为空时才发送

    WM_PAINT 消息呢?这是因为系统把在窗口中的绘制操作当作一种低优先级的操作,于是尽可能地推后做。

    不过这样也有利于提高绘制的效率:两个 WM_PAINT 消息之间通过 InvalidateRect 和InvaliateRgn 使之失效

    的区域就会被累加起来,然后在一个 WM_PAINT 消息中一次得到 更新,不仅能避免多次重复地更新同一区域,也优化了

    应用的更新操作。

    这种通过 InvalidateRect 和 InvalidateRgn 来使窗口区域无效,依赖于系统在合适的时机发送 WM_PAINT

    消息的机 制实际上是一种异步工作方式,也就是说,在无效化窗口区域和发送 WM_PAINT 消息之间是有延迟的;有时候

    这种延迟并不是我们希望的,这时我们当然可以在无效化窗口区域后利用 SendMessage 发送一条 WM_PAINT消息来强

    制立即重画,但不如使用 Windows GDI 为我们提供的更方便和强大的函数: UpdateWindow 和 RedrawWindow。

    UpdateWindow 会检查窗口的 Update Region,当其不为空时才发送 WM_PAINT 消息; RedrawWindow 则给我

    们更多的控制:是否重画非客户区和背景,是否总是发送 WM_PAINT 消息而不管 Update Region 是否为空等。

    2. BeginPaint

    BeginPaint 和 WM_PAINT 消息紧密相关。试一试在 WM_PAINT 处理函数中不写 BeginPaint 会怎样?程序会像

    进入了一个死循环一样达到惊人的CPU占用率,你会发现程序总在处理一个接 一个的 WM_PAINT 消息。这是因为在通常情

    况下,当应用收到 WM_PAINT 消息时,窗口的 Update Region 都是非空的(如果为空就不需要发送WM_PAINT 消息

    了), BeginPaint 的一个作用就是把该 Update Region 置为空,这样如果不调用 BeginPaint,窗口的

    Update Region 就一直不为空,如前所述,系统就会一直发送 WM_PAINT 消息。

    BeginPaint 和 WM_ERASEBKGND 消息也有关系。当窗口的 Update Region 被标志为需要擦除背景时,

    BeginPaint 会发送 WM_ERASEBKGND 消息来重画背景,同时在其返回信息里有一个标志表明窗口背景是否被重画过。

    当我们用 InvalidateRect 和 InvalidateRgn 来把指定区域加到 Update Region 中时,可以设置该区域是否

    需要被擦除背景,这样下一个 BeginPaint 就知道是否需要发送 WM_ERASEBKGND 消息了。

    另外要注意的一点是,BeginPaint 只能在 WM_PAINT 处理函数中使用。

    补充几点:

    1.WM_Paint 是一个被动消息,不能通过普通的方法简单的 sendmessage WM_paint 了事

    这是不行的;但通过消息由程序员引发不是不可能;通过几个特殊的常数可以做到,不过要到delphi下找

    2.sendmessage 可以将消息发送到消息队列;但windows会自动判断是否存在无效的画图区域;

    如果存在无效的画图区域,则可能会重画,反之则弃用该消息.

    3.可以使用 InvalidateRect 等几个APi将屏幕上任意一个个矩形区域设置为无效区域,在UpdateWindow后调用后,windows会自动查找是否存在无效,并重画,该矩形区域;
  • 相关阅读:
    无锁队列的实现
    C/C++语言中闭包的探究及比较
    Linus:利用二级指针删除单向链表
    Unix考古记:一个“遗失”的shell
    “C++的数组不支持多态”?
    Alan Cox:单向链表中prev指针的妙用
    二叉树迭代器算法
    C语言全局变量那些事儿
    数据即代码:元驱动编程
    C++模板”>>”编译问题与词法消歧设计
  • 原文地址:https://www.cnblogs.com/lidabo/p/2574261.html
Copyright © 2011-2022 走看看