使用驱动器上的目录和文件填充TreeView

时间:2014-11-18 17:35:18

标签: c++ winapi treeview directory subdirectory

我的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;
}

我用来首先列出目录的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? 谢谢大家!

1 个答案:

答案 0 :(得分:1)

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

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

因此,您目前拥有nLevel == 1,{+ 1}}。

要在展开子文件夹时填充子文件夹,您需要一个AddItemToTree(hwndTree, "text", TVI_ROOT)处理程序来监视TVN_ITEMEXPANDED通知。

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

AddItemToTree