下载
第8章 使用G D I和字体的图像编程
本章内容:
• TImage:D e l p h i的图像显示
• 使用T C a n v a s的属性
• 使用T C a n v a s的方法
• 坐标系统和映射模式
• 创建一个绘画程序
• 编写动画程序
• 高级字体
• 实际创建一种字体
在前面的章节中,你已经使用了 C a n v a s 属性。它命名为C a n v a s再恰当不过,因为您可以把窗口看
作是画家的画布,在上面可以画很多的事物。按钮、窗口、光标等只不过是像素的集合,通过不同的
颜色表现出不同的外观。事实上,可以把每个窗口看作一个平面,组件就画在它上面。为了更深入地
分析,我们假设您是一位画家,需要用不同的工具来完成工作。你需要调色板来选取不同的颜色,需
要使用不同样式的刷子和画图工具以及特技。从编程的角度讲, Wi n 3 2 提供了类似的工具和技术,来
画出用户想要的事物。这些工具可以通过图形设备接口 (即G D I )来得到。
Wi n 3 2使用G D I 在计算机屏幕上画图。传统的 Wi n d o w s编程直接使用 G D I 函数和工具。现在,
T C a n v a s封装并简化了这些工具和技术的使用。本章将教你如何利用 T C a n v a s来实现一些有用的图像功
能。也可以用Delphi 5和Win32 GDI来创建高级的程序。我们将通过创建一个绘图程序和动画程序来加
以说明。
8.1 TImage:Delphi的图像显示
T I m a g e组件可以在Delphi 5的组件面板上找到,用于在窗体的任何地方显示图像。通过 T I m a g e,
可以调入和显示位图( . b m p )、1 6 位的Wi n d o w s图元文件( . w m f ) 、3 2位增强图元文件( . e m f )、图标( . i c o ) 或
其他能由T G r a p h i c处理的格式。T I m a g e组件显示的图像保存在P i c t u r e 属性中,它的类型是 T P i c t u r e。
图像:位图、图元文件、图标
1. 位图
Wi n 3 2位图是以位形式排列的二进制信息。更专业地说,位图保存了称为像素的颜色信息。位图
有两种类型:与设备有关的位图( D D B )和与设备无关的位图( D I B )。
作为一个Wi n 3 2 编程人员,可能不太关心 D D B ,因为这种格式只是为了向后兼容而保留的。与设
备有关的位图,正如其名字所揭示的,与所在的设备有关。当保存 D D B 格式的位图时,既不保存颜色
第二部分 高 级 技 术
调色板的信息,也不保存分辨率。相反,当保存与设备无关的位图时,则保存这些信息。这样,在任
何设备上就不会改变其外观。在内存中,大部分的 D D B和D I B 的结构是相同的。一个主要的不同点是,
D D B 使用系统提供的调色板,而 D I B使用自己的调色板。进一步说, D D B是原生存储,由视频驱动程
序和视频硬件来处理。 D I B 是标准化的像素格式,由 G D I例程来处理,保存在全局内存中。一些视频
卡用D I B像素格式作为原生的存储格式,这种情况下 D D B和D I B 相同。通常,D I B 更灵活更简单,但有
时会影响性能。D D B的速度更快,但不方便。
2. 图元文件
与位图不同的是,图元文件是基于矢量的图像。图元文件是保存着一系列 G D I例程的文件,允许
你把对G D I 函数的调用保存到磁盘,这样,以后就可以再次显示。同时,还可以与其他程序共享作图
例程,而不必在每个程序中都调用这些 G D I 函数。另一个好处就是可以进行放大而仍保持直线和圆弧
的光滑,而位图则做不到这一点。事实上,这就是 Wi n 3 2 打印引擎用增强图元文件存储来进行打印的
原因之一。图元文件有两种格式:一是标准图元文件,以 . w m f为扩展名。另一个是增强图元文件,
以. e m f为扩展名。
标准图元文件是从Wi n 1 6系统而来的。增强图元文件更健壮、更精确。如果要在应用程序中创建
图元文件,则应当使用E M F格式。如果要把图元文件输出到可能不能使用 E M F格式的旧程序中,则应
当使用1 6 位的 W M F格式。但是, 1 6 位的W M F 格式将失去 G D I 中E M F 支持而W M F不支持的特性。
Delphi 5的T M e t a F i l e支持这两种图元文件。
3. 图标
图标作为Wi n 3 2资源往往以. i c o为扩展名保存在图标文件中。它们可以存在于资源文件 ( . r e s )中。在
Wi n d o w s 中,有两种典型尺寸的图标。一种是大图标, 3 2×3 2 像素。另一种是小图标, 1 6×1 6像素。
所有的Wi n d o w s 应用程序都能使用这两种尺寸的图标。小图标显示在应用程序的主窗口的左上角,也
可用于Wi n d o w s 的列表视图控件中。D e l p h i 把这个控件封装为T L i s t Vi e w组件,这个组件可以在组件面
板的Wi n 3 2页上找到。
图标由两个位图组成。一个位图是实际要显示的图像,另一个位图是图标显示时的蒙版。图标可
用于许多不同的用途。例如,图标可以出现在应用程序的任务栏,或者出现在需要惊叹号、停止符号
的消息框中。
T P i c t u r e 为T G r a p h i c 的容器,后者是一个抽象类。容器意味着 T P i c t u r e可以引用和显示 T B i t M a p 、
T M e t a F i l e、T I c o n或其他T G r a p h i c类型,而不必关心实际是哪个。你可以使用 T I m a g e . P i c t u r e对象的属
性和方法来调入图像文件给T I m a g e组件。请看下面的语句:
M y I m a g e . P i c t u r e . L o a d F o r m F i l e ( ' F i l e N a m e . b m p ' ) ;
利用类似的语句可以调入图标或图元文件。例如,下面调入了一个 Wi n 3 2图元文件:
M y I m a g e . P i c t u r e . L o a d F o r m F i l e ( ' F i l e N a m e . e m f ' ) ;
而下面的语句则调入了一个Wi n 3 2图标文件:
M y I m a g e . P i c t u r e . L o a d F o r m F i l e ( ' F i l e N a m e . i c o ' ) ;
在Delphi 5中,T P i c t u r e可以使用与调用位图相同的技术来调用 J P E G格式图象:
M y I m a g e . P i c t u r e . L o a d F r o m F i l e ( ' F i l e N a m e . j p e g ' ) ;
8.2 存储图像
要保存一个图像,请使用S a v e To F i l e ( )方法:
M y I m a g e . P i c t u r e . S a v e To F i l e ( ' F i l e N a m e . b m p ' ) ;
T B i t m a p封装了Wi n 3 2位图和调色板,具有调入、保存、显示和复制位图图像的功能。 T B i t m a p也
1 6 8 第二部分 高 级 技 术
下载
能够自动管理调色板着色。这意味着。管理位图的繁重工作被 T B i t m a p大大简化了,你的注意力可以
集中在位图的使用上,而不必考虑操作的细节。
注意 T B i t m a p不是管理调色板着色的唯一对象。T I m a g e、T M e t a f i l e以及其他T G r a p h i c的派生
类也可以实现位图的调色板。如果要创建一个包含 2 5 6 色的T B i t m a p 对象,需要覆盖它的
GetPaletle()方法,以得到位图的彩色调色板。
例如,要创建一个T B i t m a p的实例并调入一个图像,可以使用如下命令:
M y B i t m a p : = T B i t M a p . C r e a t e ;
M y B i t m a p . L o a d F o r m F i l e ( ' M y B M P. B M P ' ) ;
提示 把位图调到应用程序的另一个办法是从资源文件中读取。后面将简单讨论它。
要复制一个位图,可以用T B i t m a p . A s s i g n ( )方法:
B i t m a p 1 . A s s i g n ( B i t m a p 2 ) ;
也可以从一个TBitmap 的实例中复制位图的一部分给另一个,还可以使用 C o p y R e c t ( )方法复制给
窗体的画布。
v a r
R 1 : Tr e c t ;
b e g i n
with R1 do
b e g i n
To p : = 0 ;
L e f t : = 0 ;
Right:=BitMap2.Height div 2;
Bottom:=BitMap2.Height div 2;
e n d ;
B i t m a p 1 . C a n v a s . C o p y R e c t ( C l i e n t R e c t , B i t M a p 2 . C a n v a s , R 1 ) ;
e n d ;
上面的代码中,先给T R e c t 记录中的每个字段赋值,然后调用 T C a n v a s . C o p y R e c t ( )复制位图的一部
分,T R e c t是这样定义的:
T R e c t = r e c o r d
Case Integer of
0 : ( L e f t , To p , R i g h t , B o t t o m : I n t e g e r ) ;
1 : ( TopLeft,BottomRight: TPoint);
e n d ;
这个技术将在后面要介绍的P a i n t程序中使用。C o p y R e c t ( )自动把要复制的部分缩放以适合目标矩形。
警告 前面两种复制位图的方法在资源开销上有显著的不同。C o p y R e c t ( )耗费的内存双倍于后
者,因为内存中有两份图像。而A s s i g n ( )则没有开销,因为两个位图对象引用的是内存中的同
一个图像。如果其中一个位图对象修改了,VCL将克隆该图像。
另一个复制整个位图到窗体画布并能适当缩放以适应画布边界的方法是 S t r e t c h D r a w ( ):
C a n v a s . S t r e t c h D r a w ( R 1 , M y B i t m a p ) ;
本章的后面将讨论T C a n v a s的方法。
8.3 使用TCanvas的属性
诸如T F o r m和T G r a p h i c等高级类都有C a n v a s 属性。这是一块画布,为窗体上的组件充当了绘制的
第8章 使用G D I和字体的图像编程 1 6 9
下载
平面。T C a n v a s用于绘画的工具有画笔、刷子和字体。
8.3.1 画笔
在这一节,先来说明如何使用T P e n对象,然后列举用到这个对象的例子。
画笔使你可以在画布上画线,它可以通过 C a n v a s . P e n属性来访问。通过修改T p e n的C o l o r、Wi d t h 、
S t y l e和M o d e属性就可以控制如何画线。
C o l o r属性用于指定画笔的颜色。Delphi 5提供了预定义的颜色常量。例如,常量 c l R e d和c l Ye l l o w
分别对应着红色和黄色。Delphi 5还定义了表示Wi n 3 2系统屏幕元素颜色的常量,例如 c l A c t i v e C a p t i o n
和c l H i g h t Te x t ,它们对应于Wi n 3 2 中活动的标题和突出显示的文本。下面的代码把画笔的颜色设为蓝
色。
C a n v a s . P e n . C o l o r : = c l B l u e ;
下面的代码演示了怎样把C a n v a s的画笔设为随机颜色:
P e n . C o l o r = T C o l o r ( R G B ( R a n d o m ( 2 5 5 ) , R a n d o m ( 2 5 5 ) , R a n d o m ( 2 5 5 ) ) ) ;
R G B ( ) 与Tc o l o r
Wi n 3 2用长整数来表示颜色。其中,最低的三个字节分别代表红、绿、蓝的强度。这三个值组合
起来构成合法的Wi n 3 2颜色。R G B ( R ,G,B )函数需要传递三个参数,分别表示红、绿、蓝三种颜色
的强度,并返回一个长整数作为 Wi n 3 2 颜色。颜色是用 T C o l o r 表示的。每种颜色强度有 2 5 5个值,
R G B ( )函数可以返回大约1 6 0 0 万种颜色。例如R G B ( 0,0,0 )返回黑色,R G B ( 2 5 5 ,2 5 5,2 5 5 ) 返回白色,
R G B ( 2 5 5 ,0,0 )、R G B ( 0,2 5 5 ,0 ) 、R G B ( 0 ,0,2 5 5 ) 分别返回红、绿、蓝色。通过改变传递给
R G B ( )的参数,就可以获得色谱中的任何颜色。
T C o l o r是针对V C L的,并参照G r a p h i c s . p a s单元中常量的定义。这些常量对应着系统调色板上最匹
配的颜色或者Wi n d o w s控制面板中定义的颜色。例如, c l B l u e对应蓝色,而c l B t n F a c e 对应着按钮面板
的颜色。除了用三个字节表现颜色外, T C o l o r的最高位字节说明匹配了何种颜色。假如最高位字节是
0 0,那么对应的颜色即为系统调色板中最接近的匹配颜色。值 0 1 则对应当前调色板中最接近的匹配颜
色。值0 2 则对应当前设备环境的逻辑调色板内最接近的颜色。你可以在 D e l p h i 帮助文件的“ T C o l o r
t y p e”下找到更多信息。
提示 通过C o l o r To R G B ( ),可以把Wi n 3 2系统颜色(如c l Wi n d o w )转换为R G B颜色。这个函数在
Delphi 5的在线帮助中有描述。
通过S t y l e属性,画笔就可以以不同的风格画线。表8 - 1 列出了P e n . S t y l e属性可能的值。
表8-1 画笔样式
样 式 绘 制 样 式 绘 制
p s C l e a r 不可视线 p s D o t 点线
p s D a s h 虚线 p s I n s i d e F r a m 内框
p s D a s h D o t 点划线 p s S o l i d 实线
p s D a s h D o t D o t 双点划线
下面的代码演示了如何改变画笔的样式:
C a n v a s . P e n . S t y l e : = p s D a s h D o t ;
图8 - 1 显示了用不同画笔在窗体的画布上所画的线。有一件事情要注意,线条的内侧颜色来自画刷
的颜色。如果你想在红色矩形中画黑色虚线,应当把 C a n v a s . B r u s h . C o l o r设为 c l R e d 或者把 C a n v a s .
B r u s h . S t y l e设为b s C l e a r。设置画笔和画刷的颜色以了解画出的效果,比如穿过白色矩形画一条红色和
1 7 0 第二部分 高 级 技 术
下载
蓝色的虚线。
图8-1 不同的线型
P e n . Wi d t h属性用于指定画笔的笔宽 (以像素为单位 )。此属性设得越大,画笔画出来的线也就越
粗。
注意 点划线样式只适用于宽度为1的画笔。如果把宽度设为2,画出的将是实线。这是从16位
G D I 而来的, Wi n 3 2 保留它是为了兼容。 Windows 95/98不能画粗的点划线,但 Wi n d o w s
NT/2000可以,不过要使用扩展的GDI功能集。
有三个因素决定了Wi n 3 2如何在画布上画出像素或线:画笔的颜色、画布表面的颜色以及 Wi n 3 2 对
两个颜色值进行的逐位操作。这个操作称为光栅操作 ( R O P )。P e n . M o d e属性用于指定画布的R O P模式。
表8 - 2列出了Wi n 3 2预定义的1 6种模式。
表8-2 Wi n 3 2在P e n . C o l o r ( S )画笔颜色与目标颜色( D )上的画笔模式
p m B l a c k 总是黑色 0
p m W h i t e 总是白色 1
p m N O P 不变 D
p m N O T 把屏幕上的颜色反转 not D
p m C o p y 以C o l o r属性设定的颜色代替 S
p m N o t C o p y 把画笔的颜色反转 not S
p m M e rg e P e n N o t 把画笔的颜色和屏幕颜色反转后的颜色进行或操作 S or not D
p m M a s k P e n N o t 把画笔的颜色和屏幕颜色反转后的颜色进行与操作 S and not D
p m M e rg e N o t P e n 把屏幕颜色和画笔颜色反转后的颜色进行或操作 not S or D
p m M a s k N o t P e n 把屏幕颜色和画笔颜色反转的颜色进行与操作 not S and D
p m M e rg e 把画笔的颜色和屏幕的颜色进行或操作 S or D
p m N o t M e rg e 把p m M e rg e反转 not (S or D)
p m M a s k 把画笔颜色和屏幕颜色进行与操作 S and D
p m N o t M a s k 把p m M e rg e 反转 not (S and D)
p m X o r 把画笔颜色跟屏幕颜色进行或非操作 S XOR D
pmNotXor 把p m X o r反转 not(S XOR D)
P e n . m o d e 默认设为p m C o p y ,这意味着,画笔的颜色由它的 C o l o r特性指定。假设要在一个白色背
景上画一条黑线,如果一条直线与另一条直线相交,屏幕上应当为白而不是黑。一种简单的办法是,
检查交点区域的颜色。如果背景为白色,就把 P e n . C o l o r设为黑色。如果背景为黑色,就把P e n . C o l o r设
为白色。尽管这个办法可行,但它太笨拙了。较好的办法是把 Pen.Color 设为c l B l a c k,而把P e n . m o d e
第8章 使用G D I和字体的图像编程 1 7 1
下载
评论3