如何实现完全模拟Windows资源管理器,用树形控件(CTreeCtrl)?100分

muxiu007 2003-12-10 09:20:37
小弟在做一个树形控件,需要能够在对话框中完全实现Windows的资源管理器,既一摸一样,它能够根据

当前操作系统的不同自动改换资源管理器风格。
你在WindowsXP和Windows98下使用同一软件能显示不同效果。

在CJLibrary的6.08版本中的一个IE浏览器的DEMO版本能够实现绝大部分,我把它的DLL剥离出来给自己用

了(既使用了CCJShellTree类),可以实现和它一样的程度。但是它少了一个桌面显示。
请问怎样实现?


而且,我的功能还要求能够记录上次用户打开的目录,这就需要能够遍历我的电脑中所有硬盘。怎样方便

的利用CCJLibrary实现给定一个目录字符串,找到对应ITEM而展开?

其实,主要是有几句CJLibrary中的代码不明白。请高手帮忙“翻译”。参见CJLibrary的CCJShellTree.cpp中函数
void CCJShellTree::FillTreeView(LPSHELLFOLDER lpsf, LPITEMIDLIST lpifq, HTREEITEM hParent)
{
TV_ITEM tvi; // TreeView Item.
TV_INSERTSTRUCT tvins; // TreeView Insert Struct.
HTREEITEM hPrev = NULL; // Previous Item Added.
LPENUMIDLIST lpe=0;
LPITEMIDLIST lpi=0, lpifqThisItem=0;
LPTVITEMDATA lptvid=0;
LPMALLOC lpMalloc=0;
ULONG ulFetched;
HRESULT hr;
char szBuff[256];
HWND hwnd=GetParent()->GetSafeHwnd();

hr=SHGetMalloc(&lpMalloc);
if (FAILED(hr))
return;

// Hourglass on!

SetCapture();
CWaitCursor wait; // display wait cursor

if (SUCCEEDED(hr))
{
SetRedraw(FALSE);

hr=lpsf->EnumObjects(hwnd,
SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &lpe);

if (SUCCEEDED(hr))
{
while (S_OK==lpe->Next(1, &lpi, &ulFetched))
{
//Create a fully qualified path to the current item
//The SH* shell api's take a fully qualified path pidl,
//(see GetIcon above where I call SHGetFileInfo) whereas the
//interface methods take a relative path pidl.

ULONG ulAttrs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER;

lpsf->GetAttributesOf(1, (const struct _ITEMIDLIST **)&lpi, &ulAttrs);

if (ulAttrs & (SFGAO_HASSUBFOLDER | SFGAO_FOLDER))
{
//We need this next if statement so that we don't add things like
//the MSN to our tree. MSN is not a folder, but according to the
//shell is has subfolders....

if (ulAttrs & SFGAO_FOLDER)
{
tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE |
TVIF_PARAM;

if (ulAttrs & SFGAO_HASSUBFOLDER)
{
//This item has sub-folders, so let's put the + in the TreeView.
//The first time the user clicks on the item, we'll populate the
//sub-folders then.

tvi.cChildren=1;
tvi.mask |= TVIF_CHILDREN;
}

//OK, let's get some memory for our ITEMDATA struct

lptvid = (LPTVITEMDATA)lpMalloc->Alloc(sizeof(TVITEMDATA));
if (!lptvid)
goto Done;

//Now get the friendly name that we'll put in the treeview...

if (!m_shell.GetName(lpsf, lpi, SHGDN_NORMAL, szBuff))
goto Done;
tvi.pszText = szBuff;
tvi.cchTextMax = MAX_PATH;

lpifqThisItem=m_shell.ConcatPidls(lpifq, lpi);

//Now, make a copy of the ITEMIDLIST

lptvid->lpi=m_shell.CopyITEMID(lpMalloc, lpi);

m_shell.GetNormalAndSelectedIcons(lpifqThisItem, &tvi);

lptvid->lpsfParent=lpsf; //Store the parent folders SF
lpsf->AddRef();

//So, you ask, what's the story here? Why do we have 2
//functions that apparently do the same thing? Well,
//ParseDisplayName() (used in GetFullyQualPidl) does not
//work well for non-file system objects such as the My
//Computer and Net Hood. So, since we know that these
//guys will only show up when we are enumerating the root
//of the namespace (as identified by an hParent of TVI_ROOT),
//we special case this here. You *could* use ConcatPidls()
//in ALL cases, but the GetFullyQualPidl() is shown for
//demonstration purposes, since it's the more intuative way.

//Commented out for now, since we need ConcatPidls for *any* non-file system object.
//This includes things like Control Panel, et al.

// if (hParent==TVI_ROOT)
lptvid->lpifq=m_shell.ConcatPidls(lpifq, lpi);
// else
// lptvid->lpifq=GetFullyQualPidl(lpsf, lpi);

tvi.lParam = (LPARAM)lptvid;

// Populate the TreeVeiw Insert Struct
// The item is the one filled above.
// Insert it after the last item inserted at this level.
// And indicate this is a root entry.

tvins.item = tvi;
tvins.hInsertAfter = hPrev;
tvins.hParent = hParent;

// Add the item to the tree

hPrev = InsertItem(&tvins);
}

lpMalloc->Free(lpifqThisItem);
lpifqThisItem=0;
}

lpMalloc->Free(lpi); //Finally, free the pidl that the shell gave us...
lpi=0;
}
}

}
else {
SetRedraw();
return;
}

Done:

// Hourglass off!

ReleaseCapture();

if (lpe) lpe->Release();

//The following 2 if statements will only be TRUE if we got here on an
//error condition from the "goto" statement. Otherwise, we free this memory
//at the end of the while loop above.
if (lpi && lpMalloc) lpMalloc->Free(lpi);
if (lpifqThisItem && lpMalloc) lpMalloc->Free(lpifqThisItem);

if (lpMalloc) lpMalloc->Release();
SetRedraw();
}

多谢!一定多多给分!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
...全文
320 点赞 收藏 16
写回复
16 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
claider 2004-02-16
http://expert.csdn.net/Expert/topic/2696/2696077.xml?temp=.3440515
回复
spark_zh 2004-01-07
我没用过CJLibrary,但用shell建一个目录树,就要从桌面一级一级的遍历下来。
所以桌面肯定已经得到了,就是没有加。那么找到他加根节点的地方把桌面先加上
回复
shenke410 2004-01-07
我做过类似的系统,我很不满意。
来这里学习学习。
我苦闷的“树”啊!!!!!!!!!!!!!!!!
回复
muxiu007 2004-01-06
谢谢feiniaoliang(飞鸟良) 的回复

小弟现在很想知道,如果我想加一个显示桌面的项目,如何实现?
谢谢哪位用过CJLibrary的大侠共享一下此代码

回复
feiniaoliang 2003-12-25
FillTreeView这个函数就是枚举当前目录下(应该是lpsf)的所有的目录,并将他加入到父节点的下面,若是子节点还有子目录的话,就会做个标志(这个很关键的,其实Ctreectrl就是通过这个标子的有无来调用FillTreeView的)。
回复
EricTangHL 2003-12-25
mark
回复
muxiu007 2003-12-24
请高手回复!
谢谢!
回复
muxiu007 2003-12-12
请高手不吝赐教!
谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢!
回复
muxiu007 2003-12-11
CJLibrary是一个界面编程的dll,里面扩展了很多界面控件,使功能更强大,配合VC是个很不错的库。
CJLibrary6.08是免费的好像,大家可以在google中搜索,很多地方有下载,它带有很多demo学习应用较方便。
最新版本好像是6.10已经商业化,需要收费了。
回复
tszzp 2003-12-11
我上次做了一个类似Explorer的东西,但没有它那么功能强大。你说的CCJLibrary能不能发给我一份。谢谢,我的mail是tszzp108@sina.com。大家一块研究。
回复
canjian 2003-12-11
我觉得利用注册表可以方便的实现吧
回复
phoenixli 2003-12-10
up
回复
kongyunzhongque 2003-12-10
mark
回复
crystal_heart 2003-12-10
up
回复
muxiu007 2003-12-10
希望高手指点迷津,然后可以开发出一个强大的资源管理器dll,这样大家用起来就很方便,公开代码。就可以自己添加新功能,例如,我这里就需要记录上次打开目录。

请高手提供好的解决方法。
回复
namelessone 2003-12-10
ding
回复
相关推荐
发帖
界面
创建于2007-09-28

1.5w+

社区成员

VC/MFC 界面
申请成为版主
帖子事件
创建了帖子
2003-12-10 09:20
社区公告
暂无公告