6.4.7.2 刪除目錄
在實現目錄刪除過程中,遠不如創建目錄那麼順利。碰到的問題是:
1.RmDir不允許刪除當前目錄。但為了操作方便,我們要求刪除的恰恰是當前目錄;
2.目錄刪除後調用Refresh方法或Update方法並不能使該目錄從屏幕顯示中去除。因而當用戶試圖進入該目錄時會導致系統崩潰。
對第一個問題,我們的解決辦法是把當前目錄轉換到其父目錄。假如讀者記得目錄也被操作系統作為一種特殊的文件對待的話,那麼就不會對下面的語句感到奇怪了:
path := DirectoryOutline.Directory;
Directoryoutlin.Directory := ExpandFilePath(Path);
而後調用RmDir過程:
RmDir(Path);
第二個問題的解決卻頗為費神。因為DirectoryOutline是Delphi提供的示例部件,沒有Help文件支持。通過試驗發現:只有當DirectoryOutline的Drive屬性改變時,才重新從相應驅動器讀取目錄。而且它基本上是只讀的,除非清除( Clear) 它,象Add、Delete這些方法對它都是無效的。
我曾經考慮過一個笨拙的方法,那就是先改變當前驅動器而後再改回來。但這種方法一方面速度無法忍受,另一方面當只存在一個驅動器可用時會導致系統崩潰。
正當我一籌莫展時,突然想到:DirectoryOutline是一個Sample部件,Delphi 提供了它的源代碼。而當我分析了它的源代碼後,我知道應該做什麼了,那就是為DirectoryOutline增添一個Reset方法!
6.7.3 為部件增添一個方法
嚴格地說,我們所做的工作屬於創建一個新部件。但因為我們有源代碼,所以不必從DirectoryOutline繼承而是直接修改它。這樣我們可以省去與創建部件有關的許多繁瑣工作。對創建新部件感興趣的讀者可閱讀本書第三編的有關章節。
在Delphi IDE中打開DirectoryOutline的源文件後:
1.把庫單元名改為DirPlus,類名改為TDirectoryOutlinePlus,表明這是DirectoryOutline的增強版。而後存入另一個目錄中;
2.添加一個公有方法Reset。這一方法的作用是重新讀取當前驅動器的目錄。程序清單如下。
procedure TDirectoryOutlinePlus.Reset;
begin
ChDir(FDrive + ':');
GetDir(0, FDirectory);
FDirectory := ForceCase(FDirectory);
if not (csLoading in ComponentState) then BuildTree;
end;
讀者也許被這段代碼弄糊塗了。由於篇幅所限,而且涉及到許多自定義部件開發的內容,我們也不准備去詳細解釋它。假如讀者想徹底搞懂它,我建議先看一下本書第三編有關自定義部件開發的內容,而後再對照原DirectoryOutline的源代碼進行分析。
3.編譯成一個庫文件DirPlus.tpu;
4.把DirPlus加入部件的Samples頁中。
如何添加一個部件見第三編有關章節的介紹。
當增強的目錄樹准備好以後,必須修改我們的子窗口設計,但卻不必親自修改源代碼。
1.刪除子窗口中的TDirectoryOutline類部件DirectoryOutline。此時FileList占據了整個客戶區;
2.把FileList的Align屬改為None,並留出左邊的空白供放部件用;
3.在窗口左部加入TDirectoryOutlinPlus類的部件DirectoryOutline;
4.把DirectoryOutline的Align屬性改為Left,FileList的Align屬性還原為Client;
5.在DirectoryOutline的事件OnChange列表中選取DirectoryOutlineChange,即原DirectoryOutline的處理過程。
以上工作的最終目標是實現目錄創建、刪除後屏幕的正確顯示。這只需要調用DirectoryOutline的Reset方法即可。
目錄刪除過程的實現代碼如下。
procedure TFMForm.DeleteDirectory1Click(Sender: TObject);
var
path: String;
k: Integer;
begin
{$I-}
path := DirectoryOutline.Directory;
DirectoryOutline.Directory := ExtractFilePath(Path);
if MessageDlg('Delete ' + path + '?', mtConfirmation,[mbYes, mbNo], 0) = idYes then
RmDir(path);
if IOResult <> 0 then
MessageDlg(' Cannot remove directory! The path might not'+
'exist,non-empty or is the current logged directory.',mtWarning,[mbOk], 0)
else
DirectoryOutline.Reset;
end;
修改後的目錄創建過程如下。
procedure TFMForm.CreateDirectory1Click(Sender: TObject);
var
NewDir: TNewDir;
Dir: String;
begin
{$I-}
NewDir := TNewDir.Create(self);
with NewDir do
begin
CurrentDir.Caption := DirectoryOutline.Directory;
if (ShowModal <> idCancel) and (DirName.Text <> '') then
Dir := ExpandFileName(DirName.text);
end;
MkDir(Dir);
if IOResult <> 0 then
MessageDlg('Cannot Create directory', mtWarning, [mbOk], 0)
else
DirectoryOutline.Reset;
end;
當完成了這些工作,把程序重新編譯、運行後,可以發現我們所希望實現的功能完全實現了!同時,我們有了一個更好的目錄樹部件。