DELPHI教程第四章.doc_第1頁
DELPHI教程第四章.doc_第2頁
DELPHI教程第四章.doc_第3頁
DELPHI教程第四章.doc_第4頁
DELPHI教程第四章.doc_第5頁
已閱讀5頁,還剩24頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第四章文本編輯器的設(shè)計(一)本章介紹多文本界面(MDI)、多頁面界面(MPI)技術(shù);VCL庫中TMemo,TEdit 控件以及有關(guān)文本編輯的常用對話框的使用。我們開發(fā)的MPIEdit.dpr是一個文本編輯的實用程序,可實現(xiàn)如下功能: MDI的編輯環(huán)境 MPI的編輯環(huán)境 創(chuàng)建打開、編輯、保存文件 查找、替換文件中指定的字符串 復(fù)制、粘貼、剪切字符串 設(shè)置文件字體大小 打印文件本章將通過MPIEdit實用程序逐一介紹在Delphi中如何實現(xiàn)上述功能。文本編輯器是一種常用的應(yīng)用程序。用戶在編輯器中編輯多種文件,在多個文件之間進行數(shù)據(jù)交換,對文件進行各種屬性設(shè)置,并按自己要求打印文件。4.1 多文本界面多文本界面是一種在一個應(yīng)用程序中同時打開兩個或更多文件的界面形式。例如在字處理程序可同時打開多個文件,用戶可在多個文件中方便地進行切換.MDI應(yīng)用程序提供了一種方便的方式,使得用戶在同一工作區(qū)域內(nèi)對多個文檔進行觀察和交換數(shù)據(jù)。MDI工作區(qū)域可分為父窗體和子窗體,在Dephi的MDI應(yīng)用程序中,父窗體通常是程序的主窗體。在MDI中,父窗體之外的窗體稱為子窗體,文檔或其它數(shù)據(jù)在子窗體打開。這些文檔可以是相同的文件格式,或在應(yīng)用程序支持下也可以是不同的文件格式。在設(shè)計階段,可創(chuàng)建 MDI 父窗體作為應(yīng)用程序主窗體, 亦可創(chuàng)建子窗體樣板。Delphi允許創(chuàng)建多個子窗體類型,但MDI應(yīng)用程序只支持其中的一種。本節(jié)講述創(chuàng)建MDI應(yīng)用程序的基本步驟: 創(chuàng)建主窗口 創(chuàng)建子窗口 創(chuàng)建主窗口菜單 融合菜單 運行時創(chuàng)建子窗口4.1.1 創(chuàng)建父窗口在MDI應(yīng)用程序中,主窗口為應(yīng)用文檔提供一個工作區(qū)域。這個區(qū)域可打開一個或多個子窗口,創(chuàng)建父窗口是建立MDI應(yīng)用程序的第一步。創(chuàng)建父窗口與其它窗口類似,不同之處在于設(shè)置窗體的FormStyle屬性。FormStyle屬性可決定一個窗體是父窗口還是子窗口,或不是MDI類型。 只能在設(shè)計階段確定FormStyle。在Object Inspector窗口中將FormStyle屬性設(shè)置成fsMDIForm。值得注意的是應(yīng)當(dāng)把父窗口定義為應(yīng)用程序的主窗體,否則程序編譯會出錯。4.1.2 創(chuàng)建子窗口設(shè)計階段可創(chuàng)建子窗口的樣板,用戶在運行進使用樣板的實例。子窗口是缺省可見的,如果應(yīng)用程序在運行進創(chuàng)建子窗口,不要讓Delphi自動地創(chuàng)建。創(chuàng)建子窗口時將窗體的FormStyle屬性設(shè)置為fsMDIChild。如果程序在運行時創(chuàng)建子窗口,則1. 選擇OPtions|Project菜單,系統(tǒng)彈出自動創(chuàng)建列表對話框;2. 在自動創(chuàng)建列表中選中子窗口;3. 單擊按鈕將子窗口移至可得到(Available)窗體列表;4. 并單擊OK按鈕退出。4.1.3 創(chuàng)建應(yīng)用程序菜單與菜單融合父窗口的菜單應(yīng)作為應(yīng)用程序主菜單。如果子窗口有菜單, 則當(dāng)子窗口在運行獲得焦點并最大化時,子窗口的菜單項將融合父窗口菜單。創(chuàng)建父窗口與子窗口菜單的方法與創(chuàng)建普通窗體菜單類似, 詳細步驟見第一章。菜單融合是指程序運行過程中,子菜單與父窗口菜單的相互作用。 如當(dāng)子窗口獲得焦點時,子窗口的菜單或插入主窗口的菜單中,或?qū)⑻鎿Q部分或全部的父窗口菜單。進行菜單融合需設(shè)置的兩個屬性: 窗體的Menu屬性 菜單項的GroupIndex屬性Menu屬性定義窗體的活動菜單,而菜單融合只對活動菜單進行。如果窗體有多個菜單部件,運行時可通過以下代碼進行改變: Form1.Menu := SecondMenu;GroupIndex屬性決定出現(xiàn)在菜單條中各菜單項的位置,在菜單融合中,GroupIndex 將決定融合菜單是插入還是替換主窗體菜單條中的菜單。GroupIndex的缺省值是0,可以用下規(guī)則確定其值: 1. 數(shù)值越小,菜單的位置越靠左。例如:GroupIndex為0的菜單將出現(xiàn)在菜單條中的最左端。隨著GroupIndex數(shù)值的增大,菜單項依次向右排列。2. 若需替換主菜單中的某一菜單項,則將子菜單相應(yīng)菜單項的GroupIndex設(shè)為與之相等的值。這條規(guī)則適合一個或多個菜單項。例如,主菜單中的Edit菜單項的GroupIndex 的值為1。將子菜單的一個或多個菜單項的GroupIndext的值設(shè)為1,則在運行時,這些菜單項替換主窗口的Edit菜單。將同一窗體的多個菜單項的GroupIndex設(shè)為相同值,原有的排列順序在菜單融合時將保持不變。3. 若要在菜單融合時插入菜單項,需在主菜單中預(yù)留數(shù)值“位置”。例如,主菜單的兩菜單項數(shù)值為0,5,則子菜單GroupIndex數(shù)值為1,2,3,4的菜單在融合時將插入其中。在使用MDI界面時,用戶通常會打開多個窗體。為了使用戶方便地進行窗體切換,常設(shè)有一個進行切換的菜單項.此菜單列出了打開窗體的名稱,當(dāng)用戶選擇其中的一個時,程序進行相應(yīng)的窗體切換。在Delphi的MDI設(shè)計時,可非常方便地實現(xiàn)這一功能。方法是將父窗口的WindowMenu設(shè)置成該菜單項的名字即可。4.2 多頁面界面多頁面界面是一種非常友好的界面形式。它由一個窗體和多個頁面組成, 關(guān)于每個頁面的信息列在窗體底部的標(biāo)簽(Tabs)上,用戶可通過選擇標(biāo)簽來進行頁面切換。 每次只有一個頁面顯示在窗體中。MPI較MDI使用更為方便,且切換速度更快。本章例程就是多頁面界面的例子。另外Delphi集成開發(fā)環(huán)境中的代碼編輯(Code Editor)窗體是MPI應(yīng)用在文本編輯中的實例。在MPI中,一個窗體內(nèi)的多個文件可以方便地進行切換和交換數(shù)據(jù)。多頁面界面分為靜態(tài)MPI和動態(tài)MPI兩種形式。靜態(tài)MPI的標(biāo)簽數(shù)量固定,用戶在事先設(shè)計好的多個頁面上進行切換。象選擇對話框(Option Dialog)就屬于靜MPI。動態(tài)MPI的標(biāo)簽數(shù)量不固定,由程序根據(jù)需要動態(tài)的產(chǎn)生或消除,象代碼編輯窗體就是動態(tài)MPI,程序可根據(jù)用戶的需要產(chǎn)生多個文本頁面,也可以動態(tài)地關(guān)閉頁面。利用Delphi的TNotebook和Ttabset 可十分方便地設(shè)計靜態(tài)MPI。設(shè)計動態(tài)MPI則需要編寫專門的代碼。4.2.1 靜態(tài)多頁面界面TNotebook,TTabSet可用來開發(fā)靜態(tài)多頁面界面。TNotebook部件能顯示多頁, 每頁都有相應(yīng)的控制。通常TNotebook與TTabset配合進行控制。TTabset 有一組水平的標(biāo)簽,每個標(biāo)簽可通過創(chuàng)建字符串列表進行某種控制。MPIEDit例程中的主窗體中有一個TNotebook 部件和 TTabSet 部件。 把兩個部件的Aglin屬性設(shè)置成bsTop和bsBotton,使它們分別處在窗體的上下兩部分。為了使TTabSet與TNotebook配合工作,使用下代碼:TabSet1.Tabs := Notebook1.Page;另外,在TabSet的OnClick事件中定義下如下代碼,可使用戶在選擇標(biāo)簽時開打相應(yīng)的頁。procedure TEditForm.TabSetClick(Sender : TObject);beginNotebook1.PageIndex := TabSet1.TabIndex;end;設(shè)計靜態(tài)MPI時,可在部件窗體(Component Palette)的WIN3。1頁面中選中TNotebook 部件,然后在Object inspector窗體中雙擊TNotebook的Pages屬性,Dephi 將彈出對話框,用戶可以在此確定Notebook的頁數(shù)和字符串列表,如圖4.6。關(guān)閉對話框后, 可對每一頁進行設(shè)計,使用鼠標(biāo)右按鈕彈出快速菜單進行頁面切換。4.2.2 動態(tài)多頁面界面使用Delphi進行靜態(tài)MPI設(shè)計非常簡單,進行動態(tài)MPI設(shè)計則需編寫專門的代碼。 對于一個多頁面文本編輯器,應(yīng)能實現(xiàn)以下功能: 動態(tài)生成頁面,每個頁面均能進行文本編輯 動態(tài)關(guān)閉頁面,直到窗體中只有一個頁面為止 頁面切換不影響各種文本編輯操作為了實現(xiàn)以上功能,程序中使用了動態(tài)頁面類(TDynaPage),其定義如下:type TDynaPage = Class(TObject);該類可根據(jù)需要動態(tài)的產(chǎn)生頁面, 每個頁面上創(chuàng)建了可進行文本編輯的TMeno部件。procedure. puclicCurPage : integer;FileList : TSringList;end;CurPage表示當(dāng)前用戶選擇的頁面數(shù),用戶切換、增加、刪除頁面均影響CurPage 的值,CurPage初如化為零頁。FileList存放打開或創(chuàng)建文件的名字以及與這些文件相關(guān)的編輯部件TMemo,頁面動態(tài)創(chuàng)建、刪除將影響FilstList的值。TNotebook部件創(chuàng)建后至少有一個頁面,因此Pages屬性不是空值,只要往Pages中加入字符串,Delphi自動地把該字符串與TPage類對象相聯(lián)系。TPage類是TCustomEdit派生出來的,在對象瀏覽器(Object Browse)中可觀察到TPage的數(shù)據(jù)成員和方法。靜態(tài)生成的頁面也是 TPage類。要創(chuàng)建多頁面編輯器,必須從TPage的父件(Parent屬件)創(chuàng)建相應(yīng)編輯部件。但在動態(tài)創(chuàng)建頁面時,TPage只是一個與字符串相聯(lián)系的TObject類,不能寫成:MemoParent := Notebook1.Pages.Object ;在Delphi中,宣稱對象和創(chuàng)建對象都是用指針來標(biāo)識, 因此可用無類型指針進行指針傳遞。varPi : Pointer;beginPi := Notebook1.Pages.Object;Memo.Parent := Pi;end;這樣就可在TPage上動態(tài)創(chuàng)建編輯部件了。往Notebook1中動態(tài)生成頁面時,頁面應(yīng)所相應(yīng)的切換,TDynaPage. Notebook1.Tabset1有關(guān)的屬性要作相應(yīng)的調(diào)整。TDynaPage的DynaAdd方法定義如下:procedure TDynaPage.DynaAdd(Sender:TNotebook;FileName:String);varPi:Pointer;Memo:TMemo;beginSender.Pages.add(FileName);Pi:= Sender.Pages.ObjectsSender.Pages.Count-1;DynaMemo(pi);DynaPage.FileList.addObject(FileName,Memo1);EditForm.TabSet1.Tabs := Sender.Pages;EditForm.Tabset1.TabIndex:=Sender.Pages.Count-1;EditForm.Notebook1.PageIndex := EditForm.Tabset1.TabIndex;DynaPage.CurPage:= Sender.Pages.Count-1;end;procedure DynaMemo(Pi:Pointer);varMemo:TMemo;beginMemo:=TMemo.Create(Pi);Memo.Parent:=Pi;Memo.Align:=alClient;Memo.borderStyle:=bsNone;Memo.HideSelection:=False;Memo1:=Memo;end;procedure TDynaPage.Del(Sender:TNotebook;No:integer); varPi:pointer;beginSender.Pages.delete(No);EditForm.TabSet1.Tabs.delete(No);Filelist.Delete(No);DynaPage.CurPage:=EditForm.TabSet1.TabIndex;Sender.PageIndex := EditForm.Tabset1.TabIndex;Pi:=FileList.ObjectsDynaPage.CurPage;Memo1:=Pi;EditForm.Caption:=Sender.Pages.StringsDynaPage.CurPage;end;當(dāng)用戶在多個頁面中進行切換時,程序應(yīng)當(dāng)保證對當(dāng)前頁面進行編輯。 例如在多頁編輯器中,用戶選中某一頁面,即可對該頁面中的文件進行編輯、尋找、設(shè)置、打印等。為了實現(xiàn)這一功能,定義了一個TMemo類型的變量:Memo1,該變量沒有實例化,每次調(diào)用DynaAdd,DynaDel方法均定把TabIndex指定頁面的Memo指針傳給Memo1。這樣在程序運行中,始終有一個實例化的Memo指針賦給Memo1,而菜單中的文本編輯功能均對Memo1進行操作。這種指針傳遞就能保證對當(dāng)前頁進行操作。定義了TDynaPage后,只需在Open,Close菜單項中加入如下代碼,即可方便的在用戶打開關(guān)閉文件時創(chuàng)建成刪除頁面。procedure TEditForm.Close1Click(Sender: TObject);begin if DynaPage.CurPage0 thenDynaPage.Del(Notebook1,DynaPage.CurPage);if Notebook1.Pages.count = 1 thenClose1.Enabled:=False;end;procedure TEditForm.Open1Click(Sender: TObject);beginif OpenDialog1.Execute thenbeginif not(OpenFile or NewFile) thenbeginOpenFile:=true;Open(OpenDialog1.FileName);Notebook1.Pages.Strings0:=ExtractFileName( OpenDialog1.FileName);TabSet1.Tabs:=Notebook1.Pages;endelsebeginDynaPage.DynaAdd( Notebook1, ExtractFileName(OpenDialog1.FileName);Open(OpenDialog1.Filename);if Notebook1.Pages.count 1 thenClose1.Enabled:=True;end;end;end;4.3 文本編輯部件及應(yīng)用4.3.1 TEdit 部件TEdit部件是一個標(biāo)準(zhǔn)的編輯框,用戶可在編輯框中輸入數(shù)據(jù)。編輯框也可向用戶顯示數(shù)據(jù)。編輯時只能讀寫一行信息。 TEdit的Text屬性存放著用戶輸入的數(shù)據(jù)或向用戶顯示的數(shù)據(jù),Modified屬性用以標(biāo)識 Text的數(shù)據(jù)是否改變,可通過設(shè)置Maxlength屬性值來限制用戶輸入字符的個數(shù)量,CharCase屬性可定義編輯框中字符的大小寫。如果設(shè)計者想禁止用戶輸入,可將ReadOnly屬性設(shè)置成真值。編輯框也能用做密碼輸入框。通過設(shè)置PassWordChar 屬性的值,可將用戶輸入的字符在編輯框中顯示成指定的字符,如*號等。編輯框還可以進行字符選擇操作、粘貼、復(fù)制和剪切操作。4.3.2 TMemo 部件TMemo部件與TEdit部件類似,能向用戶顯示數(shù)據(jù),用戶也可輸入數(shù)據(jù)。與TEdit 部件不同的是,TMemo部件可以處理多行文本,因此主要用于編輯文件。TMemo的Text屬性只能在運行時才能訪問。Modified屬性用以標(biāo)識Text的數(shù)據(jù)是否改變,通過設(shè)置MaxLength屬性值來限制用戶輸入字符的數(shù)量。如果把文本當(dāng)成一個整體進行訪問,可使用Text屬性;若想逐行訪問,則要使用Lines屬性。Lines屬性能對文件更方便地進行訪問。Lines是TStrings類型的,因此可使用Add 、Delete方法,例如在Memo1中加入一行字符串的代碼如下: Memo1.Lines.Add(Another line is added);通過Lines屬性可以方便地把文件讀入部件中,例程中使用下面的代碼將文件讀入Memo1:Memo1.Lines.loadFromFile(Filename).從TMemo 部件中剪切、復(fù)制、粘貼文本非常方便,只需使用 CutToclipboard ,CopyToClipBroad,PasteFromClipBoard方法,其代碼如下:Memo1.CopyToClipboardMemo1.CutToClipboardMemo1.PasteFromClipboardTMemo有一些屬性,用以控制文本的顯示效果。ScrollBars屬性可以定義部件的水平滾動條和垂直滾動條。當(dāng)文件字體改變時,使用AutoSize屬性可使部件大小做相應(yīng)的調(diào)整。設(shè)置WordWrap屬性可以實現(xiàn)自動換行。例程中Edit|WordWrap菜單項提供了設(shè)置WordWrap的功能,并可根據(jù)WordWrap的值決定滾動條的形式。當(dāng)WordWrap為真時,不需要水平滾動條, 并在菜單中作出檢查記號。其代碼如下:procedure TEditForm.SetWordWrap(Sender: TObject);beginwith Memo1 dobeginWordWrap := not WordWrap;if WordWrap thenScrollBars := ssVertical elseScrollBars := ssBoth;WordWrap1.Checked := WordWrap;end;SetEditRect;end;TMemo部件提供了一組關(guān)于選擇文本的屬性和方法。如果想在部件成為當(dāng)前控件時自動選擇文本,可設(shè)置 AutoSelect 屬性。運行時可用SelectAll 方法選中部件的全部文本。 Selstart屬性返回選中文本的開始位置,SelText 包含著被選中的文本。SelLength屬性返回選中文本的長度,這兩個屬性可用于字符串的查找和替換。下一節(jié)將詳細討論。TMemo的Modified屬性是一個運行時才能得到的屬性,可判斷部件被創(chuàng)建時或Modified屬性最后一次設(shè)置成假值之后,部件上的文本是否修改。如果修改了,Modified 將設(shè)成真值,反之假值。例程中在關(guān)閉文件時將測試文件的modified屬性,如果文件修改后尚未保存, 將出現(xiàn)對話框,詢問用戶是否保存文件,其代碼如下: procedure TEditForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);varDialogValue: Integer;FName: string;beginif Memo1.Modified thenbeginFName := Caption;DialogValue := MessageDlg(Format(SWarningText, FName), mtConfirmation,mbYes, mbNo, mbCancel, 0);case DialogValue ofid_Yes: Save1Click(Self);id_Cancel: CanClose := False;end;end;end;4.4 常用對話框的使用 Delphi的可視部件類庫(Vistual Component Liberty)中,有一組對話框部件,在對象選擇板的Dialog 頁面中可以找到。 本節(jié)著重介紹與文件編輯有關(guān)的字體對話框(TFontDialog Componement),查找對話框(TFindDialog Componement) ,替換對話框(TReplace Dialog Componement),文件對開對話框(TOpenDIalog Componement). 應(yīng)用這幾個對話框可對文件進行字體設(shè)置、查找、替換等操作,但需要編寫相應(yīng)的代碼。4.4.1字體對話框部件字體對話框部件在應(yīng)用程序中產(chǎn)生字體對話框, 用戶可在對話框中進行字體選擇和屬性設(shè)置。用戶選擇字體并按下OK按鈕之后,有關(guān)信息便貯存在部件的Font屬性中。應(yīng)用程序可通過調(diào)用字體對話框的Execult方法來顯示對話框,當(dāng)用戶選擇OK按鈕時,Execult返回True值,否則返回Flase值。應(yīng)用程序可以使用Options屬性來定義字體對話框的顯示和行為方式:例如可在對話框中定義一個幫助按鈕或指定出現(xiàn)在字體列表框中的字體。有關(guān)Options的主要取值如下表4.1:表4.1 字體對話框的Options取值及含義取值 含義AdAnsiOnly 如果是真值,只能使用Window字符集,fdEffects 如果是真值,對話框中顯示顏色列表和效果檢查框;用戶可使用效果檢查框定義Strikout下劃線文本;使用顏色列表定義字體顏色。fdForceFontExise 如果是真值,用戶在字體組合框中輸入字體名后選擇OK按鈕,將出現(xiàn)一個用戶字體無效的消息框。fdNoOEMFont 如果是真值,字體組合框中將不顯示向量字體。fdShowHelp 如果是真值,對話框顯示Help按按鈕。fdWysiwyg 如果是真值, 只有打印和屏幕均可得到的字體才會出現(xiàn)在字體 組合框中。例程中(Edit/Font)菜單具有設(shè)置文本字體的功能,其代碼如下:procedure TEditForm.SetFont(Sender : TObject);beginFontDialog.Font := Memo1.Font;if FontDialog1.Execult thenMemo1.Fout := FontDialog1.Font;SetEdit Rect;end;第四章文本編輯器的設(shè)計(二)4.4.2查找對話框部件查找對話框部件為應(yīng)用程序提供查找對話框, 用戶可使用查找對話框在文本文件中查找字符串。可用Execult方法顯示查找對話框,如圖4.8。應(yīng)用程序要查找的字符放到FindText屬性中。Options 屬性可決定查找對話框中有哪些選項。例如, 用戶可選擇是否顯示匹配檢查框。Options的常用選項如表4.2所示。如果用戶在對話框中輸入字符并選擇FindNext按鈕,對話框?qū)l(fā)生OnFind事件。表4.2 查找對話框的Options屬性的取值及含義取值 含義frDown 如果是真值,對話框中出現(xiàn)Down按鈕,查找方向向下。如果是假值,Up按鈕將被選中,查找方向向上,frDown 值可在設(shè)計或運行時設(shè)置。frDisableUpDown 如果是真值,Up和Down按鈕將變灰,用戶不能進行選??;如果是假值,用戶可以選擇其中之一。frFindNext 如果是真值,應(yīng)用程序查找在FindNext屬性中的字符串。frMatchCase 如果是真值,匹配檢查框被選中。設(shè)計、運行時均可設(shè)置。frWholeWord 如果是真值,整字匹配檢查框被選中,設(shè)計、運行時均可設(shè)置。在OnFind事件中可使用Options屬性來決定以何種方式查找。Find方法響應(yīng)查找對話框的OnFind事件。 procedure TEditform.Find(Sender: TObject);beginwith Sender as TFindDialog doif not SearchMemo(Memo1, FindText, Options) thenShowMessage(Cannot find + FindText + .);end;其中SearchMemo函數(shù)是Search單元中定義的,SearchMemo可在TEdit,TMemo,以及其它TCustomEdit派生類中查找指定的字符串。查找從控件的脫字號()開始, 查找方式由Options決定。如果向后查找從控件的StlStart處開始,如果向前查找則從控件的SelEnd處查找。如果在控件中找到相匹配的字符串,則字符串被選中,函數(shù)返回真值。如無匹配的字符串,函數(shù)返回假值。特別注意的是TEdit,TMemo中有一個HideSeletion屬性,它決定當(dāng)焦點從該控制轉(zhuǎn)移至其它控制時,被選中的字符是否保持被選中的狀態(tài)。如果是真值,則只有獲得焦點才能保持被選中狀態(tài)。查找時,焦點在查找對話框上,因此要想了解查找情況,必須將HideSeletion設(shè)成假值??刂频娜笔≈禐檎嬷?。SearchMemo代碼如下:unit Search;interfaceuses WinProcs, SysUtils, StdCtrls, Dialogs;constWordDelimiters: set of Char = #0.#255 - a.z,A.Z,1.9,0;function SearchMemo(Memo: TCustomEdit;const SearchString: String;Options: TFindOptions): Boolean;function SearchBuf(Buf: PChar; BufLen: Integer;SelStart, SelLength: Integer;SearchString: String;Options: TFindOptions): PChar;implementationfunction SearchMemo(Memo: TCustomEdit;const SearchString: String;Options: TFindOptions): Boolean;varBuffer, P: PChar;Size: Word;beginResult := False;if (Length(SearchString) = 0) then Exit;Size := Memo.GetTextLen;if (Size = 0) then Exit;Buffer := StrAlloc(Size + 1);tryMemo.GetTextBuf(Buffer, Size + 1);P := SearchBuf(Buffer, Size, Memo.SelStart,Memo.SelLength,SearchString, Options);if P nil thenbeginMemo.SelStart := P - Buffer;Memo.SelLength := Length(SearchString);Result := True;end;finallyStrDispose(Buffer);end;end;function SearchBuf(Buf: PChar; BufLen: Integer;SelStart, SelLength: Integer;SearchString: String;Options: TFindOptions): PChar;varSearchCount, I: Integer;C: Char;Direction: Shortint;CharMap: array Char of Char;function FindNextWordStart(var BufPtr: PChar): Boolean;begin (True XOR N) is equivalent to(not N) Result := False; (False XOR N) is equivalentto (N) When Direction is forward (1), skip nondelimiters, then skip delimiters. When Direction is backward (-1), skip delims, thenskip non delims while (SearchCount 0) and(Direction = 1) xor (BufPtr inWordDelimiters) dobeginInc(BufPtr, Direction);Dec(SearchCount);end;while (SearchCount 0) and(Direction = -1) xor (BufPtr inWordDelimiters) dobeginInc(BufPtr, Direction);Dec(SearchCount);end;Result := SearchCount 0;if Direction = -1 thenbegin back up one char, to leave ptr on first nondelim Dec(BufPtr, Direction);Inc(SearchCount);end;end;beginResult := nil;if BufLen = 0 then Exit;if frDown in Options thenbeginDirection := 1;Inc(SelStart, SelLength); start search past end ofselection SearchCount := BufLen - SelStart - Length(SearchString);if SearchCount BufLen thenExit;endelsebeginDirection := -1;Dec(SelStart, Length(SearchString);SearchCount := SelStart;end;if (SelStart BufLen) then Exit;Result := BufSelStart; Using a Char map array is faster than callingAnsiUpper on every character for C := Low(CharMap) to High(CharMap) doCharMapC := C;if not (frMatchCase in Options) thenbeginAnsiUpperBuff(PChar(CharMap), sizeof(CharMap);AnsiUpperBuff(SearchString1,Length(SearchString);end;while SearchCount 0 dobeginif frWholeWord in Options thenif not FindNextWordStart(Result) then Break;I := 0;while (CharMapResultI = SearchStringI+1) dobeginInc(I);if I = Length(SearchString) thenbeginif (not (frWholeWord in Options) or(SearchCount = 0) or(ResultI in WordDelimiters) thenExit;Break;end;end;Inc(Result, Direction);Dec(SearchCount);end;Result := nil;end;end.4.4.3 替換對話框部件替換對話框部件為應(yīng)用程序提供替換對話框。如圖4.9。它包括查找對話框的所有功能,此外還允許使用者更換被選中的字符串。FindText 屬性是應(yīng)用程序需查找的字符串。ReplaceText屬性是被選中字符的替換字符串。Options 屬性決定對話框的顯示方式。其值如表4.3所示。與查找對話框一樣,替換對話框亦有OnFind 事件。用戶輸入查找字符串并按FindNext按鈕時,發(fā)生OnFind 事件。用戶選擇Replace 或ReplacAll 時, 對話框發(fā)生OnRelpace事件,要替換的字符串存入ReplaceText屬性中,要編寫相應(yīng)的代碼以支持替換功能。表4.3 替換對話框的Options屬性的取值及含義 取值含義frRelpace 如果是真值, 應(yīng)用程序?qū)eplaceText 屬性中的字符串替換 FindText屬性中的字符串。frReplacAll 如果是真值,應(yīng)用程序?qū)eplaceText屬性中的字符串替換, 查找到的所有FindText屬性中的字符串。例程中TEditForm.Replace方法響應(yīng)OnReplace事件,Replace方法首先判斷控制中被選中字符串是否與替換字符串相等,如果不等則進行替換。而后根據(jù)Options中的方式循環(huán)進行查找替換。直至無匹配字符串為止。其代碼如下: procedure TEditForm.Replace(Sender: TObject);varFound: Boolean;beginwith ReplaceDialog1 dobeginif AnsiCompareText(Memo1.SelText, FindText) = 0 thenMemo1.SelText := ReplaceText;Found := SearchMemo(Memo1, FindText, Options);while Found and (frReplaceAll in Options) dobeginMemo1.SelText := ReplaceText;Found := SearchMemo(Memo1, FindText, Options);end;if (not Found) and (frReplace in Options) thenShowMessage(Cannot find + FindText + .);end;end;4.4.4 打開對話框部件打開對話框部件為應(yīng)用程序顯示打開對話框。使用Execute方法可顯示打開對話框用戶通過選擇文件類型下拉框中的文件類型,可以確定顯示在文件列表中的文件。 例如,如果用戶選擇*.txt文件類型,那么只有在當(dāng)前目錄下的文本文件才會顯示在文件列表中。文件擴展名通常也稱為過濾器。打開對話框包含一個Filters(過濾器)的屬性,它可確定文件類型和在文件類型下拉框中的順序。應(yīng)用程序可以為打開對話框定義多個過濾器,對話框的FilterIndex 屬性可以決定哪個過濾器是文件類型下拉框中的缺省過濾器。如FilterIndex等于2,表示程序運行時出現(xiàn)在文件類型下拉框的過濾器是第2個過濾器。例程中關(guān)于文件打開的代碼如下: procedure TEditForm.Open/Click(Sender : TObject);beginif OpenDialog/.Execult thenbeginOpen(Open Dialog/.FileName)endend;打開,保存對話框中的Options屬性值見表4.4表4.4 打開、保存對話框的Options屬性取值及含義值含義ofAllowMultiSelect 如果是真值,則允許在文件名列表中選擇多個文件。ofCreatePrompt 如果是真值,當(dāng)用戶在文件編輯框中輸入一不存在的文件名,并選擇OK按鈕,則會出現(xiàn)消息框, 提示用戶此文件不存在并詢問是否以此文件名創(chuàng)建一新文件。ofExiengronDifferent 如果是真值,從對話框中返回的文件擴展名將不同于缺省擴展名。其值存入DefaultExt屬性中。ofFileMustExist 如果是真值, 當(dāng)用戶在文件編輯框中輸入一個不存在的文件名時,并選擇OK按鈕, 則會出現(xiàn)一消息框提示用戶此文件不存,并詢問是否輸入了正確的路徑和文件名。ofNoChangeDir 如果是真值,當(dāng)前目錄將設(shè)置成對話框第一次出現(xiàn)的目錄,并忽略任何目錄改變。ofOverWritePrompt 如果是真值,當(dāng)用戶試圖保存一個已存在的文件時, 將出現(xiàn)一消息框,提示用戶此文件已存在,并詢問是否覆蓋。ofPathMastExit 如果是真值,用戶在文件名編輯框只能輸入有效路徑名, 否則出現(xiàn)消息框,提示用戶路徑無效。表4.4 打開、保存對話框中的Options屬性取值及含義文件保存對話框與打開對話框類似,如圖4.11。它的Option屬性見上表。例程在保存文件前先對文件進行讀寫判斷,如果文件是只讀文件或未指定文件名的新文件, 則程序?qū)ξ募槐4?,否則備份文件。代碼如下: procedure TEditForm.Save1Click(Sender: TObject);procedure CreateBackup(const Filename: string);varBackupFilename: string;beginBackupFilename := ChangeFileExt(Filename, BackupExt);DeleteFile(BackupFilename);RenameFile(Filename, BackupFilename);end;function IsReadOnly(const Filename: string): Boolean;beginResult := Boolean(FileGetAttr(Filename) and faReadOnly);if Result then MessageDlg(Format(%s is read only.,ExtractFilename(Filename), mtWarning, mbOK, 0);end;beginif (Filename = ) or IsReadOnly(Filename) thenSaveAs1Click(Sender)elsebeginCreateBackup(Filename);Memo1.Lines.SaveToFile(Filename);Memo1.Modified := False;end;end;其中CreateBackup過程用以改變需備份文件的擴展名。IsReadOnly 用以判斷文件屬性。4.5 文件打印在Delphi中,文件打印有兩種方式:1. 將文件變量分配給打印機,用此變量名創(chuàng)建或打開文件后, 往此文件變量寫入的任何文本都視為向打印機輸出,以下過程可實現(xiàn)文件的打印。procedure TEditForm,Print1Click(Sender: TObject);varLine: Integer;PrintText: System.Text;beginif PrintDialog1.Execute thenbeginAssignPrn(PrintText)Rewrite(PrintText);Print.Canv

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論