第2章 资源管理器
许多用户可以通过Windows操作系统提供的资源管理器,查看计算机系统中的所有资源。特别是,该资源管理器提供了树形文件系统结构,非常清楚和直观地显示文件或文件夹所存放的路径,而且使用资源管理器,不同文件夹之间的切换也十分方便,可以节省查找的时间。本章将设计一个资源管理器,可以实现文件资源的查找。
2.1 需求分析
资源管理器的主要功能就是能够清楚和直观地查看计算机中的文件夹和文件。本章设计的资源管理器包括以下一些基本功能。
(1)具有树形文件系统结构列表,可以通过该列表展开任何层次的文件夹。
(2)具有文件显示列表,可以显示树形文件列表中被选中文件夹中的所有内容。
(3)可以使用鼠标拖动方式实现窗体分隔,便于查看树形文件列表和文件显示列表中的内容。
(4)当窗体大小被改变时,窗体中的控件仍然能够充满整个窗口。
(3)能够显示当前被查看文件夹的地址路径。
(4)可以直接转到用户手动设置的地址路径下。
(5)可以通过菜单栏和工具栏命令实现文件列表的平铺、图表、列表和详细信息4种方式查看。
(6)风格与Windows操作系统提供的资源管理器相似。图2-1为资源管理器的界面图。
图2-1 资源管理器界面
2.2 技术要点
在VB中,使用控件组合设计资源管理器,实现文件查找的方法一般有两种。
其一,可以使用DriveListBox、DirListBox和FileListBox三个文件系统控件实现。使用DriveListBox控件确定磁盘位置,DirListBox控件显示目录层次,FileListBox控件显示指定类型的文件列表。文件系统控件的这种资源管理功能可用于制作文件打开和保存对话框,但是这种方法的不足之处,是没有树形文件结构,只能逐层打开和查看,效率很低。
其二,使用TreeView和ListView控件实现。这种方法很直观,具备树形文件结构和文件列表,在很多数据库的显示和查找中应用十分广泛。但是,如果要将其用于显示计算机中的所有文件资源,实现的难度比较大。因为,用TreeView控件设计这么深的目录层次十分不易,而且还要将其中的文件一一加载到ListView控件中。通常,TreeView控件做到2~4层的小型文件结构系统,如数据库系统等。
本章要介绍两个第三方控件ExplorerTree和ExplorerList,来实现资源管理器的设计。使用该控件之后,可以解决上述两种方法的不足,使得资源管理器的程序代码设计变得十分简单。这两个控件包含在NEWEX.OCX文件中,读者可以从网上下载该免费文件,并加载到控件工具箱中,其加载方法如下。
(1)从“工程”菜单项的下拉列表框中,选择“部件…”子菜单项。
(2)在“控件”选项卡中,单击“浏览”按钮,弹出“添加ActiveX控件”对话框。
(3)通过“添加ActiveX控件”对话框,查找到NEWEX.OCX文件,并将其选中。单击“打开”按钮,可将NEWEX ActiveX Control Module添加到控件列表框中。
(4)在控件列表框中选择NEWEX ActiveX Control Module选项,单击“确定”按钮,即可将ExplorerTree和ExplorerList控件添加到控件工具箱中。图2-2为控件工具箱中的ExplorerTree和ExplorerList控件。
图2-2 控件工具箱中的ExplorerTree和ExplorerList控件
ExplorerTree控件为树形列表控件,外观与TreeView控件相似。将ExplorerTree控件添加到窗体之后,即可显示文件层次结构。ExplorerTree控件的常用属性名称及其说明,如表2-1所示。
表2-1 ExplorerTree控件的常用属性名称和说明
ExplorerList控件的外观与ListView控件相似。该控件可以方便地显示文件夹和文件,并且可以对文件夹和文件进行平铺或列表查看。ExplorerList控件的常用属性名称及其说明,如表2-2所示。
表2-2 ExplorerList控件的常用属性名称和说明
此外,就资源管理器作为一个普通的窗口而言,其尺寸大小会根据需要而被用户随意改变。但是,该窗口中的一些区域必须随窗口尺寸的变化而做相应调整,保证其仍然能充满整个窗口,如显示文件夹层次的ExplorerTree控件和显示文件列表的ExplorerList控件。从图2-1中还可以看到,在ExplorerTree控件和ExplorerList控件之间还具有一个分隔条。用户可以根据查看需要,重新分配这两个区域的大小。因此,窗体分隔、尺寸重置和标准坐标系统也是本章的技术要点。
2.3 系统结构
创建一个新的工程,添加一个Form窗体,在该Form窗体上添加ExplorerTree、ExplorerList、ImageList、Toolbar、PicturBox 、Label、TextBox和CommandButton等控件。工程的对象及其属性值,如表2-3所示。
表2-3 工程的对象及其属性值
Form窗体的菜单栏中主要是“查看”菜单项,用于实现文件夹或文件的4种查看方式。Form窗体的菜单栏列表,如表2-4所示。
表2-4 菜单栏列表
Form窗体的工具栏主要是“查看”按钮,其功能与“查看”菜单项中的命令相同。表2-5为Form窗体中的工具栏列表。
表2-5 工具栏列表
工具栏控件Toolbar中索引为1的按钮样式被设置为3,作为按钮间的分隔使用。
2.4 实现过程
根据表2-3向窗体上添加相应控件,并设置其属性,根据表2-4和表2-5设计菜单栏和工具栏。图2-3 为资源管理器的窗体设计界面,资源管理器的实现过程可以分为文件夹选择、查看方式菜单设计和窗体重置与分隔等部分。
图2-3 窗体设计界面
2.4.1 文件夹选择
ExplorerTree和ExplorerList控件可以分别显示文件夹层次目录和文件列表。两者之间具有如下所示的双重关系。
(1)单击选择ExplorerTree控件中的某一文件夹,在ExplorerList控件中列出该文件夹中的所有下一层文件夹和文件。
(2)双击选择ExplorerList控件中列出的某一文件夹,在ExplorerTree控件也要加亮显示到该文件夹,同时ExplorerList控件显示该文件夹内的所有内容。
ExplorerTree和ExplorerList控件之间的这种双重关系可以通过几行简单的代码实现。程序代码如程序清单2-1所示。
程序清单2-1文件夹选择
1. Private Sub exptTree_TreeDataChanged() 2. explList.TreeDatas=exptTree.TreeDatas 3. End Sub 4. 5. Private Sub explList_FolderClick() 6. exptTree.FolderClick(explList.FileName) 7. End Sub
8. 9. Private Sub cmdTransfer_Click() 10. exptTree.BrowseFrom=txtAddress.Text '转到 11. End Sub
程序说明:第2行是使用ExplorerTree控件的TreeDataChanged事件,在单击选择其中的文件夹时,使ExplorerList列出该文件夹中的所有文件夹或文件。第6行是使用ExplorerList控件的FolderClick事件,在双击选择其中的文件夹时,使ExplorerTree加亮显示该文件夹。同时,系统会自动在ExplorerList控件显示该文件夹的所有下一层文件夹和文件。第10行通过ExplorerTree控件的BrowseFrom属性,转到txtAddress中所设置的地址路径下。
通常情况下,在用户单击选择ExplorerTree控件中的某一文件夹时,地址文本框中的地址路径会相应改变。程序代码如程序清单2-2所示。
程序清单2-2地址路径改变程序
1. Private Sub exptTree_OnDirChanged() 2. txtAddress.Text=exptTree.Path 3. End Sub
程序说明:改变地址文本框中的地址路径比较简单,只要在ExplorerTree控件的OnDirChanged事件中,将该控件的Path属性返回的地址路径赋给地址文本框txtAddress即可。
2.4.2 查看方式
查看方式的选择有两个地方,一个是通过选择“查看”菜单项下的4个子菜单项的命令实现;另一个是通过选择工具栏“查看”按钮的下拉命令列表中的4个命令实现。图2-4为单击“查看”菜单项后弹出的下拉子菜单,图2-5 为单击工具栏“查看”按钮后弹出的下拉命令列表。
图2-4 单击“查看”菜单项
图2-5 单击“查看”按钮
细心的读者会发现图中的下拉菜单或者下拉命令列表是相同的。事实上,两者都是菜单。前者是普通菜单;后者是弹出式菜单,但是弹出的位置是固定的,即“查看”按钮的下方。查看方式选择的程序代码如程序清单2-3所示。
程序清单2-3查看方式选择
1. Private Sub mnuViewS_Click() 2. explList.View=0 '平铺 3. End Sub 4. 5. Private Sub mnuViewN_Click() 6. explList.View=1 '图标 7. End Sub 8. 9. Private Sub mnuViewL_Click() 10. explList.View=2 '列表 11. End Sub 12. 13. Private Sub mnuViewD_Click() 14. explList.View=3 '详细信息 15. End Sub 16. 17. Private Sub tlbTool_ButtonClick(ByVal Button As MSComctlLib.Button) '工具栏 18. Select Case Button.Index 19. Case 2 20. PopupMenu mnuView,,Button.Left,Button.Top+Button.Height 21. End Select 22. End Sub
程序说明:第1~15行为4种查看方式的选择程序,通过ExplorerList控件的View属性即可实现。第20行为单击工具栏“查看”按钮时,显示弹出式菜单。
2.4.3 窗体重置与分隔
窗体分隔及其尺寸重置都涉及到部分控件在窗体中的移动和尺寸变化。本章以PictureBox控件作为分隔条,用于分隔ExplorerTree和ExplorerList控件。
1. 控件定位
Form窗体就是一个容器,其他控件放置在该窗体中是通过4个属性来定位的,这些属性分别为:
(1)用于定位控件左侧与Form窗体左侧距离的Left属性,对应标准坐标系统中的横坐标X。
(2)用于定位控件上侧与Form窗体上侧距离的Top属性,对应标准坐标系统中的纵坐标Y。
(3)用于确定控件宽度的Width属性,Width属性确定了控件在标准坐标系统中横向尺寸。
(4)用于确定控件高度的Height属性,Height属性确定了控件在标准坐标系统中纵向尺寸。
只要确定了上述4 个属性值的变化规律,那么这些控件在Form窗体中定位就变得十分简单。表2-6为Form窗体中在窗体分隔及其尺寸重置时,相应尺寸或位置会发生变化的控件及其属性。
表2-6 尺寸或位置变化的控件及其属性
需要说明的是,表2-6中那些不变的属性是在窗体设计时确定的,如Top属性都是不变的。根据图2-3 所示通过鼠标拖动确定控件在窗体中的格局和定位,而不必使用程序代码实现,这也是VB可视化编程的一个重要特点。
表2-6中的6个控件其实可以分为两类。第一类就是txtAddress和cmdTransfer,只与窗体宽度变化有关,而且只有一个属性变化,很容易实现。第二类就是其余控件,相对要复杂些,本章主要以ExplorerTree控件exptTree和ExplorerList控件explList来定位。
2. 窗体重置
在设计窗体重置与分隔程序之前,需要在Form窗体的通用代码段声明一些窗体级变量,程序代码如程序清单2-4所示。
程序清单2-4变量声明
1. Private Const P_ECART=30 2. Private intTreeX As Integer 'ExplorerTree控件的X坐标 3. Private intTreeY As Integer 'ExplorerTree控件的Y坐标 4. Private intListX As Integer 'ExplorerList控件的X坐标 5. Private intListY As Integer 'ExplorerList控件的Y坐标 6. Private intTreeWidth As Integer 'ExplorerTree控件的宽度 7. Private intTreeHeight As Integer 'ExplorerTree控件的高度 8. Private intListWidth As Integer 'ExplorerList控件的宽度 9. Private intListHeight As Integer 'ExplorerList控件的高度 10. Private lngSplitterX As Long '分隔条相对移动X坐标
程序说明:第1行声明的常量事实上就是分隔条PictureBox控件picSplitter的宽度。第2~9行声明了用于定位ExplorerTree和ExplorerList控件的变量。第10行声明了用于记录分隔条在标准坐标系统中的相对移动距离。
当窗体大小变化时,系统会自动产生Form窗体的Resize事件。因此,只要在Resize事件中对表2-6中的6个控件所有变化的属性进行相应操作,即可实现窗体重置。程序代码如程序清单2-5所示。
程序清单2-5窗体重置
1. Private Sub Form_Resize() '窗体的大小改变 2. Const B_ECART=1 3. On Error Resume Next 4.
5. intTreeY=lblFile.Top+lblFile.Height+B_ECART 6. intTreeHeight=ScaleHeight-intTreeY-B_ECART*2 7. intListY=lblFile.Top+B_ECART 8. intListHeight=ScaleHeight-intListY-B_ECART*2 9. 10. intTreeX=B_ECART 11. intTreeWidth=exptTree.Width 12. intListX=intTreeX+exptTree.Width+P_ECART-1 13. intListWidth=ScaleWidth-intListX-B_ECART 14. 15. cmdTransfer.Move ScaleWidth-cmdTransfer.Width-B_ECART*50 16. txtAddress.Width=ScaleWidth-txtAddress.Left-_ 17. cmdTransfer.Width-B_ECART*100 18. 19. lblFile.Move intTreeX-1,,intTreeWidth 20. exptTree.Move intTreeX-1,intTreeY,intTreeWidth,intTreeHeight 21. explList.Move intListX,intListY,intListWidth+1,intListHeight 22. picSplitter.Move intTreeX+exptTree.Width-1,intListY,P_ECART,intListHeight 23. End Sub
程序说明:第5~8行和10~13行分别确定ExplorerTree和ExplorerList控件纵坐标和高度相关的变量值,以及横坐标和宽度相关的变量值。第15~17行用于调整cmdTransfer的位置和txtAddress的宽度,第19~22行用于调整exptTree和explList等的位置。
3. 窗体分隔
窗体重置主要是由窗体尺寸大小发生变化而进行控件位置、高度或宽度的调整,而窗体分隔主要是由于分隔条位置变化导致的。用户在分隔窗口时,对分隔条有三步操作,即鼠标左键在分隔条picSplitter上按下、拖动和松开。鼠标按下主要是确定本次分隔前的初始位置;拖动分隔条picSplitter主要是确定本次分隔的终止位置;松开鼠标时就执行本次分隔。程序代码如程序清单2-6所示。
程序清单2-6窗体分隔
1. '------------------当鼠标按下分隔条picSplitter的时候--------------------------- 2. Private Sub picSplitter_MouseDown(Button As Integer,Shift As Integer,_ 3. X As Single,Y As Single) 4. If Button=vbLeftButton Then 5. picSplitter.BackColor=&H808080 6. lngSplitterX=CLng(X) 7. End If 8. End Sub 9. 10. '------------------当移动分隔条picSplitter的时候---------------------------------- 11. Private Sub picSplitter_MouseMove(Button As Integer,Shift As Integer,_ 12. X As Single,Y As Single) 13. If lngSplitterX<>&H7FFFFFFF Then 14. If CLng(X)<>lngSplitterX Then 15. picSplitter.Move picSplitter.Left+X,intListY,P_ECART,_
16. ScaleHeight-intListY-2 17. lngSplitterX=CLng(X) 18. End If 19. End If 20. End Sub 21. 22. '------------------当鼠标松开分隔条picSplitter的时候------------------------------- 23. Private Sub picSplitter_MouseUp(Button As Integer,Shift As Integer,_ 24. X As Single,Y As Single) 25. If lngSplitterX<>&H7FFFFFFF Then 26. If CLng(X)<>lngSplitterX Then 27. picSplitter.Move picSplitter.Left+X,intTreeY,P_ECART,_ 28. ScaleHeight-tlbTool.Height-2 29. End If 30. 31. lngSplitterX=&H7FFFFFFF 32. picSplitter.BackColor=&H8000000F 33. 34. If picSplitter.Left>100 And picSplitter.Left<(ScaleWidth-100)Then 35. exptTree.Width=picSplitter.Left-exptTree.Left 36. lblFile.Width=picSplitter.Left-exptTree.Left 37. ElseIf picSplitter.Left<100 Then 38. exptTree.Width=100 39. lblFile.Width=100 40. Else 41. exptTree.Width=ScaleWidth-100 42. lblFile.Width=ScaleWidth-100 43. End If 44. 45. Form_Resize 46. End If 47. End Sub
程序说明:根据窗体分隔的三步操作步骤,分别在分隔条的MouseDown、MouseMove和MouseUp事件中进行编程实现。第4行使用判断语句来确定只有当鼠标左键按下时才记录分隔条初始位置。第15~16行是在鼠标拖动分隔条时将分隔条移动到鼠标的新位置。第34~43行是用于确定最终分隔位置的。本段程序设置了分隔的极限位置,就是距离当前窗体的左右边框的100 之间。第45 行调用了Form窗体的Resize事件过程实现lblFile、exptTree和explList三个控件的位置或尺寸调整,简化了程序代码。