在Windows编程中,会经常提到句柄这个名词。要理解句柄,应注意以下几点:
句柄是一个4字节的整数,Windows利用它标志应用程序创建和使用的资源,包括应用程序实例、窗口、菜单、控件、内存、外设、文件以及与图形相关的画笔、刷子等。
句柄是Windows内部表资源数据存储的内存索引值,Windows利用它可访问表中的信息。通常,在程序中,要访问某个资源时,需要提供该资源的句柄,因此句柄可理解为是内存的索引值。
Windows平台下,不仅可以运行多个程序,还可以对同一个程序多次加载。每加载一次,Windows会创建一个运行的备份,即实例。同时系统为每个实例分配一个唯一的句柄,该句柄称为实例句柄。常用句柄类型及其说明如下表所示。
图形设备接口(GraphicsDevice Interface,简称为GDI),是Windows操作系统的子系统,负责在显示设备上显示图形。显而易见,GDI子系统是Windows1I常重要的组成部分。不但Windows应用程序显示图形时需要使用GDI,就连Windows本身也使用GDI来显示窗口、菜单和鼠标光标等用户界面对象。
GDI的主要目标之一是支持在各种输出设备(如显示器、打印机和绘图仪等)上进行与设备无关的图形输出。Windows的图形大部分是由GDI.DLL动态链接库输出的函数来处理的。GDI动态链接库通过调用在不同设备驱动程序模块中的例程来控制输出设备。例如,显示设备驱动程序用于访问与视频显示器有关的硬件。通过GDI,Windows可以确定驱动程序能够进行什么工作,并且由于应用程序只与GDI进行交互,所以GDI通过将应用程序与不同的输出设备隔离,使得应用程序可以在支持Windows的任意图形输出设备上工作。这就实现了图形输出的与设备无关性。
设备描述表(DeviceContext,简称为DC),是GDI保存的数据结构。设备描述表与特定的显示设备(如显示器、打印机等)相关,对于显示器,设备描述表总是与特定的窗口相关。
设备描述表中保存了显示图形所需使用的各种参数值,例如,显示的颜色、显示的坐标、显示的方式和背景的颜色等。Windows-GDI函数实际上是在设备描述表里显示正文及绘图的。当程序显示文字或绘图时,首先必须获得一个设备描述表句柄,完成输出文字或绘图后,还必须释放该句柄,否则会大大减少Windows存储单元。释放之后的句柄就不会再有效了。一般说来,在处理某条消息时,获取和释放设备描述表句柄必须成对出现,而且不同设备描述表的获取与释放的方法也不同。而这只是所使用的函数不同而已。
这个“万能驱动”就是Windows给我们提供的一个DC。由DC去和设备驱动程序打交道,完成图形的绘制。至于图形的效果,就要由所使用的图形设备来决定了。其实,DC也是一种资源,它也不是什么“万能驱动”,但是无论是显示,还是打印,我们都可以获取DC的句柄,然后在DC上操作,由DC映射到这些物理设备上就行了。
当应用程序需要绘图的时候,必须先获得设备描述表句柄,在获得了该句柄以后,Windows会以默认的属性值填充内部的属性表结构。随后,应用程序需要调用相应的GDI函数,以指定的属性值代替需要改变的默认值,当绘图完毕以后,应用程序必须释放设备描述表句柄,通常,应用程序使用下面几种方法来获取设备描述表句柄。
使用BeginPaint来获得设备描述表句柄
hdc =BeginPaint(hWnd,&ps);
//其他GDI操作
EndPaint(hWnd,&ps);
注意:设备描述表句柄的取得和释放必须成对使用,否则会引起严重问题
虽然通常在处理WM_PAINT消息时更新窗口的用户去,但有时也需要在处理非WM_PAINT消息时绘制用户区部分或者全部。在处理非WM_PAINT消息时可以通过调用GetDC函数来获取设备描述表句柄,GetDC函数的定义如下:
HDC GetDC(
HWND hWnd //所属窗口的句柄
);
该函数仅需要一个参数,即窗口函数所属窗口的句柄。该函数返回设备描述表句柄。当使用完毕后,应当调用ReleaseDC函数释放该设备描述表句柄。Release函数定义如下:
Int ReleaseDC(
HWND hWnd, //所属窗口句柄
HDC hDC //需要释放的设备描述表句柄
);
同样,GetDC与ReleaseDC函数必须成对使用,并且,不应当在处理一个消息时调用GetDC而在处理另一个消息时调用ReleaseDC函数。
GetDC传回用于写入窗口显示区域(客户区)的设备内容句柄,而GetWindowDC传回写入整个窗口设备内容句柄(而不仅限于窗口的客户区)。例如,您的程序可以使用从GetWindowDC传回的设备内容句柄在窗口的标题列上写入文字。然后,程序同样也应该处理WM_NCPAINT(非显示区域绘制)的消息。
Hdc =CreateDC(pszDriver,pszDevice,pszOutput,pData);
…
…
DeleteDC(hdc);
注意上面的释放句柄函数是DeleteDC。可以通过下面的调用来取得整个屏幕的设备描述表句柄(可以做出汉王手写板的效果):
Hdc = CreateDC(TEXT(“DISPLAY”),NULL,NULL,NULL);
hdcMem =CreateCompatibleDC(hdc);
…
DeleteDC(hdcMem);
GetDC函数与BeginPaint有两点不同:
1.通过BeginPaint函数所获得的操作区域是用户区中的无效矩形区域,后继的绘图操作只能在该无效区域内进行,而该区域以外的操作将被忽略。GetDC所获得的操作区域则是整个用户区,其后操作可以在用户区的任意部分进行,而不只是在无效矩形区域内。
2.BeginPaint函数会自动将无效区域变为有效,如果需要使整个用户区变为有效,则可以调用ValidateRect函数,并将其第二个参数设为NULL。
Windows使用设备描述表来保存控制GDI函数如何在显示设备上工作的“当前属性”。例如,在使用TextOut函数时,应用程序只需指定设备描述表句柄、文本显示的起始位置坐标、需要显示的文本及其长度,而不需要指定文本的字体、颜色、背景色、和字符间距等。Window可以从设备描述表中获取这些信息(默认值)。
当应用程序使用GetDC或BeginPaint函数获得一个设备描述表句柄时,Windows会自动用默认值设置其所有的属性。应用程序可以通过相应的GDI函数调用获取、修改所有的属性值。
通常,在调用GetDC或BeginPaint函数以获取设备描述表句柄时,Windows会自动用默认值填充设备描述表的各个字段,应用程序需要随后修改其中那些希望更改的字段。但是,在应用程序调用ReleaseDC或EndPaint函数以释放设备描述表句柄时,所作的所有更改都会丢失这就意味着,如果应用程序需要使用非默认的设备描述表属性,则必须在每次获取设备描述表句柄时,显示的初始化设备描述表。通常的操作如下:
HDC hdc;
HWND hwnd;
PAINTSTRUCT ps;
case: WM_PAINT:
hdc = BeginPaint(hwnd,&ps);
//初始化设备描述表属性
//其他GDI操作
EndPaint(hwnd, &ps);
属性包括:
背景模式、位图、画刷、起始位置、剪裁域、颜色调色板、绘图方式、字体、字符间距、映射方式、画笔、多边形填充方式、缩放模式、文本颜色、视图范围、视图原点、窗口范围、窗口原点等。
背景色:GetBkColor SetBkColor
背景模式:GetBkMode SetBkMode
位图:CreateBitMap CreateBitMapIndirectCreateCompatibleBitmap SelectObject
R\G\B三色,每种颜色8位, 共24位.
32位颜色:颜色数量24位颜色, 多出来的8位
表示灰度
Win32下,颜色的定义COLORREF(DWORD), RGB宏
定义颜色
COLORREFnColor = RGB( 0, 0, 0 );
COLORREF nColor = RGB( 255,255,255 );
COLORREF nColor = RGB( 255,0, 0 );
从一个颜色中获取RGB三色:
int nBlue = GetBValue( nColor );
int nRed = GetRValue( nColor );
int nGreen= GetGValue( nColor );