获取设备环境句柄函数

1>BeginPaint:

函数为指定窗口进行绘图工作的准备,并用将和绘图有关的信息填充到一个
PAINTSTRUCT结构中。
函数原形:
HDC BeginPaint(
HWND hwnd,            // 窗口的句柄
LPPAINTSTRUCT lpPaint // 绘制信息
);
参数:
hwnd:[输入]被重绘的窗口句柄
lpPaint:[输出]指向一个用来接收绘画信息的PAINTSTRUCT结构
返回值:
如果函数成功,返回值是指定窗口的“显示设备描述表”句柄。
如果函数失败,返回值是NULL,表明没有得到显示设备的内容。
Windows NT/2000/XP: 使用GetLastError得到更多的错误信息
2>EndPaint: 
原形:
EndPaint函数标记指定窗口的绘画过程结束;这个函数在每次调用BeginPaint函数之后被请求,但仅仅在绘画完成以后。
BOOL EndPaint(
HWND hWnd,                  // 窗口句柄
CONST PAINTSTRUCT *lpPaint  // 绘制窗口的数据
);
hWnd:[输入]已经被重画的窗口的HANDLE
lpPaint:[输入]指向一个PAINTSTRUCT结构,该结构包含了绘画信息,是BeginPaint函数返回的返回值:
返回值:
返回值始终是非0
备注:
PAINTSTRUCT 结构体包含了用于绘制窗口客户区的信息。
PAINTSTRUCT定义:
typedef struct tagPAINTSTRUCT {
HDC hdc;
BOOL fErase;
RECT rcPaint;
BOOL fRestore;
BOOL fIncUpdate;
BYTE rgbReserved[32];
} PAINTSTRUCT, *PPAINTSTRUCT;
hdc是用于绘制的句柄,fErase如果为非零值则擦除背景,否则不擦除背景,rcPaint 通过制定左上角和右下角的坐标确定一个要绘制的矩形范围,该矩形单位相对于客户区左上角,后面三个参数都是系统预留的,编程一般用不到。
3>GetDC
函数功能:该函数检索一指定窗口的客户区域或整个屏幕的显示设备上下文环境的句柄,以后可以在GDI函数中使用该句柄来在设备上下文环境中绘图。
GetDCEx函数是GetDC的一个扩展,它能使应用程序更多地控制在客户区域内如何或是否发生剪切。
函数原型:HDC GetDC(HWND hWnd);
参数:
hWnd:设备上下文环境被检索的窗口的句柄,如果该值为NULL,GetDC则检索整个屏幕的设备上下文环境。
Windows 98,WindowsNT 5.0或以后版本:如果该参数为Null,GetDC检索首要显示器的设备上下文环境,要得到其他显示器的设备上下文环境,可使用EnumDisplayMonitors和CreateDc函数。
返回值:如果成功,返回指定窗口客户区的设备上下文环境;如果失败,返回值为Null。
Windows NT:若想获得更多错误信息,可调用GetLastError函数。
注释:GetDC函数根据指定的等级类型检索指定窗口普通的、典型的或特有的设备上下文环境。
对于普通设备上下文环境,GetDC在每次检索的时候部分分配给它缺省特性,对于典型和特有的设备上下文环境,GetDC不改变先前设置的特性。
在使用普通设备上下文环境绘图之后,必须调用ReleaseDc函数释放该设备上下文环境,典型和特有设备上下文环境不需要释放,设备上下文环境的个数仅受有效内存的限制。
还有一点要特别注意,getdc函数对系统的相对开销比较大,如果你的程序里使用了几百个getdc函数而又不通过ReleaseDC函数释放的话,那你机器运行速度将是龟速。
4>GetWindowDC函数
GetWindowDC函数:返回hWnd参数所指定的窗口的设备环境。
获得的设备环境覆盖了整个窗口(包括非客户区),例如标题栏菜单、滚动条,以及边框。这使得程序能够在非客户区域实现自定义图形,例如自定义标题或者边框。当不再需要该设备环境时,需要调用ReleaseDC函数释放设备环境。注意,该函数只获得通用设备环境,该设备环境的任何属性改变都不会反映到窗口的私有或者类设备环境中(如果窗口有的话)!
函数原型:
                      HDC GetWindowDC(HWND hWnd   // 窗口句柄);
api函数名(function):GetWindowDC
GetWindowDC 别名(alias):
GetWindowDC 库名(library):User32
GetWindowDC 操作系统(os):Requires Windows NT 3.1 or later; Requires Windows 95 or later
GetWindowDC 参数表(parameter):
hwnd ----------- Long,将获取其设备场景的窗口?hWndIdentifies the window with a device context that is to be retrieved.GetWindowDC 返回值(return):
Long,执行成功为窗口设备场景,失败则为0 If the function succeeds, the return value is the handle of a device context for the specified window. If the function fails, the return value is NULL, indicating an error or an invalid hWnd parameter. GetWindowDC 说明(description):
获取整个窗口(包括边框、滚动条、标题栏、菜单等)的设备场景 The GetWindowDC function retrieves the device context (DC) for the entire window, including title bar, menus, and scroll bars. A window device context permits painting anywhere in a window, because the origin of the device context is the upper-left corner of the window instead of the client area.GetWindowDC 声明(declare):
Declare Function GetWindowDC Lib "user32" Alias "GetWindowDC" (ByVal hwnd As Long) As LongGetWindowDC 不推荐在vb里使用这个函数。用完后一定要用ReleaseDC函数释放场景
另:
1>InvalidateRect
该函数向指定的窗体更新区域添加一个矩形,然后窗口客户区域的这一部分将被重新绘制。
BOOL InvalidateRect(
HWND hWnd, // handle of window with changed update region
CONST RECT *lpRect, // address of rectangle coordinates
BOOL bErase // erase-background flag
);
参数:
hWnd:要更新的客户区所在的窗体的句柄。如果为NULL,则系统将在函数返回前重新绘制所有的窗口, 然后发送 WM_ERASEBKGND  WM_NCPAINT 给窗口过程处理函数。
lpRect:无效区域的矩形代表,它是一个结构体指针,存放着矩形的大小。如果为NULL,全部的窗口客户区域将被增加到更新区域中。
bErase:指出无效矩形被标记为有效后,是否重画该区域,重画时用预先定义好的画刷。当指定TRUE时需要重画。
返回值:
函数成功则返回非零值,否则返回零值。
说明:被标记为无效矩形的区域直到WM_PAINT消息被处理完之后才会消失,或者使用ValidateRect(),ValidateRgn()函数来使之有效。当应用程序消息队列中为空时,并且窗体要更新的区域非空时,系统会发送一个WM_PAINT消息到窗体。
这两个都用于声明客户区无效,当下一个WM_PAINT消息到来时发生重画。
其中InvalidateRect(hwnd, NULL, true);重画时将擦除背景。
InvalidateRect(hwnd, NULL, false);重画时不擦除背景
其他说明:InvalidateRect是将窗口中的一块矩形区域标注为“无效”,系统会不断向窗口发送WM_PAINT消息令其重绘。在响应WM_PAINT消息时,需要调用BeginPaint获取DC来进行重绘。该函数会合并所有“无效”区域,对DC进行裁剪,将整个窗口标注为“有效”,清除WM_PAINT消息。DC经裁剪之后,在进行绘制时,超出DC范围的操作将不被处理,所以即使在响应WM_PAINT消息时绘制的是整个窗口,而实际上绘制的也只是“无效”区域。恰当地使用InvalidateRect进行刷新比刷新整个窗口的效率要高。在WM_PAINT消息时,应尽量根据PAINTSTRUCT结构中rcPaint指定的矩形来处理重绘,减少执行不必要的代码,从而提高效率。
调用InvalidateRect后不需要手动发送WM_PAINT消息。
2>ValidateRect
功能:该函数更新指定窗口的无效矩形区域,使之有效。
原形:BOOL ValidateRect(
HWND hWnd,          // 窗口的句柄
CONST RECT *lpRect  // 指向RECT结构的指针
);
参数:
hWnd:
[输入]标识一个想要修改状态的窗口。若该参数为NULL, 系统将更新所有的窗口,然后在函数返回前发送WM_ERASEBKGND  WM_NCPAINT 消息给窗口过程处理函数。
lpRect:
[输入]指向一个包含需要生效的矩形的更新区域坐标的RECT 结构体. 如果该参数为NULL,所有的客户区域将会生效。
返回值:
成功执行返回非零值,否则返回零值。
想得到更多错误信息,请调用GetLastError函数。
说明:
BeginPaint函数会自动使全部客户区生效。如果在下一个WM_PAINT消息产生之前,一个区域的的更新区域必须有效,那么不要调用ValidateRect或ValidateRgn函数。
系统继续产生WM_PAINT 消息直到当前的更新区域生效。 
3>InvalidateRgn
函数通过添加一个区域到一个窗口的更新区域中来使指定矩形的客户区域无效;这个无效的区域和所有更新区域中的其他区域将被标记用来在下一个WM_PAINT消息发生的时候描绘。
BOOL InvalidateRgn(
HWND hWnd,    // 窗口的句柄
HRGN hRgn,    // 区域的句柄
BOOL bErase   // 擦除状态
);
参数:
hWnd:[输入]更新区域被修改的窗口HANDLE
hRgn:[输入]被添加到更新区域的区域HANDLE;这个区域被假定有一个客户区坐标。如果这个参数是NULL,整个客户区都被添加进更新区域。
bErase:[输入]说明当更新区域被处理的时候更新区域内的背景是否要擦除。如果这个参数是TRUE,当BeginPaint函数被调用的时候背景将被擦除,如果参数是FALSE,背景不会改变。
返回值:
返回值总是非0。
备注:
无效的区域被累积,直到下个WM_PAINT消息被处理或着通过ValidateRect或ValidateRgn来使区域变有效。
系统发送一个WM_PAINT消息给到一个窗口,无论窗口的更新区域是不是空的,有没有其他的消息在窗口的应用程序队列中。
指定的区域必须已经通过一个区域函数创建了。
如果更新区域中任何部分的bErase参数是TRUE,整个区域的背景都被擦除,而不是指定的那部分。
4>ValidateRgn
说明
激活窗口中指定区域,把它从刷新区移走
返回值
Long,执行成功为非零值,失败为0
参数表
参数 类型及说明
hwnd Long,窗口句柄
hRgn Long,定义要激活区的区域句柄,该区域以窗口客户坐标表示
5>Invalidate
原形:void Invalidate( BOOL bErase = TRUE );
参数: bErase 决定了是否要在WM_PAINT消息前发送WN_ERASEBKGND
该函数的作用是使整个窗口客户区无效。窗口的客户区无效意味着需要重绘,例如,如果一个被其它窗口遮住的窗口变成了前台窗口,那么原来被遮住的部分就是无效的,需要重绘。这时Windows会在应用程序的消息队列中放置WM_PAINT消息。MFC窗口类提供了WM_PAINT的消息处理函数OnPaint,OnPaint负责重绘窗口。视图类有一些例外,在视图类的OnPaint函数中调用了OnDraw函数,实际的重绘工作由OnDraw来完成。参数bErase为TRUE时,重绘区域内的背景将被擦除,否则,背景将保持不变。
与UpdateWindow()区别:
UpdateWindow( )的作用是使窗口立即重绘。调用Invalidate等函数后窗口不会立即重绘,这是由于WM_PAINT消息的优先级很低,它需要等消息队列中的其它消息发送完后才能被处理。调用UpdateWindow函数可使WM_PAINT被直接发送到目标窗口,从而导致窗口立即重绘。
与WM_PAINT的关系
]系统会在多个不同的时机发送WM_PAINT消息:当第一次创建一个窗口时,当改变窗口的大小时,当把窗口从另一个窗口背后移出时,当最大化或最小化窗口时,等等,这些动作都是由系统管理的,应用只是被动地接收该消息,在消息处理函数中进行绘制操作;大多数的时候应用也需要能够主动引发窗口中的绘制操作,比如当窗口显示的数据改变的时候,这一般是通过InvalidateRect和  InvalidateRgn函数来完成的。InvalidateRect和InvalidateRgn把指定的区域加到窗口的Update  Region中,当应用的消息队列没有其他消息时,如果窗口的Update Region不为空时,系统就会自动产生WM_PAINT消息。
        系统为什么不在调用Invalidate时发送WM_PAINT消息呢?又为什么非要等应用消息队列为空时才发送WM_PAINT消息呢?这是因为系统把在窗口中的绘制操作当作一种低优先级的操作,于是尽可能地推后做,这样有利于提高绘制的效率:在两个WM_PAINT消息之间多个Invalidate调用使之失效的区域就会被累加起来,然后在一个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是否为空等