Windows程序设计(三)

 

第三章:Windows图形基础

一:设备描述表

设备描述表是Windows应用程序、设备驱动程序和输出设备之间的桥梁,它与一个特定的设备相关联。例如,对显示器来说,设备描述表通常指显示器上的某个窗口。设备描述表描述了所选定的绘图工具、字体、字体颜色、工具在设备上绘制(或者说是映射)的方式及设备上可使用的输出区域等属性。WindowsGDI函数实际上是在设备描述表里显示正文及绘图的。 当程序显示文字或绘图时,首先必须获得一个设备描述表句柄,完成输出文字或绘图之后,还必须及时释放该句柄,否则会大大减少Windows的存储单元。释放之后的句柄就不会再有效了。一般说来,在处理某条消息时,获取和释放设备描述表句柄必须成对出现,而且不同设备描述表的获取与释放的方法也不同。而这只是所使用的函数不同而已。

 

二:显示缓冲区

Windows环境是基于图形操作的,图形设备接口(GDI)是一个在Windows应用程序中执行与设备无关的函数库。这些函数在不同的输出设备上产生图形及文字输出。

显示缓冲区是一种“设备缓冲区”,特别用于窗口用户区的输出。设备缓冲区定义设备,绘图工具及有关设备的完整信息。显示缓冲区只定义与窗口用户区有关的内容,包括输出设备、当前绘图工具、颜色,以及其它一些GDI输出函数产生输出所需的信息。在窗口中绘图,需要使用窗口的句柄,根据窗口句柄,可以得到窗口用户区的显示缓冲区句柄,所有GDI输出函数都需要一个显示缓冲区句柄,没有它就无法完成输出。

可以根据输出的需要选择获得显示缓冲区句柄的方法。画和写操作可以存在于应用程序中的任何地方(包括WinMain函数中),大多数应用程序把它们放在窗口函数中。每当对窗口的操作可能影响用户区内容时,Windows发送WM_PAINT消息给窗口函数。应用程序通常在响应WM_PAINT消息时,完成画和写。Windows发送WM_PAINT消息给窗口函数,并由它刷新用户区,因为只有应用程序才知道用户区的内容。

通常用BeginPaint函数来响应WM_PAINT消息。如果要在没有WM_PAINT消息的时刻画用户区,必须使用GetDC函数得到显示缓冲区的句柄。

当应用程序需要得到窗口的显示缓冲区时,Windows把它暂时借给应用程序。显示缓冲区是一种共享资源,一个应用程序占有它之后,其它应用程序就无法得到它。因此,应用程序在利用显示缓冲区画完窗口内容之后,就必须使用ReleaseDC函数释放它。同理,要求用EndPaint函数释放由BeginPaint函数获得的显示缓冲区。

显示缓冲区中有缺省的画笔、画刷和缺省字体。

 

1:GetDC函数

在处理非WM_PAINT消息时,应用程序获取窗口用户区设备描述表句柄使用GetDC函数,它常常用来对用户的某些动作提供反馈。例如,当用户移动鼠标光标穿越窗口时,在屏幕上画一条线。GetDC函数返回一个显示缓冲区句柄,它可以用于任何GDI输出函数。

请看下面这个程序段:

case WM_PAINT:

hDC=GetDC(hWnd);

TextOut(hDC,10,10, "Hello",5);

ReleaseDC(hWnd,hDC);

Break;

在这里,我们用设备环境句柄hDC定义了一个设备描述表句柄hDC,然后利用函数GetDC取得hWnd参数所标识窗口的显示缓冲区的显示描述表赋给hDC,再通过TextOut函数在窗口用户区(10,10)位置显示包含5个字符的字符串,使用完之后,及时用函数RealeaseDC释放这个显示描述句柄hDC。

使用GetDC函数获得显示缓冲区句柄,在窗口函数中处理WM_PAINT消息。当窗口函数接收到影响用户区内容的WM_PAINT消息时,用户区中先前已画的内容可能被擦掉。这是因为在处理WM_PAINT消息的过程中,Windows发送WM_ERASEBKGND消息给窗口函数,如果把WM_ERASEBKGND消息交给DefWindowProc函数处理,DefWindowProc函数使用这种窗口类的背景色填满受影响的区域,并擦掉原先已经画的内容。

 

2: WM_PAINT消息

在前面我们已经认识了WM_PAINT,让我们再来看一下。由于Windows是一个多任务环境,某个应用程序的窗口上面可能被对话框或窗口覆盖,当撤消这些对话框或窗口时,这个应用程序窗口中就有一个”空洞”,这个”空洞”就是一块无效的用户区域。为重新显示无效用户区域,Windows发送WM_PAINT消息实现。要求Windows发送WM_PAINT的情况有:改变窗口大小,覆盖用户区的菜单或对话框关闭,使用UpdateWindow和ScrollWindow函数等。

Windows发送WM_PAINT消息时,把它放到应用程序队列的最后,使得其它的输入能够先于WM_PAINT消息被处理。GetMessage函数也得到队列中WM_PAINT消息之后的其它消息,即只有没有其它消息的情况下,才从队列中取出WM_PAINT消息进行处理。这样做是为了让应用程序首先完成影响窗口显示结果的其它操作,不致因为频繁地执行输出操作而引起显示器的闪烁。Windows把WM_PAINT消息放在队列最后就是这个原因。

Windows并非WM_PAINT消息的唯一来源,使用InvalidateRect或InvalidateRgn函数也可以产生绘图窗口的WM_PAINT消息。这两个函数把用户区全部或部分标记成无效用户区而要求重新显示。下面的函数调用是把整个用户区标记成无效:

InvalidateRect(hWnd,NULL,TRUE);

这个例子把hWnd句柄参数指定的窗口用户区标记成无效。作为矩形结构的NULL参数指定整个用户区。TRUE参数表示擦除背景。

InvalidateRect和InvalidateRgn函数并不实际产生WM_PAINT消息。当用户区无效时,Windows就发送一个WM_PAINT消息,如果用户区的其它部分也被标记成无效,Windows就不再发送另一条WM_PAINT消息,而是把已有的无效区域合并,以便根据同一条WM_PAINT消息处理所有这些区域。

如果想改变重新显示的用户区,可以调用ValidateRect和ValidateRgn函数使相应的用户区有效,这两个函数取消原有的无效区,并在没有无效区的情况下取消队列中的WM_PAINT消息。

如果不想等待应用程序队列中的WM_PAINT消息,使用UpdateWindow函数直接发送WM_PAINT消息给指定窗口的窗口函数。如果还存在无效的用户区,UpdateWindow函数从队列中取出WM_PAINT消息,并把它直接发送给指定窗口的窗口函数。UpdateWindow函数通常用在窗口需要立即更新它的用户区,如在窗口刚被创建时使用。

用BeginPaint函数获得输出文字等的显示缓冲区句柄:

PAINTSTRUCT ps;

case WM_PAINT:

hdc=BeginPaint(hWnd,&ps);

    /* 输出操作 */

EndPaint(hWnd,&ps);

Break;

结构PAINTSTRUCT函数原型如下:

typedef struct tagPAINTSTRUCT

{

HANDLE  hDC;           //设备描述表句柄

BOOL     rErase;       //确定背景是否已被重画

RECT     rePaint;      //给出无效矩形的边界

BOOL     fRestore;     //内部使用的保留字段

BOOL     fIncUpdate;  //保留字段

BYTE     rgbReserved; //保留字段

}PAINTSTRUCT;

无效区域是一个矩形区域,它是一个RECT结构,其在window.h定义为

typedef struct tagRECT

{

int left;        //矩形左上角的X坐标

int top;    //矩形左上角的Y坐标

int right;      //矩形右下角的X坐标

int bottow;     //矩形右下角的Y坐标

}RECT

例中BeginPaint函数返回一个显示缓冲区句柄,它可用于其它的GDI输出函数中。

EndPaint函数通知Windows所有输出操作均已处理完毕,并释放显示缓冲区。

 

三:坐标系统

为了准备显示缓冲区,Windows调整设备的原点,使它位于用户区而不是显示器的左上角,并且还设置了一个剪辑区,使显示缓冲区的输出被”剪辑”到用户区。也就是说,用

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值