您的位置:首页 > 其它

windows窗口绘制总结

2015-09-15 12:00 211 查看
一般情况下在那个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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: