以往开发
Windows
图形软件大多用 VC++作为开发工具,VC++强大的图形功能可以让程序员编制出许多优秀的与图形相关的软件。VC++中与绘图相关的函数都封装在
CDC
及其衍生的
CClientDC,CpaintDC,CwindowDC
中。
Delphi
中也有一个与
CDC
相类似的类
Tcanvas,
它封装了
Delphi
中的绘图函数。我们可以把
Delphi
和
VC
中相同或相近的方法做个有趣的比较。
(一)
Canvas
和
CDC
绘图方法比较:
我们可以从以下表格中看到
Tcanvas
和
CDC
相似的函数:
表 1
--1
Canvas方法
CDC方法 功能
Arc
Arc 画一个椭圆弧
Chord
Chord 画一根玄。
CopyRect
拷贝指定矩形区域中图象到指定矩形
Draw
BitBlt 拷贝位图
Ellipse
Ellipse 画椭圆
FillRect
PaintRgn 使用刷子填充一个又一个矩型
FloodFill
FloodFill 用当前刷子填充区域
FrameRect
FrameRect 画一个矩形框
Lineto
Lineto 画线到
Moveto
Moveto 移
到
Pie
Pie 画扇形
Polygon
Polygon 画多边形
PolyLine
PolyLine 画多根相连的线
Rectangle
Rectangle 画一个实心矩形
RoundRect
RoundRect 画一个圆角的矩形
StretchDraw
StretchBlt 从源图象中
移动图象到指定矩形
TextWidth
GetCharWidth 返回字符宽
TextOut
TextOut 在指定坐标写字
TextRect
ExtTextOut 在制定矩形中写字
上表中,我们只列出部分绘图函数,详细了解,请参阅有关
Delphi
和
VC
书籍
.
与
VC++
相类似,
Delphi
也提供了绘图工具,如
Tpen,Tbrush
等,与
VC
不同的是,
Delphi
的绘图工具封装在
Tcanvas
中。
Delphi
也提供字形及字体大小的类
Tfont,
下面我们用具体例子来分析它们的用法。
(二)用
Delphi
制作
Window
图形软件
象使用VC 一样,我们先用
Delphi
的
Wizard
建立一个 SDI 应用程序。
Delphi
自动建立
SDI
框架, 先运行一次。程序现在还不能干任何事。下一步开始添加代码。
编辑主菜单。 增加
Write,Draw
俩个下拉菜单项。 在
"Write"
下增加
"HelloWorld!!","Iamateacher "
,
"Font.."
菜单项
.
在
aw"
下增加
"Arc"
,
"Line"
,
"Polygon"
,
"RoundRect"
,
"Rectangle"
,
"color."
,
"LineStyle"
,
"WidthLine".
在
"LineStyle"
菜单下增加
"Solid","Dash","Dot"
,
"DashDot"
,
"DashDotDot"
子菜单。
相应的在
SdiForm
中增加
ColorDialog,FontDialog,
控件。
在OnPaint事件中增加如下代码:
procedureTSDIAppForm.FormPaint(Sender:TObject);
begin
canvas.FillRect(rect);
...
{清空桌面画布}
withSDIappformdo
posx:
=
clientwidthdiv2;
posy:
=
clientheightdiv2;
...
{确定客户区中心点}
casedetectIof
1
:
begin
setpenstate;
canvas.Ellipse(posx
-
50
,posy
-
50
,posx
+
50
,posy
+
50
);
//
penwidth:=oldwidth;
end;
...
{在客户区中心点画圆}
2
:
begin
setpenstate;
canvas.MoveTo(posx
-
60
,posy
-
60
);
canvas.LineTo(posx
+
60
,posy
+
60
);
//
penwidth:=oldwidth;
end;
...
{在客户区画直线}
3
:
begin
fposx:
=
trunc(
50
*
cos(pi
/
6
));
fposy:
=
trunc(
50
*
sin(pi
/
6
));
setpenstate;
Canvas.Polygon([Point(posx
-
fposy,posy
-
fposx),
Point(posx
+
fposy,posy
-
fposx),
Point(posx
+
50
,posy),Point(posx
+
fposy,posy
+
fposx),
point(posx
-
fposy,posy
+
fposx),point(posx
-
50
,posy)]);
//
penwidth:=oldwidth;
end;
...
{在客户区中心点画多边形}
4
:
begin
setpenstate;
canvas.RoundRect(posx
-
100
,posy
-
50
,posx
+
100
,posy
+
50
,
20
,
20
);
end;
...
{在客户区中心点画带圆角的矩形}
5
:
begin
setpenstate;
sdiappform.Canvas.Brush.Color:
=
clred;
canvas.Rectangle(posx
-
100
,posy
-
50
,posx
+
100
,posy
+
50
);
sdiappform.Canvas.Brush.Color:
=
bcolor;
end
...
{在客户区中心点用红色刷子画矩形}
else
begin
canvas.Font:
=
formfont;
canvas.TextOut(
30
,posy,str);
end;
end;
...
{写字}
end;
上面程序中出现的变量在事件OnCreate中初始化。
procedureTSDIAppForm.FormCreate(Sender:TObject);
begin
str:
=
;
...
{要写在画布上的字符串}
formfont:
=
canvas.font;
...
{字体和大小}
detectI:
=
0
;
...
{确定画布上出现何种图形的参数}
rect:
=
sdiappform.ClientRect;
...
{客户区矩形}
oldwidth:
=
sdiappform.Canvas.Pen.Width;
...
{最初画笔宽度}
penwidth:
=
oldwidth;
...
{画笔宽度}
penstyle:
=
sdiappform.Canvas.Pen.Style;
...
{画笔类型}
pencolor:
=
sdiappform.Canvas.Pen.Color;
...
{画笔颜色}
bcolor:
=
sdiappform.Canvas.Brush.Color;
...
{画刷颜色}
end;
为了减少代码,定义了一个Public过程,设定画笔。代码如下:
procedureTSDIAppForm.setpenstate;
begin
withsdiappform.Canvas.Pendo
begin
color:
=
pencolor;
style:
=
penstyle;
width:
=
penwidth;
end;
end;
响应每一个菜单项OnClick事件本程序设计得非常简单,如果有兴趣,读者也可以加上一些代码,完成许多复杂的工作。
procedureTSDIAppForm.LineColor1Click(Sender:TObject);
begin
ifcolordialog1.Executethen
begin
pencolor:
=
colordialog1.Color;
SdiAppForm.Canvas.Pen.Style:
=
psInsideFrame;
ifpenwidth$#@
60
;1then
SdiAppForm.Canvas.Pen.Width:
=
3
;
SdiAppForm.Canvas.Pen.Color:
=
pencolor;
invalidate;
end;
end;
...
{完成画笔颜色设定}
//
{完成画笔笔形设定}
procedureTSDIAppForm.Solid1Click(Sender:TObject);
begin
penStyle:
=
pssolid;
invalidate;
end;
procedureTSDIAppForm.Dot1Click(Sender:TObject);
begin
PenStyle:
=
psdot;
invalidate;
end;
procedureTSDIAppForm.Dash1Click(Sender:TObject);
begin
penStyle:
=
psdash;
invalidate;
end;
procedureTSDIAppForm.DashDot1Click(Sender:TObject);
begin
PenStyle:
=
psdashdot;
invalidate;
end;
procedureTSDIAppForm.DashDotDot1Click(Sender:TObject);
begin
penStyle:
=
psdashdotdot;
invalidate;
end;
/**/
//////////////////////////////////
procedureTSDIAppForm.RoundRect1Click(Sender:TObject);
begin
detectI:
=
4
;
invalidate;
end;
procedureTSDIAppForm.Rectangle1Click(Sender:TObject);
begin
detectI:
=
5
;
invalidate;
end;
procedureTSDIAppForm.Helloworld1Click(Sender:TObject);
begin
detectI:
=
0
;
str:
=
helloworld
!!
;
Invalidate;
end;
procedureTSDIAppForm.Imateacher1Click(Sender:TObject);
begin
detectI:
=
0
;
str:
=
Iamateacher
!!
;
Invalidate;
end;
procedureTSDIAppForm.Fonts1Click(Sender:TObject);
begin
iffontdialog1.Executethen
begin
detectI:
=
0
;
formfont:
=
fontdialog1.font;
invalidate;
end;
end;
...
{设定字体和大小}
编译并运行,可以看到画图的效果。
(三)图形的拷贝和剪贴
通过剪贴板可以完成拷贝和剪贴的功能。
Canvas
不直接支持剪贴板,完成
Canvas
上图画拷贝和张贴关键技巧是通过一个
Tbitmap
变量,把
Canvas
上的图形先复制到
Tbitmap
上,再把
Tbitamp
和
window
的剪贴板连起来,反过来也一样。
Delphi通过鉴定Wizard建立的SDI程序中,有关 Edit命令的Click事件定义在ActionList控件中,相关代码如下:
//
拷贝图形到剪贴板
procedureTSDIAppForm.EditCopy1Execute(Sender:TObject);
var
bmp:tbitmap;
//
设置一个图形变量
begin
bmp:
=
tbitmap.Create;
bmp.Width:
=
rect.Right
+
10
;
bmp.Height:
=
rect.Bottom
+
10
;
bmp.canvas.CopyRect(rect,sdiappform.canvas,rect);
clipboard.Assign(bmp);
bmp.free;
end;
//
从剪贴板上复制
procedureTSDIAppForm.EditPaste1Execute(Sender:TObject);
var
bmp:tbitmap;
//
设置一个图形变量
begin
ifclipboard.HasFormat(CF_BITMAP)then
begin
bmp:
=
tbitmap.create;
bmp.Assign(clipboard);
sdiappform.Canvas.draw(
0
,
0
,bmp);
bmp.free;
end
elseifclipboard.HasFormat(CF_TEXT)then
begin
str:
=
clipboard.AsText;
detectI:
=
0
;
invalidate;
end;
end;
//
剪下图形拷贝到剪贴板
procedureTSDIAppForm.EditCut1Execute(Sender:TObject);
begin
EditCopy1Execute(sender);
withsdiappform.Canvasdo
begin
copymode:
=
cmwhiteness;
copyRect(rect,sdiappform.Canvas,rect);
CopyMode:
=
cmSrcCopy;
end;
end;
也可以把已有的图形文件直接拷贝在Canvas上,本程序通过菜单Open命令完成这一操作。
procedureTSDIAppForm.FileOpen1Execute(Sender:TObject);
var
bmp:Tbitmap;
currentfile:
string
;
begin
ifOpenDialog.Executethen
begin
currentfile:
=
OpenDialog.filename;
ifcurrentfile$#@
60
;$#@
62
;then
try
bmp:
=
tbitmap.Create;
bmp.LoadFromFile(currentfile);
sdiappform.Canvas.StretchDraw(rect,bmp);
finally
bmp.Free;
end;
end;
end;