Как получить порядок отображения папок Windows с помощью C++

Мне нужно получить изображения в папке Windows и отсортировать их в соответствии с порядком, в котором они отображаются. Теперь есть способ обойти все элементы отображения папки через дескриптор, получив дескриптор окна папки. Однако у этого метода есть недостаток: он не может получить порядок неоткрытой папки, потому что нет ни открытого файла, ни дескриптора окна. Используется QT. Прошу простить мои грамматические ошибки.

//Find out the current folder window according to the mouse click position
HWND findOpenFileWindow(const QString& path)
{
    Sleep(3 * 1000);
    POINT pNow = { 0, 0 };
    if (!GetCursorPos(&pNow))
        return NULL;

    TCHAR  szClass[255] = {0};
    HWND pMouseChooseHandle = WindowFromPoint(pNow);
    HWND pParent = ::GetParent(pMouseChooseHandle);

    GetClassName(pParent, szClass, 255);
    if (_tcscmp(szClass, L"SHELLDLL_DefView") == 0 || _tcscmp(szClass, L"NSEViewClass") == 0 )
    {
        bool bQingDisk = _tcscmp(szClass, L"NSEViewClass") == 0;
        pParent = ::GetParent(pParent);
        GetClassName(pParent, szClass, 255);
        if (_tcscmp(szClass, L"WorkerW"))
        {
            pParent = pMouseChooseHandle;
            for (int i = 0; i < 6; i++)
            {
                if(pParent != NULL)
                    pParent = ::GetParent(pParent);
            }
            HWND pChild = ::GetWindow(pParent, GW_CHILD);
            GetClassName(pChild, szClass, 255);
            while (pChild != NULL)
            {
                GetClassName(pChild, szClass, 255);
                if (_tcscmp(szClass, TEXT("ShellTabWindowClass")) == 0)
                {
                    pParent = pChild;
                    break;
                }
                pChild = ::GetNextWindow(pChild, GW_HWNDNEXT);
            }
            TCHAR  exploreWndName[MAX_PATH] = {0};
            ::GetWindowText(pParent, exploreWndName, MAX_PATH);
            if(QFileInfo(path).fileName() == QString().fromWCharArray(exploreWndName))
                return pParent;
        }
    }
    return NULL;
}

//Traverse window display items, get them
QStringList listNormalFolderFile( const QString& path, const QStringList& filter )
{
    HWND folderWnd = findOpenFileWindow(path);

    HWND          hwnd;
    IDispatch     *pDispatch;
    CComPtr<IShellWindows> pShellWindows;

    CoInitialize(NULL);
    HRESULT hr = CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pShellWindows));
    if (FAILED(hr)) 
    {
        CoUninitialize();
        return QStringList();
    }
    LONG lCount = 0;
    pShellWindows->get_Count(&lCount);

    QStringList fileList;
    for (LONG i = 0; i < lCount; i++) 
    {
        CComPtr<IShellBrowser> pShellBrowser;
        VARIANT  var;
        var.vt = VT_I4;
        var.lVal = i;
        if(SUCCEEDED(pShellWindows->Item(var, &pDispatch))) 
        {
            if(SUCCEEDED(IUnknown_QueryService(pDispatch, SID_STopLevelBrowser, IID_PPV_ARGS(&pShellBrowser))))
            {
                if (SUCCEEDED(IUnknown_GetWindow(pShellBrowser, &hwnd)))
                {
                    TCHAR  szBuf[256];
                    GetWindowText(hwnd, szBuf, sizeof(szBuf) / sizeof(TCHAR));
                    if(QFileInfo(path).fileName() != QString().fromWCharArray(szBuf))
                        continue;

                    CComPtr<IShellView> pShellView;
                    if(FAILED(pShellBrowser->QueryActiveShellView(&pShellView)))
                        continue;

                    CComPtr<IFolderView> pFv = NULL;
                    /*
                    do something here
                    */

                    CComPtr<IPersistFolder2 > pFolder;
                    if( FAILED(pFv->GetFolder(IID_IPersistFolder2, (void**) &pFolder)))
                        continue;

                    LPITEMIDLIST pidl = nullptr;
                    if( SUCCEEDED(pFolder->GetCurFolder(&pidl)))
                    {
                        wchar_t cPath[32767];
                        if( ::SHGetPathFromIDList(pidl, cPath))
                        {
                            QString filePath;
                            QFileInfo fileInfo(filePath.fromWCharArray(cPath));
                            if(fileInfo.absoluteFilePath() == QFileInfo(path).absoluteFilePath())
                            {
                                if(folderWnd == NULL || folderWnd == hwnd)
                                {
                                    fileList = listFileInBrowser(pShellBrowser, filter);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    CoUninitialize();
    return fileList;

person Ryan    schedule 10.12.2020    source источник
comment
Вы ищете это: stackoverflow.com/questions/29573501/   -  person Simon Mourier    schedule 10.12.2020
comment
Я не уверен, правильно ли я понимаю, вы хотите перечислить все файлы изображений (рекурсивные подпапки) по пути, и вам также нужно перечислить по порядку, верно? Тогда рекомендую использовать FindFirstFile/FindNextFile, но это не по порядку, нужно перебрать все файлы в текущей папке, отсортировать их вручную, а потом рекурсивно зайти в дочернюю папку.   -  person Drake Wu    schedule 10.12.2020
comment
Большое спасибо. Но это не то, чего я хочу. Я хочу получить порядок файлов, отображаемых при открытии проводника Windows, а не просто получить их и отсортировать самостоятельно.   -  person Ryan    schedule 10.12.2020
comment
Как вы реализуете функцию listFileInBrowser? Вы пытались использовать SHParseDisplayName для преобразования абсолютного пути в PIDL, а затем SHBindToParent, который дает вам указатель IShellFolder, а затем вы могли бы вызвать метод EnumObjects?   -  person Drake Wu    schedule 11.12.2020
comment
благодарить! Но это тоже не то, чего я хочу. Я надеюсь, что порядок пройденных файлов и папок такой же, как порядок, отображаемый проводником Windows. Ваше предложение может получить содержимое папок, но по умолчанию используется сортировка по имени.Я использую исходный код официального сайта Microsoft, еще раз спасибо, Вы дали мне направление для усердной работы.   -  person Ryan    schedule 11.12.2020
comment
Даже в присланном вами образце он не пронумерован в порядке отображения. Но вы можете определить порядок сортировки каждого окна Проводника. Насколько я знаю, нет способа получить порядок отображения неоткрытого окна оболочки, они даже еще не отображаются. В качестве альтернативы вы можете использовать ShellExecute для временного запуска проводника с помощью nShowCmd = SW_HIDE, а затем уничтожить окно после обхода.   -  person Drake Wu    schedule 14.12.2020
comment
большое спасибо! Я выбрал другой путь. просто сортирую сам. А я пробовал ваш способ, ShellExecute открывает папки, которые сортируются по имени по умолчанию.   -  person Ryan    schedule 24.12.2020
comment
@Ryan Рад, что ты решил проблему, ты мог опубликовать свой ответ и принять себя.   -  person Drake Wu    schedule 25.12.2020