版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、第10章 其他編程 Delphi實(shí)用教程*第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)兩點(diǎn)所 確定的橢圓所決定?;〉钠瘘c(diǎn)是橢圓圓周和橢圓中心與(x3,y3) 連線的交點(diǎn)?;【匦谓K點(diǎn)是橢圓周和橢圓中心與(x4,y4)連線的 交點(diǎn),以逆時(shí)針方向畫弧。 例如,以下的程序?qū)⒃诖翱谥袑⒃诖翱谥欣L制一個(gè)圓?。?procedure TForm1.FormPa
2、int(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方法連接橢圓上的兩點(diǎn),橢圓由(x1,y1)、 (x2,y2)兩點(diǎn)所確定的矩形決定,(x3,y3)是始點(diǎn), (x4,y4)是終點(diǎn)。 例如,在Form1窗體上放置一個(gè)按鈕“
3、連接橢圓上的兩點(diǎn)”, 雙擊該按鈕,輸入下面的代碼: 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類的Chord方法示例 *第4頁,共110頁。10.1.1畫布的通用屬性和方法(3
4、)Brushcopy方法 語法: Brushcopy(const Dest: TRect;Bitmap: Tbitmap; const Source TRect;Color:Tcolor)Brushcopy方法把位圖的一部分復(fù)制到畫布的某個(gè)矩形區(qū)域,并用畫筆的當(dāng)前顏色替換位圖的顏色。Dest定義畫布的一個(gè)矩形區(qū)域,該矩形用以填充位圖,Bitmap定義位圖;Source定義位圖中的矩形區(qū)域,該區(qū)域上的位圖將被復(fù)制;Color定義畫筆中,用以替換位圖的顏色。 *第5頁,共110頁。10.1.1畫布的通用屬性和方法(4)CopyRect方法 語法: CopyRect(Dest:TRect;Canva
5、s:TCanvas;SourceTRect)此方法從另一個(gè)畫布對象上復(fù)制部分圖像到該畫布。Canvas表示復(fù)制畫布,Source是源畫布上要復(fù)制的圖像區(qū)域,Dest表示目標(biāo)畫布上將接受復(fù)制圖像的矩形區(qū)域。 *第6頁,共110頁。10.1.1畫布的通用屬性和方法(5)Draw方法 語法:Draw(x,y:Integer;Graphic:Tgraphic)此方法在畫布給定的像素點(diǎn)坐標(biāo)(x,y)處畫由參數(shù)Graphic所給的圖像,該圖像可以是位圖、圖標(biāo)或元位圖。Tcanvas的其他方法列于表中。 *第7頁,共110頁。10.1.1畫布的通用屬性和方法2. Tpen Object(畫筆對象) 用于在畫
6、布上繪制各種線段,該對象常用的屬性有:l Color:定義筆的顏色;l Width:定義線段寬度;l Style:定義線段的各種類型,如表所示; *第8頁,共110頁。10.1.1畫布的通用屬性和方法 Mode:定義線段的顏色,取值如表所示。 *第9頁,共110頁。10.1.1畫布的通用屬性和方法3. Tbrush Object(畫刷對象)畫刷對象用以填充圖形,如用畫刷顏色或圖案對矩形或橢圓進(jìn)行填充。Tbrush擁有一個(gè)畫刷句柄(Hbrush)。畫刷的顏色定義在Color屬性中,畫刷還有一個(gè)Bitmap屬性,該屬性只能在運(yùn)行時(shí)得到,畫刷可使用位圖填充圖形以產(chǎn)生特殊效果。 *第10頁,共110頁
7、。10.1.1畫布的通用屬性和方法4. TColor類型 TColor類型用于定義一個(gè)對象的顏色。很多部件的顏色屬性就是TColor類型,在Graphics單元中TColor定義如下:TColor=-(COLOR_ENDCOLORS+1)$02FFFFF;*第11頁,共110頁。10.1.2 圖形圖像組件 Image組件 Image組件是一個(gè)容器組件,它在應(yīng)用程序窗體窗口中提供了一個(gè)矩形區(qū)域,用于顯示和輸出位圖、圖標(biāo)、圖元文件或用戶自定義的圖形文件。Image組件的常用屬性表。 *第12頁,共110頁。10.1.2 圖形圖像組件 2. Shape組件 Shape組件用于在窗體中繪制幾何圖形,如
8、橢圓、矩形和圓角矩形等。該組件的常用屬性有: l Shape:指明需要繪制的幾何圖形,它可能的取值和含義 如表所示; lBrush:指明在幾何圖形中填充的樣式; l Pen:指定幾何圖形所使用的線型。 *第13頁,共110頁。10.1.2 圖形圖像組件 3. PaintBox組件 該組件是一個(gè)簡單的畫板,它為應(yīng)用程序提供了可在窗體的特定矩形區(qū)域內(nèi)畫圖的方法。PaintBox組件的主要屬性有: (1) Anchors屬性 該屬性包含4個(gè)子屬性(akLeft、akTop、akRight和akBotton),用來指定在運(yùn)行過程中,當(dāng)父組件是可調(diào)時(shí),它相對于父組件邊沿的位置。(2) BoundsRec
9、t屬性 該屬性用來指定組件的矩形邊界,用其父組件的坐標(biāo)系來表示。 *第14頁,共110頁。10.1.2 圖形圖像組件 例如,以下代碼用于繪制矩形:procedure Tform1.Button1Click(Sender:TObject);var MyRect:TRect;begin MyRect:=ActiveControl.BoundsRect; MyRect.right=MyRect.Left+2*(MyRect.Right-MyRect.Left); MyRect.Botton:=MyRect.Top+(MyRect.Botton-MyRect.Top) div 2; ActiveCon
10、trol.BoundsRect:=MyRect;end;(3) Canvas屬性 該屬性僅在運(yùn)行時(shí)有效,使用該屬性可以在組件表面的特定區(qū)域進(jìn)行繪圖。 (4) Color屬性該屬性可用于除“顏色”對話框以外的所有組件或?qū)ο蟆?(5) Constaints屬性該屬性強(qiáng)制指定組件的大小。 *第15頁,共110頁。10.1.3圖形(Picture)對象 讀取圖像 讀取圖像需要使用LoadFromFile方法來調(diào)用,同時(shí)配合 OpenDialog函數(shù)來選擇相應(yīng)的圖像文件。下面的代碼實(shí)現(xiàn)對 圖像文件的讀?。?procedure Tform1.Open1Click(Sender:Tobject); begi
11、n if OpenDialog1.Execute then begin CurrentFile:=OpenDialog1.Filename;Image.Picture.LoadFromFile(CurrentFile); end; end; *第16頁,共110頁。10.1.3圖形(Picture)對象 2. 保存圖像 為將Image組件中的圖像保存為文件,可調(diào)用Image組件的Picture屬性的SaveToFile方法。SaveToFile方法需要一個(gè)保存文件的文件名。下面的代碼是一般程序常用的“Save”和“Save As”菜單的處理程序: procedure Tform1.Save1C
12、lick(Sender:Tobject) beginif CurrentFile then Image.Picture.SaveToFile(CurrentFile)else SaveAsClick(Sender);end;procedure Tform.Saveas1Click(Sender:TObject);begin if SaveDialog1.Execute then begin CurrentFile:=SaveDialog1.FileName; Save1Click(Sender); end;end; *第17頁,共110頁。10.1.3圖形(Picture)對象 3. 替換圖像
13、 用戶可以在任何進(jìn)修替換掉Image組件中的圖像,只要將一新的圖像對象賦給Picture就可以了。下面的代碼實(shí)現(xiàn)用一個(gè)新的位圖對象代替原有的Image組件中的Picture中的圖像對象的功能:Bitmap:Tbitmap:beginBitmap:=Tbitmap.Create;Bitmap.Width:=NewWidth;Bitmap.Height:=NewHeight;Image.Picture.Graphic:=Bitmap;CurrentFile:=;end; *第18頁,共110頁。10.1.3圖形(Picture)對象 【例】屏幕復(fù)制,將當(dāng)前屏幕的圖像抓下來,顯示到窗口中;還可以文件
14、的形式保存起來。步驟如下: (1) 建立用戶界面:建立窗體Form1,添加一個(gè)Panel、一個(gè)Timer、 一個(gè)SavePictureDialog、四個(gè)Button控件并在Panel控件上添加一個(gè) Image控件。 (2) 再創(chuàng)建窗體Form2,用于窗口抓圖的顯示窗口;在該窗體中添加一個(gè)Image控件和Timer控件,其中Image控件用于保存圖像。 (3) 設(shè)置控件屬性:對添加的控件按下表設(shè)置其屬性。*第19頁,共110頁。10.1.3圖形(Picture)對象 控件的屬性設(shè)置 *第20頁,共110頁。10.1.3圖形(Picture)對象(4) 激活第一個(gè)單元文件,單擊Delphi 7的F
15、ile菜單下的Use Unit項(xiàng), 出現(xiàn)窗口,選擇Unit2,單擊OK。(5) 編寫程序代碼如下 : procedure TForm1.Timer1Timer(Sender: TObject); / 完成對屏幕的復(fù)制,并粘帖到Image控件中 var Fullscreen:Tbitmap; Fullscreencanvas:tcanvas; dc:HDC; begin timer1.Enabled:=false; fullscreen:=tbitmap.Create; / 建立一個(gè)BITMAP來存放圖像 fullscreen.Width:=screen.Width; dc:=getdc(0);
16、 / API函數(shù),獲取屏幕 fullscreencanvas:=tcanvas.Create;/ 建立一個(gè)CANVAS對象 fullscreencanvas.Handle:=dc; fullscreen.Canvas.CopyRect(rect(0,0,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.Bit
17、map:=fullscreen; / 將拷貝下的圖像賦給IMAGE對象 image1.Width:=fullscreen.Width; image1.Height:=fullscreen.Height; fullscreen.Free; form1.WindowState:=wsnormal; form1.Show; messagebeep(1); end; procedure TForm1.Button4Click(Sender: TObject); begin close; end;*第22頁,共110頁。10.1.3圖形(Picture)對象 procedure TForm1.Butto
18、n1Click(Sender: TObject); begin form1.WindowState:=wsminimized; form1.Hide; timer1.Enabled:=true; end; procedure TForm1.Button3Click(Sender: TObject); begin if form1.SavePictureDialog1.Execute then begin form2.Image1.Picture.SaveToFile(savepicturedialog1.FileName); end; end;*第23頁,共110頁。10.1.3圖形(Pict
19、ure)對象procedure TForm1.Button2Click(Sender: TObject); begin form1.Hide; form2.Hide; form2.Timer1.Enabled:=true; end; end. var Form2: TForm2; foldx,x1,y1,x2,y2,oldx,oldy,foldy:integer;flag,trace:boolean;implementationuses unit3;$R *.dfm*第24頁,共110頁。10.1.3圖形(Picture)對象 procedure TForm2.Timer1Timer(Send
20、er: TObject); var fullscreen:TBitmap;fullscreencanvas:TCanvas;dc:HDC; beginform2.timer1.enabled:=false; fullscreen:=tbitmap.create; fullscreen.width:=screen.Width; fullscreen.Height:=screen.Height; dc:=getdc(0); fullscreencanvas:=tcanvas.Create; fullscreencanvas.Handle:=dc; fullscreen.Canvas.CopyRec
21、t(rect(0,0,screen.Width,screen.Height), fullscreencanvas,rect(0,0,screen.Width,screen.Height); fullscreencanvas.Free; releasedc(0,dc);*第25頁,共110頁。10.1.3圖形(Picture)對象 image1.Picture.Bitmap:=fullscreen; image1.Width:=fullscreen.Width; image1.Height:=fullscreen.Height; fullscreen.Free; form2.WindowStat
22、e:=wsnormal; form2.Show; messagebeep(1); foldx:=-1; foldy:=-1; image1.Canvas.Pen.Mode:=pmnot; / 筆的模式取反 image1.Canvas.Pen.Color:=clblack;/ 筆的顏色 image1.Canvas.Brush.Style:=bsclear; / 刷子的格式 flag:=true; end;*第26頁,共110頁。10.1.3圖形(Picture)對象 procedure TForm2.Image1MouseMove(Sender:Tobject;Shift:TShiftState
23、;X,Y:Integer); begin if trace=true then / 追蹤鼠標(biāo) begin / 擦除舊的圖形并畫上新的圖形 with image1.Canvas do begin rectangle(x1,y1,oldx,oldy); rectangle(x1,y1,x,y); oldx:=x; oldy:=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.He
24、ight); 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頁,共110頁。10.1.3圖形(Picture)對象 procedure TForm2.Image1MouseDown (Sender:Tobject;Button:TMouseButton;Shift:TShiftState;X,Y:Integer); / 繪制區(qū)域
25、圖像 var width,height:integer; newbitmap:TBitmap; begin if(trace=false) then begin / 首次點(diǎn)擊鼠標(biāo)左鍵,開始追蹤鼠標(biāo) flag:=false; with image1.Canvas do begin moveto(foldx,0); lineto(foldx,screen.Height); moveto(0,foldy); lineto(screen.Width,foldy);*第29頁,共110頁。10.1.3圖形(Picture)對象end; x1:=x; y1:=y; oldx:=x; oldy:=y; tr
26、ace:=true; image1.Canvas.Pen.Color:=clblack; image1.Canvas.Brush.Style:=bsclear; end else begin / 第2次點(diǎn)擊鼠標(biāo),得到矩形,并將它拷貝到FORM1的IMAGE上 x2:=x; y2:=y; trace:=false;*第30頁,共110頁。10.1.3圖形(Picture)對象image1.Canvas.Rectangle(x1,y1,oldx,oldy); width:=abs(x2-x1); height:=abs(y2-y1); orm1.Image1.Width:=width; form1
27、.Image1.Height:=height; newbitmap:=Tbitmap.Create; / 生成Bitmap對象 newbitmap.Width:=width; newbitmap.Height:=height; newbitmap.Canvas.CopyRect(rect(0,0,width,height),form2.Image1.Canvas,rect(x1,y1,x2,y2); form1.Image1.Picture.Bitmap:=newbitmap;/ 放到FORM的IMAGE上 newbitmap.Free; form2.Hide; form1.Show; end
28、;end;end.*第31頁,共110頁。10.1.3圖形(Picture)對象(6) 運(yùn)行得到如圖的結(jié)果。 *第32頁,共110頁。10.2 多媒體編程 10.2.1 簡易媒體播放器實(shí)例 制作一個(gè)媒體播放器,需要在窗體上設(shè)置一個(gè)TmediaPlayer(該組件位于組件面板的System選項(xiàng)卡上,圖標(biāo)為)、十個(gè)Tbutton、一個(gè)TopenDialog(位于組件面板的Dialogs選項(xiàng)卡上,圖標(biāo)為)等組件)、一個(gè)Edit、一個(gè)ComboBox、一個(gè)Timer如圖所示。各個(gè)組件的名字(Name屬性)采用默認(rèn)值。 *第33頁,共110頁。10.2.1 簡易媒體播放器實(shí)例該媒體播放器的工作過程是:單
29、擊“打開”按鈕,就會(huì)打開OpenDialog對話框,讓用戶從中選擇一個(gè)文件。單擊 “播放”按鈕,就會(huì)播放用戶所選擇的文件。下面的代碼是用于處理Button8的OnClick事件,它將打開媒體播放器。 procedure Tform1.Button8Click(Sender:Tobjict); begin if opendialog1.Execute then begin mediaplayer1.FileName:=opendialog1.FileName; mediaplayer1.open end; end. *第34頁,共110頁。10.2.1 簡易媒體播放器實(shí)例為了OpenDialog
30、對話框只列出多媒體文件,需要在屬性查看器中設(shè)置OpenDialog1的Filter屬性,單擊打開Filter屬性設(shè)置旁的按鈕,將打開Filter Editor對話框,如圖所示,在該對話框中鍵入所要打開文件的類型,如*.WAV、*.AVI、*.MID等,單擊OK。設(shè)置好上述內(nèi)容后,保存該工程,這樣一個(gè)簡單的媒體播放器就制作好了。運(yùn)行這個(gè)程序,打開一個(gè)多媒體文件即可。 *第35頁,共110頁。10.2.2 媒體播放器組件 1. MediaPlayer組件 媒體播放器組件 媒體播放器組件屬性 *第36頁,共110頁。10.2.2 媒體播放器組件2. MediaPlayer組件的屬性(1)AutoEn
31、able屬性 該屬性值是Boolean類型。如果這個(gè)屬性設(shè)為True,媒體播放器在運(yùn)行過程中能夠自動(dòng)控制哪些按鈕當(dāng)前可用,哪些按鈕當(dāng)前不可用(不可用的按鈕以灰色顯示)。 (2)AutoOpen屬性 該屬性值是Boolean類型。如果這個(gè)屬性設(shè)為True,媒體播放器自動(dòng)打開DeveceType屬性指定的多媒體設(shè)備(如果DeviceType屬性設(shè)為dtAutoSelect,媒體播放器將自動(dòng)打開FileName屬性中指定的文件)。 (3)AutoRewind屬性 該屬性值是Boolean類型,用于設(shè)置是否具有自動(dòng)重繞功能。 *第37頁,共110頁。10.2.2 媒體播放器組件(4)Capabilit
32、ies屬性 該屬性值是只讀TMPDevCapsSet類型,返回當(dāng)前設(shè)備可以進(jìn)行 的操作,它的值及值的含義如表所示。 *第38頁,共110頁。10.2.2 媒體播放器組件(5)ColoredButton屬性 該屬性值是TbuttonSet集合類型,用于設(shè)置哪些按鈕彩色顯示,哪些按鈕用黑白顯示,默認(rèn)時(shí)全部按鈕均用彩色顯示。 *第39頁,共110頁。10.2.2 媒體播放器組件 MediaPlayer組件的其他屬性列于表中。 *第40頁,共110頁。10.2.2 媒體播放器組件上表Mode屬性的取值及含義見表 *第41頁,共110頁。10.2.2 媒體播放器組件3. MediaPlayer組件的過程
33、和函數(shù) (1)AutoButtonSet過程 該過程用來指定媒體播放器的按鈕是否可用。 (2)Back過程 該過程使媒體播放器退回?cái)?shù)個(gè)幀。 (3)Click過程 這是一個(gè)動(dòng)態(tài)過程,該過程決定當(dāng)OnClick事件被觸發(fā)時(shí)執(zhí)行什么動(dòng)作。在默認(rèn)狀態(tài)下,當(dāng)OnClick事件觸發(fā)時(shí),該過程不招待任何動(dòng)作,僅僅是調(diào)用一個(gè)事件處理程序,連接到媒體播放器的OnClick事件處理程序中。該過程可以根據(jù)需要重新加載事件處理程序。 (4)Close過程該過程關(guān)閉已打開的多媒體播放設(shè)備。當(dāng)應(yīng)用程序中止時(shí),自動(dòng)調(diào)用該過程。 *第42頁,共110頁。10.2.2 媒體播放器組件(5)Create函數(shù) 這是一個(gè)動(dòng)態(tài)的構(gòu)造函
34、數(shù),該函數(shù)可在運(yùn)行時(shí)建立一個(gè) MediaPlayer對象,并對其進(jìn)行初始化,使得媒體播放器既可 以在設(shè)計(jì)時(shí)靜態(tài)建立,也可以在運(yùn)行時(shí)通過調(diào)用Create方法 動(dòng)態(tài)建立。(6)Destroy函數(shù) 這是一個(gè)動(dòng)態(tài)的析構(gòu)函數(shù),該函數(shù)用于撤銷媒體播放器對象。 應(yīng)用程序不能直接調(diào)用該函數(shù),應(yīng)先調(diào)用Free過程檢查媒體播 放器對象是否空閑,如果空閑就釋放其占用的內(nèi)存空間。該函 數(shù)執(zhí)行前,必須確保媒體設(shè)備已經(jīng)關(guān)閉。 *第43頁,共110頁。10.2.2 媒體播放器組件MediaPlayer媒體播放器的其他過程表。 *第44頁,共110頁。10.2.2 媒體播放器組件 MediaPlayer媒體播放器的其他過程表
35、。*第45頁,共110頁。10.2.2 媒體播放器組件4. MediaPlayer組件的事件 (1)OnClick事件 當(dāng)用戶移動(dòng)光標(biāo)到媒體播放器控制按鈕組的任一按鈕上,單擊鼠標(biāo)左鍵或者當(dāng)媒體播放器控制按鈕獲得焦點(diǎn)時(shí),單擊空格鍵都將會(huì)觸發(fā)該事件。(2)OnNotify事件 如果Notify屬性設(shè)置為True,當(dāng)一個(gè)媒體控制方法( 如Back、Close、Eject、Next、Open、Pause、PauseOnly、 Play.Previous、Resume、StartRecording、Step、Stop等)執(zhí) 行結(jié)束時(shí),觸發(fā)該事件。OnNotify事件觸發(fā)后,必須重新 設(shè)置Notify屬性
36、為True,以便觸發(fā)下一個(gè)OnNotify事件。 *第46頁,共110頁。10.2.2 媒體播放器組件(3)OnPostClick事件 當(dāng)OnClick事件處理程序被調(diào)用以后,觸發(fā)該事件。(4)OnEnter事件 當(dāng)一個(gè)控件接收到鍵入焦點(diǎn)時(shí),觸發(fā)該事件。 *第47頁,共110頁。10.3 線程 10.3.1 線程概念 所謂多線程,是指操作系統(tǒng)同時(shí)運(yùn)行多個(gè)執(zhí)行體的能力。線程概念與并發(fā)性是緊密相關(guān)的,多線程的出發(fā)點(diǎn)就是為了提高系統(tǒng)的并發(fā)度。 線程與進(jìn)程的差別主要體現(xiàn)在兩個(gè)方面: 線程和進(jìn)程雖然都是系統(tǒng)的基本執(zhí)行單元,線程的劃分單位比進(jìn)程小,因此支持多線程的系統(tǒng)比只支持多進(jìn)程的系統(tǒng)并發(fā)度高;進(jìn)程將內(nèi)
37、存作為自己獨(dú)享的資源,每個(gè)進(jìn)程都有自己的內(nèi)存空間;而線程共享內(nèi)存空間,并通過共享內(nèi)存交換信息,因此有利于提高系統(tǒng)效率。 *第48頁,共110頁。10.3.2 TThread類 TThread類 TThread類是直接從Tobject繼承下來的,它是抽象類,即不能創(chuàng)建TThread類的實(shí)例,而只能創(chuàng)建TThread派生類的實(shí)例即創(chuàng)建線程對象。 創(chuàng)建線程對象的方法是,選擇Delphi 7主菜單下的FileNewOther,在彈出的“New Items”對話框的“New”選項(xiàng)卡中選擇Thread Object圖標(biāo),如圖所示。 *第49頁,共110頁。10.3.2 TThread類 當(dāng)雙擊Thread
38、 Object圖標(biāo)后,將出現(xiàn)如圖所示的對話框,提示輸入 線程對象的名稱,線程對象名稱是一個(gè)標(biāo)識符,如TestThread。 輸入線程對象名后,Delphi 7會(huì)自動(dòng)創(chuàng)建一個(gè)包括該線程對象的單 元,該單元給出了線程的框架,其最初的內(nèi)容如下所示: *第50頁,共110頁。10.3.2 TThread類unit Unit1;interfaceuses Classes;type TestThread = class(TThread) private Private declarations protected procedure Execute; override;end;implementation
39、 TestThread procedure TestThread.Execute;begin Place thread code here end;end.*第51頁,共110頁。10.3.2 TThread類TThread派生類中唯一必須覆蓋的方法是Excute(),即需要定義線程所執(zhí)行的功能。 當(dāng)Create()需要參數(shù)為False,則當(dāng)調(diào)用Create()后,線程對象的Execute()方法將會(huì)自動(dòng)被調(diào)用,即自動(dòng)地執(zhí)行Execute()的代碼。當(dāng)Create()需要參數(shù)為False ,則不自動(dòng)執(zhí)行Execute()的代碼,而是要通過TThread的Resume()方法來喚醒線程。 *第5
40、2頁,共110頁。10.3.2 TThread類2. 與VCL同步 大多數(shù)VCL都要求在任一時(shí)刻只允許一個(gè)線程訪問它,因此在Delphi中使用多線程,還有一個(gè)重要的注意事項(xiàng),即對VCL訪問只能在主線程中進(jìn)行,這表明所有與用戶交互的代碼只能在主線程中。同時(shí),Delphi為了使線程中的方法也能在主線程中執(zhí)行,在TThread中設(shè)置了一個(gè)Synchronize()方法,該方法聲明如下:procedure Synchronize(Method:TThreadMethod); Synchronize()方法的參數(shù)就是用來傳遞需要在主線程中執(zhí)行的線程中的方法。 *第53頁,共110頁。10.3.3 線程的
41、終止 當(dāng)線程對象的Execute()方法執(zhí)行完畢后,就認(rèn)為該線程終止了,此時(shí)Delphi會(huì)自動(dòng)調(diào)用一個(gè)標(biāo)準(zhǔn)例程EndThread(),該例程將再調(diào)用API函數(shù)ExitThread(),由ExitThread()來清除線程所占用的棧。線程終止時(shí),將觸發(fā)OnTerminate事件,可以利用在退出Execute()之前將FreeOnTerminate屬性置為True的方法來及時(shí)清除線程對象。procedure TestThread.Execute;var i:integer;Begin FreeOnTerminate := True; /設(shè)置FreeOnTerminate為true以便及時(shí)清除線程對
42、象 For i:=1 to 10000 dobegin If Terminated then break; Value:=Value+1; end;End; *第54頁,共110頁。10.3.3 線程的終止 【例】創(chuàng)建如圖所示的窗體,單擊“開始”按鈕后,將創(chuàng)建一個(gè)附 屬線程,該線程執(zhí)行一個(gè)計(jì)算任務(wù),與此同時(shí)主線程并發(fā)執(zhí)行,用戶可在文本區(qū)域輸入任意的字符。示例中所使用的窗體和組件的屬性列于表中,未列的屬性均取默認(rèn)值。 主窗體(設(shè)計(jì)時(shí)) *第55頁,共110頁。10.3.3 線程的終止 窗體與組件的屬性設(shè)置 *第56頁,共110頁。10.3.3 線程的終止保存主窗體單元為Main.pas,源程序如
43、下: unit Main; interface 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.
44、3 線程的終止var MainForm: TMainForm;implementation$R *.dfmprocedure TMainForm.Button1Click(Sender: TObject);begin TTestThread.Create(False); 創(chuàng)建線程,使其立即執(zhí)行 end;end.*第58頁,共110頁。10.3.3 線程的終止創(chuàng)建線程單元ThrdU.pas,選擇主菜單的FileNewUnit,輸入線程對象名為TtestThread,再輸入以下源程序:unit ThrdU;interfaceuses Classes;type TTestThread = class
45、(TThread) 線程TTestThread類定義 private Answer:integer; 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; 執(zhí)行一
46、個(gè)較長的計(jì)算任務(wù)Var i:integer;begin FreeOnTerminate:=True; for i:=1 to 2000000 do begin if Terminated then break; Inc(Answer,Round(abs(sin(sqrt(i); Synchronize(GiveAnswer); 使GiveAnswer能在主線程中執(zhí)行 end;end;end.*第60頁,共110頁。10.3.3 線程的終止單擊F9運(yùn)行程序,結(jié)果如圖所示。 *第61頁,共110頁。10.3.4 線程同步 編寫多線程應(yīng)用程序時(shí),需要控制好線程間的同步資源訪問,以保證線程的安全運(yùn)行。
47、 所謂線程同步,簡單說就是協(xié)調(diào)線程間的執(zhí)行時(shí)序。Win32 API提供了一組同步對象,包括信號量、互斥、臨界區(qū)和事件等,來解決線程的同步問題。 Delphi分別將事件對象和臨界區(qū)對象封裝為TEvent和TCriticalSection對象,使得事件和臨界區(qū)更易使用。 *第62頁,共110頁。10.3.4 線程同步臨界區(qū) 臨界區(qū)是指一次只能由一個(gè)線程執(zhí)行的一段代碼。在使用 臨界區(qū)之前,要使用InitializeCriticalSection()過程來初始化它, 其聲明如下:procedure InitializeCriticalSection(var lpCriticalSection:TRTL
48、CriticalSection);stdcall; lpCriticalSection是一個(gè)TRTLCriticalSection類型的記錄, 在該參數(shù)中傳遞未初始化的記錄, InitializeCriticalSection()過程就會(huì)填充這個(gè)記錄。 TRTLCriticalSection是一個(gè)與臨界區(qū)資源相關(guān)的類型,。 *第63頁,共110頁。10.3.4 線程同步創(chuàng)建臨界區(qū),使用EnterCriticalSection()和LeaveCriticalSection()過程來封裝代碼塊。這兩個(gè)過程的聲明如下:procedure EnterCriticalSection(var lpCrit
49、icalSection: TRTLCriticalSection);stdcall;procedure LeaveCriticalSection(var lpCriticalSection: TRTLCriticalSection);stdcall; 當(dāng)不再需要TRTLCriticalSection記錄時(shí),要調(diào)用DeleteCriticalSection()過程將其刪除。 *第64頁,共110頁。10.3.4 線程同步【例】設(shè)有一個(gè)全局?jǐn)?shù)組,分別用兩個(gè)線程對其進(jìn)行兩次初始化,需要對這兩個(gè)線程同步,否則將出現(xiàn)數(shù)據(jù)不確定的情形。用臨界區(qū)方式進(jìn)行兩線程的同步,將對數(shù)組各元素賦值的代碼設(shè)為臨界區(qū)。程序
50、界面如圖所示,當(dāng)單擊“初始化”按鈕后,將生成兩個(gè)線程并執(zhí)行,在列表框中顯示數(shù)組元素值。 (1)創(chuàng)建應(yīng)用程序界面,新建如圖所示的窗體,并放置一個(gè) label、一個(gè)button和一個(gè)listbox組件,各組件及其屬性設(shè)置列于表中。 *第65頁,共110頁。10.3.4 線程同步窗體與組件的屬性設(shè)置 *第66頁,共110頁。10.3.4 線程同步 (2)在Form1對應(yīng)的Unit1單元文件中輸入程序代碼: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, For
51、ms, Dialogs, StdCtrls,unit2; Type TForm1 = class(TForm) Button1: TButton; ListBox1: TListBox; Label1: TLabel; procedure Button1Click(Sender: TObject); end; *第67頁,共110頁。10.3.4 線程同步var Form1: TForm1; CS:TRTLCriticalSection; / 聲明臨界區(qū)資源記錄變量implementation$R *.dfmprocedure TForm1.Button1Click(Sender: TObje
52、ct);begin InitializeCriticalSection(CS); / 初始化臨界區(qū) TInitThread.Create(False); / 創(chuàng)建TinitThread線程對象并執(zhí)行 TInitThread.Create(False);end;end.*第68頁,共110頁。10.3.4 線程同步(3)創(chuàng)建線程對象TinitThread,選擇主菜單的 FileNewOther,在New Items的New選項(xiàng)卡中雙擊 “Thread Object”圖標(biāo),在彈出的對話框中輸入線程名 “TinitThread”。(4)在系統(tǒng)自動(dòng)新建的Unit2單元中輸入程序代碼: unit Uni
53、t2; interface uses Windows, SysUtils, Classes; / 在此要添加Windows和SysUtils Type以下是TinitThread類定義 TInitThread = class(TThread) protected procedure ShowResult; / 顯示結(jié)果 procedure Execute; override; end; *第69頁,共110頁。10.3.4 線程同步implementationuses Unit1; const SIZE=10; / 數(shù)組大小var next:integer=0; / 全局變量定義 tag:in
54、teger=0; A:array 1.SIZE of integer; procedure TInitThread.ShowResult; var i:integer; begin inc(tag); if tag=2 then begin / 兩個(gè)線程均執(zhí)行完畢 for i:=1 to SIZE do /在列表框中顯示數(shù)組各元素值 Form1.ListBox1.Items.Add(intToStr(Ai); DeleteCriticalSection(CS); / 移去臨界區(qū) end;end;*第70頁,共110頁。10.3.4 線程同步procedure TInitThread.Execu
55、te; var i:integer; begin EnterCriticalSection(CS); / 進(jìn)入臨界區(qū) for i:=1 to SIZE do / 為數(shù)組各元素賦值begin Ai:=next; Inc(next); Sleep(5); end; LeaveCriticalSection(CS); / 臨界區(qū)終止 Synchronize(ShowResult);/ 使ShowResult能在主線程中執(zhí)行end; end.*第71頁,共110頁。10.3.4 線程同步(5)單擊F9運(yùn)行程序,結(jié)果如圖所示。 *第72頁,共110頁。10.3.4 線程同步說明:在第一個(gè)線程調(diào)用了Ent
56、erCriticalSection()之后,其他的線程就不能進(jìn)入臨界區(qū)代碼,它們將睡眠;直到第一個(gè)線程調(diào)用LeaveCriticalSection()后,下一個(gè)需要進(jìn)入臨界區(qū)的線程才被喚醒。 *第73頁,共110頁。10.3.4 線程同步2. 互斥 (1)互斥(mutex)與臨界區(qū)非常相似,但有兩個(gè)主要區(qū)別:互斥可用于不同進(jìn)程的線程間同步,而臨界區(qū)不可;互斥可被賦予一個(gè)字符串名,通過該名字可創(chuàng)建該互斥對象的 附加句柄。(2)創(chuàng)建互斥對象的函數(shù)是CreateMutex(),其原型為 function CreateMutex(lpMutexAttibutes:PsecurityAttributes
57、;bInitialOwner:BOOL;lpName:Pchar):Thandle;stdcall; lpMutexAttibutes參數(shù)為一個(gè)指向TsecurityAttributes記錄的指針,通 常置為0,表示使用默認(rèn)的安全屬性。 BInitialOwner參數(shù)用于指出創(chuàng)建互斥對象的線程是否要成為此互斥對 象的擁有者,該參數(shù)為false表示互斥對象沒有擁有者。 LpName參數(shù)指出互斥對象的名稱 。*第74頁,共110頁。10.3.4 線程同步(3)互斥對象不再使用時(shí),應(yīng)調(diào)用CloseHandle()過程來關(guān)閉它。當(dāng) 一個(gè)線程不需再擁有互斥對象時(shí),應(yīng)調(diào)用ReleaseMutex()過程。
58、 (4)為了防止其他線程進(jìn)入同步區(qū)代碼,需使用aitForSingleObject() 函數(shù),原型為:function WaitForSingleObject(hHandle: Thandle; dwMilliseconds:DWORD):DWAORD;stdcall; DwMilliseconds參數(shù)可設(shè)為兩個(gè)值: 當(dāng)值為0時(shí),函數(shù)將只檢查由hHandle參數(shù)指定的互斥對象是否處 于發(fā)信號狀態(tài),檢查完畢后函數(shù)立即返回 當(dāng)值為INFINITE時(shí),則函數(shù)將一直等待,直到信號出現(xiàn)為止 hHandle參數(shù)指定的互斥對象 返回值有3種: WAIT_ABANDONED,表明指定對象是互斥對象,并且擁有該
59、 互斥對象的線程在未釋放該對象之前就已終止 WAIT_OBJECT_0,表明指定的對象處于發(fā)信號狀態(tài) WAIT_TIMEOUT,表明等待的時(shí)間已過,對象仍是非發(fā)信號 狀態(tài) *第75頁,共110頁。10.3.4 線程同步【例】對于臨界區(qū)的例題,使用互斥方式進(jìn)行兩線程的同步,該應(yīng)用程序與臨界區(qū)的例題的差別僅在于線程同步方式不同,其余均相同。程序兩個(gè)單元文件的內(nèi)容分別為: / 文件Unit1.pasunit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Di
60、alogs, StdCtrls,Unit2;type TForm1 = class(TForm) Button1: TButton; Label1: TLabel; ListBox1: TListBox; procedure Button1Click(Sender: TObject);end;*第76頁,共110頁。10.3.4 線程同步var Form1: TForm1; hMutex:THandle=0; / 聲明互斥量implementation$R *.dfmprocedure TForm1.Button1Click(Sender: TObject);begin hMutex:=Cre
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 廣西壯族自治區(qū)桂林市2025-2026學(xué)年上學(xué)期期末高二物理試卷(無答案)
- 安徽省宣城市旌德縣2025-2026學(xué)年八年級上學(xué)期期末質(zhì)量檢測語文試卷(含答案)
- 韋達(dá)定理題目及答案
- 肺脹診療相關(guān)知識考試試題及答案
- 過山車中的物理知識課件
- 鋼結(jié)構(gòu)BIM應(yīng)用技術(shù)要領(lǐng)
- 地板輻射采暖技術(shù)要領(lǐng)
- 建筑設(shè)備安裝工藝與識圖復(fù)習(xí)要點(diǎn)及部分答案模板
- 上海高一集合試題及答案
- 汽修專業(yè)知識試題及答案
- 書館數(shù)據(jù)管理制度規(guī)范
- 2025年延安市市直事業(yè)單位選聘(76人)考試參考試題及答案解析
- 2025-2026年人教版二年級上冊語文期末考試卷及答案
- 檔案管理操作規(guī)程及實(shí)施細(xì)則
- 寒假班安全協(xié)議書
- 精神科醫(yī)生精神科醫(yī)療質(zhì)量控制方案
- 2026年高考語文專題復(fù)習(xí):文學(xué)類文本散文閱讀 講義(含練習(xí)題及答案)
- 2025廣東省南粵交通投資建設(shè)有限公司招聘筆試歷年參考題庫附帶答案詳解
- 2025年人工智能在電力調(diào)度中的應(yīng)用項(xiàng)目可行性研究報(bào)告及總結(jié)分析
- DB1310T 370-2025 化學(xué)分析實(shí)驗(yàn)室玻璃儀器清洗規(guī)范
- GB/T 46738-2025家用和類似用途電器的安全使用年限房間空氣調(diào)節(jié)器的特殊要求
評論
0/150
提交評論