1.2.2002
V tomto článku si ukážeme, jak získat seznam souborů a podsložek, obsažených v zadané složce. Výsledkem bude program, který vyvolá již probíranou funkci pro výběr složky, upravenou tak, že během procházení jednotlivými složkami uživatelem bude do ListBoxu na hlavním dialogu zobrazován seznam všech souborů v této složce (s odfiltrováním podsložek) s uvedením jejich velikosti a data poslední změny, jak je vidět na následujícím obrázku:
Získání obsahu složky nám umožňují funkce FindFirstFile a FindNextFile. Princip použití je následující: nejprve zavoláme funkci FindFirstFile, které zadáme vzor, kterému musí vyhovovat nalezené objekty (soubory či složky). Funkce nám v případě úspěchu naplní strukturu WIN32_FIND_DATA a vrátí handle. Tyto hodnoty pak použijeme v opakovaném hledání dalších objektů pomocí funkce FindNextFile. Nakonec musíme zavřít použitý handle. Struktura WIN32_FIND_DATA obsahuje různé informace o nalezeném objektu. V našem případě použijeme jméno souboru (cFilename) a prvek dwFileAttributes, pomocí kterého zjistíme, zda objektem je složka, které chceme ze seznamu vyloučit. Celý postup je vidět v následujícím výpisu:
void PridejSoubor(HWND hListBox, LPWIN32_FIND_DATA lpWFD) { TCHAR szText[MAX_PATH+60]; TCHAR szVelikost[25]; TCHAR szCas[25]; FILETIME fileTime; SYSTEMTIME sysTime; StrCpy(szText, lpWFD->cFileName); StrFormatByteSizeA(lpWFD->nFileSizeLow, szVelikost, sizeof(szVelikost)); FileTimeToLocalFileTime(&lpWFD->ftLastAccessTime, &fileTime); FileTimeToSystemTime(&fileTime, &sysTime); _stprintf(szCas, _T("změněno dne: %d.%d.%d"), sysTime.wDay, sysTime.wMonth, sysTime.wYear); StrCat(szText, _T(" ( velikost: ")); StrCat(szText, szVelikost); StrCat(szText, _T(", ")); StrCat(szText, szCas); StrCat(szText, _T(" )")); SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)szText); } void PridejZeSlozky(HWND hWnd, LPTSTR lpSlozka) { TCHAR szSoubor[MAX_PATH]; StrCpy(szSoubor, lpSlozka); StrCat(szSoubor, _T("\\*.*")); HWND hListBox = GetDlgItem(hWnd, IDC_LISTBOX); // Nejprve odstraníme případné staré položky ListBoxu SendMessage(hListBox, LB_RESETCONTENT, 0, 0); WIN32_FIND_DATA wfd; ZeroMemory(&wfd, sizeof(wfd)); // Nalezneme 1. objekt HANDLE hFind = FindFirstFile(szSoubor, &wfd); if ( hFind == INVALID_HANDLE_VALUE ) return; // Vyloučit složky if ( !(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) PridejSoubor(hListBox, &wfd); // Procházíme všemi objekty ve složce while ( FindNextFile(hFind, &wfd) ) { if ( !(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) PridejSoubor(hListBox, &wfd); } // Zavřít handle vyhledávání FindClose(hFind); }
Ve funkci PridejSoubor je dále vidět, jak lze pomocí funkce StrFormatByteSize získat textové vyjádření zadané velikosti (v bytech), přičemž funkce sama zvolí použití jednotky (kB, MB..) podle aktuální velikosti. Dále je zde ukázán převod a výpis časového údaje v souboru (typ FILETIME) na místní čas.
Nyní si ukážeme, jak zařídit, aby uvedená funkce byla volaná vždy při změně složky v dialogu výběru složky. Ve funkci BrowseCallbackProc využijeme parametr lpData, který představuje prvek lParam struktury BROWSEINFO, kterou plníme před voláním funkce SHBrowseForFolder. Využijeme ho pro předání handle dialogu, potřebné při volání funkce PridejZeSlozky, kterou si tak můžeme zavolat přímo zevnitř této callback funkce, jak je vidět na jejím výpisu:
int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData) { TCHAR szDir[MAX_PATH]; switch ( uMsg ) { case BFFM_INITIALIZED: if ( chStartBrowseDir != NULL ) SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)chStartBrowseDir); break; case BFFM_SELCHANGED: if ( SHGetPathFromIDList((LPITEMIDLIST)lParam, szDir)) { SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)szDir); PridejZeSlozky((HWND)lpData, szDir); } break; } return 0; }
Pro úplnost uvedeme také její volání:
BOOL VyberSlozku(LPTSTR lpVybranaSlozka, LPCTSTR lpStart, LPCTSTR lpNadpis, HWND hVlastnik) { if ( lpStart != NULL ) lstrcpy(chStartBrowseDir, lpStart); BOOL bResult = TRUE; LPITEMIDLIST pidl = NULL; BROWSEINFO bi; ZeroMemory(&bi, sizeof(bi)); LPMALLOC pMalloc = NULL; SHGetMalloc(&pMalloc); if ( IsWindow(hVlastnik) ) { bi.hwndOwner = hVlastnik; bi.lParam = (LPARAM)hVlastnik; } else bi.hwndOwner = NULL; bi.pszDisplayName = 0; bi.pidlRoot = 0; bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT; bi.lpfn = BrowseCallbackProc; if ( lpNadpis == NULL ) bi.lpszTitle = _T("Vyberte požadovanou složku"); else bi.lpszTitle = lpNadpis; pidl= SHBrowseForFolder(&bi); if ( pidl ) { if ( !SHGetPathFromIDList(pidl, lpVybranaSlozka) ) bResult = FALSE; pMalloc->Free(pidl); } else bResult = FALSE; pMalloc->Release(); return bResult; }
Doprovodný projekt je ke stažení zde: win_api_find_file.zip
Školení
Kontakt
739 219 991
live:radekchalupa_1
Nové články