Заполните TreeView с каталогами и файлами на дисках

У меня есть TreeView в моем проекте Win32 API.
Я хочу заполнить это 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;
}

Вектор для FileNames, который я использую, чтобы сначала перечислить каталоги, а затем файлы.

Функция 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 с каталогами?
Спасибо всем заранее!

0

Решение

Обычно то, как вы это делаете, не 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);
}
1

Другие решения


По вопросам рекламы [email protected]