VFP中制作磁盤分區清單和檔案夾清單 紅飛狐 作為一名程式員,經常要在程式中對磁盤和檔案夾進行操作,VB、DELPHI中都有相應的可視控件,但VFP中沒有這類控件, 我們通常用Getdir()或将List控件資料源設定為“7-檔案”來實作對檔案夾的操作, 但界面實在不敢恭維,操作上也不很友善。事實上利用Windows的公用控件結合Windows API函數, 我們也可以制作出類似的VFP可視類(效果見下圖)。 例圖是我在VFP6.0中制作并放入表單的兩個可視類。左邊是利用ImageComboBox和ImageList制作的磁盤清單, 右邊是利用TreeView和ImageList制作的檔案夾清單。好,下面讓我們開始吧。 一、制作磁盤清單。 1、標明使用控件。 ImageComboBox、TerrView、ImageList三個控件都包含在MSComctl.ocx中,是随VFP一起安裝的。 我這裡選用版本的是6.0。使用時最好将他們加入表單控件工具欄,便于標明。 方法是VFP主菜單-〉工具—〉選項,點選控件頁面,将此三項標明,然後點選“設定為預設值”。 2、建立新類。 VFP主菜單-〉檔案-〉建立-〉建立檔案。類命名為DirCom,派生于Control(容器),存儲于c:/myvcx/DirCom.Vcx。确定 3、添加控件。點選表單工具欄檢視類,選中ActiveX控件,将一個ImageComboBox和ImageList控件放入容器。為使用友善,将Name分别改為Ole1和Ole2。 4、建立屬性。VFP主菜單-〉類-〉建立屬性。名稱定為SelDrv,說明為:“標明驅動器”,并将其值由“.F.”改為空(顯示為“(無)”)。 5、設定屬性。 DirCom: Backstyle=0-透明; BorderWidth=0 (這樣在使用時不帶邊框) 6、添加圖示。點中ImageList,即Ole2,按滑鼠右鍵,選擇最後一行“ImageLi…”,進入屬性設定。首先一定選中16 x 16,将下面的UseMaskColor選中(這樣圖示就沒有讨厭的背景),然後進入Images頁,按“Insert Picture”,加入圖示,我這裡放入7張圖示,依次代表軟碟、軟碟、硬碟、網絡驅動器、CD光牒、Rom盤、我的電腦。然後點選應用,确定 7、添加代碼。 在ImageComboBox,即Ole1的init event中加入以下代碼: */将清單設定為與容器相适應的寬度 This.width=This.Parent.Width If This.Width>2 This.Width=This.Width-2 Endif */調用Windows Api函數擷取本機驅動器的符号和類型 Declare Integer GetLogicalDriveStrings In Win32Api Long, string @Alldrv Declare integer GetDriveType In "kernel32" String */用GetLogicalDriveStrings擷取所有驅動器,存入Alldrv,其形勢為”A:/C:/D:/….”,最後為*/一空字元,應除去 Alldrv=Spac(120) =GetLogicalDriveStrings(120,@Alldrv) nQdqs=(len(allt(Alldrv))-1)/4 &&計算驅動器數量 cDqqdq=SyS(5)+"/" &&擷取目前磁碟機代號 nDqqdq=1 */定義三維數組,存放驅動器資訊 */aDrive(n,1)存放磁碟機代號 */aDrive(n,2)存放驅動器類型的漢字名稱和符号 */aDrive(n,3)存放驅動器類型 Dime aDrive(nQdqs,3) For i=1 To nQdqs aDrive(i,1)=Upper(Subs(Alldrv,1,3)) &&依次取出磁碟機代號 If Alltrim(cDqqdq)==aDrive(i,1) nDqqdq=I &&目前驅動器值 Endif */調用GetDriveType 函數确定驅動器類型 nLx=GetDriveType(aDrive(i,1)) Do Case Case nLx=2 aDrive(i,2)='軟碟' aDrive(i,3)=2 Case nLx=3 aDrive(i,2)='硬碟' aDrive(i,3)=3 Case nLx=4 aDrive(i,2)='網絡驅動器' aDrive(i,3)=4 Case nLx=5 aDrive(i,2)='CD光牒' aDrive(i,3)=5 Case nLx=6 aDrive(i,2)='RAM盤' aDrive(i,3)=6 Endcase cDrvName=aDrive(i,1) aDrive(i,1)=aDrive(i,2)-Space(2)+Left(aDrive(i,1),Len(cDrvName)-1) Alldrv=Subs(Alldrv,5) Endf */下拉清單第一項緊靠左邊 This.indentation = 0 */設定下拉清單關聯的ImageList This.imageList = This.Parent.ole2 This.Comboitems.Add(1,"我的電腦","我的電腦") &&添加清單第一項 This.Comboitems("我的電腦").image = 7 &&設定第一項圖示 */從第二項起較第一項右縮進2個機關 This.indentation = 2 */添加本機磁碟機代號,名稱和圖示 For i=2 To nQdqs+1 This.Comboitems.Add(i,"驅動器"+Alltrim(str(i-1)),aDrive(i-1,1)) This.Comboitems("驅動器"+Alltrim(str(i-1))).image = aDrive(i-1,3) Endfor */将目前驅動器設定為初始顯示值 This.Selecteditem=This.Comboitems("驅動器"+Alltrim(str(nDqqdq))) 在Ole1的LostFocus中加入代碼: */将使用者標明的驅動器存入SelDrv,供使用者調用 If This.Text<>"我的電腦" This.Parent.SelDrv=Right(This.Text,2)+"/" Else This.Parent.SelDrv="" Endif 好,你可以儲存類,并将其加入表單看看效果。 二、制作檔案夾清單 這裡與制作磁盤清單步驟基本相同,隻是将類名改為DirTree,第4步添加三個新屬性: cWjjsx 存放檔案夾屬性,供程式運作時調用; Wjjsx 存放使用者要求列出的檔案夾屬性,即ADIR()函數的5個屬性AHRSD的任意組合,最好在說明中加以注明; Seleml 使用者標明的檔案夾。 以上三個屬性的初值均必須設為字元型,否則出錯。 第6步的圖示依次改為軟碟、硬碟、網絡驅動器、CD光牒、我的電腦、打開的檔案夾、關閉的檔案夾、資源回收筒。 将Ole1(即Treeview)屬性設定為: Indentation=5; LabelEdit=1-Manual; Linestyle=1-RootLines 添加代碼: 在Ole1的Init Event中加入: */設定使用者要求顯示的檔案夾的屬性,即ADIR()的檔案屬性 This.Parent.cWjjsx="D" &&必須含有”D”,否則ADIR()不會找到檔案夾 If "A"$Upper(This.Parent.wjjsx) This.Parent.cWjjsx=This.Parent.cWjjsx+"A" &&普通 Endif If "H"$Upper(This.Parent.wjjsx) This.Parent.cWjjsx=This.Parent.cWjjsx+"H" &&隐藏 Endif If "R"$Upper(This.Parent.wjjsx) This.Parent.cWjjsx=This.Parent.cWjjsx+"R" &&隻讀 Endif If "S"$Upper(This.Parent.wjjsx) This.Parent.cWjjsx=This.Parent.cWjjsx+"S" &&系統 Endif */将Ole1的大小設定為與容器适應 */以下與ImageComboBox相同部分不再做注釋 This.Top=0 This.Left=0 This.Width=This.Parent.Width-1 This.Height=This.Parent.Height-1 Declare Integer GetLogicalDriveStrings In Win32Api Long, string @Alldrv Declare integer GetDriveType In "kernel32" String Alldrv=Spac(120) =GetLogicalDriveStrings(120,@Alldrv) nQdqs=(len(allt(Alldrv))-1)/4 cDqqdq=SyS(5)+"/" nDqqdq=1 Dime aDrive(nQdqs,4) &&這裡設為4維數組,多出的用來存放最後不含”/”的檔案夾名 For i=1 To nQdqs aDrive(i,1)=Upper(Subs(Alldrv,1,3)) If Alltrim(cDqqdq)==aDrive(i,1) nDqqdq=i Endif nLx=GetDriveType(aDrive(i,1)) Do Case Case nLx=2 aDrive(i,2)='軟碟' aDrive(i,3)=1 Case nLx=3 aDrive(i,2)='硬碟' aDrive(i,3)=2 Case nLx=4 aDrive(i,2)='網絡驅動器' aDrive(i,3)=3 Case nLx=5 aDrive(i,2)='CD光牒' aDrive(i,3)=4 Case nLx=6 aDrive(i,2)='RAM盤' aDrive(i,3)=2 Endcase cDrvName=aDrive(i,1) aDrive(i,4)=aDrive(i,2)-Space(2)+Left(aDrive(i,1),Len(cDrvName)-1) Alldrv=Subs(Alldrv,5) Endf This.imageList = This.parent.ole2 */添加根節點:“我的電腦” =This.Nodes.Add(, , "我的電腦", "我的電腦",5)) */将本機驅動器作為根節點的子節點加入 For i=1 to nQdqs =This.Nodes.Add("我的電腦",4,adrive(i,1) ,aDrive(i,4),adrive(i,3)) Endfor */判斷某一驅動器是否有子檔案夾,如有,将第一個加入成為其子節點,否則不會顯示”+”。 */這裡為了減少加入清單的時間,隻加入一個子節點,可以取得同樣的效果 For i=1 To nQdqs nMls=Adir(aWj,aDrive(i,1)+"*.*",This.Parent.cWjjsx) For j=1 To nMls If "D"$aWj(j,5) =This.Nodes.Add(aDrive(i,1),4,aDrive(i,1)+aWj(j,1),aWj(j,1),7) Exit Endif Endfor Endfor */将目前驅動器設定為標明,這樣可以将在開始就将根節點展開,并選中目前驅動器 This.selecteditem=This.Nodes(cDqqdq) 在Ole1的Expand event(展開某一節點)中加入代碼: */以下兩句為系統自動生成 *** ActiveX 控件事件 *** LPARAMETERS node */如果展開根節點,不做處理 If node.Key="我的電腦" Retu 0 Endif */判斷此節點是否曾經展開,如已經展開,不做處理 If Empty(node.tag) node.tag="打開" Else Retu 0 Endif */判斷展開的節點是否驅動器,如不是将展開圖示設定為“打開檔案夾” If Len(node.Key)<>3 node.Expandedimage=6 Endif */删除第一個子節點,因為為減少展開時間,沒有展開過的檔案夾隻有一個子節點,必須*/删除重新添加所有下級節點 This.nodes.remove(node.child.key) */将展開節點的Key(此值唯一)給變量cDqml(目前目錄) cDqml=node.key cDqsywj=Alltrim(cDqml)+"*.*" */利用DIR()将展開的檔案夾下的所有檔案和檔案夾存入aWj_father數組 nWjs_Father=Adir(aWj_father,cDqsywj,This.Parent.cWjjsx) Dime cNodeKey(nWjs_father,2) For i=1 To nWjs_father */判斷檔案夾名第一個字元是否“.”或“..”,必須将這兩個特殊的檔案夾除去 If left(aWj_father(i,1),1)="." cNodeKey(i,2)=.f. Loop Endif If "D"$aWj_father(i,5) cNodeKey(i,1)=cDqml+aWj_father(i,1)+"/" cNodeKey(i,2)=.t. */判斷檔案夾是否為資源回收筒,此處我的處理不全面,希望得到指正 */如為資源回收筒将其圖示設為資源回收筒,否則設為“關閉的檔案夾” If Upper(aWj_father(i,1))<>Upper("Recycled") This.Nodes.Add(node,4,cNodeKey(i,1),aWj_father(i,1),7) Else This.Nodes.Add(node,4,cNodeKey(i,1),"資源回收筒",8) Endif Else cNodeKey(i,2)=.f. Endif Endfor node.Sorted=.t. &&将加入的檔案夾清單排序 */以下同樣是為了判斷檔案夾是否含有子檔案夾,如有,将第一個加入作為子節點 For i=1 To nWjs_father If cNodeKey(i,2)=.f. Loop Endif nWjs_Child=Adir(aWj_Child,cNodeKey(i,1)+"*.*",This.Parent.cWjjsx) For j=1 To nWjs_Child If left(aWj_Child(j,1),1)="." Loop Endif If "D"$aWj_child(j,5) cNodeKey_child=cNodeKey(i,1)+aWj_child(j,1) This.Nodes.Add(cNodeKey(i,1),4,cNodeKey_child,"") Exit Endif Endfor Endfor This.getvisiblecount &&此句必須要,這樣能避免在清單的最下端展開節點卻看不見任何子節點 在Ole1的Nodeclick中加入代碼: *** ActiveX 控件事件 *** LPARAMETERS node */如果標明了根節點,将Seleml置空,否則置為指定的檔案夾 If node.Key<>"我的電腦" This.parent.Seleml=Alltrim(node.Key) Else This.parent.Seleml=Space(1) Endif Ok,現在可以儲存類,加入表單看看,是不是還有點專業的味?! 請大家注意,如果将這兩個可視類加入你的應用程式,别忘了在制作安裝盤時将MSComctl.ocx檔案加入安裝程式,安裝或者拷到Windows的system檔案夾中。 此主題相關圖檔如下: |