Как да получите ред на показване на папки на 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 Explorer, вместо просто да ги взема и сортирам сам.   -  person Ryan    schedule 10.12.2020
comment
Как внедрявате функцията listFileInBrowser? Опитвали ли сте да използвате SHParseDisplayName, за да преобразувате абсолютния път в PIDL и след това SHBindToParent, което ви дава указателя IShellFolder, след което можете да извикате метода EnumObjects?   -  person Drake Wu    schedule 11.12.2020
comment
благодаря! Но това също не е това, което искам. Надявам се, че редът на обходените файлове и папки е същият като реда, показан от Windows Explorer. Вашето предложение може да получи съдържанието на папките, но по подразбиране е сортиране по име.Използвам изходния код на официалния уебсайт на Microsoft, Благодаря отново, Вие ме насочихте да работя здраво.   -  person Ryan    schedule 11.12.2020
comment
Дори в мостра, която изпратихте, тя не е изброена по реда на показване. Но можете да Определяне как се сортира всеки прозорец на Explorer. AFAIK, няма начин да получите реда на показване на неотворен shellwindow, те дори не са показани още. Като алтернатива можете да използвате 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