一般情况下在那个WM_PAINT消息哪里去绘制窗口,
处理这个消息的时候,一般是调用:
BeginPaint()
在这一对函数里面绘制窗口。
EndPaint()
这个BeginPaint函数在调用期间,系统会send WM_NCPAINT and WM_ERASEBKGND
去更新窗口的非客户区和刷新窗口背景。
窗口的非客户区:title bar, window menu (also known as the System menu), and scroll bars
一般的程序调用DefWindowProc函数去绘制。
BeginPaint会填充一个结构体 PAINTSTRUCT,表示那个区域需要更新,背景是否需要绘制等信息。
这个函数还会clear update region,以免系统不停的发送WM_PAINT消息。
所以在处理WM_PAINT消息的时候一定要调用BeginPaint函数。
程序可以设置窗口的更新区域:InvalidateRect or InvalidateRgn
这两个函数的调用不会立即出发WM_PAINT消息,而是会将那些无效区域汇集起来,
在必要的时刻发送一个WM_PAINT
ValidateRect and ValidateRgn这两个函数从更新区域里面剔除一部分更新区域。
通常用再自己更新了窗口之后,WM_PAINT消息处理之前。
窗口的立即绘制:
一般这个WM_PAINT消息,是优先级比较低的,这个消息要在消息列队里没有其他消息的时候系统才发过去处理。
如果你需要立即绘制窗口:
这两个函数可以做到:UpdateWindow and RedrawWindow
UpdateWindow立即发送一个WM_PAINT 到消息队列,如果update region不为空的话。
RedrawWindow就更强大,update region为空而已可以强制绘制,还可以指定是否绘制窗口的非客户区
、是否擦除背景。也是通过立即发送WM_PAINT的方式来绘制的,不过程序的消息队列里面是否
还有其他消息。
窗口的非客户区域的更新:
非客户区也有一个update region,但是系统不会合并里面的各个小区域,使用GetDCEx可以指定合并。
如果程序自己处理非客户区域激活消息: WM_NCACTIVATE,窗口过程函数需要返回true;
通常的做法:
case WM_NCPAINT:
{
HDC hdc;
hdc = GetDCEx(hwnd, (HRGN)wParam, DCX_WINDOW|DCX_INTERSECTRGN);
// Paint into this DC
ReleaseDC(hwnd, hdc);
}
如果在处理WM_NCACTIVATE的时候窗口已经最小化了,那么需要调用 DefWindowProc来处理这个消息。
窗口风格:CS_VREDRAW or CS_HREDRAW 对窗口绘制的影响:
如果窗口没有设置这两个属性:
在窗口大小发生变化的时候(通过点击最大,最小化窗口,恢复窗口,调用SetWindowPos等函数)
系统认为先前暴露出来的窗口部分,是不需要更新的,
只会认为新暴露出来的部分是需要更新的,就是窗口拉大的时候才会有更新消息。
如果设置了这两个属性,只有窗口大小发生变化,就wm_paint消息产生,全部重新绘制。
窗口的各种区域对窗口绘制的影响:
有三种区域update region,visible region,clipping region。
update region就是需要更新的区域,
visible region就是可见区域,应用程序不能直接设置这个区域,
窗口的WS_CLIPCHILDREN and WS_CLIPSIBLINGS会影响系统如何计算可见区域。
clipping region就是需要绘制的区域,一般情况下是update region与visible region先交的区域。
可以调用 SetWindowRgn, SelectClipPath and SelectClipRgn,进一步改变窗口的clipping region。
锁住窗口的更新区域:
LockWindowUpdate(hwnd)
就是不让更新,调用BeginPaint函数得到的dc的更新区域为0,
当然锁住了更新区域也是可以更新的,就是调用GetDCEx 指定DCX_LOCKWINDOWUPDATE。
LockWindowUpdate(null);//这样子就是取消
当取消更新区域的时候,系统发生一个WM_PAINT 消息到消息队列,以更新在锁住期间发生的窗口
更新要求,如果在锁住期间没有发生更新需求,就不发送这个消息了。
获取dc的函数
BeginPaint EndPaint
GetWindowDC(获取整个窗口的dc,包括非客户区) ReleaseDC
GetDCEx ReleaseDC