程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> Delphi字符串列表及應用

Delphi字符串列表及應用

編輯:Delphi

 Delphi應用程序經常要處理字符串列表,如組合框和列表框中的字符串,TMemo部件的文本行,屏幕支持的字體列表,TNotebook部件的tabs屬性,字符串網格的行、列等等。

  雖然應用程序以不同的方法使用這些列表,但Delphi通過一個叫字符串列表(Tstrings)的對象提供統一的界面,並且在不同場合可相互轉化。例如,可以在TMemo部件中編輯某一字符串,並把它當成列表框中列表項使用。

  在Delphi集成開發環境中也經常要使用字符串列表。如在Object Inspector窗體的取值欄中常列有Tstrings字符,雙擊該字符,將彈出字符列表編輯器,如圖3.1,在編輯器中可進行編輯、加入、刪除等操作 。

  在運行狀態時也可以操作字符串列表,常見的字符串列表操作如下:

  ● 列表中操作字符串

  ● 裝載、保存字符串列表

  ● 創建字符串列表

  ● 在字符串列表中加入對象

  本章將介紹字符串列表的常用操作及簡單應用。

  3.1 字符串列表的常用操作 

  3.1.1 列表中操作字符串 

  在Delphi應用程序中,經常要對列表中的字符串進行操作。例如,設計時修改字符串列表屬性。

  常見的字符串操作如下:

  ● 計算列表中字符串數目

  ● 訪問指定字符串

  ● 查找字符串的位置

  ● 往列表中加入字符串

  ● 刪除列表中的字符串

  ● 在列表中移動字符串

  ● 復制一個完整的字符串列表

  ● 復制列表中的字符串 

  3.1.1.1 計算列表中的字符串數目 

  使用Count屬性可計算列表中的字符串數目。Count是只讀屬性,用以指示列表中字符串列表數目。因為字符串列表是以零開始索引,因而Count比列表的最大索引數大一。

  例如,應用程序想計算當前屏幕支持的字體數目,可查找屏幕對象的字體列表,該列表包含了屏幕支持的所有字體的名字。

 FontCount:=Screen.Fonts.Count;

  3.1.1.2 訪問指定字符串 

  字符串列表有一個可索引的Strings屬性,可象使用字符串數組一樣使用Strings。例如,列表中第一個字符串為Strings[0]。因為Strings屬性為字符串列表中最常用的屬性,Strings屬性可做為字符串列表的缺省屬性,即使用時可省略Strings標識符。

  要訪問字符串中的指定字符,可查找該字符的起始位置或索引。字符串數目是以零開始記數的。如果列表中有三個字符串,其索引范圍為0..2。

  以下代碼是等價的: 

  Memol.Lines.Strings[0]:='This is the first line.';
Memol.Lines[0]:='This is the first line.';
 

  3.1.1.3 查找字符串的位置 

  Indexof方法可查找指定字符串的位置。Indexof有一個字符串類型的參數,方法返回列表中匹配字符串的位置。如果列表中無匹配字符串,將返回- 1。

  Indexof方法只能查找完整字符串,即必須完全匹配整個字符串。如果只匹配部分字符串,必須編寫相應代碼。

  以下代碼判定列表中是否有指定字符串:

  if FileListBox1.Items.IndexOf('AUTOEXEC.BAT') > -1 then
begin
Color := clYellow;
Label1.Caption := 'You are in the root directory!';
end;
 

  3.1.1.4 在列表中加入字符串 

  有兩種方式往列表中加入字符串:可把字符串加到列表的最後,也可插入列表之中。

  要把字符串加至列表尾部,使用Add方法,把字符串作為參數傳遞。

  要把字符串插入列表中,使用Insert方法,傳遞兩個參數:插入的位置和字符串。

  例如,要把“Three”插入至列表中的第三個位置,使用代碼Insert(2,'Three')。如果列表中的字符不到2個,Delphi將產生超出索引范圍的異常(關於異常詳見十二章)。 

 3.1.1.5 在列表中移動字符串 

  應用程序可以在列表中把指定字符串移至另一個位置,如果字符串與某個對象相連,則該對象與字符串同步移動。

  Move方法可實現字符串的移動,它有兩個參數:現行位置和要移動的位置。以下代碼把第三個字符串移至第五的位置: 

  Move(2,4); 

  3.1.1.6 刪除列表中的字符串 

  使用Delete方法可以刪除指定的字符串。Delete的參數是指定字符串的位置,如果不知道字符串的位置,可使用Indexof方法。

  要刪除字符串列表中所有的字符串,可使用Clear方法。

  以下代碼刪除列表框中的指定字符串: 

  With ListBox1.Items do
begin
if Indexof('bureaucracy')>-1 then
Delete (Indexof('bureaucracy'));
end;
 

  3.1.1.7 復制完整的字符串列表 

  把一個列表復制到另一個列表相當於把源列表賦值給目標列表,即使列表從屬於不同的部件,Delphi也可以進行這種復制。

  復制列表將覆蓋掉目標列表,如果要把源列表加到目標列表的尾部,使用Addstrings方法。

  以下代碼分別為復制列表和連接列表: 

  Outline1.Lines:=ComboBox1.Items;

  Outline1.Addstrings(ComboBox1.Items); 

  3.1.1.8 重復操作列表中的字符串 

  很多情況需要對表中的每一個字符串進行操作,如改變字符串的大小寫。象這種重復操作可以用 for 循環來實現,同時使用列表的整數類型的索引。

  以下代碼對列表框的字符串進行重復操作。當用戶按下按鈕時,對列表框中的字符串進行大小寫轉換。 

  procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
begin
for I := 0 to ListBox1.Items.Count -1 do
ListBox1.Items[I] := UpperCase(ListBox1.Items[I]);
end;

 3.1.2 裝載、保存字符串列表 

  應用程序可以非常方便的把Delphi字符串列表存入文本文件,或者從文本文件中重新裝載(或裝入另一個不同的列表),字符串列表有專門的方法處理這類操作。

  使用LoadFromFile方法從文件中裝載字符串列表,LoadFromFile從文本文件中把每一行字符串裝入列表中。

  把列表保存在文件中使用SaveToFile方法,使用時傳遞文件名的參數。如果文件不存在,SaveToFile將創建它,否則將用列表覆蓋現有文件內容。

  以下代碼裝入AUTOEXEC.BAT的文件,並以AUTOEXEC.BAK為文件名進行備份。 

  procedure TForm1.FormCreat(sender:TObject);
var
FileName:String;
begin
FileName:='C:\AUTOEXEC.BAT';
With Memo1 do
begin
LoadFromFile(FileName)
SaveToFile(ChangeFileExt(FileName,'BAK'));
end;
end;
 

  3.1.3 創建新的字符串列表 

  大多數情況下,應用程序使用的字符串列表是做為部件的某一部分,因此不必創建列表,但Delphi允許創建不依賴部件的字符串列表。

  值得注意的是程序創建的字符串列表必須在使用完之後,釋放列表所占用的內存空間。有兩種不同的情況需要處理:一是程序以簡單的方式創建、使用、釋放字符串列表;二是由程序創建,在運行期間均可能使用,在程序終止前釋放。這兩種情況主要取決於是創建短期字符串列表還是長期字符串列表。 

  3.1.3.1短期字符串列表 

  短期字符串列表用於處理簡單事物。程序在同一處創建、使用、釋放列表。這是最安全的使用字符串列表的方法。

  因為字符串列表要為自己和它的字符串分配內存,所以要用try..finally對列表進行保護,以確保發生異常後釋放列表所占用的內存空間。

創建短期字符串列表的基本步驟為:

  1. 構造字符串列表對象;

  2. 在try..finally塊中使用列表;

  3. 在finally後釋放列表空間。

  以下代碼創建列表、使用列表、最後釋放列表空間: 

  procedure TForm1.Button1Click(Sender:Tobject);
var
TemList:TStrings;
begin
Templist:=TStringList.Create;
try
{ use the string list }
finally
Templist.Free;
end;
end;
 

  3.1.3.2 長期字符串列表 

  如果要在程序運行的任何時候使用字符串列表,則需在程序開始運行時就創建列表,並在程序終止前釋放。

  運行時創建字符串列表的步驟為:

  1. 在程序主窗體對象的域中加入TStringsList類型的域;

  2. 在主窗體的OnCreate事件中創建句柄,該事件句柄在主窗體顯示前運行;

  3. 在創建事件句柄後,創建字符串列表對象;

  4. 在主窗體的OnDestroy事件創建句柄,該事件句柄在主窗體消失之前運行。

  這樣,在程序運行過程中,任何過程、事件均能訪問該字符串列表。

  以下代碼在程序中加入了一個Clicklist的字符串列表,用戶每按一次鼠標鍵,程序往Clicklist中加入一字符串,程序結束前把該列表存入文件。 

  unit Unit1; 
interface 
uses WinTYpes, WinProcs, Classes, Graphics, Forms, Controls, APPS; 
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
{ Private declarations }
public
{ Public declarations }
ClickList: TStrings; {declare the fIEld}
end; 
var
Form1: TForm1; 
implementation 
{$R *.DFM} 
procedure TForm1.FormCreate(Sender: TObject);
begin
ClickList := TStringList.Create; {construct the list}
end; 
procedure TForm1.FormDestroy(Sender: TObject);
begin
ClickList.SaveToFile(ChangeFileExt(Application.ExeName, '.LOG'));
{save the list}
ClickList.Free; {destroy the list object}
end; 
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
ClickList.Add(Format('Click at (%d, %d)', [X, Y])); {add a 
string to the list}
end; 
end.


 

 3.1.4 往字符串列表中加入對象 

  字符串列表除了能在Strings屬性中貯存字符串外,還可以在Objects屬性中貯存對象。與Stings一樣,Objects也是可以索引的,它是對象的索引。

  在應用程序使用列表中的字符串與列表中是否有對象沒有多大關系。除非程序特地訪問對象,否則Objects中的內容不變,Delphi只是保存了這些信息,應用程序在必要時對其進行操作。

  有些字符串列表忽略加入的對象。如TMemo部件中代表行的列表對加入其中的對象不保存。還有一些字符串列表,把對象與字符串聯系起來,如TNotebook部件的Pages屬性,它同時保存著頁的名字和代表頁的對象。如果應用程序往Pages中加入或刪除字符串,Delphi自動的加入或刪除與之相應的對象。

  雖然程序可分配任何類型的對象到列表中,但最常用的是在自畫式控制中把位圖與字符串聯系起來,注意位圖與字符串成對使用。

  Delphi在釋放對象的內存空間時並不破壞與之相應的字符串。 

  3.1.4.1 操作字符串列表中的對象 

  對於字符串的每一種操作方法,列表中的對象均有相應的方法。例如,應用程序可利用對象的索引來訪問對象。與字符串不同的是,不能省略Objects,因為Strings才是列表的缺省屬性。

  表3.1中總結了字符串對字符串和對象操作的方法。 

  表3.1 TStrings的字符串屬性和對象操作屬性的方法

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 

  操 作    字 符 串        對   象

  ───────────────────────────────

  訪  問      Strings屬性          Objects屬性

  加入項目      Add 方法       AddObjects方法


 

插入項目      Insert方法      InsertObjects方法

  項目定位      Indexof方法         IndexofObject方法

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 

  Delete,Clear,More操作整個項目,即刪除字符串時把相應的對象也刪除了。但LoadFromFile,SaveToFile方法只對字符串進行操作。 

  3.1.4.2 加入對象 

  如果把對象與已存在的字符串聯系起來,Delphi將分配給該對象同樣的索引號。例如,一個叫Fruits的列表中有字符串('apple'),程序可將名為AppleBitmap的位圖與apple字符相聯系。 

  With Fruits do Objects[Indexof('apple')]:=AppleBitmap; 

  另一種方法是調用列表的AddObject方法,AddObject有兩個參數:字符串和對象,如下: 

  Fruits AddObject('Apple',AppleBitmap); 

  3.2 字符串列表應用 

  Delphi應用程序經常要用到字符串列表,我們編寫的strlist. dpr是應用字符串列表的簡單程序。程序運行狀態如圖3.2所示。列表框列出了屏幕支持的各種字體名稱,並且以名稱所代表的字體顯示在列表中;Tabs的標簽不只以字符串來表示,而且附有位圖。這就是所謂的自畫式控制。下面介紹字符串列表在自畫式控制中的應用。

  列表框、組合框、Tabset部件中有一個叫“自畫(Ownerdraw)”的風格,它能替代Windows的文本輸出,部件的自畫式控制在運行狀態對每個項目進行重新繪制。最常用的是用圖像代替文本輸出。

  自畫式控制有一個共同特點:它們都包含有項目列表,缺省情況下這些列表就是字符串列表,Windows把它們當成文本顯示。Delphi可以把字符串列表與某一對象相聯系,這就使得應用程序能用對象來繪制項目。

 通常,創建自畫式控制有以下三個步驟:

  1. 設置自畫風格;

  2. 把圖像對象加入字符串列表中;

  3. 繪制自畫項目。 

  3.2.1 設置自畫風格 

  每個能進行自畫式控制的部件都有一個叫Style的屬性,Style決定部件是以缺省方式還是以自畫方式繪制項目。

  對於列表框和組合框,也有自畫式風格選項,表3.2列出了Style的取值及含義。 

  表3.2 Style的取值及含義

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  Style       含  義        舉   例

  ─────────────────────────────────

  Fixed     每個項目有相同的高度     1bOwnerDrawFixed

  高度由ItenHeight屬性決定   csOwnerDrawFixed

  Varible     每個項目有不同的高度     1bOwnweDrawVarible

  由運行數據決定            csOwnerDrawVarible

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 

  tab-set與字符串網格的Style屬性通常是Varible.

  在Strlist程序中,列表框與tab-set取值如表3.3: 

  表3.3 列表框與tab-set的取值

  ━━━━━━━━━━━━━━━━━━━━━━━━━━

  名稱         style

  ──────────────────────────

  ListBox1               lbOwnerDrawVariable

  Tabset1                tsOwnerDrawVariable

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━

  3.2.2 把圖像加入字符串列表 

上節已介紹如何把對象加入字符串列表,例程把位圖對象加入Tabset1的Tabs中: 

  procedure TForm1.FormCreate(Sender: TObject);
var
Bitmap: TBitMap;
begin
Listbox1.Items := Screen.Fonts;
Bitmap := TBitmap.Create;
Bitmap.LoadFromFile('PHONE.BMP');
Tabset1.Tabs.AddObject('phone',Bitmap);
Bitmap := TBitmap.Create;
Bitmap.LoadFromFile('PRINTER.BMP');
Tabset1.Tabs.AddObject('printer ',Bitmap);
end;
 

  3.2.3 繪制自畫項目 

  當部件的Style屬性是自畫式時,Windows不再繪制部件,相反Windows為每個可視項目產生事件,而應用程序必須在事件中繪制項目。

  在應用程序繪制自畫控制之前,Windows產生測量項目事件,這個事件告訴程序項目顯示的位置 。

  通常由Windows決定項目顯示的大小,但應用程序可以處理這個事件並自己選擇顯示區域。例如,程序要用位圖代替文本顯示,則需要把區域設置成位圖的大小。測量項目事件的名稱隨部件的名稱不同而不同,對於列表框和組合框,該事件叫OnMeasureItem。對於Tabset,該事件叫OnMeasureTab。

  測量項目事件有兩個重要參數: 項目索引號與項目的大小。這個大小是變化的。後繼項目的輸出位置由前面項目的大小決定。例如,在自畫式列表框中,如果應用程序把第一個項目的高度設置成5個象素點,則第二個項目在第六個象素點開始輸出。列表框和組合框中,應用程序只能設置成項目的高度,而項目的寬度就是部件的高度。在Tabset中,tabs的寬度是可變的,而高度則是固定的。自畫式網格允許應用程序改變網格單元的高度和寬度。

 OnMeasureItem的聲明如下:

  ListBox1 MeasureItem(Control: TwinControl;Index: Integer; var Height: Integer);

  例程中響應OnMeasureItem事件的代碼如下:  

  procedure TForm1.ListBox1MeasureItem(Control: TWinControl; Index: Integer;
var Height: Integer);
begin
with ListBox1.Canvas do
begin
Font.Name := ListBox1.Items[Index];
Height := TextHeight('A');
end;
end; 
procedure TForm1.TabSetMeasureTab(Sender: TObject; Index: Integer;
var TabWidth: Integer);
var
BitmapWidth: Integer;
begin
BitmapWidth := TBitmap( TabSet1.Tabs.Objects[Index]).Width;
Inc(TabWidth, 2 + BitmapWidth);
end;
 

  在OnMeasureItem事件發生後,Windows激發一個叫OnDrawItem的事件,這個事件也隨部件名稱不同而不同,常見的有OnDrawItem、OnDrawTab、OnDrawCell。

  OnMeasureItem的聲明如下:

  DrawItem( Control: TWinControl; Index: integer; Rect: TRect; State: TOwnerDraw); 

  其中Control是包含項目的部件引用

  Index 是項目的索引號

  Rect  是繪制的矩形

  State 是項目的狀態,如選中,得到焦點等。 

  在例程的列表框中,所列項目是屏幕支持的各種字體名稱,當列表框發生OnDrawItem事件時,程序把輸出字體設置成該項目所代表的字體,因而列表框的項目呈現出不同的字體,其代碼如下:  

  procedure TForm1.DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
begin
with ListBox1.Canvas do
begin
FillRect(Rect);
Font.Name := ListBox1.Items[Index];
TextOut(Rect.Left, Rect.Top, ListBox1.Items[Index]);
end;
end;
在Tabset部件中,則把位圖與文本同時輸出,其代碼如下: 
procedure TForm1.TabSet1DrawTab(Sender: TObject; TabCanvas: TCanvas;
R: TRect; Index: Integer; Selected: Boolean);
var
Bitmap: TBitmap;
begin
Bitmap := TBitmap(TabSet1.Tabs.Objects[Index]);
with TabCanvas do
begin
Draw(R.Left, R.Top + 4, Bitmap);
TextOut(R.Left + 2 + Bitmap.Width,
R.Top + 2, TabSet1.Tabs[Index]); 
end;
end;









 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved