在CB中如何快速的实现资源管理器??高分等你拿!!!

yulaowa 2003-11-21 05:49:37
在Dephi中有shell control compenent
分别用左边树状结构Tshelltreeviewhe和右边TShellListView就能实现
可是我把它装到CB中总是编译不过去,总说需要身么.obj或.bpi的文件dephi里没有啊

那位大侠有高招实现资源管理器,高分送上!!!
要求是树状结构,左边是list详细资料!!!
...全文
51 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
shadowstar 2003-11-22
  • 打赏
  • 举报
回复
用Delphi实现Windows文件夹管理树

摘要:本文利用Windows名空间所提供的IShellFolder接口,用Delphi实现了文件夹管理树的生成。

关键字:文件夹 接口 Delphi


一、概述

Windows95/98视觉感观上区别Windows3.1的一个重要方面就是大量采用了树形视图控件,资源管理器左侧的文件夹管理树便是如此,它将本地和网络上的文件夹和文件等资源以层次树的方式罗列出来,为用户集中管理计算机提供了极大便利,同时在外貌上也焕然一新。Delphi为我们提供了大量Windows标准控件,但遗憾的是在目录浏览方面却只提供了一个Windows3.1样式的DirectoryListBox(Delphi5的测试版也是如此),因此,在Delphi中实现Windows文件夹管理树对开发更“地道”的Windows程序有着重大意义。

二、实现原理

Windows文件夹管理树的实现实质上是对Windows名空间(Namespace)的遍历。名空间中每个文件夹都提供了一个IShellFolder接口,遍历名空间的方法是:

1)调用SHGetDesktopFolder函数获得桌面文件夹的IShellFolder接口,桌面文件夹是文件夹管理树的根节点。

2)再调用所获得的IShellFolder接口的EnumObjects成员函数列举出子文件夹。

3)调用IShellFolder的BindToObject成员函数获得子文件夹的IShellFolder接口。 4)重复步骤2)、3)列举出某文件夹下的所有子文件夹,只至所获得的IShellFolder接口为nil为止。

下面解释将要用到的几个主要函数,它们在ShlObj单元中定义:

1)function SHGetDesktopFolder(var ppshf: IShellFolder): HResult;

该函数通过ppshf获得桌面文件夹的IShellFolder接口。

2)function IShellFolder.EnumObjects(hwndOwner: HWND; grfFlags: DWORD;

out EnumIDList: IEnumIDList): HResult;

该函数获得一个IEnumIDList接口,通过调用该接口的Next等函数可以列举出IShellFolder接口所对应的文件夹的内容,内容的类型由grfFlags来指定。我们需要列举出子文件夹来,因此grfFlags的值指定为SHCONTF_FOLDERS。HwndOwner是属主窗口的句柄。

3)function IShellFolder.BindToObject(pidl: PItemIDList; pbcReserved: Pointer;

const riid: TIID; out ppvOut: Pointer): HResult;

该函数获得某个子文件夹的IShellFolder接口,该接口由ppvOut返回。pidl是一个指向元素标识符列表的指针,Windows95/98中用元素标识符和元素标识符列表来标识名空间中的对象,它们分别类似于文件名和路径。需要特别指出的是:pidl作为参数传递给Shell API函数时,必须是相对于桌面文件夹的绝对路径,而传递给IShellFolder接口的成员函数时,则应是相对于该接口所对应文件夹的相对路径。pbcReserved应指定为nil,riid则应指定为IID_IShellFolder。

其它函数可以查阅Delphi提供的《Win32 Programmer's Reference》。
shadowstar 2003-11-22
  • 打赏
  • 举报
回复
用TreeView組件編寫類似資源管理器的程序
TreeView組件是一個樹狀的列表組件,它在應用程序的編寫中有極其廣泛的應用。如:資源管理器、網際快車(FlashGet)、FoxMail等,其中,Windows的資源管理器就是一個典型的例子。
  在C++ Builder中,要使用TreeView組件是件很容易的事情,只要調用TreeView組件的Add或AddChild方法就可以很方便地為TreeView添加一個新的節點。若要將指定的磁盤或目錄的樹狀結構放到TreeView組件中,可以使用遍歷目錄樹的方法將指定磁盤或目錄下的所有目錄(包括子目錄)和文件添加到TreeView中。
  下面,讓我們通過實際的例子來實現把C盤目錄樹裝載到TreeView中。
  首先,運行Borland C++ Builder 5.0,在窗體Form1上添加兩個Button組件、一個Edit組件、一個TreeView組件和一個Animate組件。然後把組件Button1的Caption屬性改為「裝載TreeView1」,把組件Button2的Caption屬性改為「清除」,把組件Edit1的Text屬性改為「C:\」,用來設置默認的要遍歷的目錄--C盤的根目錄,組件Animate1是在遍歷目錄時用來顯示動畫,在這裡把它的CommonAVI屬性設成「aviFindComputer」,為顯示查找計算機的動畫,你也可以設為其它動畫。
  按F12鍵打開代碼編輯窗口,在「TForm1 *Form1;」語句的下面加入下面的這條語句定義自定義函數BrowDir:

void __fastcall BrowDir(TTreeNodes * Nodes,AnsiString PathName,TTreeNode * Num);

  BrowDir函數是一個通過遞歸調用來實現遍歷目錄的自定義函數。它有三個參數,第一個參數傳送一個TreeView組件的節點用以增加新的節點,第二個參數是指定目錄的路徑,第三個參數也是傳送一個節點,用來說明要在那個節點增加新節點。
下面是它的程序清單:
void __fastcall BrowDir(TTreeNodes * Nodes,AnsiString PathName,TTreeNode * Num)
{

TSearchRec sr;
TTreeNode* Layel;
//列舉所有的目錄
if (FindFirst(PathName+"*.*", faAnyFile, sr) == 0)
{

do
{

//判斷是否是目錄,並排除目錄「.」和「..」
if((sr.Attr & faDirectory) && sr.Name!="." && sr.Name!="..")
{

//增加新節點
Layel=Nodes->AddChild(Num,"目錄:" + sr.Name);
//調用函數本身,進入子目錄
BrowDir(Nodes,PathName+sr.Name+"\\",Layel);

}

} while (FindNext(sr) == 0);
FindClose(sr);

}
//列舉所有文件
if (FindFirst(PathName+"*.*", faAnyFile, sr) == 0)
{

do
{

if(!(sr.Attr & faDirectory))

Nodes->AddChild(Num,"文件:" + sr.Name);

} while (FindNext(sr) == 0);
FindClose(sr);

}

}
將自定義函數BrowDir()添加到程序中,然後雙擊Button1組件,在它的OnClick事件中加入:

//設置光標為漏斗
Screen->Cursor=crHourGlass;
//激活Animate
Animate1->Active=true;
AnsiString Path=Edit1->Text;
//如果Path最後一個字符不是「\」就在後面加上「\」
if(Path.SubString(Path.Length(),1)!="\\")

Path+="\\";

BrowDir(TreeView1->Items,Path,TreeView1->Items->Add(NULL,Path));
//設置光標為正常狀態
Screen->Cursor=crDefault;
//關閉Animate
Animate1->Active=false;

在Button2的OnClick事件中加入:

TreeView1->Items->Clear();
TreeView2->Items->Clear();

  按F9編譯運行,點擊「裝載TreeView1」按鈕,過一會兒TreeView1組件就會出現C盤目錄樹的結構。
  這種方法的優點是打開子節點的速度快,缺點就是遍歷目錄時,當子目錄和文件越多,遍歷時所需的時間就越長。用這樣例子來做資源管理器,顯然是不行的。
  我們都知道,TreeView組件有一個OnChange事件,當TreeView組件的節點發生改變的時候就會發生該事件。若在該事件中加入相應的代碼,把改變的節點所表示目錄下的子目錄添加到TreeView組件中,這樣,程序運行時速度就會很快。
這種方法實現步驟如下:
  往窗體Form1上再添加一個Button組件和一個TreeView組件,它們的Name屬性分別為:Button3和TreeView2。把Button3的Caption屬性改為「裝載TreeView2」,然後雙擊Button3組件,在Button3的OnClick事件中加入以下代碼:

AnsiString Path=Edit1->Text;
if(Path.SubString(Path.Length(),1)!="\\")

Path+="\\";

TreeView2->Items->Add(NULL,Path);

在TreeView2的OnChangeing事件中加入:

Screen->Cursor=crHourGlass;
Animate1->Active=true;
//防止重複增加節點
if(Node->Count==0)
{

TSearchRec sr;
AnsiString DirName,DirTmp;
TTreeNode * NodeTmp=Node;
DirName=Node->Text;
//得到完整的路徑
for(int I=Node->Level ;I>0 ;I--)
{

NodeTmp=NodeTmp->Parent;
DirTmp=NodeTmp->Text;
if(DirTmp.SubString(DirTmp.Length(),1)!="\\")

DirTmp+="\\";

DirName.Insert(DirTmp,0);

}
if(DirName.SubString(DirName.Length(),1)!="\\")

DirName+="\\";

if (FindFirst(DirName+"*.*", faAnyFile, sr) == 0)
{

do
{

if((sr.Attr & faDirectory) && sr.Name!="." && sr.Name!="..")
{

TreeView2->Items->AddChild(Node,sr.Name);

}

} while (FindNext(sr) == 0);
FindClose(sr);

}

}
Screen->Cursor=crDefault;
Animate1->Active=false;
這種方法速度雖然很快,但由於只是添加一層的子目錄,所得到的節點表示的目錄下不管有沒有子目錄,節點左邊都沒有「+」符號(有「+」表示有子節點),因此就有必要將它修改一下了,於是就有第三種方法的出現。
  第二種方法是因為只添加了下一級的子目錄,所以才會出現這種問題,如果我們添加到下兩級的子目錄,問題就會得到解決,這就是第三種方法。這樣,當打開一個節點的時候,OnChange事件的代碼就會把下兩級的子目錄添加進來,再打開一個節點,該節點下兩級的子目錄又被添加進來,看起來就像是把整個目錄樹放到了TreeView中一樣。
第三種方法的實現如下:
  再添加一個Button組件Button4和一個TreeView組件TreeView3到窗體Form1上,將Button4的Caption屬性改為「裝載TreeView3」,雙擊Button4組件,在Button4的OnClick事件中加入以下代碼:

AnsiString Path=Edit1->Text;
if(Path.SubString(Path.Length(),1)!="\\")

Path+="\\";

TTreeNode * Node1=TreeView3->Items->Add(NULL,Path);
TSearchRec sr;
if (FindFirst(Path+"*.*", faAnyFile, sr) == 0)
{

do
{

if((sr.Attr & faDirectory) && sr.Name!="." && sr.Name!="..")
{

TreeView3->Items->AddChild(Node1,sr.Name);

}

} while (FindNext(sr) == 0);
FindClose(sr);

}

在TreeView3的OnChangeing事件中加入:

Screen->Cursor=crHourGlass;
Animate1->Active=true;
TSearchRec sr;
TTreeNode * NodeTmp=Node;
AnsiString DirName,DirTmp;
DirName=Node->Text;
for(int I=Node->Level ;I>0 ;I--)
{

NodeTmp=NodeTmp->Parent;
DirTmp=NodeTmp->Text;
if(DirTmp.SubString(DirTmp.Length(),1)!="\\")
DirTmp+="\\";
DirName.Insert(DirTmp,0);

}
if(DirName.SubString(DirName.Length(),1)!="\\")

DirName+="\\";

for(int J=0;J<Node->Count;J++)
{

if(Node->Item[J]->Count==0);
{

if (FindFirst(DirName+Node->Item[J]->Text+"\\*.*", faAnyFile, sr) == 0)
{

do
{

if((sr.Attr & faDirectory) && sr.Name!="." && sr.Name!="..")
{

TreeView3->Items->AddChild(Node->Item[J] ,sr.Name);

}

} while (FindNext(sr) == 0);

FindClose(sr);
}

}

}
Screen->Cursor=crDefault;
Animate1->Active=false;

  好了,程序代碼加入完後,將各個組件排列一下,按F9再編譯運行一次,這三種將目錄樹的結構裝入TreeView中的方法,你比較喜歡那一種呢?自己比較一下吧。以上的程序在Win98/Win2000,Borland C++ Builder 5.0下運行通過。
shadowstar 2003-11-22
  • 打赏
  • 举报
回复
Delphi/C++ Builder的Windows资源管理器控件,包括Tree view,List view,Combo box等控件,最新版加入和对Delphi7和Windows XP的支持

http://www.fixdown.com/soft/10590.htm
chenqm 2003-11-22
  • 打赏
  • 举报
回复
左边用Win32页的TreeView控件,右边用同一页的ListView控件.
yulaowa 2003-11-21
  • 打赏
  • 举报
回复
sorry!写错了要求!!
要求是左边树状结构,右边是list详细资料!!!

604

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder VCL组件使用和开发
社区管理员
  • VCL组件使用和开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧