• WM_PAINT和WM_ERASEBKGND消息


    1、OnPaint()函数是窗口重绘消息WM_PAINT的响应函数,当窗口重绘时会产生WM_ERASEBKGND消息和WM_PAINT消息,而且WM_ERASEBKGND会先于WM_PAINT产生,所以窗口重绘时,会先调用OnEraseBkGnd()擦除窗口,再调用OnPaint绘制窗口。如果你在OnPaint()里自绘了窗口,在窗口重绘的时候会发现窗口会闪一下,原因就是OnEraseBkGnd()函数中使用默认的画刷(一般为灰白色)来擦除窗口。解决这个问题有三个方法:

    ① 在OnEraseBkGnd()中实现绘制窗口的工作,注释掉OnEraseBkGnd()中擦除窗口的代码。

    ② 在OnPaint中实现绘制窗口的工作,注释掉OnEraseBkGnd()中擦除窗口的代码。

    ③ 在OnPaint中实现绘制窗口的工作,在创建窗口时设置背景画刷为空。 

    由于WM_PAINT消息需要等消息队列中的其它消息发送完后才能被处理,而在OnEraseBkGnd()中实现绘制窗口的工作的话,窗口元件有任何小变动都会调用OnEraseBkGnd(),OnPaint()在调用之前OnEraseBkGnd()可能已经调用了好几次,所以最好的方法是在OnEraseBkGnd()中只做简单不耗时的绘图工作,而复杂的绘制工作在OnPaint()中进行。

    窗口重绘的时候并不一定会产生WM_ERASEBKGND消息,在调用Invalidate()和InvalidateRect()重绘窗口的时候可以通过参数bErase来指定是否产生WM_ERASEBKGND消息来擦除背景。

    2、Invalidate()使整个客户区无效,客户区无效则会发送WM_PAINT消息对整个客户区进行重绘。调用Invalidate后可能不会立即重绘窗口,因为它要等到消息队列中的其它消息发送完后才能被处理。函数原型:

    void Invalidate( BOOL bErase = TRUE);

        其参数决定了是否要在WM_PAINT消息前发送WM_ERASEBKGND消息来擦除窗口背景,bErase为TRUE时,重绘区域内的背景将被擦除,否则,背景将保持不变。

       InvalidateRect()Invalidate功能相同,但可以指定重绘的区域,函数原型:

    BOOL InvalidateRect(const RECT *lpRect, BOOL bErase = TRUE);

    UpdateWindow()会通过发送WM_PAINT消息对客户区进行重绘,如果没有可绘制的区域则不进行重绘。如果有可绘制的区域的话UpdateWindow()会立即重绘窗口,它发送的WM_PAINT消息不会进入消息队列而是直接调用窗口过程进行重绘。所以一般是调用Invalidate()后接着调用UpdateWindow()来达到窗口立即重绘的目的函数原型:
    void UpdateWindow();
    RedrawWindow()也是用来使窗口重绘的,它更加灵活,其flags参数可以是下面值的组合:RDW_INVALIDATE使区域无效,RDW_UPDATENOW立即重绘窗口,RDW_ERASE重绘区域内的背景将被擦除。所以RedrawWindow()可以实现
    InvalidateRect + UpdateWindow功能之和。函数原型:
    BOOL RedrawWindow(
       LPCRECT lpRectUpdate = NULL,
       CRgn* prgnUpdate = NULL,
       UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE 
    ); 

     InvalidateRgn()函数通过添加一个区域到一个窗口的更新区域中来使指定矩形的客户区域无效;这个无效的区域和所有更新区域中的其他区域将被标记用来在下一个WM_PAINT消息发生的时候描绘。 
     参考出处:http://www.cnblogs.com/BeyondTechnology/archive/2011/03/25/1995942.html 
    3、
    GetUpdateRect(LPRECT lpRect, BOOL bErase = FALSE)可以获得需要更新的区域,在调用了InvalidRect后可以用这个函数来获得无效区域,但如果调用了BeginPaint则获得的区域为空,所以在OnPaint中调用GetUpdateRect()无效。
    GetClientRect()得到的RECT以所在窗口左上角为原点,且不包括标题栏,外框。
    GetWindowRect()得到的RECT以屏幕左上角为原点,获得整个窗口的矩形。
    ScreenToClient()就是把屏幕坐标系下的RECT坐标转换为客户区坐标系下的RECT坐标。
    ClientToScreen()就是把客户区坐标系下的RECT坐标转换为屏幕坐标系下的RECT坐标。
  • 相关阅读:
    LCT 动态树 模板
    [HNOI2010] 物品调度 fsk
    [HNOI2010] 矩阵 matrix
    [HNOI2010] 平面图判定 planar
    [HNOI2010] 公交线路 bus
    [HNOI2017]抛硬币
    [HNOI2010] 弹飞绵羊 bounce
    [HNOI2010] 合唱队 chorus
    [HNOI2017]礼物
    [HNOI2017]大佬
  • 原文地址:https://www.cnblogs.com/milanleon/p/4389922.html
Copyright © 2020-2023  润新知