1、第第10章章 其他编程其他编程 Delphi实用教程实用教程*第1页,共110页。10.1 图形图像处理图形图像处理10.1.1画布的通用属性和方法画布的通用属性和方法 TCanvas Object(画布对象)(画布对象)常用方法及功能:(1)Arc方法 语法:语法:Arc(x1,y1,x2,y2,x3,y3,x4,y4:Integer)Arc方法在椭圆上画一段弧,椭圆由(x1,y1)、(x2,y2)两点所 确定的椭圆所决定。弧的起点是椭圆圆周和椭圆中心与(x3,y3)连线的交点。弧矩形终点是椭圆周和椭圆中心与(x4,y4)连线的 交点,以逆时针方向画弧。例如,以下的程序将在窗口中将在窗口中绘
2、制一个圆弧:procedure TForm1.FormPaint(Sender:TObject);var R:TRect;begin R:=GetClientRect;Canvas.Arc(R.Left,R.Top,R.Right,R.Bottom,R.Right,R.Top,R.Left,R.Top);end;*第2页,共110页。10.1.1画布的通用属性和方法画布的通用属性和方法 (2)Chord方法语法:语法:Chord(x1,y1,x2,y2,x3,y3,x4,y4:Integer)Chord方法连接椭圆上的两点,椭圆由(x1,y1)、(x2,y2)两点所确定的矩形决定,(x3,y3
3、)是始点,(x4,y4)是终点。例如,在Form1窗体上放置一个按钮“连接椭圆上的两点”,双击该按钮,输入下面的代码:procedure Tform1.Button1Click(Sender:TObject);var R:TRect;beginR:=GetClientRect;Get coordinates of the current window.Canvas.Chord(R.Left,R.Top,R.Right,R.Bottom,R.Right,R.Top,R.Left,R.Top);end;*第3页,共110页。10.1.1画布的通用属性和方法画布的通用属性和方法Canvas类的Cho
4、rd方法示例*第4页,共110页。10.1.1画布的通用属性和方法画布的通用属性和方法(3)Brushcopy方法 语法:语法:Brushcopy(const Dest:TRect;Bitmap:Tbitmap;const Source TRect;Color:Tcolor)Brushcopy方法把位图的一部分复制到画布的某个矩形区域,并用画笔的当前颜色替换位图的颜色。Dest定义画布的一个矩形区域,该矩形用以填充位图,Bitmap定义位图;Source定义位图中的矩形区域,该区域上的位图将被复制;Color定义画笔中,用以替换位图的颜色。*第5页,共110页。10.1.1画布的通用属性和方法
5、画布的通用属性和方法(4)CopyRect方法 语法:语法:CopyRect(Dest:TRect;Canvas:TCanvas;SourceTRect)此方法从另一个画布对象上复制部分图像到该画布。Canvas表示复制画布,Source是源画布上要复制的图像区域,Dest表示目标画布上将接受复制图像的矩形区域。*第6页,共110页。10.1.1画布的通用属性和方法画布的通用属性和方法(5)Draw方法 语法:语法:Draw(x,y:Integer;Graphic:Tgraphic)此方法在画布给定的像素点坐标(x,y)处画由参数Graphic所给的图像,该图像可以是位图、图标或元位图。Tca
6、nvas的其他方法列于表中。*第7页,共110页。10.1.1画布的通用属性和方法画布的通用属性和方法2.Tpen Object(画笔对象)画笔对象)用于在画布上绘制各种线段,该对象常用的属性有:l Color:定义笔的颜色;l Width:定义线段宽度;l Style:定义线段的各种类型,如表所示;*第8页,共110页。10.1.1画布的通用属性和方法画布的通用属性和方法 Mode:定义线段的颜色,取值如表所示。*第9页,共110页。10.1.1画布的通用属性和方法画布的通用属性和方法3.Tbrush Object(画刷对象)(画刷对象)画刷对象用以填充图形,如用画刷颜色或图案对矩形或椭圆进
7、行填充。Tbrush拥有一个画刷句柄(Hbrush)。画刷的颜色定义在Color属性中,画刷还有一个Bitmap属性,该属性只能在运行时得到,画刷可使用位图填充图形以产生特殊效果。*第10页,共110页。10.1.1画布的通用属性和方法画布的通用属性和方法4.TColor类型类型 TColor类型用于定义一个对象的颜色。很多部件的颜色属性就是TColor类型,在Graphics单元中TColor定义如下:TColor=-(COLOR_ENDCOLORS+1)$02FFFFF;*第11页,共110页。10.1.2 图形图像组件图形图像组件 Image组件组件 Image组件是一个容器组件,它在应
8、用程序窗体窗口中提供了一个矩形区域,用于显示和输出位图、图标、图元文件或用户自定义的图形文件。Image组件的常用属性表。*第12页,共110页。10.1.2 图形图像组件图形图像组件 2.Shape组件组件 Shape组件用于在窗体中绘制几何图形,如椭圆、矩形和圆角矩形等。该组件的常用属性有:l Shape:指明需要绘制的几何图形,它可能的取值和含义 如表所示;l Brush:指明在几何图形中填充的样式;l Pen:指定几何图形所使用的线型。*第13页,共110页。10.1.2 图形图像组件图形图像组件 3.PaintBox组件组件 该组件是一个简单的画板,它为应用程序提供了可在窗体的特定矩
9、形区域内画图的方法。PaintBox组件的主要属性有:(1)Anchors属性 该属性包含4个子属性(akLeft、akTop、akRight和akBotton),用来指定在运行过程中,当父组件是可调时,它相对于父组件边沿的位置。(2)BoundsRect属性 该属性用来指定组件的矩形边界,用其父组件的坐标系来表示。*第14页,共110页。10.1.2 图形图像组件图形图像组件 例如,以下代码用于绘制矩形:procedure Tform1.Button1Click(Sender:TObject);var MyRect:TRect;begin MyRect:=ActiveControl.Boun
10、dsRect;MyRect.right=MyRect.Left+2*(MyRect.Right-MyRect.Left);MyRect.Botton:=MyRect.Top+(MyRect.Botton-MyRect.Top)div 2;ActiveControl.BoundsRect:=MyRect;end;(3)Canvas属性 该属性仅在运行时有效,使用该属性可以在组件表面的特定区域进行绘图。(4)Color属性该属性可用于除“颜色”对话框以外的所有组件或对象。(5)Constaints属性该属性强制指定组件的大小。*第15页,共110页。10.1.3图形(图形(Picture)对象)对
11、象 读取图像读取图像 读取图像需要使用LoadFromFile方法来调用,同时配合 OpenDialog函数来选择相应的图像文件。下面的代码实现对 图像文件的读取:procedure Tform1.Open1Click(Sender:Tobject);begin if OpenDialog1.Execute then begin CurrentFile:=OpenDialog1.Filename;Image.Picture.LoadFromFile(CurrentFile);end;end;*第16页,共110页。10.1.3图形(图形(Picture)对象)对象 2.保存图像保存图像 为将I
12、mage组件中的图像保存为文件,可调用Image组件的Picture属性的SaveToFile方法。SaveToFile方法需要一个保存文件的文件名。下面的代码是一般程序常用的“Save”和“Save As”菜单的处理程序:procedure Tform1.Save1Click(Sender:Tobject)beginif CurrentFile then Image.Picture.SaveToFile(CurrentFile)else SaveAsClick(Sender);end;procedure Tform.Saveas1Click(Sender:TObject);begin if
13、SaveDialog1.Execute then begin CurrentFile:=SaveDialog1.FileName;Save1Click(Sender);end;end;*第17页,共110页。10.1.3图形(图形(Picture)对象)对象 3.替换图像替换图像 用户可以在任何进修替换掉Image组件中的图像,只要将一新的图像对象赋给Picture就可以了。下面的代码实现用一个新的位图对象代替原有的Image组件中的Picture中的图像对象的功能:Bitmap:Tbitmap:beginBitmap:=Tbitmap.Create;Bitmap.Width:=NewWidt
14、h;Bitmap.Height:=NewHeight;Image.Picture.Graphic:=Bitmap;CurrentFile:=;end;*第18页,共110页。10.1.3图形(图形(Picture)对象)对象【例】屏幕复制,将当前屏幕的图像抓下来,显示到窗口中;还可以文件【例】屏幕复制,将当前屏幕的图像抓下来,显示到窗口中;还可以文件的形式保存起来。步骤如下:的形式保存起来。步骤如下:(1)建立用户界面:建立窗体Form1,添加一个Panel、一个Timer、一个SavePictureDialog、四个Button控件并在Panel控件上添加一个 Image控件。(2)再创建窗
15、体Form2,用于窗口抓图的显示窗口;在该窗体中添加一个Image控件和Timer控件,其中Image控件用于保存图像。(3)设置控件属性:对添加的控件按下表设置其属性。*第19页,共110页。10.1.3图形(图形(Picture)对象)对象 控件的属性设置*第20页,共110页。10.1.3图形(图形(Picture)对象)对象(4)激活第一个单元文件,单击Delphi 7的File菜单下的Use Unit项,出现窗口,选择Unit2,单击OK。(5)编写程序代码如下:procedure TForm1.Timer1Timer(Sender:TObject);/完成对屏幕的复制,并粘帖到Im
16、age控件中 var Fullscreen:Tbitmap;Fullscreencanvas:tcanvas;dc:HDC;begin timer1.Enabled:=false;fullscreen:=tbitmap.Create;/建立一个BITMAP来存放图像 fullscreen.Width:=screen.Width;dc:=getdc(0);/API函数,获取屏幕 fullscreencanvas:=tcanvas.Create;/建立一个CANVAS对象 fullscreencanvas.Handle:=dc;fullscreen.Canvas.CopyRect(rect(0,0
17、,screen.Width,screen.Height),fullscreencanvas,rect(0,0,screen.Width,screen.Height);*第21页,共110页。10.1.3图形(图形(Picture)对象)对象 fullscreencanvas.Free;releasedc(0,dc);image1.Picture.Bitmap:=fullscreen;/将拷贝下的图像赋给IMAGE对象 image1.Width:=fullscreen.Width;image1.Height:=fullscreen.Height;fullscreen.Free;form1.Win
18、dowState:=wsnormal;form1.Show;messagebeep(1);end;procedure TForm1.Button4Click(Sender:TObject);begin close;end;*第22页,共110页。10.1.3图形(图形(Picture)对象)对象 procedure TForm1.Button1Click(Sender:TObject);begin form1.WindowState:=wsminimized;form1.Hide;timer1.Enabled:=true;end;procedure TForm1.Button3Click(Se
19、nder:TObject);begin if form1.SavePictureDialog1.Execute then begin form2.Image1.Picture.SaveToFile(savepicturedialog1.FileName);end;end;*第23页,共110页。10.1.3图形(图形(Picture)对象)对象procedure TForm1.Button2Click(Sender:TObject);begin form1.Hide;form2.Hide;form2.Timer1.Enabled:=true;end;end.var Form2:TForm2;f
20、oldx,x1,y1,x2,y2,oldx,oldy,foldy:integer;flag,trace:boolean;implementationuses unit3;$R*.dfm*第24页,共110页。10.1.3图形(图形(Picture)对象)对象 procedure TForm2.Timer1Timer(Sender:TObject);var fullscreen:TBitmap;fullscreencanvas:TCanvas;dc:HDC;beginform2.timer1.enabled:=false;fullscreen:=tbitmap.create;fullscreen
21、.width:=screen.Width;fullscreen.Height:=screen.Height;dc:=getdc(0);fullscreencanvas:=tcanvas.Create;fullscreencanvas.Handle:=dc;fullscreen.Canvas.CopyRect(rect(0,0,screen.Width,screen.Height),fullscreencanvas,rect(0,0,screen.Width,screen.Height);fullscreencanvas.Free;releasedc(0,dc);*第25页,共110页。10.1
22、.3图形(图形(Picture)对象)对象 image1.Picture.Bitmap:=fullscreen;image1.Width:=fullscreen.Width;image1.Height:=fullscreen.Height;fullscreen.Free;form2.WindowState:=wsnormal;form2.Show;messagebeep(1);foldx:=-1;foldy:=-1;image1.Canvas.Pen.Mode:=pmnot;/笔的模式取反 image1.Canvas.Pen.Color:=clblack;/笔的颜色 image1.Canvas
23、.Brush.Style:=bsclear;/刷子的格式 flag:=true;end;*第26页,共110页。10.1.3图形(图形(Picture)对象)对象 procedure TForm2.Image1MouseMove(Sender:Tobject;Shift:TShiftState;X,Y:Integer);begin if trace=true then /追踪鼠标 begin /擦除旧的图形并画上新的图形 with image1.Canvas do begin rectangle(x1,y1,oldx,oldy);rectangle(x1,y1,x,y);oldx:=x;old
24、y:=y;end;end else if flag=true then*第27页,共110页。10.1.3图形(图形(Picture)对象)对象begin with image1.Canvas do begin moveto(foldx,0);lineto(foldx,screen.Height);moveto(0,foldy);lineto(screen.Width,foldy);moveto(x,0);lineto(x,screen.Height);moveto(0,y);lineto(screen.Width,y);foldx:=x;foldy:=y;end;end;end;*第28页,
25、共110页。10.1.3图形(图形(Picture)对象)对象 procedure TForm2.Image1MouseDown (Sender:Tobject;Button:TMouseButton;Shift:TShiftState;X,Y:Integer);/绘制区域图像 var width,height:integer;newbitmap:TBitmap;begin if(trace=false)then begin /首次点击鼠标左键,开始追踪鼠标 flag:=false;with image1.Canvas do begin moveto(foldx,0);lineto(foldx
26、,screen.Height);moveto(0,foldy);lineto(screen.Width,foldy);*第29页,共110页。10.1.3图形(图形(Picture)对象)对象end;x1:=x;y1:=y;oldx:=x;oldy:=y;trace:=true;image1.Canvas.Pen.Color:=clblack;image1.Canvas.Brush.Style:=bsclear;end else begin/第2次点击鼠标,得到矩形,并将它拷贝到FORM1的IMAGE上 x2:=x;y2:=y;trace:=false;*第30页,共110页。10.1.3图形
27、(图形(Picture)对象)对象image1.Canvas.Rectangle(x1,y1,oldx,oldy);width:=abs(x2-x1);height:=abs(y2-y1);orm1.Image1.Width:=width;form1.Image1.Height:=height;newbitmap:=Tbitmap.Create;/生成Bitmap对象 newbitmap.Width:=width;n e w b i t m a p.H e i g h t:=h e i g h t;newbitmap.Canvas.CopyRect(rect(0,0,width,height)
28、,form2.Image1.Canvas,rect(x1,y1,x2,y2);form1.Image1.Picture.Bitmap:=newbitmap;/放到FORM的IMAGE上 newbitmap.Free;form2.Hide;form1.Show;end;end;end.*第31页,共110页。10.1.3图形(图形(Picture)对象)对象(6)运行得到如图的结果。*第32页,共110页。10.2 多媒体编程多媒体编程 10.2.1 简易媒体播放器实例简易媒体播放器实例 制作一个媒体播放器,需要在窗体上设置一个TmediaPlayer(该组件位于组件面板的System选项卡上,
29、图标为)、十个Tbutton、一个TopenDialog(位于组件面板的Dialogs选项卡上,图标为)等组件)、一个Edit、一个ComboBox、一个Timer如图所示。各个组件的名字(Name属性)采用默认值。*第33页,共110页。10.2.1 简易媒体播放器实例简易媒体播放器实例该媒体播放器的工作过程是:单击“打开”按钮,就会打开OpenDialog对话框,让用户从中选择一个文件。单击“播放”按钮,就会播放用户所选择的文件。下面的代码是用于处理Button8的OnClick事件,它将打开媒体播放器。procedure Tform1.Button8Click(Sender:Tobjic
30、t);begin if opendialog1.Execute then begin mediaplayer1.FileName:=opendialog1.FileName;mediaplayer1.open end;end.*第34页,共110页。10.2.1 简易媒体播放器实例简易媒体播放器实例为了OpenDialog对话框只列出多媒体文件,需要在属性查看器中设置OpenDialog1的Filter属性,单击打开Filter属性设置旁的按钮,将打开Filter Editor对话框,如图所示,在该对话框中键入所要打开文件的类型,如*.WAV、*.AVI、*.MID等,单击OK。设置好上述内容
31、后,保存该工程,这样一个简单的媒体播放器就制作好了。运行这个程序,打开一个多媒体文件即可。*第35页,共110页。10.2.2 媒体播放器组件媒体播放器组件 1.MediaPlayer组件组件 媒体播放器组件媒体播放器组件 媒体播放器组件属性媒体播放器组件属性*第36页,共110页。10.2.2 媒体播放器组件媒体播放器组件2.MediaPlayer组件的属性组件的属性(1)AutoEnable属性 该属性值是Boolean类型。如果这个属性设为True,媒体播放器在运行过程中能够自动控制哪些按钮当前可用,哪些按钮当前不可用(不可用的按钮以灰色显示)。(2)AutoOpen属性 该属性值是Bo
32、olean类型。如果这个属性设为True,媒体播放器自动打开DeveceType属性指定的多媒体设备(如果DeviceType属性设为dtAutoSelect,媒体播放器将自动打开FileName属性中指定的文件)。(3)AutoRewind属性 该属性值是Boolean类型,用于设置是否具有自动重绕功能。*第37页,共110页。10.2.2 媒体播放器组件媒体播放器组件(4)Capabilities属性 该属性值是只读TMPDevCapsSet类型,返回当前设备可以进行 的操作,它的值及值的含义如表所示。*第38页,共110页。10.2.2 媒体播放器组件媒体播放器组件(5)ColoredB
33、utton属性 该属性值是TbuttonSet集合类型,用于设置哪些按钮彩色显示,哪些按钮用黑白显示,默认时全部按钮均用彩色显示。*第39页,共110页。10.2.2 媒体播放器组件媒体播放器组件 MediaPlayer组件的其他属性列于表中。*第40页,共110页。10.2.2 媒体播放器组件媒体播放器组件上表Mode属性的取值及含义见表*第41页,共110页。10.2.2 媒体播放器组件媒体播放器组件3.MediaPlayer组件的过程和函数组件的过程和函数(1)AutoButtonSet过程 该过程用来指定媒体播放器的按钮是否可用。(2)Back过程 该过程使媒体播放器退回数个帧。(3)
34、Click过程 这是一个动态过程,该过程决定当OnClick事件被触发时执 行什么动作。在默认状态下,当OnClick事件触发时,该过程不招待任何动作,仅仅是调用一个事件处理程序,连接到媒体播放器的OnClick事件处理程序中。该过程可以根据需 要重新加载事件处理程序。(4)Close过程该过程关闭已打开的多媒体播放设备。当应用程序中止时,自动调用该过程。*第42页,共110页。10.2.2 媒体播放器组件媒体播放器组件(5)Create函数 这是一个动态的构造函数,该函数可在运行时建立一个 MediaPlayer对象,并对其进行初始化,使得媒体播放器既可 以在设计时静态建立,也可以在运行时通
35、过调用Create方法 动态建立。(6)Destroy函数 这是一个动态的析构函数,该函数用于撤销媒体播放器对象。应用程序不能直接调用该函数,应先调用Free过程检查媒体播 放器对象是否空闲,如果空闲就释放其占用的内存空间。该函 数执行前,必须确保媒体设备已经关闭。*第43页,共110页。10.2.2 媒体播放器组件媒体播放器组件MediaPlayer媒体播放器的其他过程表。*第44页,共110页。10.2.2 媒体播放器组件媒体播放器组件 MediaPlayer媒体播放器的其他过程表。*第45页,共110页。10.2.2 媒体播放器组件媒体播放器组件4.MediaPlayer组件的事件组件的
36、事件(1)OnClick事件 当用户移动光标到媒体播放器控制按钮组的任一按钮上,单 击鼠标左键或者当媒体播放器控制按钮获得焦点时,单击空格键都将会触发该事件。(2)OnNotify事件 如果Notify属性设置为True,当一个媒体控制方法(如Back、Close、Eject、Next、Open、Pause、PauseOnly、Play.Previous、Resume、StartRecording、Step、Stop等)执 行结束时,触发该事件。OnNotify事件触发后,必须重新 设置Notify属性为True,以便触发下一个OnNotify事件。*第46页,共110页。10.2.2 媒体播
37、放器组件媒体播放器组件(3)OnPostClick事件 当OnClick事件处理程序被调用以后,触发该事件。(4)OnEnter事件 当一个控件接收到键入焦点时,触发该事件。*第47页,共110页。10.3 线程线程 10.3.1 线程概念线程概念 所谓多线程,是指操作系统同时运行多个执行体的能力。线程概念与并发性是紧密相关的,多线程的出发点就是为了提高系统的并发度。线程与进程的差别主要体现在两个方面:线程和进程虽然都是系统的基本执行单元,线程的划分单位比进程小,因此支持多线程的系统比只支持多进程的系统并发度高;进程将内存作为自己独享的资源,每个进程都有自己的内存空间;而线程共享内存空间,并通
38、过共享内存交换信息,因此有利于提高系统效率。*第48页,共110页。10.3.2 TThread类类 TThread类类 TThread类是直接从Tobject继承下来的,它是抽象类,即不能创建TThread类的实例,而只能创建TThread派生类的实例即创建线程对象。创建线程对象的方法是,选择Delphi 7主菜单下的FileNewOther,在弹出的“New Items”对话框的“New”选项卡中选择Thread Object图标,如图所示。*第49页,共110页。10.3.2 TThread类类 当双击Thread Object图标后,将出现如图所示的对话框,提示输入 线程对象的名称,线
39、程对象名称是一个标识符,如TestThread。输入线程对象名后,Delphi 7会自动创建一个包括该线程对象的单 元,该单元给出了线程的框架,其最初的内容如下所示:*第50页,共110页。10.3.2 TThread类类unit Unit1;interfaceuses Classes;type TestThread=class(TThread)private Private declarations protected procedure Execute;override;end;implementation TestThread procedure TestThread.Execute;b
40、egin Place thread code here end;end.*第51页,共110页。10.3.2 TThread类类TThread派生类中唯一必须覆盖的方法是Excute(),即需要定义线程所执行的功能。当Create()需要参数为False,则当调用Create()后,线程对象的Execute()方法将会自动被调用,即自动地执行Execute()的代码。当Create()需要参数为False,则不自动执行Execute()的代码,而是要通过TThread的Resume()方法来唤醒线程。*第52页,共110页。10.3.2 TThread类类2.与与VCL同步同步 大多数VCL都
41、要求在任一时刻只允许一个线程访问它,因此在Delphi中使用多线程,还有一个重要的注意事项,即对VCL访问只能在主线程中进行,这表明所有与用户交互的代码只能在主线程中。同时,Delphi为了使线程中的方法也能在主线程中执行,在TThread中设置了一个Synchronize()方法,该方法声明如下:procedure Synchronize(Method:TThreadMethod);Synchronize()方法的参数就是用来传递需要在主线程中执行的线程中的方法。*第53页,共110页。10.3.3 线程的终止线程的终止 当线程对象的Execute()方法执行完毕后,就认为该线程终止了,此时
42、Delphi会自动调用一个标准例程EndThread(),该例程将再调用API函数ExitThread(),由ExitThread()来清除线程所占用的栈。线程终止时,将触发OnTerminate事件,可以利用在退出Execute()之前将FreeOnTerminate属性置为True的方法来及时清除线程对象。procedure TestThread.Execute;var i:integer;Begin FreeOnTerminate:=True;/设置FreeOnTerminate为true以便及时清除线程对象 For i:=1 to 10000 dobegin If Terminated
43、 then break;Value:=Value+1;end;End;*第54页,共110页。10.3.3 线程的终止线程的终止 【例】【例】创建如图所示的窗体,单击“开始”按钮后,将创建一个附 属线程,该线程执行一个计算任务,与此同时主线程并发执行,用户可在文本区域输入任意的字符。示例中所使用的窗体和组件的属性列于表中,未列的属性均取默认值。主窗体(设计时)主窗体(设计时)*第55页,共110页。10.3.3 线程的终止线程的终止 窗体与组件的属性设置*第56页,共110页。10.3.3 线程的终止线程的终止保存主窗体单元为Main.pas,源程序如下:unit Main;interface
44、 uses Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,Dialogs,StdCtrls,ThrdU;type TMainForm=class(TForm)Label1:TLabel;Button1:TButton;Label2:TLabel;Edit1:TEdit;Memo1:TMemo;procedure Button1Click(Sender:TObject);end;*第57页,共110页。10.3.3 线程的终止线程的终止var MainForm:TMainForm;implementation
45、$R*.dfmprocedure TMainForm.Button1Click(Sender:TObject);begin TTestThread.Create(False);创建线程,使其立即执行 end;end.*第58页,共110页。10.3.3 线程的终止线程的终止创建线程单元ThrdU.pas,选择主菜单的FileNewUnit,输入线程对象名为TtestThread,再输入以下源程序:unit ThrdU;interfaceuses Classes;type TTestThread=class(TThread)线程TTestThread类定义 private Answer:inte
46、ger;protected procedure GiveAnswer;procedure Execute;override;end;implementationuses SysUtils,Main;procedure TTestThread.GiveAnswer;begin MainForm.Edit1.Text:=InttoStr(Answer);end;*第59页,共110页。10.3.3 线程的终止线程的终止 TTestThread procedure TTestThread.Execute;执行一个较长的计算任务Var i:integer;begin FreeOnTerminate:=
47、True;for i:=1 to 2000000 do begin if Terminated then break;Inc(Answer,Round(abs(sin(sqrt(i);Synchronize(GiveAnswer);使GiveAnswer能在主线程中执行 end;end;end.*第60页,共110页。10.3.3 线程的终止线程的终止单击F9运行程序,结果如图所示。*第61页,共110页。10.3.4 线程同步线程同步 编写多线程应用程序时,需要控制好线程间的同步资源访问,以保证线程的安全运行。所谓线程同步,简单说就是协调线程间的执行时序。Win32 API提供了一组同步对象
48、,包括信号量、互斥、临界区和事件等,来解决线程的同步问题。Delphi分别将事件对象和临界区对象封装为TEvent和TCriticalSection对象,使得事件和临界区更易使用。*第62页,共110页。10.3.4 线程同步线程同步临界区临界区 临界区是指一次只能由一个线程执行的一段代码。在使用 临界区之前,要使用InitializeCriticalSection()过程来初始化它,其声明如下:procedure InitializeCriticalSection(var lpCriticalSection:TRTLCriticalSection);stdcall;lpCriticalSec
49、tion是一个TRTLCriticalSection类型的记录,在该参数中传递未初始化的记录,InitializeCriticalSection()过程就会填充这个记录。TRTLCriticalSection是一个与临界区资源相关的类型,。*第63页,共110页。10.3.4 线程同步线程同步创建临界区,使用EnterCriticalSection()和LeaveCriticalSection()过程来封装代码块。这两个过程的声明如下:procedure EnterCriticalSection(var lpCriticalSection:TRTLCriticalSection);stdcal
50、l;procedure LeaveCriticalSection(var lpCriticalSection:TRTLCriticalSection);stdcall;当不再需要TRTLCriticalSection记录时,要调用DeleteCriticalSection()过程将其删除。*第64页,共110页。10.3.4 线程同步线程同步【例】【例】设有一个全局数组,分别用两个线程对其进行两次初始化,需要对这两个线程同步,否则将出现数据不确定的情形。用临界区方式进行两线程的同步,将对数组各元素赋值的代码设为临界区。程序界面如图所示,当单击“初始化”按钮后,将生成两个线程并执行,在列表框中显
侵权处理QQ:3464097650--上传资料QQ:3464097650
【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。