第六章-文件管理(三)(6)2007-05-086.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;beginChDir(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);varpath: String;k: Integer;begin{$I-}path := DirectoryOutline.Directory;DirectoryOutline.Directory := ExtractFilePath(Path);if MessageDlg("Delete " + path + "?", mtConfirmation,[mbYes, mbNo], 0) = idYes thenRmDir(path);if IOResult <> 0 thenMessageDlg(" Cannot remove directory! The path might not"+"exist,non-empty or is the current logged directory.",mtWarning,[mbOk], 0)elseDirectoryOutline.Reset;end;修改后的目录创建过程如下。 procedure TFMForm.CreateDirectory1Click(Sender: TObject);varNewDir: TNewDir;Dir: String;begin{$I-}NewDir := TNewDir.Create(self);with NewDir dobeginCurrentDir.Caption := DirectoryOutline.Directory;if (ShowModal <> idCancel) and (DirName.Text <> "") thenDir := ExpandFileName(DirName.text);end;MkDir(Dir);if IOResult <> 0 thenMessageDlg("Cannot Create directory", mtWarning, [mbOk], 0)elseDirectoryOutline.Reset;end;当完成了这些工作,把程序重新编译、运行后,可以发现我们所希望实现的功能完全实现了!同时,我们有了一个更好的目录树部件。