Delphi中canvas(画布)的运用

本文介绍 Delphi 中 Canvas 类的应用技巧,包括为控件添加阴影、边框,实现动态帮助功能,以及创建平滑移动的字幕和图像效果。通过实际代码示例展示如何利用 Canvas 实现这些特殊效果。
  1. {
  2. 在DELPHI为编程者提供了一个灵活的绘图场所, 即本文所述的CANVAS类, 在DELPHI中的很多控件都具有此属性, 使编程者可以在这些的控件的表面随心所欲的绘图, 这对完善用户界面或者制作一些屏幕特技都有着非凡的作用, 下面举例说明几种特殊屏幕效果的形成过程。
  3. 一、CANVAS必备基本知识:
  4. 1. 具有CANVAS属性的控件:
  5. TBitmap, TComboBox, TDBComboBox, TDBGrid, TDBListBox, TDirectoryListBox,
  6. TDrawGrid, TFileListBox, TForm, THeaderControl, TImage, TListBox, TOutline,
  7. TPaintBox, TPrinter, TStatusBar, TStringGrid等,
  8. 2. CANVAS属性及命令: 篇幅所限, 省略参数及格式说明, 具体请参考文后程序及DELPHI帮助文件:
  9. canvas.rectangle(): 画矩形
  10. pen.color: 定义画笔颜色
  11. roundrect():画圆角矩形
  12. pen.width: 定义画笔宽度
  13. arc(): 画弧线(不填充)
  14. brush.color: 定义填充颜色
  15. chord(): 画弧线(填充)
  16. textout(): 在固定位置输出字符串
  17. pie: 画扇形
  18. textwidth: 取字符串高度
  19. polygon(): 画多边形填充
  20. textheight: 取字符串宽度
  21. polyline(): 多点连线(不填充)
  22. font.color: 指定字体颜色
  23. Pixels(): 指定固定象素点颜色值
  24. font.size: 指定字体大小
  25. moveto(): 指明画线起点
  26. Ellipse(): 画圆或椭圆
  27. lineto(): 指明画线终点
  28. 3. 使用CANVAS注意事项: 当窗口进行重画时, 画布上的图像将消失, 比如当窗口进行最小
  29. 化又重新恢复时,就会引起画布上图像的消失,另外当刚刚运行程序时,窗口也是属于重新
  30. 绘制,所以如果在绘制窗口之前在画布上绘图,弹出窗口后将不能显示出图像,比如在
  31. TForm1.FormCreate()事件中进行画布绘图操作将是徒劳的,但可以在此事件中进行画布操作的准备工作,比如设置画笔的颜色和宽度等。
  32. 二、CANCAS应用举例:
  33. 1. 为控件增加阴影或投影效果: 基本原理就是在利用该控件的父控件比如FORM或者其它容器控件的CANVAS, 在需要修饰的控件周围适当处填加图像, 通过线条及颜色的合理达配, 使控件与周围的图像融为一体, 形成特殊的视觉效果, 具体操作时需要根据被修饰控件的TOP、LEFT、WIDTH、HEIGHT等属性,确定需要画线的起点和终点坐标,这样操作无论被修饰控件位置及尺寸如何变化,都可以保证投影及阴影效果完美的实现;比如可在窗口中建立三个按钮,然后在按钮2和按钮3的CLICK事件中填加如下代码, 之后按下按钮2或按钮3即使按钮1形成投影和阴影效果:
  34. }
  35. procedure TForm1.Button2Click(Sender: TObject);
  36. var
  37.   x, y, i: integer;
  38. begin
  39.   x := 0; y := 0;
  40.   form1.canvas.pen.width := 1;
  41.   fori := 0 to8do
  42.   begin
  43.     form1.canvas.pen.color := $00A0A0A0;
  44.     form1.canvas.moveto(Button1.left + Button1.width + x,
  45.       Button1.top + y);
  46.     form1.canvas.lineto(Button1.left + Button1.width + x,
  47.       Button1.top + Button1.height + y);
  48.     form1.canvas.pen.color := $00606060;
  49.     form1.canvas.moveto(Button1.left + x,
  50.       Button1.top + Button1.height + y);
  51.     form1.canvas.lineto(Button1.left + Button1.width + x,
  52.       Button1.top + Button1.height + y);
  53.     x := x + 1;
  54.     y := y + 1;
  55.   end;
  56. end;
  57. procedure TForm1.Button3Click(Sender: TObject);
  58. var
  59.   x, y, i: integer;
  60. begin
  61.   x := 0; y := 0;
  62.   form1.canvas.pen.width := 1;
  63.   fori := 0 to8do
  64.   begin
  65.     form1.canvas.pen.color := $00404040;
  66.     form1.canvas.moveto(Button1.left + Button1.width + x,
  67.       Button1.top + 8);
  68.     form1.canvas.lineto(Button1.left + Button1.width + x,
  69.       Button1.top + Button1.height + 8);
  70.     form1.canvas.moveto(Button1.left + 8,
  71.       Button1.top + Button1.height + y);
  72.     form1.canvas.lineto(Button1.left + Button1.width + 8,
  73.       Button1.top + Button1.height + y);
  74.     x := x + 1;
  75.     y := y + 1;
  76.   end;
  77. end;
  78. {
  79. 2. 为控件加上边框: DELPHI中有很多控件无边框属性, 利用CANVAS可以为任意的控件填加边框, 使其轮廓清楚; 具体操作时, 可先定义出画笔的颜色、画笔的宽度(边框宽度), 之后用polyline()命令根据相应控件的位置、尺寸自动定位四角坐标,一次可完成一个固定宽度矩形的绘制工作,如果需要多种颜色或者具有立体效果的边框,可多次定义画笔颜色,画出连续的多个矩形,通过调整相邻矩形的颜色来实现特殊效果的边框绘制工作;比如在窗体中安放两个按钮, 分别在MOUSEMOVE事件中填加如下代码, 之后每当鼠标移到相应的按钮上时, 相应的按钮就会出现特殊颜色的边框, 当鼠标移到窗口空白处时, 则窗口会出现明显的边线,起到特殊的提示效果;
  80. }
  81. procedure TForm1.Button1MouseMove(Sender: TObject; Shift: TShiftState; x, y: integer);
  82. begin
  83.   form1.repaint;
  84.   form1.canvas.pen.color := clGreen;
  85.   form1.canvas.pen.width := 5;
  86.   form1.canvas.polyline([point(Button1.left, Button1.top),
  87.   point(Button1.left + Button1.width, Button1.top),
  88.   point(Button1.left + Button1.width, Button1.top + Button1.height),
  89.   point(Button1.left, Button1.top + Button1.height),
  90.   point(Button1.left, Button1.top)]);
  91. end;
  92. procedure TForm1.Button2MouseMove(Sender: TObject; Shift: TShiftState; x,y: integer);
  93. begin
  94.   form1.repaint;
  95.   form1.canvas.pen.color := clBlue;
  96.   form1.canvas.pen.width := 5;
  97.   form1.canvas.polyline([point(Button2.left, Button2.top),
  98.     point(Button2.left + Button2.width, Button2.top),
  99.       point(Button2.left + Button2.width, Button2.top + Button2.hei
  100.       ght),
  101.       point(Button2.left, Button2.top + Button2.height),
  102.       point(Button2.left, Button2.top)]);
  103. end;
  104. procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; x,y: integer);
  105. begin
  106.   form1.repaint;
  107.   form1.canvas.pen.color := clRed;
  108.   form1.canvas.pen.width := 3;
  109.   form1.canvas.polyline([point(00), point(form1.width -100),
  110.     point(form1.width - 10, form1.height - 30),
  111.     point(0, form1.height - 30), point(00)]);
  112. end;
  113. {
  114. 3. 为图形按钮或其它控件安装动态帮助功能, 此处主要使用它的字符串显示功能, 也就是当鼠标移到指定控件上时, 在其周围适当位置显示相应的字符串, 当鼠标离开时通过图像覆盖动作使字符串消失, 也可以使用一个简单的命令完成即form1.repaint, 它的作用是使FORM1内的所有控件全部重新绘制, 这样即可快速清除原来显示的字符; 编程时主要使用各个控件的MouseMove()事件;比如可在窗口中安放两个按钮, 并安排如下代码, 运行之后当鼠标移到相应按钮上时, 就会在其上方显示相应的提示信息, 鼠标移到窗口空白处则会在窗口的左下角显示"OK"字样;
  115. }
  116. procedure TForm1.Button1MouseMove(Sender: TObject; Shift: TShiftState; x, y: integer);
  117. begin
  118.   form1.repaint;
  119.   form1.canvas.brush.color := clGreen;
  120.   form1.canvas.font.size := 8;
  121.   form1.canvas.font.color := $1200FFFF;
  122.   form1.canvas.textout(Button1.left,Button1.top - 15'OPENFILE');
  123. end;
  124. procedure TForm1.Button2MouseMove(Sender: TObject; Shift: TShiftState; x, y: integer);
  125. begin
  126.   form1.repaint;
  127.   form1.canvas.font.size := 8;
  128.   form1.canvas.brush.color := clRed;
  129.   form1.canvas.font.color := $1200FFFF;
  130.   form1.canvas.textout(Button2.left, Button2.top -15'EXIT');
  131. end;
  132. procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; x,y: integer);
  133. begin
  134.   form1.repaint;
  135.   form1.canvas.font.size := 12;
  136.   form1.canvas.brush.color := clBlue;
  137.   form1.canvas.font.color := $00FFFFFF;
  138.   form1.canvas.textout(0, form1.height - 50'OK');
  139. end;
  140. {
  141. 4. 仿电视移动字幕或图像, 用此方法制作移动字幕的基本方法是:首先选定一个可作为画布
  142. 的控件, 比如FORM或IMAGE, 然后用一种填充颜色填满整个画布, 在画布的固定位置显示一个特殊前景色固定尺寸的字符串, 在TIMER控件中定时连续改变显示字符串的位置, 由于原来位置的字符串不能自动消失, 所以需要用与填充颜色相同颜色的线条覆盖多余部分, 这样即可实现平滑的字幕移动效果; 实现图像移动的方法: 可事先定义Bitmap类和Rect类变量,在程序运行阶段建立Bitmap和Rect对象, 并在Bitmap中装入指定的图像文件, 同时把对象Bitmap装入Rect对象中实现图像的显示, 然后在Timer控件中定时连续改变Rect的坐标值, 并用与填充颜色相同的线条覆盖遗留图像部分, 即可以实现图像的平稳移动; 采用上述方法实现的字符串或图像移动操作, 其效果平稳,无任何闪烁或抖动现象,视觉效果极佳,并且不需要事先建立控件,完全由程序代码实现,具有相当多的优点;编程举例: 在窗体中安放时间控件TIMER1、图像框IMAGE1, 定义TRECT及TBITMAP型变量, 并在FormCreate和Timer1Timer事件中安排如下代码,程序运行之后即会在图像框中出现至下而上的移动字幕及图像效果, 并从顶部消失, 之后重新从底部出现;
  143. }
  144. var {定义变量}
  145.   form1: TForm1;
  146.   x, tt, l, h: integer;
  147.   pic: Trect;
  148.   map: TBitmap;
  149.   {具体动画演示代码}
  150. procedure TForm1.Timer1Timer(Sender: TObject);
  151. begin
  152.   x := x - 1;
  153.   tt := tt - 1;
  154.   ifx < -160 then
  155.     x := image1.height + 20;
  156.   tt := x + 80;
  157.   image1.canvas.font.size := 18;
  158.   image1.canvas.font.color := $1200FFFF;
  159.   image1.canvas.textout(10, x, 'OK字幕移动演示');
  160.   image1.canvas.font.size := 12;
  161.   image1.canvas.font.color := $120000FF;
  162.   image1.canvas.textout(20, x + 50'字体变色效果演示');
  163.   l := image1.canvas.textwidth('字体变色效果演示');
  164.   h := image1.canvas.textheight('字体变色效果演示');
  165.   image1.canvas.pen.color := clGreen;
  166.   image1.canvas.moveto(20, h + x + 50 - 2);
  167.   image1.canvas.lineto(20 + l, h + x + 50 - 2);
  168.   pic.topleft.x := 30;
  169.   pic.topleft.y := tt;
  170.   pic.bottomright.x := pic.topleft.x + 100;
  171.   pic.bottomright.y := pic.topleft.y + 80;
  172.   image1.canvas.stretchdraw(pic, map);
  173.   image1.canvas.pen.color := clGreen;
  174.   image1.canvas.moveto(0, pic.topleft.y + 80);
  175.   image1.canvas.lineto(pic.topleft.x + 100, pic.topleft.y + 80);
  176. end;
  177. {以下设置动画初值}
  178. procedure TForm1.FormCreate(Sender: TObject);
  179. begin
  180.   timer1.enabled := true;
  181.   timer1.Interval := 10;
  182.   x := image1.height + 20;
  183.   tt := x + 80;
  184.   form1.repaint;
  185.   image1.canvas.brush.color := clGreen;
  186.   pic := Rect(00, image1.width, image1.height);
  187.   image1.canvas.FillRect(pic);
  188.   pic := Rect(-1, -111);
  189.   map := TBitmap.create;
  190.   map.loadfromfile('d:/windows/256color.bmp');
  191.   image1.canvas.stretchdraw(pic, map);
  192. end;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值