?? 017.htm
字號:
<HTML><HEAD><meta http-equiv="Content-Type" content="text/html; charset=GB2312"><TITLE>-->DELPHI基礎教程-->第六章 文件管理(二)</TITLE>
<META NAME="keywords" CONTENT=" DELPHI基礎教程 第六章 文件管理(二)">
<META NAME="description" CONTENT=" - DELPHI基礎教程 - 第六章 文件管理(二)">
<style>
<!--
#page {position:absolute; z-index:0; left:0px; top:0px}
.tt3 {font: 9pt/12pt "宋體"}
.tt2 {font: 12pt/15pt "宋體"}
a {text-decoration:none}
a:hover {color: blue;text-decoration:underline}
-->
</style>
</HEAD>
<body text="#000000" aLink=#9900ff link=#006699 vLink=#006699 bgcolor="#FFFFFF" leftmargin="3" topmargin="3" marginheight="3" marginwidth="3">
<TABLE WIDTH="100%" CELLPADDING=10 CELLSPACING=0 BORDER=0>
<TR>
<TD CLASS="tt3" VALIGN="top" width="8%" bgcolor="#e0e0e0"><strong><A HREF="018.htm"><FONT style="FONT-SIZE: 9pt">后一頁</font></A><BR>
<A HREF="016.htm"><FONT style="FONT-SIZE: 9pt">前一頁</font></A><BR>
<A HREF="index.html"><FONT style="FONT-SIZE: 9pt">回目錄</font></A><BR>
<A HREF="../../../../index.htm"><FONT style="FONT-SIZE: 9pt">回首頁</font></A><BR>
</strong>
</TD>
<TD class="tt2" bgcolor="#F5F8F8" width="84%"><center><B><FONT style="FONT-SIZE: 16.5pt" COLOR="#FF6666" FACE="楷體_GB2312">第六章 文件管理(二)</FONT></B></center>
<hr color="#EE9B73" size="1" width="94%">
<p>6.2.7 <font face="宋體" lang="ZH-CN">記錄的刪除、插入、排序 </p>
<p> 刪除一條記錄的基本思路是:獲取當前記錄的位置并把該位置后的記錄逐個向前移動。</font>
<font face="宋體" lang="ZH-CN">文件在最后一條記錄前截斷。 </p>
<p> </font>for i:=CurrentRec+1 to Count-1 do</p>
<p>begin</p>
<p>seek(MethodFile,i);</p>
<p>read(MethodFile,MethodRec);</p>
<p>seek(MethodFile,i-1);</p>
<p>Write(MethodFile,MethodRec);</p>
<p>end;</p>
<p>Truncate(MethodFile);<font face="宋體" lang="ZH-CN"> </font></p>
<p><font face="宋體" lang="ZH-CN">
為避免誤刪除,在進行刪除操作前彈出一個消息框進行確認。刪除后要更新全局變量的值和顯示內容: </p>
</font><p>Count := Count - 1;</p>
<p>ChangeGrid; </p>
<p><font face="宋體" lang="ZH-CN">
完整的程序如下: </p>
</font><p>procedure TRecFileForm.DeleteButtonClick(Sender: TObject);</p>
<p>var</p>
<p>NewFile: MethodFileType;</p>
<p>MethodRec: TMethod;</p>
<p>NewFileName: String;</p>
<p>i: Integer;</p>
<p>begin</p>
<p>if FileOpened = False then Exit;</p>
<p>CurrentRec := StringGrid1.Row-1;</p>
<p>if CurrentRec < 0 then Exit;</p>
<p>if MessageDlg('Delete Current Record ?', mtConfirmation,</p>
<p>[mbYes, mbNo], 0) = idYes then</p>
<p>begin</p>
<p>HazAttr.text := '';</p>
<p>for I := CurrentRec+1 to Count-1 do</p>
<p>begin</p>
<p>seek(MethodFile,i);</p>
<p>read(MethodFile,MethodRec);</p>
<p>seek(MethodFile,i-1);</p>
<p>Write(MethodFile,MethodRec);</p>
<p>end;</p>
<p>Truncate(MethodFile);</p>
<p>Count := Count-1;</p>
<p>ChangeGrid;</p>
<p>end;</p>
<p>end;</p>
<p><font face="宋體" lang="ZH-CN"> 這里所顯示的刪除操作簡單明了。但在程序開始設計時我卻走了一條彎路,后來發現雖然這種方法用于記錄的刪除操作顯得笨拙、可笑,但卻恰恰是記錄插入、排序的思想。</font></p>
<font face="宋體" lang="ZH-CN"><p> 這種思想的核心是創建一個新文件保存更新后的內容。若新文件順利創建,則刪除原文件,否則恢復原來的文件。程序清單如下: </p>
</font><p>procedure TRecFileForm.DeleteButtonClick(Sender: TObject);</p>
<p>var</p>
<p>NewFile: MethodFileType;</p>
<p>MethodRec: TMethod;</p>
<p>NewFileName: String;</p>
<p>i: Integer;</p>
<p>begin</p>
<p>if FileOpened = False then Exit;</p>
<p>CurrentRec := StringGrid1.Row-1;</p>
<p>if CurrentRec < 0 then Exit;</p>
<p>if MessageDlg('Delete Current Record ?', mtConfirmation,</p>
<p>[mbYes, mbNo], 0) = idYes then</p>
<p>begin</p>
<p>HazAttr.text := '';</p>
<p>NewFileName := ChangeFileExt(FileName,'.sav');</p>
<p>try</p>
<p>AssignFile(NewFile,FileName);</p>
<p>ReWrite(NewFile);</p>
<p>Except</p>
<p>On EInOutError do</p>
<p>begin</p>
<p>Rename(MethodFile,FileName);</p>
<p>Exit;</p>
<p>end;</p>
<p>end;</p>
<p>for i := 1 to Count do</p>
<p>if I <> CurrentRec+1 then</p>
<p>begin</p>
<p>MethodRec := GridToRec(i);</p>
<p>Write(NewFile,MethodRec);</p>
<p>end;</p>
<p>closeFile(MethodFile);</p>
<p>try</p>
<p>AssignFile(MethodFile,Filename);</p>
<p>Reset(MethodFile);</p>
<p>except</p>
<p>on EInOutError do</p>
<p>begin</p>
<p>DeleteFile(FileName);</p>
<p>AssignFile(MethodFile,NewFileName);</p>
<p>Reset(MethodFile);</p>
<p>Rename(MethodFile,FileName);</p>
<p>Exit;</p>
<p>end;</p>
<p>DeleteFile(NewFileName);</p>
<p>Count:=Count-1;</p>
<p>ChangeGrid;</p>
<p>end;</p>
<p>end;</p>
<font face="宋體" lang="ZH-CN"><p> 對于記錄插入,方法基本同上。對于排序,可先將關鍵域讀入排序,而后再按排序結果對應的記錄號順序重寫文件。 </p>
</font><p>6.2.8 <font face="宋體" lang="ZH-CN">結果綜合 </p>
<p> 對不同方法的評估結果,可按一定的公式進行綜合。當用戶按下“計算”按鈕時,系統進行計算并把綜合結果寫入</font>HazAttr<font
face="宋體" lang="ZH-CN">只讀編輯框中。</p>
<p> 為保證結果顯示的正確性,每次增加、修改、刪除操作確認后</font>HazAttr<font
face="宋體" lang="ZH-CN">編輯框清空。 </p>
</font><p>6.2.9 <font face="宋體" lang="ZH-CN">編輯對話框的輸入檢查 </p>
<p> 當用戶單擊“增加”或“修改”按鈕時系統將彈出一個編輯對話框,讓用戶輸入或修改記錄內容。其中的三個編輯框,一個組合列表框分別對應</font>TMethod
<font face="宋體" lang="ZH-CN">的四個域。由于</font>TMethod<font face="宋體"
lang="ZH-CN">的</font>Result<font face="宋體" lang="ZH-CN">域必須是</font>[0,1]<font
face="宋體" lang="ZH-CN">間的小數,因此當用戶按</font>OK<font face="宋體"
lang="ZH-CN">鍵關閉對話框時應進行類型和范圍檢查。</p>
<p> 在</font>VB<font face="宋體" lang="ZH-CN">中我做過同樣的工作,那時需要對用戶輸入的鍵碼逐個進行判斷。但這種方法很繁瑣、很難做圓滿</font>(<font
face="宋體" lang="ZH-CN">如不能很好地支持編輯鍵</font>)<font face="宋體"
lang="ZH-CN">。而</font>Object Pascal<font face="宋體" lang="ZH-CN">提供了更好的方法。這種方法的關鍵就在于它的類型轉換函數</font>Val<font
face="宋體" lang="ZH-CN">: </p>
</font><p>procedure Val(Str: String;var V; var Code: Integer)<font face="宋體"
lang="ZH-CN">; </p>
<p> </font>V<font face="宋體" lang="ZH-CN">是由</font>Str<font face="宋體"
lang="ZH-CN">轉換成的整型或實型數。若字符串非法,則出錯位置返至</font>Code;<font
face="宋體" lang="ZH-CN">否則置</font>Code<font face="宋體" lang="ZH-CN">為</font>0<font
face="宋體" lang="ZH-CN">。字符串非法并不會引發一個轉換異常。</p>
<p> 如果轉換后的數超出了我們的范圍,則顯式把</font>Code<font
face="宋體" lang="ZH-CN">置為</font>-1<font face="宋體" lang="ZH-CN">。最后統一通過檢測</font>Code<font
face="宋體" lang="ZH-CN">是否為</font>0<font face="宋體" lang="ZH-CN">來判斷輸入是否合法。</p>
<p> 我們把輸入檢查放在對話框的</font>OnCloseQuery<font face="宋體"
lang="ZH-CN">事件處理過程中。如輸入非法,則禁止對話框關閉,并將輸入焦點置于</font>Result<font
face="宋體" lang="ZH-CN">編輯框中。但假如用戶按了</font>Cancel<font
face="宋體" lang="ZH-CN">按鈕,則這種檢查是多余的。為此定義一個布爾變量</font>IsCancel<font
face="宋體" lang="ZH-CN">,對話框生成時置為</font>False<font face="宋體"
lang="ZH-CN">。假如用戶按下</font>Cancel<font face="宋體" lang="ZH-CN">,則置為</font>True<font
face="宋體" lang="ZH-CN">,此時</font>OnCloseQuery<font face="宋體" lang="ZH-CN">事件不進行輸入檢查。</p>
<p> 對話框的</font>OnCloseQuery<font face="宋體" lang="ZH-CN">事件處理過程的程序清單如下: </p>
</font><p>procedure TEditForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);</p>
<p>var</p>
<p>Res: Real;</p>
<p>k: Integer;</p>
<p>begin</p>
<p>if IsCancel = False then</p>
<p>begin</p>
<p>val(Result.text,Res,k);</p>
<p>if (Res > 1) or (Res < 0) then k := -1;</p>
<p>if k <> 0 then</p>
<p>begin</p>
<p>MessageDlg('<font face="宋體" lang="ZH-CN">非法輸入</font> <font face="宋體"
lang="ZH-CN">!</font>',mtWarning,[mbOK],0);</p>
<p>Result.text := '';</p>
<p>CanClose := False;</p>
<p>Result.SetFocus;</p>
<p>end;</p>
<p>end;</p>
<p>end; </p>
<p>6.2.10 <font face="宋體" lang="ZH-CN">文件和系統的關閉 </p>
<p> 文件關閉須調用</font>CloseFile<font face="宋體" lang="ZH-CN">過程: </p>
<p> </font> CloseFile(MethodFile); </p>
<p><font face="宋體" lang="ZH-CN">并對系統的狀態重新進行設置。 </font></p>
<p><font face="宋體" lang="ZH-CN">
系統關閉時首先檢測當前是否有打開的文件。若有則先關閉文件。這在主窗口的</font>OnCloseQuery<font
face="宋體" lang="ZH-CN">事件中實現。</font></p>
<p><font face="宋體" lang="ZH-CN">實現文件關閉的程序清單如下: </p>
</font><p>procedure TRecFileForm.CloseButtonClick(Sender: TObject);</p>
<p>begin</p>
<p>if FileOpened then</p>
<p>begin</p>
<p>CloseFile(MethodFile);</p>
<p>FileOpened := False;</p>
<p>ClearGrid;</p>
<p>OpenButton.Enabled := True;</p>
<p>NewButton.Enabled := True;</p>
<p>CloseButton.Enabled := False;</p>
<p>RecFileForm.Caption := FormCaption;</p>
<p>end;</p>
<p>end; </p>
<p><font face="宋體" lang="ZH-CN">實現系統關閉前檢查的程序清單如下:</p>
</font><p>procedure TRecFileForm.FormCloseQuery(Sender: TObject;</p>
<p>var CanClose: Boolean);</p>
<p>begin</p>
<p>if FileOpened then</p>
<p>closeFile(MethodFile);</p>
<p>end; </p>
<p>6.2.11 <font face="宋體" lang="ZH-CN">記錄文件小結 </p>
<p> 我們所舉的例子雖然簡單,但基本覆蓋了記錄文件操作的主要方面。這里關鍵問題在于靈活應用</font>Delphi<font
face="宋體" lang="ZH-CN">提供的文件管理函數。同時,為了保證程序的健壯性應對異常進行捕獲并處理。在數據庫應用技術發展的今天,記錄文件的重要性也許有所下降,但對象我們這里所處理的簡單問題它仍有用武之地。</p>
<p> 這里所舉的例子一次只能處理一個文件。但讀者可以很容易把它改為一個</font>MDI<font
face="宋體" lang="ZH-CN">程序。雖然對于這里的實際情況來說,似乎并無必要。 </p>
</font><p align="center">6.3 <font face="宋體" lang="ZH-CN">文件控件的應用 </p>
<p> </font>Delphi<font face="宋體" lang="ZH-CN">文件管理的最大特色是提供了一組文件操作控件。利用這些控件我們可以快速開發一個文件名瀏覽系統。其功能強大與其所需書寫代碼之少所形成的強烈反差,正是</font>Dephi<font
face="宋體" lang="ZH-CN">生命力的體現。 </p>
</font><p>6.3.1 <font face="宋體" lang="ZH-CN">文件控件及其相互關系 </p>
<p> </font>Delphi<font face="宋體" lang="ZH-CN">提供的專用文件控件如下表所示。 </p>
<p> 表</font>6.4 Delphi<font face="宋體" lang="ZH-CN">專用文件控件━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</font></p>
<font face="宋體" lang="ZH-CN"><p>控件名</font> <font face="宋體" lang="ZH-CN">功
能</font></p>
<p><font face="宋體" lang="ZH-CN">─────────────────────────────────────</p>
</font><p>DriveComboBox <font face="宋體" lang="ZH-CN">驅動器組合列表框。用于選擇當前驅動器</p>
</font><p>FileListBox <font face="宋體" lang="ZH-CN">文件列表框。用于顯示當前目錄中的文件和選中當前文件</p>
</font><p>FilterComboBox <font face="宋體" lang="ZH-CN">文件類型組合列表框。用于選擇顯示文件的類型</p>
</font><p>DirectoryOutline <font face="宋體" lang="ZH-CN">目錄樹</font>(6.4<font
face="宋體" lang="ZH-CN">節專門介紹</font>) </p>
<p><font face="宋體" lang="ZH-CN">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</p>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -