没有合适的资源?快使用搜索试试~ 我知道了~
我们将讲述程式在显示区域显示资讯的方式,但比上一章说明的显示方式更加复杂。当程式在显示区域显示文字或图形时,它经常要「绘制」它的显示区域。本章著重讲述绘制的方法
资源推荐
资源详情
资源评论
4. 输出文字
在前一章,您看到了一个简单的 Windows 98 程式,它在视窗中央,或者更准确地说,在显示
区域中央显示一行文字。正如我们学到的,显示区域是整个应用程式视窗中未被标题列、视窗
边框,以及可选的功能表列、工具列、状态列和卷动列占据的部分。简而言之,显示区域是视
窗中可以由程式任意书写和传递视觉资讯的部分。
对於程式的显示区域,您几乎可以为所欲为,只不过您不能假定视窗大小是某一特定尺寸,或
者在程式执行时其大小会保持不变。如果您不熟悉图形视窗环境的程式设计,这些限制可能会
使您感到惊讶:不能再假设萤幕上的一行文字一定有 80 个字元了。您的程式必须与其他
Windows 程式共用视讯显示器。Windows 使用者控制程式视窗在萤幕上显示的方式。尽管可以
建立固定大小的视窗(这对於计算器之类的应用是合理的),但在大多数情况下,使用者应该
能够改变应用程式视窗的大小。您的程式必须能够接受指定给它的大小,并且合理地利用这一
空间。
这有两种可能的情况。一种可能是,程式只有仅能显示「hello」的显示区域;还有另一种可能,
即程式在一个大萤幕、高解析度的系统上执行,其显示区域大得足以显示两整页文字。灵活地
处理这两种极端是 Windows 程式设计的要点之一。
这一章,我们将讲述程式在显示区域显示资讯的方式,但比上一章说明的显示方式更加复杂。
当程式在显示区域显示文字或图形时,它经常要「绘制」它的显示区域。本章著重讲述绘制的
方法。
尽管 Windows 为显示图形提供了强大的图形装置介面(GDI)函式,但在这一章中,我只介绍
简单文字行的显示。我也将忽略 Windows 能够使用的不同字体外形及字体大小,仅使用
Windows 的内定系统字体。这看起来似乎是一种限制,其实不然,本章涉及和解决的问题适用
於所有 Windows 程式设计。在混合显示文字和图形时,Windows 内定字体的字元大小通常决
定了图形的尺寸。
本章表面上是讨论绘图的方法,实际上是讨论与装置无关的程式设计基础。Windows 程式只能
对显示区域大小甚至字元的大小做很少的假定,相反地,必须使用 Windows 提供的功能来取得
关於程式执行环境的资讯。
绘制和更新
在文字模式环境下,程式可以在显示器的任意部分输出,程式输出到萤幕上的内容会停留在原
处,不会神秘地消失。因此,程式可以丢掉重新生成萤幕显示时所需的资讯。
在 Windows 中,只能在视窗的显示区域绘制文字和图形,而且不能确保在显示区域内显示的内
容会一直保留到程式下一次有意地改写它时还保留在那里。例如,使用者可能会在萤幕上移动
另一个程式的视窗,这样就可能覆盖您的应用程式视窗的一部分。Windows 不会保存您的视窗
中被其他程式覆盖的区域,当程式移开後,Windows 会要求您的程式更新显示区域的这个部分。
Windows 是一个讯息驱动系统。它通过把讯息投入应用程式讯息伫列中或者把讯息发送给合适
的视窗讯息处理程式,将发生的各种事件通知给应用程式。Windows 通过发送 WM_PAINT 讯
息通知视窗讯息处理程式,视窗的部分显示区域需要绘制。
WM_PAINT 讯息
大多数 Windows 程式在 WinMain 中进入讯息回圈之前的初始化期间都要呼叫函式
UpdateWindow。Windows 利用这个机会给视窗讯息处理程式发送第一个 WM_PAINT 讯息。
这个讯息通知视窗讯息处理程式:必须绘制显示区域。此後,视窗讯息处理程式应在任何时刻
都准备好处理其他 WM_PAINT 讯息,必要的话,甚至重新绘制视窗的整个显示区域。在发生
下面几种事件之一时,视窗讯息处理程式会接收到一个 WM_PAINT 讯息:
在使用者移动视窗或显示视窗时,视窗中先前被隐藏的区域重新可见。
使用者改变视窗的大小(如果视窗类别样式有著 CS_HREDRAW 和
CS_VREDRAW 位元旗标的设定)。
程式使用 ScrollWindow 或 ScrollDC 函式滚动显示区域的一部分。
程式使用 InvalidateRect 或 InvalidateRgn 函式刻意产生 WM_PAINT 讯息。
在某些情况下,显示区域的一部分被临时覆盖,Windows 试图保存一个显示区域,并在以後恢
复它,但这不一定能成功。在以下情况下,Windows 可能发送 WM_PAINT 讯息:
Windows 擦除覆盖了部分视窗的对话方块或讯息方块。
功能表下拉出来,然後被释放。
显示工具提示讯息。
在某些情况下,Windows 总是保存它所覆盖的显示区域,然後恢复它。这些情况是:
滑鼠游标穿越显示区域。
图示拖过显示区域。
处理 WM_PAINT 讯息要求程式写作者改变自己向显示器输出的思维方式。程式应该组织成可
以保留绘制显示区域需要的所有资讯,并且仅当「回应要求」-即 Windows 给视窗讯息处理程
式发送 WM_PAINT 讯息时才进行绘制。如果程式在其他时间需要更新其显示区域,它可以强
制 Windows 产生一个 WM_PAINT 讯息。这看来似乎是在萤幕上显示内容的一种舍近求远的方
法。但您的程式结构可以从中受益。
有效矩形和无效矩形
尽管视窗讯息处理程式一旦接收到 WM_PAINT 讯息之後,就准备更新整个显示区域,但它经
常只需要更新一个较小的区域(最常见的是显示区域中的矩形区域)。显然,当对话方块覆盖
了部分显示区域时,情况即是如此。在擦除对话方块之後,需要重画的只是先前被对话方块遮
住的矩形区域。
这个区域称为「无效区域」或「更新区域」。正是显示区域内无效区域的存在,才会让
Windows 将一个 WM_PAINT 讯息放在应用程式的讯息伫列中。只有在显示区域的某一部分失
效时,视窗才会接受 WM_PAINT 讯息。
Windows 内部为每个视窗保存一个「绘图资讯结构」,这个结构包含了包围无效区域的最小矩
形的座标以及其他资讯,这个矩形就叫做「无效矩形」,有时也称为「无效区域」。如果在视
窗讯息处理程式处理 WM_PAINT 讯息之前显示区域中的另一个区域变为无效,则 Windows 计
算出一个包围两个区域的新的无效区域(以及一个新的无效矩形),并将这种变化後的资讯放
在绘制资讯结构中。Windows 不会将多个 WM_PAINT 讯息都放在讯息伫列中。
视窗讯息处理程式可以通过呼叫 InvalidateRect 使显示区域内的矩形无效。如果讯息伫列中已
经包含一个 WM_PAINT 讯息,Windows 将计算出新的无效矩形。否则,它将一个新的
WM_PAINT 讯息放入讯息伫列中。在接收到 WM_PAINT 讯息时,视窗讯息处理程式可以取得
无效矩形的座标(我们马上就会看到这一点)。通过呼叫 GetUpdateRect,可以在任何时候取
得这些座标。
在处理 WM_PAINT 讯息处理期间,视窗讯息处理程式在呼叫了 BeginPaint 之後,整个显示区
域即变为有效。程式也可以通过呼叫 ValidateRect 函式使显示区域内的任意矩形区域变为有效。
如果这呼叫具有令整个无效区域变为有效的效果,则目前伫列中的任何 WM_PAINT 讯息都将
被删除。
GDI 简介
要在视窗的显示区域绘图,可以使用 Windows 的图形装置介面(GDI)函式。Windows 提供了
几个 GDI 函式,用於将字串输出到视窗的显示区域内。我们已经在上一章看过 DrawText 函式,
但是目前使用最为普遍的文字输出函式是 TextOut。该函式的格式如下:
TextOut 向视窗的显示区域写入字串。psText 参数是指向字串的指标,iLength 是字串的长度。
x 和 y 参数定义了字串在显示区域的开始位置(不久会讲述关於它们的详细情况)。hdc 参数是
「装置内容代号」,它是 GDI 的重要部分。实际上,每个 GDI 函式都需要将这个代号作为函式
的第一个参数。
装置内容
读者可能还记得,代号只不过是一个数值,Windows 以它在内部使用物件。程式写作者从
Windows 取得代号,然後在其他函式中使用该代号。装置内容代号是 GDI 函式的视窗「通行
证」,有了这种装置内容代号,程式写作者就能自如地在显示区域上绘图,使图形如自己所愿
地变得好看或者难看。
装置内容(简称为「DC」)实际上是 GDI 内部保存的资料结构。装置内容与特定的显示设备
(如视讯显示器或印表机)相关。对於视讯显示器,装置内容总是与显示器上的特定视窗相关。
装置内容中的有些值是图形「属性」,这些属性定义了 GDI 绘图函式工作的细节。例如,对於
TextOut,装置内容的属性确定了文字的颜色、文字的背景色、x 座标和 y 座标映射到视窗的显
示区域的方式,以及显示文字时 Windows 使用的字体。
当程式需要绘图时,它必须先取得装置内容代号。在取得了该代号後,Windows 用内定的属性
值填入内部装置内容结构。在後面的章节中您会看到,可以通过呼叫不同的 GDI 函式改变这些
预设值。利用其他的 GDI 函式可以取得这些属性的目前值。当然,还有其他的 GDI 函式能够在
视窗的显示区域真正地绘图。
当程式在显示区域绘图完毕後,它必须释放装置内容代号。代号被程式释放後就不再有效,且
不能再被使用。程式必须在处理单个讯息处理期间取得和释放代号。除了呼叫 CreateDC(函
式,在本章暂不讲述)建立的装置内容之外,程式不能在两个讯息之间保存其他装置内容代号。
Windows 应用程式一般使用两种方法来取得装置内容代号,以备在萤幕上绘图。
取得装置内容代号:方法一
在处理 WM_PAINT 讯息时,使用这种方法。它涉及 BeginPaint 和 EndPaint 两个函式,这两个
函式需要视窗代号(作为参数传给视窗讯息处理程式)和 PAINTSTRUCT 结构的变数(在
WINUSER.H 表头档案中定义)的地址为参数。Windows 程式写作者通常把这一结构变数命名
为 ps 并且在视窗讯息处理程式中定义它:
在处理 WM_PAINT 讯息时,视窗讯息处理程式首先呼叫 BeginPaint。BeginPaint 函式一般在
准备绘制时导致无效区域的背景被擦除。该函式也填入 ps 结构的栏位。BeginPaint 传回的值是
装置内容代号,这一传回值通常被保存在叫做 hdc 的变数中。它在视窗讯息处理程式中的定义
如下:
HDC 资料型态定义为 32 位元的无正负号整数。然後,程式就可以使用需要装置内容代号的
TextOut 等 GDI 函式。呼叫 EndPaint 即可释放装置内容代号。
一般地,处理 WM_PAINT 讯息的形式如下:
!"#$
%& '(
使用 ) 函式
* '(
++,
在处理 WM_PAINT 讯息时,必须成对地呼叫 BeginPaint 和 EndPaint。如果视窗讯息处理程式
不处理 WM_PAINT 讯息,则它必须将 WM_PAINT 讯息传递给 Windows 中 DefWindowProc
(内定视窗讯息处理程式)。DefWindowProc 以下列代码处理 WM_PAINT 讯息:
!"#$
& '(
* '(
++,
这两个 BeginPaint 和 EndPaint 呼叫之间中没有任何叙述,仅仅使先前无效区域变为有效。但
以下方法是错误的:
!"#$
++,--!)...
Windows 将一个 WM_PAINT 讯息放到讯息伫列中,是因为显示区域的一部分无效。如果不呼
叫 BeginPaint 和 EndPaint(或者 ValidateRect),则 Windows 不会使该区域变为有效。相反,
Windows 将发送另一个 WM_PAINT 讯息,且一直发送下去。
绘图资讯结构
前面提到过,Windows 为每个视窗保存一个「绘图资讯结构」,这就是 PAINTSTRUCT,定义
如下:
/+
剩余46页未读,继续阅读
资源评论
zhang_xiu_yang
- 粉丝: 0
- 资源: 1
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功