windows窗口绘制总结



一般情况下在那个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

你可能感兴趣的:(windows,gdi)