本章要点
þ TCanvas对象的常用属性、方法及其使用 þ TGraphic对象的常用属性、方法及其使用 þ TBitmap对象的常用属性、方法及其使用 þ TPicture对象的常用属性、方法及其使用 þ Delphi中的图形图像组件及其使用
12.1 理论知识
12.1.1 TCanvas对象的使用
在Delphi中,TCanvas对象不是一个组件,而是窗体、图像框、PaintBox等组件的一个对象属性。该对象相当于一块画布,使用它的属性和方法,可以很灵活地绘制出直线、椭圆、矩形等图形。
1.TCanvas对象的属性
TCanvas对象的基本属性有Pen(画笔)、Brush(画刷)和Pixels(像素),以及一些其他属性。
(1)Pen属性
该属性也是一个对象,相当于绘图时的“画笔”。 Pen属性也有自己的属性,通过设置它的属性值可以改变画图时的线条宽度、样式和颜色等。下面介绍Pen属性的常用属性。
① Color属性:用于设置所画线条的颜色,默认时为黑色。该属性的设置方法有三种,分别如下:
l 使用Delphi提供的系统颜色常量,如语句:
Form1.Canvas.Pen.Color:=clBlue
该语句的作用是把Form1的Canvas对象的画笔颜色设置为蓝色。表12-1列出了Delphi系统的颜色常量及其表示的色彩。
l 使用RGB函数,RGB函数的一般格式如下:
RGB(R,G,B)
参数R、G、B分别代表红、绿、蓝三种颜色的成分,取值在0~255之间。如语句:
第12章 图形图像编程
Form1.Canvas.Pen.Color:=RGB(0,0,255)
243
其作用与语句“Form1.Canvas.Pen.Color:=clBlue”的作用是一样的。
表12-1 颜色常量及其表示的颜色
颜 色 常 量 clAqua clBlack clBlue clDkGray clFuchsia clGray clGreen clLime clLtGray clMaroon clNavy clOlive clPurple clRed clSilver clTeal clWhite clYellow clBackground clActiveCaption clInactiveCaption
浅绿色 黑色 蓝色
深灰(灰黑色) 紫红色 灰色 绿色 橙色 浅灰色 枣栗色 深蓝色 橄榄绿 紫色 红色 银灰色
Teal青凫色(一种蓝) 白色 黄色
当前桌面的背景色 当前窗体的标题栏色 当前不被激活的标题栏的颜色
表示的颜色
颜 色 常 量 clMenu clWindow clWindowFrame clMenuText clWindowText clCaptionText clActiveBorder clInactiveBorder clAppWorkSpace clHighlight clHightlightText clBtnFace clBtnShadow clGrayText
clInactiveCaptionText clBtnHighlight cl3DDkShadow cl3DLight clInfoText clInfoBk
表示的颜色
当前菜单的背景颜色 当前窗体的背景色 当前窗体框架的颜色 当前菜单文字的颜色 当前窗体中文字的颜色 当前标题的颜色 当前激活的边界的颜色 当前没被激活的边界的颜色 当前工作区的颜色 当前的高亮色 当前的高亮文本的颜色 当前按钮的颜色 当前按钮背影的颜色 当前灰色字体的颜色
当前没被激活的窗体标题文字的颜色 当前按钮高亮的颜色
当前3D按钮的颜色(只用于Windows 95或NT 4.0)
高亮的3D按钮的颜色(只用于Windows 95或NT 4.0)
工具栏提示字符的颜色(只用于Windows 95或NT 4.0)
工具栏提示背景色(只用于Windows 95或 NT 4.0)
l 直接以数字表示颜色。在Delphi 7中,可通过在十六进制数前面加$符号来表示颜色。因为Windows 98中的颜色系统是32位的,故其前面的8位不使用,一般写成0。后面的每8位表示一种颜色分量,从低到高依次是红、绿、蓝分量的取值。例如,如下语句:
Form1.Canvas.Pen.Color:=$00FF00FF;
该语句与下面的语句作用是相同的:
Form1.Canvas.Pen.Color:=RGB(255,0,255);
提示:4位二进制数可用1位十六进制数表示。
② Style属性:用于设置线条的样式,如:实心线、虚线、点划线等。各种线条样式的含义如表12-2所示。该属性的默认值为PsSolid(实线)。
244
Delphi 7应用教程
表12-2 Style属性值及说明
线 条 样 式 PsClear PsSolid PsDash PsDot PsDashDot PsDashDotDot
含 义
绘制的线条不可见 绘制实线 绘制由虚线 绘制圆点组成的线条 绘制点划线 绘制双点划线
例如,下面语句的作用是把Form1窗体的Canvas的画笔风格设置为点划线:
Form1.Canvas.Pen.Style:= PsDashDot;
③ Width属性:用于设置线条的粗细宽度,单位是像素,其最小值为1。下面的代码会将线条的粗细宽度设置为10个像素。
Form1.Canvas.Pen.Width:= 10;
④ Mode属性:用于设置画笔的颜色与背景颜色之间的作用效果,效果方案也有很多。例如,一直为黑色、一直为白色、将屏幕的颜色反转等。Mode属性的取值及其含义如表12-3所示。
表12-3 Mode属性的取值及其含义
取 值
pmBlack pmWhite pmNop pmNot pmCopy pmNotCopy pmMask pmMaskPenNot pmMaskNotPen pmMerge pmMergeNotPen pmMergePenNot pmNotMerge pmNotMask pmXor pmNotXor
一直黑色 一直白色
不改变,所有的图像都不画,使绘图失效 将屏幕上的颜色反转 以Color属性设置颜色 将画笔的颜色反转
将画笔的颜色与屏幕的颜色进行“与”操作 将画笔的颜色与反转后的屏幕的颜色进行“与”操作 将屏幕的颜色与反转后的画笔的颜色进行“与”操作 将画笔的颜色与屏幕的颜色进行“或”操作 将屏幕的颜色与反转后的画笔的颜色进行“或”操作 将画笔的颜色与反转后的屏幕的颜色进行“或”操作
将画笔的颜色与屏幕的颜色进行“或”操作,再把结果按位取反 将画笔的颜色与屏幕的颜色进行“与”操作 将画笔的颜色与屏幕的颜色进行“异或”操作
将画笔的颜色与屏幕的颜色进行“异或”操作,再把结果按位取反
含 义
第12章 图形图像编程
245
例如,有如下语句:
Form1.Canvas.Pen.Mode:= pmXor;
其作用是画线时把画笔的颜色与屏幕的颜色进行异或操作。 (2)Brush属性
Brush属性也是一个对象属性,相当于绘图时的画刷。使用该属性可设置在图形内或画布上某区域的填充方式,同样它也有自己的属性。可以通过它的属性来设定填充颜色、图案等。下面介绍Brush对象属性的常用属性。
① Color属性:用于设置填充色,取值及含义与Pen的Color属性一样。
② Style属性:用于设置填充样式。图12-1所示为Brush颜色值为clBlack时,Style属性值及其代表的样式。
图12-1 Brush对象的Style属性值及其代表的填充样式
(3)Pixels属性
该属性是一个二维数组属性,其声明如下:
property Pixels[X,Y:Integer]:TColor;
该属性是一个二维数组属性,数组中的每个元素用来存放画布中一个像素所对应的颜色值。在画布上绘图,实际上就是改变画布上某些点所对应的像素值。一般只有在必须访问单个像素颜色时,才使用Pixels数值。属性中的X、Y表示像素的坐标,坐标的原点在Canvas对象的左上角。
(4)Font属性
该属性用于设置在画布对象上输出文字的字体格式,它也有自己的属性,通过设置它的属性,可以决定在画布上输出文字的字体、大小、颜色及字体风格等。
(5)ClipRect属性 该属性的声明如下:
property C1ipRect:TRect;
该属性用于对图形进行剪裁,使它只显示在指定的矩形区域内。当输出图形大于给定值时,超出的部分将被裁剪。
(6)CopyMode属性
该属性用于设置从其他画布拷贝图像的方式,其取值及含义如表12-4所示,该属性的默认值为cmSrcCopy(表示拷贝的像素将覆盖画布上原有的像素)。
246
Delphi 7应用教程
表12-4 CopyMode的属性值及其含义
CopyMode属性的取值
cmSrcCopy cmBlackness cmDsInvert cmMergeCopy cmMergePaint cmNotSrcCopy cmNotSrcErase cmPatCopy cmPatlnvert cmPatPaint cmSrcAnd cmSrcCopy cmSrcErase cmSrclnvert cmSrcPaint cmWhiteness
含 义
拷贝的像素将覆盖画布上原有的像素 以黑色输出 将目标图像反转
将原先的图像和源图像进行“与”操作 将源图像反转后,再和目标图像进行“或”操作 将源图像反转拷贝
先将源图像和目标图像进行“或”操作,再将结果反转 将源图像进行“异或”操作后,再拷贝到目标设备 将目标点位图与图案进行“异或”操作 先将源点位图反转后,再和图案进行“或”操作 将目标像素与源点位图进行“与”操作 拷贝并覆盖目标点位图
先将目标点位图反转,再与源点位图进行“与”操作 将源图和目标图的像素进行“异或”操作 将源图和目标图的像素进行“或”操作 将所有的输出变成白色
(7)Handle属性
该属性用于返回画布对象的句柄。 (8)PenPos属性
该属性的类型是Tpoint型,用于设置或返回当前画笔位置所在的点。
2.TCanvas对象的方法
利用Tcanvas对象的方法可以完成常用的绘图功能,如绘制直线、椭圆、矩形等。TCanvas对象最常用的方法如下。
(1)MoveTo方法 [格式]:
procedure MoveTo(X,Y Integer);
[功能]:将画笔移到坐标(X,Y)指定的位置,使该点成为当前位置。 (2)LineTo方法 [格式]:
procedure LineTo(X,Y Integer);
[功能]:使用画笔从当前位置画一条直线到指定位置(X,Y),画好后,画笔的位置将移至坐标(X,Y)处。
(3)Arc方法 [格式]:
procedure Arc(X1,Y1,X2,Y2,X3,Y3,X4,Y4:Integer);
第12章 图形图像编程
247
[功能]:用于画一段椭圆弧。其中,椭圆是由点(X1,Y1)的点(X2,Y2)所确定的矩形所决定,弧的起点是椭圆中心和点(X3,Y3)的连线与椭圆的交点,弧的终点是椭圆中心和点(X4,Y4)的连线与椭圆的交点,并以逆时针方向画弧。
(4)Ellipse方法 [格式]:
procedure Ellipse(X1,Y1,X2,Y2:Integer);
[功能]:用于绘制椭圆,该椭圆是由点(X1,Y1)和点(X2,Y2)所决定矩形的内切椭圆。椭圆的边界使用当前的Pen(画笔)绘制,椭圆的内部使用当前的Brush(画刷)填充。
(5)Rectangle方法 [格式]:
procedure Rectangle(X1,Y1,X2,Y2:Integer);
[功能]:用于绘制矩形,该矩形是由点(X1,Y1)和点(X2,Y2)所确定。矩形的边界使用当前的Pen绘制,矩形的内部使用当前的Brash填充。
(6)RoundRect方法 [格式]:
procedure RoundRect(X1,Y1,X2,Y2,X3,Y3:Integer);
[功能]:用于绘制带有圆角的矩形,该圆角矩形的矩形范围是由点(X1,Y1)和点(X2,Y2)所确定,X3、Y3分别指定圆角的长半度和短半径。
(7)Pie方法 [格式]:
procedure Pie(X1,Y1,X2,Y2,X3,Y3,X4,Y4:Longint);
[功能]:用于绘制扇形(椭圆的一部分)。该椭圆内切于由点(X1,Y1)和点(X2,Y2)所确定的矩形,扇形区域是由椭圆中心到(X3,Y3)和(X4,Y4)两点所组成的椭圆部分所决定。并且扇形的内部使用当前的Brash填充。
(8)Draw方法 [格式]:
procedure Draw(X,Y Integer;Graphic:TGraphic);
[功能]:用于在画布上由(X,Y)指定的位置处,输出由Graphic参数所指供的图像,该图像可以是位图,也可以是图标或图元文件。
注意:要想绘制已存在的图像文件,可先建立一个图形对象,使用它将图像从文件中读出来,然后再以它为参数,调用Draw方法将图像画到画布上去。
(9)CopyRect方法 [格式]:
procedure CopyRect(Dest:TRect;Canvas:Tcanvas;Source:TRect);
[功能]:用于将一个画布上的一部分图形图像拷贝到当前画布上。其中,Dest参数指定
248
Delphi 7应用教程
目标画布的区域,Canvas参数指定源画布,Source参数指定源画布上要拷贝的矩形区域。
(10)FillRect方法 [格式]:
procedure FillRect(const Rect:TRect);
[功能]:使用当前的Brush填充由参数Rect所指定的矩形区域。 (11)StretchDraw方法 [格式]:
procedure StretchDraw(const Rect:TRect; Graphic:TGraphic);
[功能]:用于将Graphic参数指定的图像输出在Rect参数指定的区域内,并将图像自动放大或缩小以适应区域。
(12)TextOut方法 [格式]:
procedure Textout(X,Y:Integer, const Text:String);
[功能]:用于在画布上以当前字体输出字符串。输出的字符串由参数Text指定,输出的位置由参数X和Y指定。
(13)Polygon方法 [格式]:
procedure Polygon([Point(X1,Y1),Point(X2,Y2),Point(X3,Y3),…]);
[功能]:Polygon方法是用于画由一系列点定义的多边形,其中(Xi,Yi)为多边形的顶点。绘制的多边形为封闭图形。
(14)Chord方法 [格式]:
procedure Chord(X1,Y1,X2,Y2,X3,Y3,X4,Y4);
[功能]:Chord方法用来连接椭圆上的两点,以形成“帽图”。椭圆由(X1,Y1)、(X2,Y3)两点所确定的矩形决定,连线的起点为(X3,Y3),连线的终点是(X4,Y4)。
【例12-1】 编写一个程序,用来绘制一个椭圆和几个圆角矩形。程序执行时,单击【画图】按钮,运行界面如图12-2所示。
【实现分析】
画椭圆可使用TCanvas对象的Ellipse方法,画圆角矩形可使用TCanvas对象的RoundRect方法。在画椭圆时,给它填充的是一幅位图,因此应创建一个位图对象并赋值给Brush属性的Bitmap属性。画的三个圆角矩形的填充风格均不同,可通过设置TCanvas的Brush.Style属性来设置填充风格。另外填充色也不同,可通过设置TCanvas的Brush.Color属性来设置填充色。
【界面设计】
为窗体添加一个Button组件,设置它的Caption属性值为“画图”。
第12章 图形图像编程
249
图12-2 程序运行界面
【程序代码】
主要的程序代码如下:
procedure TForm1.Button1Click(Sender: TObject); var
bitmap:TBitmap; //用来存放创建位图,该位图作为填充图像 CurDir:String; //存放应用程序当前目录 begin
GetDir(0,CurDir); //获得应用程序的当前目录 With Canvas do begin
Bitmap:=TBitmap.Create; //创建位图 try
Bitmap.LoadFromFile(Curdir+'\\1.BMP'); //装载位图 Brush.Bitmap :=Bitmap; // 把创建的位图赋值给Brush.Bitmap,作为填充图像 Ellipse(0,0,100,100); //画椭圆,以位图填充 Finally
Form1.Canvas.Brush.Bitmap :=nil; //卸除Bitmap位图 end; end;
With Canvas do begin
pen.Color :=RGB(0,0,255); //设置画笔颜色为蓝色 pen.Width :=5; //设置画笔的宽度为5个像素 brush.Color :=$00FF0000; //设置画刷的填充颜色为蓝色 brush.Style :=bsDiagCross; //设置画刷的填充风格为交叉对角线 RoundRect(110,10,210,100,0,0); //画圆角矩形 brush.Color :=$0000FF00; // 设置画刷的填充颜色为绿色 brush.Style :=bsCross; // 设置画刷的填充风格为交叉线 RoundRect(210,10,310,100,50,50); //画圆角矩形 brush.Color :=$000000FF; // 设置画刷的填充颜色为红色 brush.Style :=bsBDiagonal; //设置画刷的填充风格为斜对角线 RoundRect(310,10,410,100,100,100); //画圆角矩形 end; end;
250
Delphi 7应用教程
12.1.2 TGraphic对象的使用
在TCanvas对象的Draw和StretchDraw方法中将使用TGraphic型的参数。TGraphic对象是TBitmap、TIcon、TMetaffie对象的抽象基类,如果不知道图像的具体类型,可以使用它来存放。
1.TGraphic对象的属性
TGraphic对象有Height、Width、Empty等属性。Height和Width属性用来设置对象的宽度和高度。Empty属性是一个Boolean型的只读属性,其值为True时,表示TGraphic对象中已经包含有图像,其值为False时,表示TGraphic对象中不包含图像。
2.TGraphic对象的方法
TGraphic对象的方法如下。 (1)LoadFromFile方法 [格式]:
procedure LoadFromFile(const FileName:String);
[功能]:该方法从参数FileName作为文件名指定的文件中读取图像,并装入TGraphic对象中。
(2)SaveToFile方法 [格式]:
procedure SaveToFile(const FileName:String);
[功能]:该方法把TGraphic中的图像保存到指定的文件中,保存文件的文件名由参数FileName指定。
12.1.3 TPicture对象的使用
TPicture对象可以存储任意类型的图像,它是TGraphic对象的容器。
1.TPicture对象的属性
TPicture对象的属性如下。 (1)Bitmap属性
该属性的类型为TBitmap型,若Tpicture对象包含的是位图,可使用该属性指定位图。 (2)Icon属性
该属性的类型为TIcon型,若Tpicture对象包含的是图标,可使用该属性指定图标。 (3)Metafile属性
该属性的类型为TMetafile型,若TPicture对象包含的是图元文件,可使用该属性指定图元文件。
(4)Graphic属性
该属性用于设置或返回TPicture对象中包含的图像。
2.TPicture对象的方法
TPicture对象的主要方法有LoadFromFile和SaveToFile,这两个方法的格式和功能与
第12章 图形图像编程
251
TGraphic对象的同名方法完全一致。
【例12-2】 编写一个绘制位图的程序,程序的运行界面如图12-3所示。程序执行时单击【绘制位图】按钮,将从窗体的左上角开始原样绘制一幅图片,然后再把该图片缩小在一个矩形框内绘制,如图12-3所示。
图12-3 程序运行界面
【实现分析】
绘制位图可以使用Canvas对象的Draw方法和StretchDraw方法,Draw方法用于原样绘制位图,StrtechDraw方法用于把一个位图在一个矩形框中绘制,位图自动调整大小以填满矩形框。
【界面设计】
为窗体添加一个Button组件,设置它的Caption属性值为“绘制位图”。 【程序代码】
主要的程序代码如下:
procedure TForm1.Button1Click(Sender: TObject); var
CurDir:String; Picture:Tpicture; begin
GetDir(0,Curdir);
Picture:=Tpicture.create;
Picture.LoadFromFile(CurDir+'\\1.bmp'); //从文件中装载位图 With Canvas do begin
Draw(0,0,Picture.Graphic ); //从画布的左上角原样绘图 StretchDraw(Rect(0,0,150,150),picture.Graphic );
//在一个矩形区域内绘图,图自动变化大小以适应矩形框 end end;
252
Delphi 7应用教程
12.1.4 TBitmap对象的使用
TBitmap对象可以包含一个位图图像,拥有位图图像和调色板的句柄,可以自动管理调色板。另外TBitmap对象还具有Canvas属性,利用它可以绘制图形。
1.TBitmap对象的属性
TBitmap对象的主要属性如下。 (1)Handle属性
该属性的类型是HBitmap,用于返回位图图像的句柄。在调用Windows API时,许多API函数均需要传递图像的句柄,通过该属性就可以获得TBitmap对象中的位图图像的句柄。
(2)IgnorePalette属性
该属性是一个布尔型属性,若其值设置为True,则表示TBitmap对象不使用调色板。 (3)Monochrome属性 该属性是一个布尔型属性,若其值设置为True时,则表示TBitmap对象将显示为单色(黑白图像);若其值设置为False时,则表示TBitmap对象将显示为彩色。
(4)Palette属性
该属性的类型是HPalette型,表示的是TBitmap对象的调色板。若Palette=0,则表示对象不使用调色板,此时可以使用CreatePalette方法来创建自己的调色板。
2.TBitmap对象的方法
TBitmap对象的主要方法有LoadFromFile、SaveToFile、Releasehandle等。LoadFromFile方法和SaveToFile方法的格式和功能与TGraphic对象的同名方法完全一致。
Releasehandle方法的格式与功能如下。 [格式]:
Function Releasehandle:Hbitmap;
[功能]:释放TBitmap对象的调色板。
12.1.5 Delphi中的图形图像组件
1.TShape组件
TShape组件的作用是绘制图形,它的主要属性有Brush、Pen、Shape等。Brush和Pen属性与TCanvas对象的相应属性基本相同,此处不再赘述。Shape属性用来设置TShape组件显示的图形形状,其取值及其表示的图形如表12-5所示。
表12-5 Shape属性
属 性 值
stCircle stRectangle stSquare
圆 矩形 正方形
图 形
stEllipse stRoundRect stRoundSquare
属 性 值
椭圆 圆角矩形 圆角正方形
图 形
【例12-3】 编写一个Shape形状演示程序,程序的设计界面如图12-4所示。程序运行
第12章 图形图像编程
253
时,单击【随机画图】按钮,TShape组件的形状将依次在6种图形之间转换,同时在Label组件中显示图形的名称,TShape组件的填充风格也自动在8种填充风格之间转换,并且填充的色彩随机产生。每种图形的转换时间为200毫秒。程序的运行界面如图12-5所示。
图12-4 程序设计界面 图12-5 程序运行界面
【实现分析】
为了能够使图形每隔200毫秒转换一次,可使用一个TTimer组件,把该组件的Interval属性设置为200,在该组件的Timer事件中改变图形。为使图形依次在6种图形之间转换,可设一个单元(窗体/模块)级变量Num,其初值为0,在Timer事件中用该变量的值除以6求余,显然余数在0~5之间,设定每一个数对应一种图形,通过Case多分支语句进行判断并给TShape组件的Shape属性赋相应的值。填充风格也同样设置,只是应除8取余。填充色是随机的,可通过Random函数产生3个255之内的随机整数作为红、绿、蓝三色的分量,通过RGB函数产生色彩并赋值给Brush的Color属性。在Timer事件的最后使变量Num的值加1。
【界面设计】
本例组件对象及其属性设置如表12-6所示。
表12-6 例12-3组件对象及其属性设置
对 象 名 Label1 Shape1 Timer1 Button1
Interval Enabled Caption 属 性 名
200 False
'随机画图' 属 性 值
显示图形形状名 顺序显示图形形状
每隔200毫秒设置一次图形形状、图形的填充风格和填充色 单击它进行初始化工作并启动计时器组件工作
说 明
【程序代码】
implementation var Num:Integer; 数 {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin //Num表示Timer1的Timer事件的发生次
254
Num:=0; Timer1.Enabled :=True; Delphi 7应用教程
//Num的初值为0 //启动Timer1,开始计时 Randomize; //随机数初始化 end; procedure TForm1.Timer1Timer(Sender: TObject); var k,r,g,b:Integer; begin k:=Num Mod 6; //k为6种形状之一 Case k of //本Case语句根据k的值决定显示何种图形 0: begin Shape1.Shape:=stCircle; Label1.caption:='圆形';end; 1: begin Shape1.Shape :=stEllipse; Label1.caption:='椭圆';end; 2: begin Shape1.Shape :=stRectangle; Label1.caption:='矩形';end; 3: begin Shape1.Shape :=stRoundRect; Label1.caption:='圆角矩形';end; 4: begin Shape1.Shape :=stSquare; Label1.caption:='正方形';end; 5: begin Shape1.Shape :=stRoundSquare;Label1.caption:='圆角正方形';end; end; k:=Num Mod 8; //此时K代表填充图案,共有8种 Case k of //本case语句根据k的值决定以何种图案进行填充 0:Shape1.Brush.Style :=bsBDiagonal; 1:Shape1.Brush.Style :=bsClear; 2:Shape1.Brush.Style :=bsCross; 3:Shape1.Brush.Style :=bsDiagCross; 4:Shape1.Brush.Style := bsFDiagonal; 5:Shape1.Brush.Style :=bsHorizontal; 6:Shape1.Brush.Style := bsSolid; 7:Shape1.Brush.Style :=bsVertical; end; Num:=Num+1; //Timer1的Timer事件又执行了一次 r:=random(255);g:=random(255);b:=random(255); //随机产生红、绿、蓝三种色彩成分 Shape1.Brush.Color :=RGB(r,g,b); //作为填充色 if Num>=1000 then //只执行1000次 Application.Terminate ; end; 2.TImage组件
TImage组件主要用于显示和处理图像,能够显示BMP、JPEG、ICO、WMF、EMF等多种格式的图片。它的主要属性如下。
(1)Canvas属性
画布属性,同Tcanvas对象。 (2)Picture属性
该属性用于指定在Image组件中显示的图像。可在设计阶段在属性窗口(对象浏览器)中找到该属性,单击属性后面的【…】按钮,以选择一幅图片在TImage组件中显示。也可以在运行时通过函数LoadFromFile为TImage组件加载一幅图片。例如,有如下语句:
第12章 图形图像编程
Image1.Picture.LoadFromFile('D:\\A1.JPG');
255
该语句的作用是把“D:\\A1.JPG”图像文件显示在TImage组件中。 (3)Stretch属性
该属性是一个Boolean型属性,其值为True时,表示将自动对图像进行拉伸或缩小操作,调整图像的尺寸以填满整个TImage组件;当其值为False时,若图像比TImage组件大,多余的部分将显示不出来,若图像比TImage组件小,则图像没有填满TImage组件。
图12-6 TImage组件的Stretch属性取值及图像显示情况
(4)Center属性
该属性是一个Boolean型属性,用于确定图像是否居中显示在TImage组件中。若Center设置为True,则表示图像将居中显示;否则,图像将从TImage组件的左上角开始显示。
3.TPaintBox组件
TPaintBox组件主要提供一个可以用来绘制几何图形的矩形区域,它有一个Canvas属性,可以使用它的绘图方法来绘制图形。TPaintBox组件的使用方法与Form窗体基本上一样,不同的是在TPaintBox组件中绘图时,绘图的坐标是以TPaintBox组件的左上角为原点,而不是以窗体的左上角为原点。当TPaintBox组件的背景色与Form相同时,在其上绘图和在窗体上绘图的效果一样。可见,使用TPaintBox组件绘图的惟一好处就是将图形绘制在TPaintBox组件内,省去了计算坐标的麻烦。其使用方法与窗体绘图基本一致,此处不再赘述。
12.2 典型实例
12.2.1 典型实例一
【实例题目】:背景填充程序
编写一个以位图填充窗体背景的应用程序,程序的设计界面如图12-7所示。程序运行时,单击【选择图片】按钮,将弹出【打开】对话框供用户选择一幅作为背景填充的图片,并根据单选钮的状态进行“平铺”或“拉伸”填充。单击【平铺】单选钮,图片将以“平铺”方式填充整个窗体,如图12-8所示。单击【拉伸】单选钮,图片将以“拉伸”方式填充整个窗体,如图12-9所示。
256
Delphi 7应用教程
图12-7 程序设计界面 图12-8 程序运行界面(一) 图12-9 程序运行界面(二)
【实现方法】
为实现在矩形区域中填充位图,可先给Brush对象的Bitmap赋一个位图对象,然后再绘制出矩形,该矩形将以指定的位图进行填充。但该方法无法实现位图的拉伸填充,要实现位图的拉伸填充,可使用TCanvas对象的StretchDraw方法。该方法以某一个TGraphic对象中包含的图形在一个矩形区域内拉伸填充,因此使用该方法之前应产生一个TGraphic对象。
【界面设计】
本实例组件属性设置及组件作用如表12-7所示。
表12-7 组件的属性设置及组件作用
对 象 名 Button1 OpenDialog1 RadioButton1 RadioButton2
属 性 名 Caption Filter Caption Caption
'选择图片'
'位图文件|*.bmp|JPEG文件|*.jpg' '平铺' '拉伸'
设 置 值
对 象 作 用
单击它出现打开对话框供用户选择填充图片 用来选择图片文件
用来设置以“平铺”方式填充 用来设置以“拉伸”方式填充
【程序代码】
本例主要程序代码如下:
implementation var
FName:String; //背景填充的图片文件名 {$R *.dfm}
procedure btile() ; //平铺填充 var
Bitmap:TBitmap; begin
Bitmap:=TBitmap.Create ; //创建位图对象 Bitmap.LoadFromFile(FName ); //装载图像
Form1.Canvas.Brush.Bitmap :=Bitmap; //把位图对象赋值给Brush.bitmap,以便填充 Form1.Canvas.rectangle(0,0,Form1.width,Form1.height); //在整个窗体内画矩形,用位图填充,平铺效果 Bitmap:=nil; //卸载位图 end;
procedure bStretch(); //拉伸填充 var
第12章 图形图像编程
psicture:TPicture;
begin
Picture:=TPicture.Create ; //创建Picture位图 Picture.LoadFromFile(FName ); //装载图像
Form1.Canvas.Stretchdraw(Rect(0,0,Form1.width,Form1.height),Picture.Graphic ); //使用StretchDraw方法在整个窗体上绘图,拉伸效果 Picture:=nil; //卸载Picture对象 end;
procedure TForm1.FormCreate(Sender: TObject); var
CurDir:String; begin
GetDir(0,CurDir); //获取当前路径 FName:=CurDir+'\\Default.BMP'; //设置默认填充的图片名 end;
procedure TForm1.FormPaint(Sender: TObject); begin
if RadioButton1.Checked then bTile else
bstretch; end;
procedure TForm1.Button1Click(Sender: TObject); //选择一个图片文件以填充 begin
if OpenDialog1.Execute then //弹出【打开】对话框以选择文件 begin
Fname:=OpenDialog1.FileName ; if RadioButton1.Checked then //如果选择了【平铺】单选钮 btile //“平铺”填充 else
bStretch; //“拉伸”填充 end; end;
procedure TForm1.RadioButton1Click(Sender: TObject); begin
BTile; //平铺填充 end;
procedure TForm1.RadioButton2Click(Sender: TObject); begin
Bstretch; //拉伸填充 end;
257
12.2.2 典型实例二
【实例题目】:照片自动展示程序
制作一个照片自动展示程序,程序启动后将循环显示照片,每张照片在屏幕上停留0.5
258
Delphi 7应用教程
秒。当用户单击图片时将显示一个提示框,询问用户是否停止展示,如果用户选择【是】将停止展示,选择【否】将接着展示。程序的设计界面如图12-10所示,程序的运行界面如图12-11所示。
图12-10 程序设计界面 图12-11 程序运行界面
【实现方法】
本实例要求每隔0.5秒展示一张照片,可用一个TTimer组件来实现。由于每次展示的照片并不是同一张照片,故在TTimer组件的Timer事件中还应形成要展示的照片文件名。照片文件命名必须符合一定的规则,本例规定照片文件名分别为TZY1.jpg,TZY2.JPG,TZY3.JPG,……,直到TZJ08.JPG。为形成文件名,可设一个单元(窗体/模块)级变量(假设为Num),在每次发生Timer事件时,取Num除以8的余数,该余数加1作为要显示照片的照片序号,再根据它不难形成照片文件名。然后让Num的值加1,准备显示下一张照片。
【界面设计】
在窗体上放置一个TImage组件(Image1),用来显示照片,设置它的align属性值为alClient。再放置一个TTimer控件(Timer1),用来每隔0.5秒显示一张照片。
【程序代码】
本例的程序代码如下:
implementation var
Num:Integer; //表示计时器控件的Timer事件发生的次数 {$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject); begin
Num:=0;
Image1.Stretch :=True; //使照片充满整个图像框 Timer1.Interval:=500; //每隔0.5秒发生一次Timer事件 Timer1.Enabled :=True; //启动计时器控件 end;
procedure TForm1.Timer1Timer(Sender: TObject); var
xh:Integer;
CurDir,PicFile:string; begin
第12章 图形图像编程
XH := Num Mod 8 ; //得到要展示的照片文件的序号 259
GetDir(0,CurDir); PicFile:= CurDir+'\zy'+inttostr(XH+1)+'.jpg'; //形成要展示文件的文件名 Image1.Picture.LoadFromFile (PicFile); //展示照片 Num := Num + 1; //准备展示下一张照片 if Num=1000 Then //如果Num的值很大,再把它置0 Num:=0; end; procedure TForm1.Image1Click(Sender: TObject); begin if MessageDlg('退出照片展示吗?',mtConfirmation, [mbYes, mbNo],0) = mrYes then begin close; end; end; 程序的运行界面如图12-11所示。运行时如果单击照片,将会出现如图12-12所示的退出提示信息,在该提示框中单击【Yes】按钮将退出图片展示程序,单击【No】将继续展示。
图12-12 提示信息
12.3 上机练习
12.3.1 上机练习一
【练习题目】:转动的秒针
编写一个程序,程序运行时将出现一个钟表的轮廓和一个秒针,如图12-13所示。秒针以每秒12度的速度移动,图12-14是某个时刻的程序运行情况。
【要点提示】
(1)秒针移动和实现。秒针可通过画线来实现,为演示出秒针的移动,可画两次直线:一次用来覆盖掉原来的线条,方法是使背景色为白色,然后置画笔模式为pmNotXor;另一次是计算出新的坐标位置,然后以pmCopy模式画线条。由于每隔一段时间就要移动指针,故可使用一个计时器组件,设置它的Interval属性值为1000,使它每秒钟发生一次Timer事件,在Timer事件中实现覆盖原来指针和重画指针的功能。
260
Delphi 7应用教程
图12-13 程序设计界面 图12-14 程序运行界面
(2)画线的线条终点的计算。假设指针在窗体的坐标位置为(x1,y1)至(x2,y2),以(x1,y1)为圆心,按顺时针方向改变(x2,y2),则指针根据圆的参数方程的规律移动。圆的参数方程如下:
x=asin(t)
y=acos(t)
其中a是圆的半径,t参数(单位为度)。则x2和y2的值可用下式来计算: x:=Floor(65*sin(t*3.1415926/180)); y:=Floor((−1)*65*cos(t*3.1415926/180)); 其中t为指针的当前度数。 【参考代码】
var
Form1: TForm1; Num:integer; x,y:integer; implementation {$R *.dfm}
procedure TForm1.Timer1Timer(Sender: TObject); begin
Form1.Canvas.Pen.Width :=3; if num=0 then begin x:=0; y:=-65;
Form1.Canvas.Pen.Mode:=pmCopy; Form1.Canvas.Ellipse(5,5,155,155); Form1.Canvas.MoveTo(80,80); Form1.Canvas.pen.Color :=Clred;
Form1.Canvas.LineTo(80+x,80+y); end else
begin
Form1.Canvas.pen.Color :=Clred;
Form1.Canvas.Pen.Mode :=pmNotXor;
x2:=x1+x; y2:=y1+y;
//第一次执行该事件
//画圆
//画起始指针
第12章 图形图像编程
num:=num mod 360;
Form1.Canvas.MoveTo(80,80); Form1.Canvas.LineTo(80+x,80+y); x:=Floor(65*sin(Num*3.1415926/180)); y:=Floor((-1)*65*cos(Num*3.1415926/180)); Form1.Canvas.Pen.Mode:=pmCopy; Form1.Canvas.MoveTo(80,80);
Form1.Canvas.LineTo(80+x,80+y); end;
num:=num+12; end;
procedure TForm1.FormCreate(Sender: TObject); begin
Num:=0; end;
261
//擦除原来的指针 //计算圆的参数
//重画指针
注意:由于使用了Floor函数,应当把“Math”单元包含进来。
12.3.2 上机练习二
【练习题目】:简单画图程序
编写一个能够根据用户的选择画椭圆和矩形的程序。程序的设计界面如图12-15所示,程序的运行界面如图12-16所示。程序运行时,默认画椭圆,也可以选择要画的图形。当在画图区域按下并拖动鼠标时,将出现一个相应图形的轮廓,显示在释放鼠标时所画图形的形状与大小,当松开鼠标的时候将创建一个内部填充色为蓝色的与图形轮廓一样大的相应图形。
图12-15 程序设计界面 图12-16 程序运行界面
【要点提示】
(1)鼠标拖动时图形轮廓的显示。为显示图形轮廓,可设置两个Tpoint型的变量:StartPt和EndPt,分别用来存放鼠标按下时的坐标和当前坐标。可通过下述方法来实现“可擦写”的轮廓并画图:当按下鼠标时,程序将捕获所有的鼠标输入,并在名为StartPt的变量中记录鼠标的(x,y)坐标,同时用鼠标的(x,y)坐标初始化EndPt变量,然后设置画笔和笔刷的颜色,以画出所需图形的轮廓,把画笔的模式设置成pmNot,这样画笔会以与底色相反的颜色绘图。现在,每当鼠标移动时,可两次画图:一次是在老地方擦写已画过的“可擦写”图形轮廓,
262
Delphi 7应用教程
一次是在新位置上绘制出所需要的图形轮廓,然后在变量EndPt中记录鼠标新位置(x,y)坐标。最后当用户释放鼠标时,擦除上次的“可擦写”图形,并以最终的色彩画出图形来。
(2)识别用户要画的图形。为了识别用户要画的图形,可定义一个整型变量(Shape Kind),在选择图形时(发生按钮的Click事件),给该整型变量赋不同的值:椭圆为1、矩形为2。在绘制图形时,根据该变量的值就知道应绘制什么样的图形。
【参考代码】
implementation var
StartPt,EndPt:TPoint; Capture:boolean;
shapekind:integer; //表示画图的种类,1表示椭圆,2表示矩形 {$R *.dfm}
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin
StartPt.x:=x; //设定起始点 StartPt.Y:=y;
EndPt:=StartPt; Capture:=True; //捕获鼠标操作 With Image1.Canvas do begin
pen.Mode:=pmNot; //设定的画笔的模式为pmNot,两次画同一点,等于没有画 Pen.Color:=clBlack; //画笔的颜色为黑色 Brush.Style:=bsClear; //画刷的填充风格为无 end; end;
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); //在该事件中消除上一次的轮廓线,画本次轮廓线 begin
if(Capture)and((EndPt.x<>x)or(EndPt.Y<>Y)) Then //如果鼠标发生了移动 Begin
case Shapekind Of //判断要画的是哪一种图形 1: begin
Image1.Canvas.Ellipse(StartPt.X,StartPt.Y,EndPt.X,EndPt.Y ); //擦除刚才的椭圆轮廓 Image1.Canvas.Ellipse(StartPt.X,StartPt.Y,x,y); //重画新的椭圆轮廓 end; 2: begin
Image1.Canvas.Rectangle(StartPt.X,StartPt.Y,EndPt.X,EndPt.Y ); //擦除刚才的矩形轮廓 Image1.Canvas.Rectangle(StartPt.X,StartPt.Y,x,y); //重画新的矩形轮廓 end; end;
EndPt.x:=x; //设置新的结束点位置
第12章 图形图像编程
EndPt.Y:=y; end; end;
procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); //消除最后的轮廓线并画出需要的图形 begin
Capture:=False; //取消对鼠标的捕获 With Image1.Canvas do begin
case Shapekind Of //判断要画的是哪一种图形,并把鼠标轮廓线去除 1: Ellipse(StartPt.X,StartPt.Y,EndPt.X,EndPt.Y ); 2: Rectangle(StartPt.X,StartPt.Y,EndPt.X,EndPt.Y ); end;
Pen.Mode:=pmCopy; //设置画笔的模式 Brush.Color:=clBlue; //设置画刷的填充色为蓝色 Brush.Style:=bsSolid; case Shapekind Of //判断要画的图形种类,绘制出需要的图形 1: Ellipse(StartPt.X,StartPt.Y,X,Y ); 2: Rectangle(StartPt.X,StartPt.Y,X,Y ); end; end; end;
procedure TForm1.FormCreate(Sender: TObject); begin
ShapeKind:=1; //开始认为要画的图形为椭圆 end;
procedure TForm1.Button1Click(Sender: TObject); begin
Shapekind:=1; //画椭圆 end;
procedure TForm1.Button2Click(Sender: TObject); begin
Shapekind:=2; //画矩形 end;
263
课后考场
一、选择题(20分,每题5分)
1.要想把窗体上的某一点设置为蓝色,应使用TCanvas对象的________属性。 A.Pen B.Brush C.Pixels D.CopyMode
2.在绘制封闭图形时,要想让它的填充色为某一指定的色彩,应设置TCanvas对象的________属性。
A.Pen.Color B.Brush.Color C.Pen.Style D.Brush.Style 3.要想在窗体上绘制一段圆弧,应使用TCanvas对象的________方法。
2
Delphi 7应用教程
A.Arc B.Draw C.Ellipse D.Pie 4.要想使TShape组件显示圆角矩形,应设置它的________属性。 A.Pen B.Shape C.Brush D.Picture 二、填空题(40分,每空5分)
1.在Form1上画图时,如果希望绘制出来的线条宽度为5个像素,则应该首先执行的一条语句为________。
2.要把Form1的Canvas对象的第5行的第6个像素设置为红色,执行的语句为_____。 3.要在Form1窗体上绘制矩形,应调用TCanvas对象的________方法。
4.要把名为“D:\\A1.BMP”图片文件显示在Image1组件中,应执行的语句是________。 5.要使TImage组件中显示的图片能够自动伸缩以填满图像框,应把它的________属性设置为True。
6.________对象可以包含一个位图图像,拥有位图图像和调色板的句柄,可以自动管理调色板。
7.以下语句的作用是把Form1窗体的Canvas的画笔风格设置为点划线:
Form1.Canvas.________:= PsDashDot;
8.________对象是TBitmap、TIcon、TMetaffie对象的抽象基类,如果不知道图像的具体类型,可以使用它来存放。
三、程序设计题(40分,每题20分)
1.编写一个用户用鼠标画图的程序,程序运行时,用户按住鼠标并移动时,将沿着鼠标的轨迹画线,线的宽度为5个像素,线的颜色为蓝色。程序的运行界面如图12-17所示。
2.编写一个照片浏览程序。程序运行时,将自动打开并显示当前目录下的名为“Default.jpg”的照片文件。用户可以通过单击窗体弹出一个【打开】对话框,从中选择要显示的照片。照片刚好填满整个窗体,当窗体改变大小时,照片也改变大小以填满整个窗体。程序的运行界面如图12-18所示。
图12-17 编程题一程序运行界面 图12-18 编程题二程序运行界面
第13章 多媒体应用程序开发
本章要点
þ 多媒体的基本概念
þ Delphi 7开发多媒体应用程序的方法
þ TAnimate组件的常用属性、方法及其使用
þ TMediaPlayer组件的常用属性、方法、事件及其使用 þ 背景音乐的循环播放
13.1 理论知识
13.1.1 多媒体的概念
媒体是指信息的载体,主要分成两个方面:存储信息的媒体和表现信息的媒体。存储信息的媒体主要有软盘、硬盘、光盘等,而表现信息的媒体主要有文字、图形、图像、影片、动画、声音和音乐等。我们所讲的多媒体中的媒体主要是指表现信息的媒体。
所谓多媒体是指多种媒体的有机结合,是通过计算机的多媒体技术来实现的。“多媒体技术”在某种程度上已经成为声、文、图、动画、影像等媒体信息在计算机系统中综合应用的代名词。
多媒体技术具有下面的两个重要特点。 (1)多种媒体的综合性
单一的文本、声音或图形图像不能称为多媒体,只有把多种媒体有机地综合在一起才能称为多媒体。
(2)交互性。
多媒体的一个重要特点就是交互性,这也是它与广播电视及其他电教设备的本质不同之处。多媒体程序在运行过程中,能够根据用户的反应做出不同的响应。如考试多媒体软件,用户对某一道题做了答案后,如果正确,计算机则给出一种应答,如果错误,计算机也立即给出另一种应答。
计算机处理的媒体信息都是以文件的形式出现的。各类主要媒体文件及扩展名如下。 图像文件:位图文件(.BMP)、JPEG文件(.JPG)。 声音文件:声波文件(.WAV)、MIDI音乐文件(.MID)。 视频文件:AVI文件(.AVI)、MPEG文件(.MPG)。
在Delphi 7中,图像文件的显示是通过TImage等组件来实现的,另外在Delphi 7中还提
266
Delphi 7应用教程
供了一个TMediaPlayer组件,利用该组件不但能够对波形声音、MID音乐、视频等媒体文件进行播放和控制,而且能够控制多种多媒体设备。TMediaPlayer组件位于System选项卡中,如图13-1所示。
图13-1 TMediaPlayer组件
另外Delphi 7还提供了一个控制多个图片连续播放的动画组件——TAnimate,该组件位于Win32选项卡中,如图13-2所示。
图13-2 TAnimate组件
13.1.2 TAnimate组件的使用
1.TAnimate组件的常用属性
l Active属性:用于设置是否播放动画。值为True时,表示播放动画,值为False时,表示没有播放。 l AutoSize属性:用于决定TAnimate组件的大小是否随着播放的动画图像的大小而改变,取值为True时,其大小随着动画图像的大小而自动改变,取值为False时,大小不改变。
l Center属性:用于设置播放的动画图像是否在TAnimate 组件的。值为True时,表示播放的动画图像在TAnimate组件的,值为False时,表示播放的动画图像在TAnimate组件的左上部分。
l FileName属性:用于指明要播放的AVI的文件名(包括文件所在的路径)。如果设置了FileName属性的值,那么CommonAVI会自动指定为aviNone。注意:该组件只能播放无声AVI文件。
l CommonAVI属性:用于设定播放Windows自带的AVI动画,Windows自带了一些和文件操作有关的AVI动画,如文件的删除、复制等。该属性的取值及含义如表13-1所示。
表13-1 Commonavi属性的取值及其含义
属 性 值
aviNone aviCopyFile aviCopyFiles aviDeleteFile
含 义
不指定AVI文件,使用Filename中指定的AVI文件来播放 播放复制文件的AVI文件 播放复制多个文件的AVI文件 播放直接删除文件的AVI文件
第13章 多媒体应用程序开发
267
续表
属 性 值
aviEmptyRecycle aviFindComputer aviFindFile aviFindFolder aviRecycleFile
播放清空回收站的AVI文件 播放搜索计算机的AVI文件 播放搜索文件的AVI文件 播放搜索文件夹的AVI文件 播放删除文件到回收站的AVI文件
含 义
l StartFrame属性:用于设置从哪一帧开始播放,如果设置为1,表示从第一帧开始,默认值为1。
l StopFrame属性:用于设置播放到动画的哪一帧结束,如果该属性值大于AVI文件中的总帧数,将播放到文件结束。 l FrameCount属性:用于表示播放的AVI动画文件的总帧数,为只读属性。 l Repetitions属性:用于设置重复播放AVI文件的次数。默认值为0,表示无地播放。此时可通过把Active属性设为True来播放动画。
l Transparent属性:用于设置播放背景是否为透明的。值为True(默认)时,播放背景透明,值为False时,播放背景不透明。
2.TAnimate组件的常用方法
(1)Play方法:用于播放AVI文件。语法格式及功能如下。 [格式]:
procedure Play(FromFrame, ToFrame: Word; Count: integer);
[功能]:播放AVI文件中的若干帧。其中参数FromFrame表示播放的起始帧,ToFrame表示播放的结束帧,FromFrame的值应小于ToFrame的值。Count表示播放次数。
(2)Seek方法:用于定位到AVI动画文件的某一帧。语法格式及功能如下。 [格式]:
procedure Seek(Frame: SmallInt);
[功能]:定位到AVI动画文件的某一帧,参数Frame表示要定位到的帧数。
(3)Reset方法:用于把StartFrame属性和StopFrame属性恢复成初始值。语法格式及功能如下。
[格式]:
procedure Reset;
[功能]:把StartFrame属性和StopFrame属性恢复成初始值。 (4)Stop方法:用于终止AVI文件的播放。语法格式及功能如下。 [格式]:
procedure Stop;
[功能]:终止AVI文件的播放。
【例13-1】 利用TAnimate组件播放Windows的预设动画。要求能够任意选择要播放
268
Delphi 7应用教程
的预设动画种类,并能够设置是否循环播放。程序运行的界面如图13-3所示。
图13-3 程序运行界面
【实现分析】
使用一个下拉式列表框列出Windows的所有预设动画,程序运行时可通过从下拉式列表框中选中一种预设动画,并通过复选框来设置是否循环播放,然后单击【播放】按钮即可播放。需要注意的是,从列表框中选中的值是字符串型的,必须转换成相应的常数才能赋值给TAnimate组件的CommonAVI属性。为便于转换,可在组合框的每个选项之前加上一个编号字符,在转换的时候通过函数分离出该编号字符,再根据它把相应的预设动画赋值给TAnimate组件的CommonAVI属性。播放动画时可通过把它的Active属性值设置为True来实现。
【界面设计】
本例组件对象及其属性设置如表13-2所示。
表13-2 例13-1组件对象及其属性设置
对 象 名 Label1
属 性 名 Caption Font.Size AutoSize Items
ComboBox1
Style
Animate1 Button1 CheckBox1
CommonAVI Caption Caption
16 False '1-aviCopyFile' '2-aviCopyFiles' '3-aviDeleteFile' '4-aviEmptyRecycle' '5-aviFindComputer' '6-aviFindFile' '7-aviFindFolder' '8-aviNone' '9-aviRecycleFile' 'csDropDown' aviFindFolder '播放' '重复播放'
设置组合框中显示的选项
组合框为下列式列表框 设定播放的默认动画 单击它将播放选定的动画 用来设置是否循环播放
属 性 值
'请选择播放种类'
说 明
【程序代码】
procedure TForm1.Button1Click(Sender: TObject); begin
if checkBox1.Checked then
Animate1.Repetitions :=0
第13章 多媒体应用程序开发
else
Animate1.Repetitions :=1;
case Strtoint(Copy(combobox1.Text,1,1)) of 1: Animate1.CommonAvi:=aviCopyFile; 2: Animate1.CommonAvi:=aviCopyFiles; 3: Animate1.CommonAvi:=aviDeleteFile; 4: Animate1.CommonAvi:=aviEmptyRecycle; 5: Animate1.CommonAvi:=aviFindComputer; 6: Animate1.CommonAvi:=aviFindFile; 7: Animate1.CommonAvi:=aviFindFolder; 8: Animate1.CommonAvi:=aviRecycleFile; end;
Animate1.Active :=True; end;
procedure TForm1.FormCreate(Sender: TObject); begin
ComboBox1.Text :='1-aviCopyFile'; end;
269
13.1.3 TMediaPlayer组件的使用
1.TMediaPlayer组件概述
通过TMediaPlayer组件可以对多媒体文件和多媒体设备进行控制,TMediaPlayer组件由一系列的按钮组成,如图13-4所示。
Play Stop Prev Back Eject
Pause Next Step Record
图13-4 TMediaPlayer组件及其按钮组成
TMediaPlayer组件各按钮的功能如表13-3所示。
表13-3 TMediaplayer组件按钮及其功能
按 钮 名 称 Play Pause Stop Next Prev Step
Btplay Btpause Btstop Btnext Btprev Btstep
值
播放媒体文件 暂停或恢复播放或录制 停止媒体文件的播放 跳到下一个磁道或者文件 跳到前一个磁道或者文件 前进一个小段
功 能
续表
270
按 钮 名 称 Back Record Eject
Btback Btrecord Bteject
值
Delphi 7应用教程
功 能
后退一个小段 开始录制
弹出(释放媒体文件)
2.TMediaPlayer组件的常用属性
l AutoEnable属性:该属性是一个Boolean型属性,其值为True(默认值)时,媒体播放器可以根据Mode属性指定的当前模式和DeviceType属性指定的当前设备类型来确定哪些按钮可以使用。
注意:该属性值的设置优先于EnableButton属性的设置。
l AutoOpen属性:用于确定当应用程序运行时,媒体播放器是否自动打开媒体设备。值为True(默认值)时,在运行时可自动打开由DeviceType属性指定的多媒体设备(或若DeviceType为dtAutoSelect则打开由FileName属性指定的文件);值为False时,则必须调用Open方法来打开设备。在打开设备时若出现错误,则出现类为EMCIDeviceError的意外处理。
l AutoRewind属性:该属性为Boolean型属性,用于设置在多媒体文件播放完毕以后,是否自动返回到起点。值为True(默认值)时,多媒体文件播放结束时能够自动返回到起点并重新开始播放。
l DeviceType属性:用于设置要打开的多媒体设备的类型。它的默认值为dtAutoSelect,即在程序运行时根据打开的多媒体文件(由FileName属性决定)的扩展名来确定文件的类型;若扩展名没有与之相关联的设备,则必须设置该属性来指定正确的设备类型。该属性的取值及含义如表13-4所示。
表13-4 DeviceType属性的取值及其含义
属 性 值 dtAutoSelect dtAVIVideo dtCDAudio dtDAT dtDigitalVideo dtMMMovie dtOther dtOverlay dtScanner dtSequencer dtVCR dtVideodisc dtWaveAudio
属 性 含 义
根据要播放的多媒体文件名自动检测设备的类型
打开AVI视频文件,该文件包括音频和视频,驱动程序为AVI Video plav CD唱盘,驱动程序为CD Audio Player,一般从CD-ROM驱动器中播放 数字音频磁带,驱动程序为Digital Audio Tape Player
数字视频(AVI、MPG、MOV文件),驱动程序为Digital Audio Player for Windows 多媒体电影格式,驱动程序为MM Move Player 其他未确定的多媒体设备 模拟视频
与PC机相连的扫描仪
乐器数据化设备(播放MIDI文件),驱动程序为MIDI Sequencer for Windows 与PC机相连的录像机 与PC机相连的视频播放机
波形音频,用来打开和播放WAV文件
l Display属性:用于指定一个窗口作为多媒体文件的输出屏幕。该属性的默认值为Nil,
此时媒体播放器自动打开一个窗口用来显示输出。也可以把其他组件名(如Panel组件)
第13章 多媒体应用程序开发
271
赋值给该属性,从而实现在其他组件的窗口中播放视频。 l EnabledButtons属性:用于设置多媒体播放器组件中哪些按钮是有效的,哪些是无效的。它可以对九个按钮中的任何一个按钮进行设置。
l FileName属性:用于为多媒体播放设备指定一个待播放的多媒体文件名。如果是录制文件,指定的是保存文件的文件名。主要用来设置三类文件:音波文件(.WAV)、数字化音乐文件(.MID)和视频文件(.AVI)。
l Visible属性:用于决定TMediaPlayer组件是否可见,默认值是True,表示是可见的。 l VisibleButtons属性:用于决定TMediaPlayer组件中的各个按钮是否可见,可设置每个按钮的可见状态。
l Mode属性:用于返回多媒体设备的当前状态。其取值及其含义如表13-5所示。
表13-5 Mode属性值及含义
属 性 值 mpNotReady mpStopped mpPlaying mpRecording mpSeeking mpPaused mpOpen
属 性 含 义 多媒体设备未准备好 多媒体设备处于停止状态 多媒体设备处于播放状态 多媒体设备处于录制状态 多媒体设备处于搜索状态 多媒体设备处于暂停状态 多媒体设备处于打开状态
l Notify属性:用于决定当一个多媒体控制方法(比如Open、Play等)完成以后,是否响应下一个多媒体方法。若它的值为True,表示接受下一个多媒体控制方法,并触发onNotify事件;若它的值为False,表示不接受下一个多媒体控制方法,也不会触发onNotify事件。 l NotifyValue属性:用于表示上一个控制命令的执行情况。它的取值详见表13-6。
表13-6 NotifyValue属性的值及含义
属 性 值 Nvsuccessful NvSuperseded Nvaborted NvFailure
属 性 含 义 控制命令成功
控制命令被其他的命令所代替 控制命令被用户所终止 控制命令失败
l TimeFormat属性:用于设置描述时间的格式,该属性是一个运行属性。它的取值及其含义如表13-7所示。其中两个比较重要的值是:“tfMillisecond”表示多媒体时间计量单位为毫秒;“tfFrames”表示多媒体时间计量单位为帧。
272
Delphi 7应用教程
表13-7 TimeFormat属性的值及含义
属 性 值 tfMilliseconds tfHMS tfMSF tfFrames tfSMPTE24 tfSMPTE25 tfSMPTE30 tfSMPTE30Drop tfBytes tfSamples tfTMSF
毫秒
小时、分种和秒
分种、秒和帧数时间存储格式 帧数
小时、分钟、秒、基于每秒24帧的帧数 小时、分钟、秒、基于每秒25帧的帧数 小时、分钟、秒、基于每秒30帧的帧数 小时、分钟、秒、基于每秒30帧的Drop帧数 字节数 取样数
音轨、分钟、秒和帧数
属 性 含 义
l Tracks属性:用于表示CD音乐总轨数。 l TrackLength属性:用于表示音乐轨的长度。
l TrackPosition属性:用于表示当前音乐轨的播放位置。 l Length属性:用于表示播放媒体的总长度。长整型。 l Position属性:用于表示媒体当前的播放位置。长整型。
l Wait属性:该属性为Boolean类型,用于决定是否当媒体控制方法执行结束后,才将控制权交给应用程序。当这个属性设置为True时,必须等到媒体控制方法执行结束后,才将控制权交给应用程序;当这个属性设置为False时,程序不等前面一个媒体控制方法执行完就继续执行下面的程序代码。
l Frames属性:用于确定调用Back或Step方法时,前进或后退的帧数。
3.TMediaPlayer组件的常用方法
TMediaPlayer组件的常用方法及其作用如表13-8所示。
表13-8 TMediaPlayer组件的常用方法及其作用
名 称 Next Open Pause Previous Stop Play Back Rewind Close StartRecording Eject
作 用
跳到下一个轨道的开始,如果媒体不用轨道,将跳到媒体的结尾 打开多媒体设备 暂停多媒体设备
跳到前一个轨道的开始,如果媒体不用轨道,将跳到媒体的开始 停止多媒体设备的播放 播放多媒体文件或轨道
在当前打开的媒体中,向后移动一定数量的帧,移动的帧数由Frames属性决定 回到播放的起点 关闭多媒体设备 开始录制
弹开多媒体设备,并释放媒体
第13章 多媒体应用程序开发
273
续表
名 称 Step Resume Save
作 用
在当前打开的媒体中,向前移动一定数量的帧,移动的帧数由Frames属性决定 恢复暂停的多媒体播放或记录操作 保存已经打开的媒体信息
4.TMediaPlayer组件的常用事件
TMediaPlayer组件能够响应OnClick、OnPostClick、OnEnter、OnExit、OnNotify等多种事件,下面重点介绍OnNotify事件的使用。
当Notify属性设置为True时,每当多媒体控制方法(如前面所讲的Open,Save,Back,Close,Eject,Pause等方法)完成以后,就会产生OnNotify事件。
注意:在响应了OnNotify事件以后,Notify属性必须重新设置为True,以便系统再次产生OnNotify事件。
【例13-2】 编写一个波形音频文件的播放程序。程序的设计界面如图13-5所示。程序运行时,如图13-6所示。单击【打开】按钮将出现一个打开对话框,供用户选择一个波形音频文件。选择文件名后单击【播放】按钮将播放该波形音频文件。
图13-5 例13-2程序设计界面 图13-6 例13-2程序运行界面
【实现分析】
通过一个打开对话框组件来选择文件,选择文件的文件名保存在打开对话框组件的FileName属性中,然后可把这个FileName属性值赋值给TMediaPlayer组件的FileName属性,从而使MediaPlayer组件能够播放该文件。一般情况下给TMediaPlayer组件的FileName属性赋值前先关闭多媒体设备,赋值后再打开多媒体设备。播放可以通过调用TMediaPlayer组件的Play方法来实现。
【界面设计】
本例组件对象及其属性设置如表13-9所示。
表13-9 例13-2组件属性设置及组件作用
对 象 名 MediaPlayer1 OpenDialog1 Button1 Button2
属 性 名 Visible DeviceType Filter Caption Caption
属 性 值 False dtAutoSelect ' WAV文件|*.WAV' '打开' '播放'
选择要播放的波形音频文件
单击它将出现打开对话框供用户选择一个波形音频文件 单击它将播放选择的波形音频文件 播入选择的波形音频
作 用
274
【程序代码】
主要程序代码如下:
Delphi 7应用教程
procedure TForm1.FormCreate(Sender: TObject); var
Curdir:string; //存放应用程序所在目录的目录名 begin
GetDir(0,CurDir); //获取应用程序所在的当前目录的目录名 MediaPlayer1.FileName :=CurDir+'\\W1.wav'; //形成要播放的默认路径名 MediaPlayer1.Open ; //打开多媒体设备 end;
procedure TForm1.Button1Click(Sender: TObject); begin
OpenDialog1.Execute ; //显示打开对话框 if Opendialog1.FileName='' then //如果没有选择文件 ShowMessage('你没有选择声音文件') //提示 else
begin
MediaPlayer1.Close; //先关闭多媒体设备
MediaPlayer1.FileName:=OpenDialog1.FileName ; //设置要播放的多媒体文件名 MediaPlayer1.Open; //打开多媒体设备 end; end;
procedure TForm1.Button2Click(Sender: TObject); begin
MediaPlayer1.Play ; //播放多媒体文件 end;
13.2 典型实例
13.2.1 典型实例一
【实例题目】:唐诗朗诵程序的设计
编写一个选择唐诗并朗读的多媒体程序。程序的设计界面如图13-7所示。程序运行时,当鼠标移动到相应的唐诗标题上时,标题将出现背景色,如图13-8所示。此时若单击该唐诗标题将朗诵该唐诗。单击【退出】按钮将退出该程序的运行。
【实现方法】
当单击相应标签时,播放相应的唐诗,唐诗的录音必须是已经存放好的WAV文件,本题的文件名分别为1.WAV,2.WAV,3.WAV和4.WAV等。当发生相应标签的Click事件时,应首先关闭多媒体设备,然后把相应的唐诗文件名赋值给MediaPlayer1的Filename属性,然后调用MediaPlayer1的Open方法打开多媒体文件,最后再调用MediaPlayer1的Play方法播放该文件。另外背景色是否显示可通过设置标签组件的Transparent属性来实现。
第13章 多媒体应用程序开发
275
图13-7 程序设计界面 图13-8 程序运行界面
【界面设计】
本例组件属性设置及组件作用如表13-10所示。
表13-10 窗体及组件的属性设置
对 象 名
Color
Label1
Font.Size Transparent Autosize Caption Color
Label2
Font.Size Transparent Autosize Caption Color
Label3
Font.Size Transparent Autosize Caption Color
Label4
Font.Size Transparent Autosize
MediaPlayer1 Button1
Visible Caption
属 性 名 Caption
设 置 值 '咏 鹅' clNavy 14 True False '春 晓' clNavy 14 True False '春夜喜雨' clNavy 14 True False '登鹳鹊楼' clNavy 14 True False False '退出'
播放唐诗
单击它退出应用程序
显示唐诗名,单击它播放相应唐诗 显示唐诗名,单击它播放相应唐诗 显示唐诗名,单击它播放相应唐诗 显示唐诗名,单击它播放相应唐诗
对 象 作 用
【程序代码】
var
Form1: TForm1; cdir:string; implementation {$R *.dfm}
procedure TForm1.Label1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
//存放当前目录
276
begin
Delphi 7应用教程
Label1.Transparent :=False; //设置Label1标签不透明 end;
procedure TForm1.Label2MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin
Label2.Transparent :=False; //设置Label2标签不透明 end;
procedure TForm1.Label3MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin
Label3.Transparent :=False; //设置Label3标签不透明 end;
procedure TForm1.Label4MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin
Label4.Transparent :=False; //设置Label4标签不透明 end;
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin
Label1.Transparent :=True; //把所有标签组件的属性均设为透明 Label2.Transparent :=True; Label3.Transparent :=True; Label4.Transparent :=True; end;
procedure TForm1.FormCreate(Sender: TObject); begin
getdir(0,Cdir); //得到当前目录 end;
procedure TForm1.Label1Click(Sender: TObject); begin
MediaPlayer1.Close ; //关闭多媒体设备 mediaplayer1.FileName:=cdir+'\\1.wav'; //形成要播放的WAV文件名 mediaplayer1.open; //打开多媒体设备 mediaplayer1.play; //播放唐诗 end; ……
//以下省略了Label2Click、Label3Click、Label4Click事件代码,它们的作用与Label1Click类似 procedure TForm1.Button1Click(Sender: TObject); begin
mediaplayer1.Close ; //关闭多媒体设备 application.Terminate ; //关闭应用程序 end;
第13章 多媒体应用程序开发
277
13.2.2 典型实例二
【实例题目】:视频文件播放控制器
编写一个视频文件播放控制程序,程序的设计界面如图13-9所示,程序的运行界面如图13-10所示。程序运行时,单击【打开】按钮将出现一个打开对话框让用户选择一个视频文件,单击相应的按钮将实现相应的操作。有两点需要注意:一是在单击【暂停】按钮暂停播放时,【暂停】按钮的标题变为“恢复”,再单击该按钮将恢复视频文件的播放;二是单击【前进】或【后退】按钮时,视频文件将前进或后退5帧。
图13-9 程序设计界面 图13-10 程序运行界面
【实现方法】
可使用一个TOpenDialog对话框组件来选择文件,使用Open方法来打开多媒体设备,使用Play方法播放多媒体文件,使用Stop方法来停止多媒体设备的播放。为实现“前进”和“后退”5帧的功能,可把TMediaPlayer组件的Frames属性设置为5,然后调用Step或Back方法。
【界面设计】
本例组件属性设置及组件作用如表13-11所示。
表13-11 组件属性设置及组件作用
对 象 名 MediaPlayer1 Panel1 OpenDialog1 Button1 Button2 Button3 Button4 Button5 Button6 Button7
属 性 名 Visible Caption Filter Caption Caption Caption Caption Caption Caption Caption
设 置 值 False ''
'*.AVI|*.AVI' '打开' '播放' '前进' '后退' '暂停' '停止' '结束'
播放视频文件
作为视频文件播放的窗口 用来选择视频文件
选择视频文件并打开多媒体设备 播放视频文件 前进5帧 后退5帧
暂停或恢复视频文件的播放 停止视频文件的播放 结束当前应用程序
对 象 作 用
278
【程序代码】
Delphi 7应用教程
procedure TForm1.FormCreate(Sender: TObject); var
Curdir:string; begin
GetDir(0,CurDir);
MediaPlayer1.FileName :=Curdir+'\\A2.AVI'; //设置默认播放的视频文件名 MediaPlayer1.Display :=Panel1; MediaPlayer1.Open;
OpenDialog1.InitialDir :=CurDir; //设置打开对话框的初始目录 end;
procedure TForm1.Button1Click(Sender: TObject); begin
OpenDialog1.Execute; //调用打开对话框 MediaPlayer1.Stop; //停止播放
MediaPlayer1.FileName:=OpenDialog1.FileName; //设置播放的文件名 MediaPlayer1.Frames :=5; //设置前进或后退的帧数 MediaPlayer1.Display:=Panel1; //设置视频文件的播放窗口 MediaPlayer1.Open; //打开多媒体设备 end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin
MediaPlayer1.Stop; //停止多媒体设备的播放 MediaPlayer1.Close; //关闭多媒体设备 end;
procedure TForm1.Button2Click(Sender: TObject); begin
MediaPlayer1.Play; //播放 end;
procedure TForm1.Button5Click(Sender: TObject); begin
if Button5.Caption = '暂停' then begin
MediaPlayer1.Pause; //暂停播放 Button5.Caption :='恢复'; end else
begin
MediaPlayer1.Resume ; //恢复播放 Button5.Caption :='暂停'; end; end;
procedure TForm1.Button3Click(Sender: TObject); begin
MediaPlayer1.Step ; //前进若干帧
第13章 多媒体应用程序开发
end;
procedure TForm1.Button4Click(Sender: TObject); begin
MediaPlayer1.Back; end;
procedure TForm1.Button6Click(Sender: TObject); begin
MediaPlayer1.Stop; end;
279
//后退若干帧
//停止播放
13.3 上机练习
13.3.1 上机练习一
【练习题目】:为唐诗朗诵程序添加背景音乐
在典型实例一的基础上增加播放背景音乐的功能:要求背景音乐可以选择,并且可以循环播放。程序的设计界面如图13-11所示,程序的运行界面如图13-12所示。程序运行时单击【选择背景音乐】按钮,将出现一个【打开】文件对话框让用户选择背景音乐文件,选择过后将自动进行背景音乐的播放,并且背景音乐能够循环播放。
图13-11 程序设计界面 图13-12 程序运行界面
【要点提示】
该上机练习有两个要点。
(1)WAV文件和MID文件的同时播放。由于WAV和MID文件使用的是不同的多媒体设备,因此它们能够同时播放。但一般情况下不能同时播放两个WAV文件或两个MID文件。
(2)背景音乐的循环播放。TMediaPlayer组件有一个重要事件OnNotify,该事件在命令执行成功、失败或中止时均会发生,并可以通过TMediaPlayer组件的NotifyValue属性来判断用户命令执行的情况。为使MID文件能够循环播放,可先设置TMediaPlayer的AutoRewind属性和Notify属性的值均为True,然后在OnNotify事件中,判断命令是否正常结束,如果正常结束且媒体已经播放到文件尾,则再从头开始播放。
【参考代码】
在典型实例一的基础上增加一个MediaPlayer2组件,用来循环播放背景音乐。增加的参
280
考程序代码如下:
Delphi 7应用教程
procedure TForm1.FormCreate(Sender: TObject); begin
getdir(0,Cdir);
Mediaplayer2.Notify :=true ;
Mediaplayer2.Filename:=cdir+'\\1.mid'; //形成默认的背景文件 Mediaplayer2.Open ; //打开播放背景音乐的多媒体设备 Mediaplayer2.Play ; //播放背景音乐 end;
procedure TForm1.Button2Click(Sender: TObject); begin
Opendialog1.Execute ; //弹出打开对话框 Mediaplayer2.Close ; //关闭背景音乐的播放 if (length(Opendialog1.FileName )<>0) then //如果选了文件名 Mediaplayer2.Filename:=Opendialog1.FILENAME; //设置播放的背景音乐文件名 Mediaplayer2.Open; //打开播放背景音乐的设备 Mediaplayer2.Play; //播放背景音乐 end;
procedure TForm1.MediaPlayer2Notify(Sender: TObject); begin
if MediaPlayer2.NotifyValue =nvSuccessful then //如果命令执行成功 begin
MediaPlayer2.Position :=0; //从头开始进行播放 MediaPlayer2.Notify :=True; Mediaplayer2.Play; //播放 end; end;
13.3.2 上机练习二
【练习题目】:显示视频文件的播放进度
对典型实例二进行改造,使它能够显示出视频文件的播放进度。程序的设计界面如图13-13所示,程序的运行界面如图13-14所示。程序运行时将在一个进度条中显示视频文件播放的进度。
【要点提示】
为了能够显示多媒体文件的播放进度,可以使用一个TProgressBar组件和一个TTimer组件。在多媒体文件播放前把TProgressBar的Min属性值设置为0、Max属性值设置为多媒体文件的长度(TMediaPlayer组件的Length属性值),然后在时钟组件的Timer事件中用TMediaPlayer组件的当前播放位置(Position属性值)去更新TProgressBar组件的Position属性值即可。
第13章 多媒体应用程序开发
281
图13-13 程序设计界面 图13-14 程序运行界面
【参考代码】
procedure TForm1.Timer1Timer(Sender: TObject); begin
//用MediaPlayer1.Position属性更新ProgressBar1.Position的属性值 ProgressBar1.Position :=MediaPlayer1.Position ; end;
procedure TForm1.Button1Click(Sender: TObject); begin
OpenDialog1.Execute;
MediaPlayer1.Stop;
MediaPlayer1.FileName:=OpenDialog1.FileName; MediaPlayer1.Frames :=5; MediaPlayer1.Display:=Panel1; MediaPlayer1.Open; ProgressBar1.Min :=0;
//设置进度条的Min属性值为0
ProgressBar1.Max :=MediaPlayer1.Length ; //设置进度条的Max属性值为多媒体文件的长度 end;
procedure TForm1.Button3Click(Sender: TObject); begin
MediaPlayer1.Step ;
//用MediaPlayer1.Position属性更新ProgressBar1.Position的属性值 ProgressBar1.Position :=MediaPlayer1.Position ; end;
procedure TForm1.Button4Click(Sender: TObject); begin
MediaPlayer1.Back ;
//用MediaPlayer1.Position属性更新ProgressBar1.Position的属性值 ProgressBar1.Position :=MediaPlayer1.Position ;
282
end;
Delphi 7应用教程
课后考场
一、选择题(20分,每题5分)
1.要使TAnimate组件播放动画,只需把它的________属性设置为True即可。 A.Active B.AutoSize C.Center D.Play 2.通过TMediaPlayer组件的________属性可以设置要打开的多媒体设备的类型。 A.DeviceType B.AutoRewind C.Mode D.FileName 3.通过TMediaPlayer组件的________属性可以获知上一个控制命令的执行情况。
A.Mode B.Notify C.NotifyValue D.Wait 4.要使TMediaPlayer组件暂停播放或录制,应调用它的________方法。 A.Pause B.Stop C.Eject D.Step 二、填空题(40分,每空5分)
1.多媒体技术的两个最重要特点是________和________。
2.要使TAnimate组件播放某个AVI文件,应把它的________属性设置为AVI文件名。 3.要使TAniamte组件从动画的第5帧开始播放,需把它的________属性设置为5。 4.要使TMediaPlayer组件在播放视频时播放的窗口是Panel1,应把它的________属性设置为Panel1。
5.在用TMediaPlayer组件播放视频时,可以使用它的________属性获取当前播放的位置。使用它的________属性可以获取媒体文件的总帧数。
6.当把Notify属性值设置为True时,每当多媒体控制方法完成以后,就会产生________事件。
三、程序设计题(40分,每题20分)
1.编写一个能够播放视频和背景音乐的程序。视频和背景音乐可以由用户自己来选择。 2.编写一个CD播放器程序。播放器的设计界面如图13-15所示。
图13-15 CD播放器的设计界面
第14章 数据库应用开发
本章要点
þ 数据库的基本概念
þ Delphi中的Database Desktop应用程序的使用 þ TTable组件的常用属性、方法、事件及其使用 þ TQuery组件的常用属性、方法、事件及其使用 þ 常用的数据控制组件 þ SQL语言编程
14.1 理论知识
14.1.1 数据库的基本概念
目前,人类社会已经进入了信息社会,用“信息爆炸”来描述这个社会的信息之多并不过分。对于非专业人员来说,没有必要区分信息和数据的概念,通常所说的信息处理也可以看成是数据处理,用计算机进行数据处理已经成为很多行业日常工作不可缺少的一个环节。数据库技术可以简单地理解为最新的数据处理技术,它已经深入到我们生活的方方面面。
1.数据库
所谓数据库(Database,DB)其实就是存放在计算机的外存储器中的相关数据的集合,它是通过文件或类似于文件的数据单位组织起来的。数据库只是数据的集合,建立数据库的目的是为了使用数据库,为了对数据库中的数据进行存取,必须通过数据库管理系统(Database System Management,DBMS)。数据库管理系统是对数据进行管理的软件,是数据库系统的核心,数据库的一切操作,包括数据库的建立、数据的检索、修改、删除等操作,都是通过数据库管理系统来实现的。数据库管理系统只提供对数据的管理功能,为了实现某种具体的功能,必须要有相应的数据库应用程序。正是由于数据库应用程序的不同,才使数据库应用丰富多彩。例如,某单位的人事管理系统和财务管理系统均是由同一种数据库管理系统来完成的,但它们实现的功能是不一样的,原因就是它们的数据库应用程序不一样。
日常生活中见到的能够使用的与数据库有关的计算机系统均可认为是数据库系统。所谓数据库系统是指实际可运行的,按照数据库方式存储、维护和向应用系统提供数据或信息支持的计算机系统。它是在计算机系统中引进数据库后的系统构成,一个完整的数据库系统还应包括数据库管理员(Database Administrator,DBA),所谓数据库管理员是指一组熟悉计算机数据处理业务、负责设计和维护数据库的技术人员。
284
Delphi 7应用教程
因此一个完整的数据库系统由数据库、数据库管理系统、数据库应用程序、计算机软件和硬件系统及DBA组成。
2.数据模型与关系数据库
数据库中的数据是按照一定的数据模型组织的,数据模型是把现实世界转换为计算机能够处理的数据世界的桥梁。目前常用的数据模型有三种,分别是层次模型、网状模型和关系模型。由于层次模型和网状模型需要较深的数学基础,所以使用它们的人并不多,最常用的数据模型是关系模型。
在关系模型中,数据被组织成若干二维表的结构,每一个二维表称为一个关系或表。表中的一行称为一个元组,在计算机中存放则称为记录。表中的一列称为属性,在计算机中存放就是字段。关系的构成如图14-1所示。
图14-1 关系的构成
通常所说的关系数据库由相关的多个表组成。如要管理学生成绩,可做一个数据库,该数据库可由两个表组成:一个表用来存放学生的基本数据,如学号、姓名、年龄、年级、专业等信息;另一个表用来存放学生的选课信息,如学生学号、所选课的课号、选课的成绩等信息。
通过对表的分析,可得到下列有关表的性质: (1)表中的每一列均不可再分;
(2)表中的每一列数据的数据类型是相同的; (3)表中的两列不能取相同的名字;
(4)表中不允许有完全相同的两行,即任两条记录必须能够区分; (5)交换行和列的顺序,不改变表的含义。
在关系数据库管理系统中,要建立一个数据库通常要经过以下几个步骤: (1)建立数据库文件,数据库文件通常用来容纳各个表;
(2)建立表的结构,即建立表的各个字段的字段名、字段类型、字段宽度等; (3)向表中录入实际的数据。
14.1.2 利用数据库桌面创建数据库
1.数据库桌面的作用
数据库桌面(Database Desktop)是Delphi 7自带的一个数据库管理工具,它的主要作用
第14章 数据库应用开发
285
如下。
(1)创建和维护数据库
数据库桌面应用程序可以直接创建和维护Paradox数据库,但不仅是用于创建Paradox表,几乎当前所有格式的数据库表均可以通过它来创建。但除了Paradox表以外,要创建其他格式的数据库表,计算机必须安装相应的数据库管理系统或驱动程序,否则在创建数据库表时将会出错。
使用数据库桌面时要特别注意区分数据库和数据库表的概念,数据库是数据库表的容器,对于Access数据库来说它是一个数据库文件,对于Paradox来说,它是一个容纳数据表的目录(文件夹)。数据库表是实际容纳数据的表格。
(2)维护数据库别名
可以把数据库别名理解为存放数据库表的容器,对于像Paradox这类的数据库,一个文件就是一个数据表,因此数据库别名就是指一个存放数据库表的路径。假设有若干个Paradox表存放在D:\\P1子目录下,就可以建立一个数据库别名(假设为PP),该别名与D:\\P1对应起来。一旦建立好了这种别名和路径或数据库名的对应关系,以后需要访问数据库表的时候,就不必再指定具体的路径或数据库名,只需指明别名就行了。
在数据库桌面应用程序中,可以实现别名的创建和删除等操作。 (3)创建SQL文件和执行SQL命令
SQL是结构化查询语言的英文缩写,利用它可以实现数据库的建立、维护和查询。利用数据库桌面应用程序可以创建和执行SQL文件。
2.数据库的建立
这里通过建立一个实际的通讯录数据库来介绍在Delphi中建立数据库的方法。根据对目前通讯录信息的分析,可设计将建立的通讯录表的结构,如表14-1所示。
表14-1 通讯录表的结构
字 段 名
好友号 姓名 好友类别 年龄 出生日期 通讯地址 邮政编码 电话号码 电子邮件 QQ号码 交往大事
Alpha Alpha Alpha Short Date Alpha Alpha Alpha Alpha Alpha Memo
字 段 类 型
8 10 10
系统默认为2 由系统指定 30 6 15 15 10 系统默认
字 段 宽 度
说 明
Alpha相当于字符型 短整型 日期型
备注型存放大量文字
Delphi的本地数据库为dBase数据库和Paradox数据库,利用Database Desktop可以很方便地创建这两类数据库表。创建一个Paradox数据库表的步骤如下:
(1)在“Database Desktop”应用程序中,执行【File】→【New】→【Table】命令,将
286
Delphi 7应用教程
会出现如图14-2所示的【Create Table】(创建表)对话框。在【Table type】列表框中可以选择表的类型。
(2)选择默认的类型“Paradox 7”,单击【OK】按钮,在弹出的对话框中可以定义表的结构,即表的每个
字段的字段名、字段类型、字段宽度和主键等,并可建
立索引,如图14-3所示。 图14-2 创建表对话框
(3)在【Field Name】列下面输入字段名,如“好友号”,然后在【Type】列下面单击鼠标右键,将会出现如图14-4所示的【字段类型】下拉菜单,在该菜单中选中类型“Alpha”,然后在【Size】列下面单击,输入字段宽度为8。关于字段类型的具体含义请参考有关Paradox数据库的书籍。如果要把“学号”字段设为主键,可在该行的【Key】列双击鼠标右键,这时将会出现一个“*”号,代表该列是主键。如果要取消主键,可再双击该处,“*”号将消失。
图14-3 创建表结构对话框 图14-4 【字段类型】下拉菜单
常用的数据类型及其含义如下。
l Alpha:字符串型,宽度为1~255,由用户自己定义。 l Number:数值型,宽度由系统自动指定。 l Date:日期型,宽度由系统自动指定。 l Logical:逻辑型,宽度由系统自动指定。 l Memo:备注型,一般用来存放长度超过255个字符的数据,宽度设置范围也是0~255,但是超过宽度范围部分的数据会自动存放到另外一个文件(*.MB)里。 l Graphic:图片型,用来存放二进制位图信息,宽度由系统自动指定。
(4)按Enter键把光标移到下一行,可接着创建下一个字段。依次创建多个字段,如图14-5所示。
(5)还可以为表创建“辅助索引”(Secondary Indexes),方法是在图14-3所示的创建表结构对话框中,在【Table Properties】列表框中选中“Secondary Indexes”,然后单击【Define】
第14章 数据库应用开发
287
按钮,将会出现【Define Secondary Index】(定义辅助索引)对话框,如图14-6所示。在该对话框中选中需要定义的索引字段,如“姓名”,然后单击
288
Delphi 7应用教程
(7)表结构创建好后,单击【Save as】按钮,将会出现如图14-8所示的【Save Table As】(保存表)对话框。可以通过选中数据库别名和选择保存文件夹两种方式确定数据库表保存的位置。这里选择保存位置为“D:\\DelphiApp\\14”,表名为“通讯录”,设置完成后单击【保存】按钮,表结构将保存起来。表结构创建完毕。
图14-8 保存表对话框
(8)数据库表的结构创建后,应向其中输入数据。首先应打开数据库表,方法是执行【File】→【Open】→【Table】命令,在出现的【Open Table】(打开表)对话框中找到相应的数据表“通讯录”,单击【打开】按钮,然后按下工具栏上的EditData
按钮,使该按钮处于弹起状态。从而结束数据的录入。
图14-9 输入了几条记录的通讯录表
3.数据库别名的建立
数据库别名有两种:公共别名(Public Alias)和项目别名(Project Alias)。本书只介绍公共别名,该别名保存在BDE配置文件IDAPI32.CFG中,在任何工作目录中都能访问,并且对任何使用BDE的应用程序都是可见的。
下面将通过为子目录“D:\\DelphiApp\\14”建立一个公共数据库别名App14来说明数据库别名的创建方法。创建步骤如下。
(1)在数据库桌面应用程序中执行【Tools】→【Alias Manager】命令,将会出现如图
第14章 数据库应用开发
2
14-10所示的【Alias Manager】(别名管理)对话框。
(2)单击【New】按钮以创建数据库别名。在【Database alias】列表框中输入数据库别名“APP14”,在【Driver type】列表框中选中“STANDARD”类型,此时将出现一个【Path】文本框,在该文本框中输入路径“D:\\DelphiApp\\14”,或单击【Browse】按钮,在弹出的【Directory Browser】(浏览目录)对话框中找到所需要的目录“D:\\DelphiApp\\14”,然后单击【OK】按钮,退出【Directory Browser】对话框。此时的【Alias Manager】对话框如图14-11所示。
图14-10 【Alias Manager】对话框 图14-11 新建数据库别名的【Alias Manager】对话框
(3)单击【Alias Manager】对话框上的【OK】按钮,系统将弹出如图14-12所示提示信息,询问用户是否将数据库别名保存到BDE配置文件IDAPI32.CFG中,单击【是】按钮即可。
图14-12 保存数据库别名提示信息
14.1.3 利用BDE组件开发数据库应用程序的模式
在Delphi中进行数据库应用程序的开发,大部分都可以通过组件来实现。利用BDE组件开发数据库应用程序一般要涉及三类组件:BDE组件、Data Access组件和Data Controls组件,这些组件的关系如图14-13所示。
图14-13 Delphi各类组件之间的关系
290
Delphi 7应用教程
1.BDE组件
BDE组件的作用是与实际的物理数据库建立联系,从物理数据库中提取信息,或把信息的修改存放到物理数据库中。该类组件又称数据集组件,都是非可视的组件。最常用的BDE组件有TTable、TQuery等。BDE组件直接与实际的物理数据库打交道,从物理数据库中提取信息构成数据集。BDE组件位于组件板上的BDE选项卡中,如图14-14所示。
图14-14 BDE选项卡
2.Data Access组件
Data Access组件位于Data Access选项卡中,该类组件是连接BDE(Borland Database Engine,Borland数据库引擎)组件和数据控制组件的桥梁,通常又称数据存取组件。该类组件中有一个非常重要的组件——TDataSource组件,该组件是用户使用最多的组件。在程序运行时,该类组件也是不可见的。
3.Data Controls组件
Data Controls组件位于Data Controls选项卡中,通过该类组件可以显示和修改数据库中的数据,常把它们称为数据控制组件。与BDE组件和Data Access组件不同的是,该类组件是可视化组件。常用的数据控制组件有:TDBGrid组件、TDBEdit组件、TDBNavigator等组件等。
14.1.4 TTable组件
TTable组件用于和物理数据表建立联系,以便应用程序可以存取数据库中的数据。该组件的属性、方法和事件很多,要掌握该组件功能,应首先掌握它的一些常用事件、属性和方法。
1.TTable组件的常用属性
(1)DatabaseName属性
该属性用于指定要连接的物理数据库的名字,可以是数据库别名、数据表文件所在的磁盘路径。通常给该属性赋值一个数据库别名,这样做的好处是当数据库存放的物理位置发生变化时,只需重新使用BDE设置数据库别名,而无需改变数据库应用程序。当在属性窗口中选中该属性时,在其后将出现下拉列表,列表中列出了当前系统已经建立的数据库别名,供用户选择。
(2)TableName属性
该属性用于设定TTable组件所操作的数据表名称,通常在DatabaseName属性设置后设置。设置了DatabaseName属性后,在属性窗口中选中TableName属性时,将会在其后出现一个列表框,该列表框中列出了相应数据库中的所有表,供用户选择。DatabaseName属性和TableName属性可以在设计阶段设置也可在程序运行过程中设置,但需要注意的是:要修改这两个属性的值,必须先把TTable组件的Active属性设置为False,否则这两个属性的值将
第14章 数据库应用开发
291
不能被修改。
(3)TableType属性
该属性用于设定与TTable组件相连接的数据库表的类型。当该属性设置成ttDefault时,数据库表类型由数据表文件的扩展名决定,扩展名与类型之间的关系如下。
l 扩展名为.db或没有扩展名,数据表的类型是Paradox表。 l 扩展名为.dbf时,数据表的类型是dBASE表。 l 扩展名为.txt时,表的类型是ASCII表。 (4)Active属性
该属性用于打开或关闭TTable组件形成的数据集合,是一个逻辑型属性。值为True时,表示数据集是打开的,可以对TTable组件连接的数据表中的数据进行操作;值为False时,表示数据集是关闭的,此时不可以对TTable组件连接的数据表中的数据进行操作。
(5)ReadOnly属性
该属性是逻辑型属性,用来决定TTable组件形成的数据集是否可以修改。值为True时,为只读,不能修改,值为False时,可以修改。
(6)Modified属性
该属性是一个只读属性,只能在程序运行中使用。该属性用于表示数据表中的数据是否被修改过。如果值为True,表示数据已被修改,如果值为False,则表示数据没有被修改。在程序中,一般可以通过Modified属性的值来判断当前数据库中的数据是否被修改,从而决定相应的操作。
(7)Fields属性
该属性是一个数组属性,它的每一个元素代表着数据集的一个字段,是Tfield类型的。Fields属性又称Fields集合。通过该属性可以访问数据集中的字段:Fields[0]代表第一个字段,Fields[1] 代表着第二个字段,依此类推。
注意:引用数据集合中的字段,还可以通过FieldByName方法来实现。 (8)Bof属性
该属性用于指示记录指针是否指向数据集的第一条记录。如果记录指针指向第一条记录,则Bof值为True,否则Bof值为False。该属性是只读属性。
(9)Eof属性
该属性用于指示记录指针是否指向数据集的最后一条记录。如果记录指针指向最后一条记录,则Eof值为True,否则Eof值为False。该属性是只读属性。
2.TTable组件的常用方法
(1)FieldByName方法
该方法用于引用数据集中的某个字段,该方法的函数形式如下:
Function FieldByName(Const FieldName:string):Tfield
其中,参数FieldName表示要引用的字段名,是一个字符型参数。该函数的返回值是一个Tfield对象,通过它可以返回指定字段的相关信息。
(2)记录指针移动方法
TTable组件是一种数据集组件,数据集中有一个记录指针,它指向的记录称当前记录。
292
Delphi 7应用教程
可以通过移动记录指针来改变当前记录,用户一般对当前记录进行操作。记录指针移动的相关方法如表14-2所示。
表14-2 TTable组件记录指针移动方法
记录指针移动方法 First方法 Last方法 Prior方法 Next方法
将记录指针移到第一条记录的位置 将记录指针移到最后一条记录的位置 将记录指针移到上一条记录的位置 将记录指针移到下一条记录的位置
将记录指针从当前记录开始向前或向后移到若干条记录,格式为: Function MoveBy(Distance:Integer):Integer;
参数Distance可以为正负整数,如果为正整数则指针向表尾方向移动Distance条记录,为负数则表示向表头方向移动Distance的绝对值条记录
功 能
MoveBy方法
(3)查询记录的相关方法
TTable组件提供了四种查询记录的方法,分别是GotoKey,GotoNearest,FindKey,FindNearest。其中,GotoKey和FindKey是用于精确查找,GotoNearest和FindNearest用于模糊查找。
使用这四种方法查找记录前,必须保证要查找的字段是关键字或者已经为它建立了辅助索引,并且保证TTable组件的属性中已经设置了关键字段名和辅助索引名,可以通过TTable组件的IndexFieldNames和IndexName属性进行选择。
① GotoKey方法:用于精确查找,使用该方法的步骤如下。 l 确保要查找的字段是关键字或已经为它定义了辅助索引,并保证TTable组件的属性列表中有关键字段名(IndexFieldNames)或辅助索引名(IndexName)。 l 通过调用SetKey方法,把要查找的TTable组件置成查找模式。 l 把查找值送进被查找的Field的查找缓冲区。
l 调用TTable组件的GotoKey方法,并测试它的返回值以判断查找是否成功。
该方法执行后,如果查找成功,GotoKey将返回True,并且表中的记录指针指向找到的记录。如果查找失败,GotoKey将返回False,表中的记录指针不发生变化。
需要注意的是,如何给Field的查找缓冲区赋值,由于字段对象是不可见的,因此在大多数情况下,要使用TTable组件的FieldByName方法到字段列表中查找字段对象以便为它赋值,当TTable组件处于查找模式时,只要把查找值赋给字段对象的AsString属性就可以了。AsString的作用不只是它的表面意思,它还是一个转换属性,任何赋给字段对象的AsString属性的字符串都将转换成该字段对象对应于数据库表中的字段的数据类型。但AsString不能将查找值转换成BLOB、Bytes、Memo和Graphic类型的数据。
GotoNearest方法用于不精确查找,是一个过程,没有返回值,它把记录指针定位于最接近于查找值的记录位置上。处理过程基本同GotoKey。
② FindKey方法:是实现精确查找的另一种方法,它和GotoKey一样均是一个函数过程,其格式如下:
function FindKey(const KeyValues: array of const): Boolean;
第14章 数据库应用开发
293
与GotoKey方法的区别在于:GotoKey不带参数,而FindKey带有参数,其参数就是要索引查找的值。FindKey接受的值是放在方括号中的用逗号分开的数组,数组中的每一个值都对应于特定列的查找值,即参数中允许有多个查找值,该方法允许用户同时查找数据库表中的多个列。
该方法执行后,如果查找成功,将返回True,并且表中的记录指针指向找到的记录。如果查找失败,将返回False,表中的记录指针不发生变化。
FindNearest方法用于不精确查找,是一个过程,没有返回值,它把记录指针定位于最接近于查找值的记录位置上。处理过程基本同FindKey。
(4)数据操作的相关方法
除实现数据表的浏览、查询外,TTable组件还有一个重要的功能就是进行数据维护,如实现记录的添加、删除和修改等操作。这些数据维护都是通过TTable组件的数据操作方法来实现的,常用的数据操作方法的名称和功能如表14-3所示。
表14-3 TTable组件的数据操作方法
数据操作方法名称 Append Insert Delete Edit Post Cancel Refresh EmptyTale
功 能 说 明
在数据表的末尾追加一条空记录,并将记录指针指向该记录 在当前记录之后插入一条空记录,并将记录指针指向该记录 删除当前记录,并将指针移向下一条记录
将数据表置于编辑状态,此时用户可以修改数据表中的数据 把对数据表数据的修改结果和新添加的数据保存到数据表中 取消对数据表中数据的修改和添加
根据数据表中的数据刷新界面,即重新从数据表中获取数据 将数据表清空,即删除数据表中的所有记录
注意:使用Post或Cancel方法之前,必须已经调用过Append方法或Insert方法。
3.TTable组件的常用事件
(1)Before事件
该类事件在相应的操作发生之前被触发,Before后通常跟相应操作的名称,事件名及其发生时机如表14-4所示。
表14-4 Before事件的发生时机及作用
事 件 BeforeCancel BeforeClose BeforeDelete BeforeEdit BeforeInsert BeforeOpen BeforePost
发生时机及作用
该事件在调用数据集的Cancel方法时,在取消操作发生之前触发,是调用Cancel方法发生的第一个动作 在关闭数据集之前发生,是在数据集关闭之前发生的第一个动作
该事件在调用数据集的Delete方法时,在删除操作发生之前触发,是调用Delete方法发生的第一个动作,通常用来对删除进行确认
该事件在调用数据集的Edit方法时,在把数据表置为编辑模式之前触发,是调用Edit方法发生的第一个动作
该事件在调用数据集的Append或Insert方法时,在插入或添加操作发生之前触发,是调用Append或Insert方法发生的第一个动作
在数据集被打开之前发生的第一个动作
该事件在调用数据集的Post方法时,在更新操作发生之前触发,是调用Post方法发生的第一个动作
294
Delphi 7应用教程
(2)After事件
该类事件在相应操作完成之后时触发,After后通常跟相应操作的名称,事件名及其发生时机如表14-5所示。
表14-5 After事件的发生时机
事 件 AfterCancel AfterClose AfterDelete AfterEdit AfterInsert AfterOpen AfterPost
在调用Cancel方法之后发生 在关闭数据集之后发生
在数据集调用Delete方法删除记录之后发生 在数据集调用Edit方法之后发生
在数据集对Insert或Append方法调用之后发生 在数据集被打开之后发生
在数据集调用Post方法保存数据之后发生
发生时机和作用
该类事件通常用于在某类操作完成过后给出提示信息。 (3)On事件
On事件在相应操作发生时发生,On后通常跟相应操作的名称,事件名及其发生时机如表14-6所示。
表14-6 On事件的发生时机
事 件 OnNewRecord OnFilterRecord
发生时机和作用
在添加一个新的记录时被触发。该事件在BeforeInsert事件之后发生,在AfterInsert事件之前发生 该事件当数据集过滤器处于激活状态(Filter属性为True)并且将记录指针移到其他记录时发生
14.1.5 TDataSource组件
TDataSource组件是使用最多的数据访问组件,用于连接数据集组件和数据控制组件。 TDataSource组件最重要的属性是DataSet属性。该属性指出要与哪一个数据集组件建立联系,它的属性值是某一个数据集组件的对象名称,如:TTable、TQuery等组件的名称。TDataSource组件通过DataSet属性与数据集组件建立连接后,数据控制组件就可以借助TDataSource组件与数据集组件(如DBEdit和DBGrid等组件)建立连接,这样就可以成功地访问数据库中的数据了。
14.1.6 Data Controls组件
在Delphi的组件板中有一个【Data Controls】选项卡,在该选项卡中集中了一些常用的数据控制组件,如图14-15所示。数据控制组件的名称前面都带有DB,大部分功能均类似于Delphi相应的标准组件,只不过它和数据库表或数据库表的字段绑定在一起而已。
1.TDBNavigator组件
TDBNavigator组件的形状及其上按钮的名称如图14-16所示。
第14章 数据库应用开发
295
图14-15 Data Controls选项卡中的数据控制组件
图14-16 TDBNavigator组件及其按钮名称
TDBNavigator组件中各种按钮的功能如表14-7所示。
表14-7 TDBNavigator组件各按钮的功能
按 钮 名 称 First Prior Next Last Insert Delete Edit Post Cancel Refresh
将数据集的记录指针移到第一条记录 将数据集的记录指针移到前一条记录 将数据集的记录指针移到后一条记录 将数据集的记录指针移到最后一条记录 在当前记录之后插入一条记录
删除当前记录,当ConfirmDelete属性设置为true时,会弹出删除确认对话框 使数据集处于编辑状态
把对数据集的修改(Insert或Edit),保存到实际的数据表中 取消对数据集的修改
根据数据表的内容,刷新数据组件中的数据
按 钮 功 能
2.TDBGrid组件
TDBGrid组件是用于显示和编辑数据库表中记录信息的重要组件。该组件以列表的形式
来显示数据库中的数据记录,它包含了数据的行和列。在网格中每一行代表数据集中的一行,每一列代表数据集中的一个字段。它的用法很简单,是最常用的数据控制组件之一。组件图标为
296
Delphi 7应用教程
的尺寸改变时,图像的尺寸也跟着改变。
7.TDBCheckBox组件
该组件有两个重要的属性:ValueChecked和ValueUnchecked。 l ValueChecked属性:该属性是字符串属性,当字段的内容与该属性值匹配时,该组件被选中。 l ValueUnchecked属性:该属性也是字符串属性,当字段的内容与该属性值匹配时,该组件被清除。
如果选用字段既不能和ValueChecked属性相匹配,也不能和ValueUnChecked属性相匹配,则TDBCheckBox会呈灰色状态。
如果选用字段本身是逻辑型的,则当选用字段为True时,TDBCheckBox就会呈现选中状态,而选用字段为False时,TDBCheckBox就会呈现为未选中状态。
8.TDBRadioGroup组件
该组件主要用于为单选按钮分组。当组中的一个单选按钮被选中时,同组的其他所有单选按钮均处于未被选中状态。经常使用的该组件的属性有三个:Columns、Items和Values。
(1)Columns属性:用于设置排列单选按钮的列数,默认值为1,表示以一列的形式显示单选按钮。用户可以设置成多列排列方式。
(2)Items属性:用于设置单选按钮显示的文字。选中该属性,单击其后的【…】按钮将会出现【String List Editor】对话框,用户在其中可以每行书写一个单选按钮的提示文字(有时也称单选按钮的名称)。
(3)Values属性:也是一个字符串列表,设置方法与Items属性一样。表示相应单选按钮的值。
TDBRadioGroup组件可确保用户为字段输入一个值,也可用来显示取值有限的字段。如果用户选中TDBRadioGroup中的一个单选按钮,它的Value属性的值就会传回底层数据库。Value属性和Items属性类型一样,都是字符串列表,而且其中的字符串是一一对应的。
【例14-1】 编写一个通讯录维护程序,程序的设计界面如图14-17所示,程序运行时单击TDBNavigator组件的相应按钮将对通讯录表实现相应的操作,程序运行界面如图14-18所示。
图14-17 程序设计界面 图14-18 程序运行界面
第14章 数据库应用开发
297
【实现分析】
可使用TTable组件和数据控制组件来维护和操作数据库中的内容,使用TTable组件和数据控制组件维护与操作数据库中数据的方法步骤如下。
(1)在界面上添加一个TTable组件,通过设置它的DatabaseName和TableName属性使它与某一个数据表联系在一起,然后把它的Active属性设置为True;
(2)在界面上添加一个TDataSource组件,设置它的DataSet属性值为步骤(1)中添加的TTable组件的名称,以便能够通过它访问数据库中的数据;
(3)在界面上添加数据控制组件,设置它的DataSource属性值为步骤(2)中添加的TDataSource组件的名称,设置它的DataField属性为要显示和设置的字段名称。
【界面设计】
根据图14-17所示为窗体添加TLabel组件并设置它们的Caption属性,以显示提示文字。其他组件对象及其属性设置如表14-8所示。
表14-8 例14-1的主要组件对象及其属性设置
对 象 名 Table1 DataSource1 DBEdit1 DBEdit2 DBEdit3 DBEdit4 DBEdit5 DBEdit6 DBEdit7 DBEdit8 DBEdit9 DBMemo1 DBNavigator1
属 性 名 DatabaseName TableName Active DataSet DataSource DataField DataSource DataField DataSource DataField DataSource DataField DataSource DataField DataSource DataField DataSource DataField DataSource DataField DataSource DataField DataSource DataField DataSource
'通讯录' True 'Table1' 'DataSource1' '好友号' 'DataSource1' '姓名' 'DataSource1' '好友类别' 'DataSource1' '年龄' 'DataSource1' '出生日期' 'DataSource1' '电话号码' 'DataSource1' '通讯地址' 'DataSource1' '电子邮件' 'DataSource1' 'QQ号码' 'DataSource1' '交往大事' 'DataSource1'
浏览和维护“通讯录”表的内容 显示和修改“交往大事”字段内容 显示和修改“QQ号码”字段内容 显示和修改“电子邮件”字段内容 显示和修改“通讯地址”字段内容 显示和修改“电话号码”字段内容 显示和修改“出生日期”字段内容 显示和修改“年龄”字段内容 显示和修改“好友类别”字段内容 显示和修改“姓名”字段内容 联系Table1组件与数据控制组件 显示和修改“好友号”字段内容
属 性 值
'D:\\DelphiApp\\14\\A\\A_14_1'
用来与通讯录表相联系
说 明
【程序代码】
直接运行程序即可实现需要的功能,但当把数据库和程序复制到其他位置,执行时将找不到数据库。为了使程序通用,可先把Table1的Active属性设置为False,然后在FormCreate
298
事件中添加如下事件代码:
Delphi 7应用教程
procedure TForm1.FormCreate(Sender: TObject); var
CurDir:string; begin
Getdir(0,CurDir); //获得应用程序所在路径 Table1.DatabaseName :=CurDir; //把应用程序所在路径赋值给Table1的DatabaseName Table1.open; //打开数据库 end;
14.1.7 SQL语言
Delphi中提供了对SQL语言的支持。对一般用户而言,在Delphi中使用的SQL语言的功能主要有:数据查询、插入记录、删除记录、更新记录等。
1.数据查询
数据查询是数据库中最常见的操作,SQL中实现查询的语句是SELECT语句,该语句由一系列的子句组成,通过这些子句可以实现对数据库的任意查询。该语句的格式和功能如下。
[格式]: SELECT [ALL | DISTINCT |TOP N|TOP N PERCENT]
*|列名1或表达式1 [AS 列标题1 ] [,列名2或表达式2 [AS 列标题2]…] FROM 表名1 [ IN 数据库名1] 别名1[,表名2 [ IN 数据库名2] 别名2 …] [WHERE 条件]
[GROUP BY列名1 [, 列名2]…] [HAVING 条件]
[ORDER BY 列名1 [ASC | DESC] [, 列名2 [ASC | DESC]…]]
[功能]:从“表名1”和“表名2”等指定的表中查询满足条件的数据。 [说明]:
(1)ALL | DISTINCT| TOP N|TOP N PERCENT:ALL表示值相同的记录也包含在结果中,这是默认设置;DISTINCT表示对于相同的记录只包含第一条记录;TOP N只返回查询结果的前N条记录,N为可变参数;TOP N PERCENT表示只返回查询结果中的前百分之N条记录,N为可变参数。
(2)*|列名1或表达式1 [AS 列标题1 ] [,列名2或表达式2 [AS 列标题2]…]:用于指定查询结果中包含的选定项,可以是列名或表达式,AS后面的“列标题”用来定义对应列或表达式的标题。在“列名1”、“列名2”等别名的前面可能有包含该列的表名。若选“*”表示输出列是由FROM子句中指定的表中的所有字段。
(3)FROM 表名1 [ IN 数据库名1] 别名1[,表名2 [ IN 数据库名2] 别名2 … ]:用于指定查询操作从哪些表中获取数据,每个表可以取一个“别名”,这样就可以在选定项中用“别名”来引用相应表中的字段。
(4)WHERE 条件:用于设定查询条件或多个表之间连接条件。
第14章 数据库应用开发
299
(5)GROUP BY 列名1 [, <列名2>…]:用于指定按照哪些列进行分组,以便进行统计。 (6)HAVING条件:只有在指定分组的查询中才有效,用来对分组的结果进行筛选,只有满足条件的组信息才包含在查询结果中。
(7)ORDER BY 列名1 [ASC | DESC] [, 列名2 [ASC | DESC]…]:用于指定按照哪些列对查询结果进行排序,ASC代表升序,DESC代表降序,默认为升序。
(8)格式中的所有条件均可以是逻辑表达式或关系表达式,使用的运算符有:AND、OR、NOT、= 、<、<=、>、>=、<>、BETWEEN、LIKE、IN等。
例如,如下语句:
Select 学号,姓名,年级 from 学生 Where 专业=\"自动化\"
其作用是列出自动化专业的全部学生的学号、姓名和年级。
又如:
SELECT 学生.学号,学生.姓名,必修课成绩.课号,必修课成绩.成绩 FROM 学生,必修课成绩 WHERE 学生.学号=必修课成绩.学号
其作用是查询出所有学生的必修课的学习情况,查询结果中包含学号、姓名、课号和成绩。
2.插入记录
插入记录可使用SQL语言的INSERT语句,该语句的格式和功能如下。 [格式]:
INSERT INTO 表名[(字段名1 [, 字段名2, …])] VALUES (表达式1 [,表达式2,…])
[功能]:向“表名”指定的表中插入一条记录,VALUES后面括号中的数据就是新记录的相应字段的数据。即“表达式1”的值作为“字段名1”中的数据,“表达式2”作为“字段名2”中的数据,……如果要给记录的所有字段插入值,表名后面的字段名可以缺省,但插入数据的类型必须与表中相应字段的数据类型完全吻合;若只需要插入表中某些字段的数据,就需要列出要插入数据的字段名,并给出相应的值。
例如,下列语句:
INSERT INTO 学生(学号,姓名,专业) VALUES(\"040501\朱碧春\计算机软件\")
其功能是向学生表中插入一条记录,并给学号、姓名和专业字段赋值。
3.修改记录
在SQL语言中,对存放在表中的数据进行修改可以通过UPDATE语句来实现。UPDATE
语句的格式和功能如下。
[格式]:
UPDATE 表名 SET 字段名1 = 表达式1[,字段名2=表达式2…] [WHERE 条件]] [功能]:对由“表名”指定的表中满足WHERE后面的“条件”的记录(若无WHERE子句将修改所有记录)进行修改,修改方法是:以“表达式1”的值替换“字段名1”中的值,以“表达式2”的值替换“字段名2”中的值,以此类推。
例如,如下语句:
300
Delphi 7应用教程
UPDATE 必修课成绩 SET 成绩=成绩+3 WHERE 课号=\"02\"
其作用是将“必修课成绩”表中的“02”号课的所有成绩增加3分。
4.删除记录
当表中的记录已经失效时,应把它删除,可以使用SQL的DELETE命令来删除表中的记录。DELETE命令的格式和功能如下。
[格式]:
DELETE FROM 表名 [WHERE 条件]
[功能]:从由“表名”指定的表中删除满足给定“条件”的记录,当缺省WHERE子句时,表示删除表中的全部记录。
例如,如下语句:
DELETE FROM 学生 WHERE 专业=\"经济管理\"
其作用是从“学生”表中删除所有的“经济管理”专业的学生。
14.1.8 TQuery组件
TQuery 组件也是一种BDE组件,其在数据库应用程序中所处的位置与TTable组件基本一致,与TTable组件不同的是,TTable组件与一个具体的数据表相联系,而TQuery组件并不和某一个具体的数据表联系在一起,它主要用于执行SQL语句,通过SQL语句可以操作一个或多个表。
1.TQuery组件的常用属性
(1)DataBaseName属性
该属性用于与数据库建立连接,可以是某个数据库别名或数据表所在的路径。其设置和使用方法与TTable组件相同。
(2)SQL属性
与TTable组件不同,TQuery组件是通过执行SQL语句来对数据表进行操作的,SQL属性中存放的就是TQuery组件要执行的SQL语句。该属性是一个字符串属性,字符串中包含的是一条SQL语句,如SELECT、INSERT、UPDATE、DELETE语句等。在SQL属性中输入了合法的SQL语句后,可以通过将它的Active属性设置为True或者调用它Open方法(或ExecSQL)来执行该SQL语句。另外,该属性还提供了设置SQL语句的一些方法,如Add、Clear等,这些方法将在后面进行介绍。
(3)Active属性
当该属性设置为True时,将执行SQL属性中存放的SQL语句。
2.TQuery组件的常用方法
TQuery组件也有很多方法,许多方法与TTable组件基本一致,如控制记录指针移动的方法有:First、Next、Prior和Last等。这些方法可参考TTable组件的相关内容。
(1)Open方法
该方法用于打开或激活TQuery组件的数据集。使用该方法,TQuery组件的SQL属性中存放的应是Select查询语句,其结果产生一个数据集。Open方法只能执行Select语句,结果
第14章 数据库应用开发
301
返回一个数据集。
(2)ExecSQL方法
该方法也是执行TQuery组件中的SQL语句。与Open方法不同的是,该方法不仅能执行查询(SELECT)语句,而且能够执行添加(INSERT)、删除(DELECT)和更新(UPDATE)的SQL语句。
一般情况下,如果要执行的SQL命令是一条SELECT语句,使用Open方法,但如果要执行的SQL命令是添加、删除或者更新的语句,则必须调用ExecSQL方法执行。
(3)Close方法
该方法用来关闭数据集。 (4)Prepare方法
调用该方法,Delphi会将带参数的SQL语句传送给对应的数据库引擎,对SQL语句进行语法分析和优化,从而大大提高动态SQL语句的执行性能,特别是当反复多次执行同一条动态SQL语句时,它的优越性会更加明显。
(5)SQL属性的两个基本方法
① Add方法:用于为TQuery组件的SQL属性添加SQL语句,该方法的语法格式如下:
Query.SQL.Add(SQLState);
其中,Query是TQuery组件的名称,参数SQLState是一个字符串,字符串中存放的是SQL语句,例如:
Query1.SQL.Add('Select * From 通讯录') Query1.SQL.Add(' Where 好友类别=''朋友''');
//在前面SQL语句基础上追加SQL语句
② Clear方法:用于清除TQuery组件的SQL属性值,一般在用Add方法添加SQL语句前调用该方法将SQL属性清空,然后再添加全新的SQL语句。例如:
Query1.Close; //先关闭数据集 Query1.SQL.Clear; //将SQL属性值清空
Query1.SQL.Add('Select * From 通讯录 Where 姓名=''李建东'''); //添加SQL语句,在字符串里面用两个单引号表示一个单引号。 Query1.Open; //打开数据集,即执行SQL语句
3.使用TQuery组件实现参数查询的方法
(1)使用Params属性实现参数查询
TQuery组件具有一个Params属性,该属性只能在程序运行时访问,在程序设计时不可以使用,并且该属性是动态建立的数组属性,它的每一个元素对应要执行的SQL语句中一个参数。在SQL语句中可以使用参数,参数的表示形式是以“:”开头的一个标识符。数组属性Params是以0下标开始的,依次对应动态SQL语句中的参数,即Params[0]对应第一个参数,Params[1]对应第二个参数,依此类推。如下列语句:
Query1.SQL.Add('Select * From 通讯录'); Query1.SQL.Add('Where姓名=:XM'); Query1.Params[0].AsString :='李建东';
//注意参数的前面有\":\"号
//给参数赋值
302
Query1.Open ;
Delphi 7应用教程
//打开查询结果数据集
Query1的SQL属性中的SQL语句中有一个参数,参数名为XM。程序执行时,系统将自动创建Query1组件的Params数组属性,该数组将有一个元素Params[0],对应参数XM。在执行该SQL语句之前必须给相应的参数赋值,如语句“Query1.Params[0].AsString :='李建东'”就是给参数XM赋值为'李建东'。
(2)使用ParamByName方法实现参数查询
除了可以使用TQuery组件的Params数组属性给参数赋值外,还可以使用TQuery组件的ParamByName方法为参数赋值。ParamByName方法是一个函数,其参数是一个动态SQL语句的参数名,故使用该语句必须要知道动态SQL语句参数的名字。
如上述的语句也可以写成:
Query1.SQL.Add('Select * From 通讯录'); Query1.SQL.Add('Where姓名=:XM'); Query1.ParamsByName(''XM' ).AsString :='李建东'; Query1.Open ;
//注意参数的前面有\":\"号
//给参数赋值
//打开查询结果数据集
【例14-2】 给定出生日期范围,查询通讯录表中出生日期在该范围内的好友的通讯录信息。程序的设计界面如图14-19所示,程序的运行界面如图14-20所示。程序运行时在两个文本框中输入起始日期,然后单击【查询】按钮将把出生日期在该范围之内的好友的通讯录信息显示在网格组件中,如图14-20所示。
图14-19 程序设计界面 图14-20 程序运行界面
【实现分析】
本例需根据用户输入的数据来查询指定的信息,可通过使用TQuery组件执行SELECT查询语句来实现。可使用参数查询,设定两个参数,分别用来接收用户输入的信息,然后可通过TQuery组件的Params属性或ParamByName方法给参数赋值,再执行查询得到结果。
【界面设计】
本例组件对象及其属性设置如表14-9所示。
表14-9 例14-2的组件对象及其属性设置
对 象 名 Query1 DataSource1
DataSet
属 性 名
'Query1'
属 性 值
执行查询
联系Query1组件和DBGrid1组件
说 明
第14章 数据库应用开发
303
续表
对 象 名 DBGrid1 Label1 Edit1 Label2 Edit2 Button1
属 性 名 DataSource Caption Text Caption Text Caption
属 性 值
'DataSource1' '开始日期' '' '结束日期' '' '查询'
显示查询结果
输入起始日期
输入结束日期
说 明
单击它将执行查询
【程序代码】
procedure TForm1.FormCreate(Sender: TObject); var
Curdir:string; begin
Getdir(0,CurDir);
Query1.DatabaseName :=Curdir; end;
procedure TForm1.Button1Click(Sender: TObject); begin
Query1.SQL.Clear ; //清除SQL属性中原来的语句 Query1.SQL.Add('Select * From 通讯录'); //以下两条语句用来给SQL属性添加新的SQL语句 Query1.SQL.Add('Where 出生日期>=:D1 AND 出生日期<=:D2'); //两个参数D1和D2 Query1.Params[0].AsDate :=strtodate(Edit1.Text) ; //通过Params属性给参数赋值 Query1.ParamByName('D2').AsDate :=StrToDate(Edit2.Text) ; //通过ParamByName方法给属性赋值 Query1.Prepare ; //优化 Query1.Open ; //执行SQL语句,打开记录集 end;
14.2 典型实例
14.2.1 典型实例一
【实例题目】:通讯录浏览与维护程序(使用数据控制组件)
建立一个应用程序,用来对本章建立的“通讯录”表进行维护和管理,该程序能够实现数据库日常操作功能,这些功能包括:通讯录数据的浏览、添加一条新的通讯信息、修改通讯信息、查询某人的通讯信息、删除某人的通讯信息等。程序的主界面设计时和运行时的情况分别如图14-21和图14-22所示。要求显示数据库中的数据采用Data Controls组件板上的相应组件,查询采用SetKey方法按姓名进行查询。
304
Delphi 7应用教程
图14-21 程序设计界面 图14-22 程序运行界面(修改时)
【实现方法】
(1)功能按钮的禁止使用和允许使用。在一定的情况下,有的按钮不可以使用,如记录指针移到数据库开头时【首记录】和【前移】按钮应不可使用。如果数据表中无记录,则除【添加】按钮外的其他按钮均不可用。一开始,【确定】和【取消】按钮不可用,单击【添加】或【修改】按钮后,【确定】和【取消】按钮可用,此时其他各按钮不可用。当单击【确定】和【取消】按钮后,这两个按钮不可用,其他各个按钮可用。当记录指针处于文件尾时,【后移】和【末记录】按钮不能用,当记录指针处于文件头时【前移】和【首记录】按钮不能用。
(2)记录移动。可使用TTable控件的相应移动方法。
(3)记录的添加与修改。对表的操作,TTable组件提供了相应的方法:如添加一条记录可执行Append方法,修改记录的内容可执行Edit方法,把修改的内容存入到表中可执行Post方法,取消对表的修改可执行Cancel方法等。为控制数据只能在“添加”或“修改”时才能输入,可在没有执行“添加”或“修改”命令之前,让所有的数据控制组件不能输入或修改,在执行“添加”或“修改”命令之后,让所有的数据控制组件能够输入或修改。该功能可通过设置各数据控制组件的ReadOnly或Enabled属性来实现。
【界面设计】
在例14-1中去掉DBNavigator1组件,用DBComboBox1取代DBEdit3用来显示好友类别,然后在界面上添加11个按钮,用来实现对通讯录表的浏览和维护功能。添加组件的属性设置如表14-10所示。
表14-10 组件的属性设置及组件作用
对 象 名
DBComboBox1 Button1 Button2
属 性 名 DataSource DataField Items Caption Caption
设 置 值
'DataSource1' '好友类别' '同学' '朋友' '亲戚' '首记录' '前移'
单击它将把记录指针移到首记录 单击它将把记录指针前移一条记录 显示和修改“好友类别”字段内容
对 象 作 用
续表
第14章 数据库应用开发
对 象 名
Button3 Button4 Button5 Button6 Button7 Button8 Button9 Button10 Button11
属 性 名 Caption Caption Caption Caption Caption Caption Caption Caption Caption
'后移' '末记录' '退出' '增加' '修改' '删除' '查询' '确定' '取消'
设 置 值
对 象 作 用
305
单击它将把记录指针后移一条记录 单击它将把记录指针移到末记录 单击它将退出应用程序 单击它将增加一条新记录 单击它将对当前记录进行修改 单击它将把当前记录删除 单击它将按姓名进行查询 单击它将保存对记录的添加或修改 单击它将取消对记录的添加或修改
【程序代码】
implementation var
BM:TBookMark; //该变量用于在添加记录时把当前记录位置作为一个书签 AddOrNot:Boolean; //该变量用于表示是添加操作还是修改操作,True表示添加 {$R *.dfm}
Procedure ButtonAddEdit(); //用于设置执行添加或修改操作时各按钮的状态 begin
Form1.Button1.Enabled :=False; Form1.Button2.Enabled:=False; Form1.Button3.Enabled :=False; Form1.Button4.Enabled :=False; Form1.Button5.Enabled :=False; Form1.Button6.Enabled :=False; Form1.Button7.Enabled :=False; Form1.Button8.Enabled :=False; Form1.Button9.Enabled :=False; Form1.Button10.Enabled :=True; // 确定按钮可以使用 Form1.Button11.Enabled :=True; //取消按钮可以使用 end;
procedure ButtonOkCancel(); //用来设置执行取消或确定操作时各按钮的状态 begin
Form1.Button1.Enabled :=True; Form1.Button2.Enabled:=True; Form1.Button3.Enabled :=True; Form1.Button4.Enabled :=True; Form1.Button5.Enabled :=True; Form1.Button6.Enabled :=True; Form1.Button7.Enabled :=True; Form1.Button8.Enabled :=True; Form1.Button9.Enabled :=True;
Form1.Button10.Enabled :=False; // 确定按钮不可以使用 Form1.Button11.Enabled :=False; //取消按钮不可以使用 end;
procedure Cannotedit(); //用于设置各输入的数据控制组件不可输入 begin
Form1.dbEdit1.readOnly:=True; Form1.dbEdit2.readOnly:=True;
Form1.dbComboBox1.ReadOnly :=True; Form1.dbEdit4.readOnly:=True; Form1.dbEdit5.readOnly:=True; Form1.dbEdit6.readOnly:=True; Form1.dbEdit7.readOnly:=True; Form1.dbEdit8.readOnly:=True; Form1.dbEdit9.ReadOnly :=True; Form1.dbMemo1.readonly:=True;
306
Delphi 7应用教程
end;
procedure Canedit(); //用来设置各输入的数据控制组件可以输入 begin
Form1.dbEdit1.readOnly:=False; Form1.dbEdit2.readOnly:=False;
Form1.dbComboBox1.ReadOnly :=False; Form1.dbEdit4.readOnly:=False; Form1.dbEdit5.readOnly:=False; Form1.dbEdit6.readOnly:=False; Form1.dbEdit7.readOnly:=False; Form1.dbEdit8.readOnly:=False; Form1.dbEdit9.readonly:=False; Form1.dbMemo1.readonly:=False; end;
procedure DisabledButton(); //使所有的按钮均不可用 begin
Form1.button1.Enabled:=False; Form1.button2.Enabled:=False; Form1.button3.Enabled:=False; Form1.button4.Enabled:=False; Form1.button5.Enabled:=False; Form1.button6.Enabled:=False; Form1.button7.Enabled:=False; Form1.button8.Enabled:=False; Form1.button9.Enabled:=False; Form1.button10.Enabled:=False; Form1.button11.Enabled:=False; end;
procedure TForm1.FormCreate(Sender: TObject); var
Curdir:string; begin
getdir(0,Curdir);
Table1.DatabaseName:=Curdir; //设置Table1的Databasename为当前目录 Table1.Active :=True; //打开Table1 CannotEdit; //设置可输入组件为只读 if table1.RecordCount =0 then //如果数据库表为空 begin
disabledButton;
Button6.Enabled :=True; //只有添加按钮可用 end else
ButtonOkCancel;
Table1.IndexName :='XM'; //设置查询用的索引名 end;
procedure TForm1.Button1Click(Sender: TObject); //首记录 begin
Table1.First ;
Button1.Enabled :=False; Button2.Enabled :=False; Button3.Enabled :=True; Button4.Enabled:=True; end;
procedure TForm1.Button2Click(Sender: TObject); //前移 begin
Table1.Prior ;
button3.Enabled :=True; Button4.Enabled :=True; if Table1.Bof then //判断是否到达文件头
第14章 数据库应用开发
begin
Table1.First ;
button1.Enabled :=False; Button2.Enabled :=False; end; end;
procedure TForm1.Button3Click(Sender: TObject); //后移 begin
Table1.Next ;
Button1.Enabled :=True; Button2.Enabled :=True; if Table1.Eof then //判断是否到达文件尾 begin
Button3.Enabled :=False; Button4.Enabled :=False; Table1.Last ; end; end;
procedure TForm1.Button4Click(Sender: TObject); //末记录 begin
Table1.Last ;
Button1.Enabled :=True; Button2.Enabled :=True; Button3.Enabled :=False; Button4.Enabled:=False; end;
procedure TForm1.Button5Click(Sender: TObject); //退出 begin
Table1.Close ; //关闭表 Application.Terminate ; //结束程序运行 end;
procedure TForm1.Button6Click(Sender: TObject); //添加 begin
BM:=table1.GetBookmark ; //记下当前记录位置 CanEdit; //允许输入 Table1.Append ; //增加记录 ButtonAddEdit; //设置按钮状态 AddOrNot:=True; //是增加操作 end;
procedure TForm1.Button7Click(Sender: TObject); //修改 begin
AddOrNot:=False; //不是添加操作 Table1.Edit ; //修改 CanEdit; //让所有的数据控制组件可以使用 ButtonAddEdit; end;
procedure TForm1.Button8Click(Sender: TObject); //删除 begin
if Application.MessageBox('真的要删除吗?','删除提示框',MB_OKCANCEL)=IDOK Then Table1.Delete ;
if Table1.RecordCount =0 then //如果所有的记录均被删除
307
308
Delphi 7应用教程
begin
ShowMessage('已无记录'); DisabledButton; Button6.Enabled :=True; end; end;
procedure TForm1.Button9Click(Sender: TObject); var
xm: string; begin
xm:=trim(inputbox('输入姓名','请输入姓名','')); with Table1 do begin
setkey; FieldByName('姓名').AsString :=xm; if not GotoKey then ShowMessage('无符合条件的记录'); end end;
procedure TForm1.Button10Click(Sender: TObject); begin
if (length(trim(dbEdit1.text))=0) then begin
ShowMessage('必须输入好友号'); dbEdit1.SetFocus ; end else
begin
Table1.Post ; CannotEdit;
ButtonOkCancel; end; end;
procedure TForm1.Button11Click(Sender: TObject); begin
Table1.Cancel; if AddOrNot then Table1.GotoBookmark(Bm); CannotEdit; ButtonOkCancel; end;
//显示提示信息
//让所有按钮均不可用
//再让添加按钮可用,只能执行添加操作
//按姓名查询
//输入要查询的人的姓名
//设置查询状态 //设置要查询的姓名 //如果没有找到
//确定操作
//如果“好友号”为空
//存入到数据库中
//取消操作
//执行取消操作
//如果刚才执行的是增加操作 //把指针移到原来的位置 //不允许输入 //设置按钮的状态
14.2.2 典型实例二
【实例题目】:SQL语句执行演示程序
第14章 数据库应用开发
309
编写一个SQL语言的语句执行演示程序,程序的设计界面如图14-23所示,程序的运行界面如图14-24所示。程序操作的数据库为“通讯录”数据库。程序执行时,选中【Select语句】单选钮,可在Memo1组件中输入Select语句,输入完毕后,单击【执行】按钮,查询的结果将显示在图上面的DBGrid1组件中。如果选中【其他数据操纵语句】单选钮,将在DBGrid1中显示“通讯录”表中的信息,然后可在Memo1组件中输入DELETE、UPDATE、INSERT等SQL语句,输入完毕后单击【执行】按钮,将把执行的结果立即显示在DBGrid1中。单击【清空】按钮,将把Memo1中输入的内容清空,单击【退出】按钮将退出应用程序。
图14-23 程序设计界面 图14-24 程序运行界面
【实现方法】
使用TQuery组件可以执行任意的SQL语句,如果执行的是SELECT语句,一般使用Open方法,并将得到一个结果数据集,故只需把数据集直接显示在TDBGrid组件中即可。如果执行的是其他数据操纵语句,并不形成数据集,执行的结果在表中表现出来,故需要把表中的信息显示出来,以观看结果。
【界面设计】
按照表14-11所示为窗体添加组件并设置组件的属性。
表14-11 组件的属性设置及组件作用
对 象 名 Table1 Query1 DataSource1 DBGrid1 GroupBox1 RadioButton1 RadioButton2 Memo1 Button1
DataSource Caption Caption Caption Caption 属 性 名
'DataSource1' 'SQL语句种类' 'Select语句' '其他数据操作语句' '执行'
设 置 值
对 象 作 用
与“通讯录”表相联系 执行SQL语句
把Table1或Query1组件与DBGrid1组件联系起来 显示SQL语句执行的结果 容纳单选钮
选中它表示要执行的是SELECT语句 选中它表示要执行的是SQL的数据操作语句 用来输入要执行的SQL语句 单击它将执行输入的SQL语句
310
Delphi 7应用教程
续表
对 象 名 Button2 Button3
属 性 名 Caption Caption
设 置 值 '清空' '退出'
对 象 作 用
单击它将把Memo1中输入的内容清空 单击它将退出应用程序
【程序代码】
procedure TForm1.FormCreate(Sender: TObject); var
CurDir:String; begin
Getdir(0,CurDir);
Table1.DatabaseName :=CurDir; Table1.TableName :='通讯录'; Query1.DatabaseName :=CurDir; Memo1.Clear ; end;
procedure TForm1.RadioButton1Click(Sender: TObject); begin
//如果选择【SELECT 语句】单选钮,让DBGrid1显示Query1查询形成的数据集 DataSource1.DataSet :=Query1; DBGrid1.DataSource :=DataSource1; end;
procedure TForm1.RadioButton2Click(Sender: TObject);
begin
//如果选择【其他数据操纵语句】单选钮,就让DBGrid1显示与Table1关联在一起的
//通讯录表中的数据
DataSource1.DataSet :=Table1;
DBGrid1.DataSource :=DataSource1; Table1.Open ;
end;
procedure TForm1.Button1Click(Sender: TObject); begin
Query1.SQL.Clear ; Query1.SQL.add(Memo1.Text ); Query1.Prepare ;
if RadioButton1.Checked then Query1.Open else
begin
Query1.ExecSQL ; Table1.Refresh ; End; end;
//清除Query1组件中原来的SQL语句 //添加当前输入的SQL语句 //优化
//如果选择了【Select 语句】单选钮
//执行SQL语句,形成数据集并显示出来 //如果选择了【其他数据操纵语句】单选钮 //执行该SQL数据操纵语句
//刷新Table1组件,把执行的结果显示出来
第14章 数据库应用开发
procedure TForm1.Button2Click(Sender: TObject); begin
Memo1.Clear;
//清除输入的语句
end;
procedure TForm1.Button3Click(Sender: TObject); begin
Query1.Close ; Table1.Close ; Application.Terminate ; end;
//结束应用程序的运行
311
14.3 上机练习
14.3.1 上机练习一
【练习题目】:登录界面的设计
一般的软件系统都有登录系统用来验证访问者的身份(用户名和口令),这是一个比较通用的模块。请设计一个登录程序,完成的功能如下:合法的用户提供合法的口令就可进入系统,非法用户只能尝试三次,若不能够进入系统则应用程序自动结束。程序的设计界面如图14-25所示,程序的运行界面如图14-26所示。
图14-25 程序设计界面 图14-26 用户名和口令均输入正确时的程序运行界面
【要点提示】
(1)用户信息的存放。可建立一个用户表,用来存入用户信息,用户表中应该包含用户名、口令、是否为管理员等信息。本题可建立一个User的表,它的结构如图14-27所示,其中字段UserName用来存放用户名,字段PassWord用户存放用户口令,字段Adminstrator用来表示该用户是否为管理员,值为True时表示是管理员,值为False时表示不是管理员。在表中添加一些用户信息作为模拟数据,模拟数据如图14-28所示。
(2)功能实现。当用户输入完用户名后,程序自动在User表中的UserName字段中查找是否有该用户,如果没有该用户,则给出非法用户的提示信息,如果三次输入的用户名均不正确则应用程序自动终止。当用户名输入正确后,允许输入口令,口令输入后,程序自动把用户输入的口令与当前记录的PassWord字段值比较,若不相等则给出口令错误的提示信息,也一样允许用户输入三次,若三次均错误,则终止程序的执行。(注意:为便于讲解,本题无
312
Delphi 7应用教程
论是输入用户名还是输入口令,输入结束后均需按Enter键确认。)
图14-27 User表的结构 图14-28 User表中的模拟数据
【参考代码】
var
YHDL: TYHDL; YHM:String; //全局变量YHM用来存放用户输入的用户名信息 GLY:Boolean; //全局变量GLY用来存放当前登录的用户是否为管理员信息, //值为True时表示为管理员 KL:String; //全局变量KL用来存放用户输入的口令信息 implementation var
time:integer; //用来存放用户尝试的次数 {$R *.dfm}
procedure TYHDL.FormCreate(Sender: TObject); var
curdir:string; //curdir存放应用程序所在目录 begin
getdir(0,Curdir); //获取当前目录 Table1.DatabaseName :=Curdir; //设置数据库名 Table1.TableName:='User.db'; //设置表名为用户表 Table1.Open ; //打开表 time:=0; //尝试次数为0 end;
procedure TYHDL.Edit1KeyPress(Sender: TObject; var Key: Char); begin
if ord(key)=13 then //如果按Enter键 begin
Table1.IndexFieldNames :='UserName'; //设置索引字段名为'UserName' Table1.SetKey ; //把用户表设置为查询状态 Table1.FieldByName('UserName').AsString :=Edit1.Text ; //根据用户输入的用户名进行查找 if Table1.GotoKey then //如果找到 begin
Edit2.SetFocus ; //焦点设置在Edit2,以便输入口令 time:=0; //重新设置Time值为0,允许输入口令时也尝试三次 end
else //用户名输入错误
第14章 数据库应用开发
begin
313
time:=time+1; //尝试次数加1 if time<=2 then //如果尝试次数小于3 ShowMessage('用户名非法,请重输!') //弹出提示 else begin
ShowMessage('你是非法用户,不能进入系统!'); //尝试次数超过3次 Table1.Close; //关闭表 Application.Terminate ; //终止应用程序的执行 end; end; end; end;
procedure TYHDL.Edit2KeyPress(Sender: TObject; var Key: Char); begin
if Ord(Key) = 13 then
if Table1.FieldByName('PASSWORD').AsString <> Edit2.Text then begin
time := time + 1; if time < 3 then begin
ShowMessage ('口令错误,请重新输入!'); Edit2.Text := ''; Edit2.SetFocus; end else begin
ShowMessage ('对不起,你无法进入系统!'); Close; end end else begin
ShowMessage('欢迎你进入系统');
YHM:=Table1.FieldByName('Username').AsString ; //保存用户名到变量YHM中
GLY:=Table1.FieldByName('Admin').AsBoolean ; //保存是否为管理员信息到GLY变量中 KL:=Table1.FieldByName('PassWord').Asstring ; //保存口令信息到变量KL中 Table1.Close; //关闭用户表 YHDL.Hide ; //隐藏登录界面 // ……此处显示应用程序的主界面 end; end;
14.3.2 上机练习二
【练习题目】:用SQL语句实现通讯录的浏览和维护
使用SQL语句实现通讯录的浏览和维护,实现的功能与典型实例一基本相同,但有以下
314
Delphi 7应用教程
几点不同。
(1)显示各字段的内容的组件不再使用【Data Controls】选项卡上的组件,而是使用像TEdit、TComboBox、TMemo等的一般组件。
(2)各按钮实现的功能基本上与上一个实验相同,不同之处只是【增加】、【删除】、【修改】等操作均要使用SQL语句来实现。
(3)为了能够执行SQL语句,本题增加了一个TQuery组件用来执行SQL语句。
(4)为了能够使表中数据的变化能够立即显示出来,本题增加了一个TDBGrid组件,用来显示通讯录表的内容。
本题的程序设计界面如图14-29所示,程序的运行界面如图14-30所示。
图14-29 程序设计界面
图14-30 程序运行界面
【要点提示】
(1)由于不是采用数据控制组件显示数据库中的内容,因此每当记录指针的位置发生了变化,应该要把当前记录中的数据显示在相应组件中。
(2)本题使用TDBGrid显示通讯录表中的数据,当用户在该表上单击时可能会改变当前记录的位置,因此应当使用当前记录的值来更新各显示组件。
(3)为执行SQL语句,本题使用了TQuery组件,使用该组件执行SQL语句的一般方法是:首先执行TQuery组件的SQL.Add方法把要执行的SQL语句作为字符串加进来;如果SQL语句中带有参数,应该通过TQuery组件的Params[]给ParamByName[]数组属性的参数赋
第14章 数据库应用开发
315
值;通过调用TQuery组件的ExecuteSQL方法或Open方法来执行相应的SQL语句。
(4)“插入”操作可使用INSERT语句、“修改”操作可使用UPDATE语句,“删除”操作可使用DELETE语句。删除操作需要条件,否则删除的是全部记录,为实现当前记录的删除,可先用一个变量记下当前记录的“好友号”字段的值,然后在“删除”语句中设置条件为“好友号等于该变量的值”。
【参考代码】
implementation var
BM:TBookMark; //该变量用于在添加记录时把当前记录位置作为一个书签 AddOrNot:Boolean; //该变量用来表示是添加操作还是修改操作,True表示添加 {$R *.dfm}
procedure DispValue(); //在编辑框、组合框或Memo组件中显示当前记录的内容 begin
Form1.Edit1.Text :=Form1.Table1.fieldbyname('好友号').asstring; Form1.Edit2.Text :=Form1.Table1.fieldbyname('姓名').asstring;
Form1.ComboBox1.Text :=Form1.Table1.fieldbyname('好友类别').asstring; Form1.Edit3.Text :=Form1.Table1.fieldbyname('年龄').asstring; Form1.Edit4.Text :=Form1.Table1.fieldbyname('出生日期').asstring; Form1.Edit5.Text :=Form1.Table1.fieldbyname('电话号码').asstring; Form1.Edit6.Text :=Form1.Table1.fieldbyname('通讯地址').asstring; Form1.Edit7.Text :=Form1.Table1.fieldbyname('电子邮件').asstring; Form1.Edit8.Text :=Form1.Table1.fieldbyname('QQ号码').asstring; Form1.Memo1.Text :=Form1.Table1.fieldbyname('交往大事').asstring; end;
procedure ClearValue(); //消除在编辑框、组合框或Memo组件中显示的内容 begin
Form1.Edit1.Text :=''; Form1.Edit2.Text :='';
Form1.ComboBox1.Text:=''; Form1.Edit3.Text :=''; Form1.Edit4.Text :=''; Form1.Edit5.Text :=''; Form1.Edit6.Text :=''; Form1.Edit7.Text :=''; Form1.Edit8.Text :=''; Form1.Memo1.Text :=''; end;
//省略了ButtonAddEdit和ButtonOkCancel两个过程,参见典型实例一 procedure Cannotedit(); //用来设置各输入的数据控制组件不可输入 begin
Form1.Edit1.readOnly:=True; Form1.Edit2.readOnly:=True;
Form1.ComboBox1.Enabled :=False; Form1.Edit3.readOnly:=True; Form1.Edit4.readOnly:=True; Form1.Edit5.readOnly:=True; Form1.Edit6.readOnly:=True; Form1.Edit7.readOnly:=True; Form1.Edit8.ReadOnly :=True; Form1.Memo1.readonly:=True; end;
procedure Canedit(); //用来设置各输入的数据控制组件可以输入 begin
316
Delphi 7应用教程
Form1.Edit1.readOnly:=False; Form1.Edit2.readOnly:=False;
Form1.ComboBox1.Enabled:=True; Form1.Edit3.readOnly:=False; Form1.Edit4.readOnly:=False; Form1.Edit5.readOnly:=False; Form1.Edit6.readOnly:=False; Form1.Edit7.readOnly:=False; Form1.Edit8.readonly:=False; Form1.Memo1.ReadOnly :=False; end;
……//此处省略了DisabledButton过程,参见典型实例一 procedure TForm1.FormCreate(Sender: TObject); var
Curdir:string; begin
……//省略的部分同典型实例一 DispValue;
Query1.DatabaseName:=Curdir; //设置Table1的Databasename为当前目录 end;
procedure TForm1.Button1Click(Sender: TObject); //首记录 begin
……//省略的部分同典型实例一 DispValue; end;
procedure TForm1.Button2Click(Sender: TObject); //前移 begin
……//省略的部分同典型实例一 DispValue; end;
procedure TForm1.Button3Click(Sender: TObject); //后移 begin
……//省略的部分同典型实例一 DispValue; end;
procedure TForm1.Button4Click(Sender: TObject); //末记录 begin
……//省略的部分同典型实例一 DispValue; end;
……//省略了Button5Click事件过程,参见典型实例一 procedure TForm1.Button6Click(Sender: TObject); //添加 begin
ClearValue; BM:=table1.GetBookmark ; //记下当前记录位置 CanEdit; //允许输入 ButtonAddEdit; //设置按钮状态 AddOrNot:=True; //是增加操作 end;
procedure TForm1.Button7Click(Sender: TObject); //修改 begin
第14章 数据库应用开发
AddOrNot:=False;
//不是增加操作
317
CanEdit; ButtonAddEdit; end;
procedure TForm1.Button8Click(Sender: TObject); //删除 var
hyh:string; begin
if Application.MessageBox('真的要删除吗?','删除提示框',MB_OKCANCEL)=IDOK then begin
hyh:=Table1.FieldbyName('好友号').AsString ; Query1.SQL.Clear ;
Query1.SQL.Add('Delete From TXL WHERE 好友号=(:A1)'); Query1.Params[0].AsString :=hyh; QUERY1.ExecSQL ; Table1.Refresh ; DispValue; end; end;
……//省略了Button9Click事件过程,参见典型实例一 procedure TForm1.Button10Click(Sender: TObject); //确定操作 var
hyh:string; begin
If (length(trim(Edit1.text))=0) then //好友号为空 begin
ShowMessage('必须输入好友号'); edit1.SetFocus ; end else begin
if AddOrNot then begin
Query1.SQL.Clear ;
Query1.SQL.Add('INSERT INTO 通讯录(好友号,姓名,好友类别,年龄,出生日期, 电话号码,通讯地址,电子邮件,QQ号码,交往大事)') ;
Query1.SQL.Add('Values ((:P1),(:P2),(:P3),(:P4),(:P5),(:P6),(:P7),(:P8),(:P9),(:P10))'); end else
begin
hyh:=Table1.fieldbyname('好友号').AsString ; Query1.SQL.Clear ;
Query1.SQL.Add('Update 通讯录 SET 好友号=(:P1),姓名=(:P2),好友类别 =(:P3)');
Query1.SQL.Add(',年龄=(:P4),出生日期=(:P5),电话号码=(:P6)');
Query1.SQL.Add(',通讯地址=(:P7),电子邮件=(:p8),QQ号码=(:P9),交往大 事=(:P10)');
Query1.SQL.Add('WHERE 好友号=(:P11)'); Query1.Params[10].AsString:=hyh ;
318
end;
Delphi 7应用教程
Query1.Params[0].AsString:=Edit1.Text ;
Query1.Params[1].AsString :=Edit2.Text ;
Query1.Params[2].Asstring:=Combobox1.Text ;
Query1.Params[3].AsSmallInt :=strtoint(Edit3.Text ); Query1.Params[4].AsDate :=strtodate(Edit4.Text); Query1.Params[5].AsString :=Edit5.Text; Query1.Params[6].AsString :=Edit6.Text ; Query1.Params[7].AsString :=Edit7.Text ; Query1.Params[8].AsString :=Edit8.Text ; Query1.Params[9].AsString :=Memo1.Text ; Query1.ExecSQL ; CannotEdit; ButtonOkCancel; Table1.Refresh ; end; end;
procedure TForm1.Button11Click(Sender: TObject); begin
if AddOrNot then Table1.GotoBookmark(Bm); CannotEdit; ButtonOkCancel; DispValue(); end;
procedure TForm1.DBGrid1CellClick(Column: TColumn); begin
DispValue; end;
//取消操作
//如果刚才执行的是增加操作 //把指针移到原来的位置 //不允许输入 //设置按钮的状态
//显示当前记录
课后考场
一、选择题(20分,每题5分)
1.要使TDataSource组件与TTable组件相联系,应把它的________属性设置为TTable组件的名称。
A.DataSet B.DataField C.DataSource D.DatabaseName
2.要使TDBText组件能够显示数据表中的某一字段的内容,除应设置它的DataSource属性外,还应把它的________属性设置为对应的字段名。
A.DataField B.DataFormat C.ListField D.Text
3.TQuery组件主要用于执行SQL语句,它执行的SQL语句存放在________属性中。 A.DatabaseName B.TableName C.DataSource D.SQL
第14章 数据库应用开发
319
4.要使TQuery组件中的SQL语句执行后返回一个结果数据集,应调用TQuery组件的________方法。
A.Add B.Open C.ExecSQL D.Open和ExecSQL 二、填空题(40分,每空5分)
1.TDataSource组件是通过________属性与TTable组件建立联系的。
2.数据控制组件要访问数据集中的某个字段,首先应通过设置它的________属性以便和TDataSource组件建立联系,然后应设置它的________属性以便和具体的字段建立联系。
3.当记录指针位于________位置时,TTable组件的Eof属性为True,当记录指针位于________位置时,TTable组件的Bof属性为True。
4.调用TQuery语句的SQL属性的________方法可以清除掉SQL属性中存放的字符串。 5.调用TQuery语句的SQL属性的________方法可以把SQL语句增加进它的SQL属性中。
6.要实现参数查询,可以在TQuery1组件中增加包含参数的SQL语句,为了给参数赋值,应使用TQuery组件的________数组属性。
三、程序设计题(40分)
首先建立一个TSXX的表,表的结构如图14-31所示。注意在定义表结构时,建立了两个索引,索引名为BOOKNAME(以书名作为索引字段)和BOOKNO(以书号作为索引字段)。然后在表中输入十条以上的数据,如图14-32所示。表结构建立成功并输入数据后,设计一个对该表进行浏览和管理的程序,程序的设计界面如图14-33所示,程序的运行界面如图14-34所示。要求使用以下方法来实现程序的功能:(1)显示各字段内容的组件不再使用Data Controls选项卡上的组件,而是使用像TEdit、TCheckBox等的一般组件;(2)查询使用FindKey方法来实现。
图14-31 TSXX表的结构
320
Delphi 7应用教程
图14-32 TSXX表的内容
图14-33 程序设计界面
图14-34 查询时的程序运行界面
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- huatuo0.cn 版权所有 湘ICP备2023017654号-2
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务