gpt4 book ai didi

c++ - 用驱动器上的目录和文件填充 TreeView

转载 作者:行者123 更新时间:2023-11-28 06:34:18 25 4
gpt4 key购买 nike

我的 win32 api 项目中有一个 TreeView。我想用驱动器上的目录和文件填充 TreeView。我使用一个函数获取所有可用驱动器,然后使用驱动器盘符作为参数调用此函数:

bool ListDirectoryContents(const char *sDir)
{
WIN32_FIND_DATA fdFile;
HANDLE hFind = 0;
vector<string> FileNames;

char sPath[2048];
sprintf(sPath, "%s\\*.*", sDir);

if((hFind = FindFirstFile(sPath, &fdFile)) == INVALID_HANDLE_VALUE)
{
printf("Path not found: [%s]\n", sDir);
return false;
}

do
{
if(strcmp(fdFile.cFileName, ".") != 0 && strcmp(fdFile.cFileName, "..") != 0)
{
sprintf(sPath, "%s%s", sDir, fdFile.cFileName);
if((fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
if((fdFile.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == 0)
{
// Directories
AddItemToTree(hwndTree, sPath, 2);
//FileNames.insert(sPath);
//ListDirectoryContents(sPath); // Recursion
}
}
else
{
if((fdFile.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == 0)
{
//Files
//AddItemToTree(hwndTree, sPath, 2);
FileNames.push_back(sPath);
}
}
}
}
while(FindNextFile(hFind, &fdFile));

FindClose(hFind);

for(vector<string>::iterator FileName = FileNames.begin(); FileName != FileNames.end(); ++FileName)
{
AddItemToTree(hwndTree, (char*)FileName->c_str(), 2);
}

return true;
}

我使用的文件名 vector 首先列出目录,然后列出文件。

AddItemToTree 函数:

HTREEITEM AddItemToTree(HWND hwndTree, char *text, int nLevel)
{
TVINSERTSTRUCT tvins;
static HTREEITEM hPrev = (HTREEITEM)TVI_FIRST;
static HTREEITEM hRootItem = NULL;
static HTREEITEM hPrevLev2Item = NULL;
//tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_PARAM;
tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIS_STATEIMAGEMASK;
tvi.iImage = AddIconToTree(hwndTree, text);
tvi.iSelectedImage = tvi.iImage;
tvi.pszText = GetFileNameFromPath(text);
tvins.hInsertAfter = hPrev;
tvins.item = tvi;

if(nLevel == 1)
{
tvins.hParent = TVI_ROOT;
}
else if(nLevel == 2)
{
tvins.hParent = hRootItem;
}
else
{
TVITEM tviSetup;
tviSetup.hItem = hPrev;
tviSetup.mask = TVIF_PARAM;
TVITEM * tviLocal = &tviSetup;
TreeView_GetItem(hwndTree, tviLocal);

if(nLevel > tviLocal->lParam)
{
tvins.hParent = hPrev;
}
else
{
HTREEITEM hPrevLocal = TreeView_GetParent(hwndTree, hPrev);
tviLocal->hItem = hPrevLocal;
TreeView_GetItem(hwndTree, tviLocal);
for(int i = nLevel; i <= tviLocal->lParam;)
{
HTREEITEM hPrevLocalTemp = TreeView_GetParent(hwndTree, hPrevLocal);
hPrevLocal = hPrevLocalTemp;
tviLocal->hItem = hPrevLocal;
TreeView_GetItem(hwndTree, tviLocal);
}
tviLocal->mask = TVIF_TEXT;
TreeView_GetItem(hwndTree, tviLocal);
tvins.hParent = hPrevLocal;

}
}

hPrev = (HTREEITEM)SendMessage(hwndTree, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);

if(hPrev == 0)
{
return false;
}
if(nLevel == 1)
{
hRootItem = hPrev;
}

return hPrev;
}

问题是,如果我在 ListDirectoryContents 函数中使用递归调用,那么填充 TreeView 中的所有目录和文件需要很长时间。

所以我认为它可以像这样以某种方式工作:

  • 首先,我将添加根目录(所有驱动器,例如 C:\、D:\...)
  • 我会找到驱动器中的所有子目录和文件,并将它们添加为驱动器根目录的子目录。
  • 然后如果我展开根节点,它会找到以前找到的驱动器子目录的所有子目录等等...

但是问题来了,如何在某个地方插入一些项目?我的意思是 AddItemToTree 函数中的第三个参数是什么?

有没有更简单的方法来用目录填充 TreeView?提前谢谢大家!

最佳答案

通常,您执行此操作的方式根本不是使用 nLevel 参数,而是使用 hItemParent 参数。

也就是说,当您调用 AddItemToTree 时,您会将与父项对应的 HTREEITEM 传递给该函数。当您插入新项目时,这将被馈送到 tvins.hParent 成员。

因此,在您当前拥有 nLevel == 1 的地方,您将拥有 AddItemToTree(hwndTree, "text", TVI_ROOT)

要在展开时填充子文件夹,您需要一个 WM_NOTIFY 处理程序来监视 TVN_ITEMEXPANDED通知。

当您收到此消息时,它会告诉您扩展了哪个项目 - 这是您要传递给 AddItemToTree 的参数。

case WM_NOTIFY:
if (((LPNMHDR)lParam)->code == TVN_ITEMEXPANDED)
{
// work out the path to read, and then ...
AddItemToTree(hwndTree, <path>, ((LPNMTREEVIEW)lParam)->itemNew.hItem);
}

关于c++ - 用驱动器上的目录和文件填充 TreeView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27000450/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com