[MFC] Cum enumar fisiere?

Despre MFC, ATL si alte biblioteci C++ de la Microsoft (forum moderat)
Post Reply
User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

[MFC] Cum enumar fisiere?

Post by Ovidiu Cucu » 23 Oct 2007, 15:20

Intrebare
Cum enumar fisierele dintr-un folder?

Raspuns
Simplu, folosind clasa MFC CFileFind.

Exemplu 1

Code: Select all

int CFoo::EnumFiles(LPCTSTR pszDir, LPCTSTR pszWildcard, CStringArray& arrFiles)
{
   _ASSERTE(NULL != pszDir); // put something here, dude! 
   arrFiles.RemoveAll();
   CString strToFind;
   if(NULL == pszWildcard)
      strToFind.Format(_T("%s\\*.*"), pszDir);
   else
      strToFind.Format(_T("%s\\%s"), pszDir, pszWildcard);

   CFileFind ff;
   BOOL bFound = ff.FindFile(strToFind);
   while(bFound)
   {
      bFound = ff.FindNextFile();
      if(!ff.IsDirectory() && !ff.IsDots())
      {
         // get the file name and add it to tha array
         CString strFile = ff.GetFileName();
         arrFiles.Add(strFile);
      }
   }
   return arrFiles.GetSize();
}
Intrebare
Cum enumar fisierele cu o anumita extensie dintr-un folder si din toate subfolderele sale?

Raspuns
Va trebui sa scriem o functie recursiva, ca in exemplul de mai jos.

Exemplu 2

Code: Select all

int CFoo::EnumFilesRec(LPCTSTR pszDir, LPCTSTR pszExtension, CStringArray& arrFiles)
{
   _ASSERTE(NULL != pszDir); // come on, buddy!
   CString strToFind;
   strToFind.Format(_T("%s\\*.*"), pszDir);

   CFileFind ff;
   BOOL bFound = ff.FindFile(strToFind);
   while(bFound)
   {
      bFound = ff.FindNextFile();
      if(!ff.IsDots())
      {
         // get the full path and file name
         CString strFilePath = ff.GetFilePath();
         if(ff.IsDirectory())
         {
            EnumFilesRec(strFilePath, pszExtension, arrFiles);
         }
         else
         {
            if(NULL == pszExtension)
            {
               arrFiles.Add(strFilePath); // add anyway
            }
            else
            {
               int nPos = strFilePath.ReverseFind(_T('.'));
               if(-1 != nPos)
               {
                  // extract file extension
                  CString strExtension = 
                     strFilePath.Right(strFilePath.GetLength() - nPos - 1);
                  if(!strExtension.CompareNoCase(pszExtension)) 
                  {
                     // extension matches, then add to the array
                     arrFiles.Add(strFilePath);
                  }
               }
            }
         }
      }
   }
   return arrFiles.GetSize();
}
Intrebare
In functia de la exemplul 2 se cauta dupa o anumita extensie. Se poate modifica in asa fel incat sa se faca o cautare dupa wildcards. De exemplu, vrem sa cautam toate fisierele care incep cu "My" si au extensia .doc, .dot, trimitand ca parametru ceva de genul "My*.do?" ?

Raspuns
O metoda ar fi sa folosim doua "cautari", una pentru fisiere si alta pentru subfoldere.

Exemplu 3

Code: Select all

int CFoo::EnumFilesRec(LPCTSTR pszDir, LPCTSTR pszWildcard, CStringArray& arrFiles)
{
   _ASSERTE(NULL != pszDir); // Hmmm... I said this twice!
   CString strToFind;
   CFileFind ff;

   // find files in the current folder
   if(NULL == pszWildcard)
      strToFind.Format(_T("%s\\*.*"), pszDir, pszWildcard);
   else
      strToFind.Format(_T("%s\\%s"), pszDir, pszWildcard);

   BOOL bFound = ff.FindFile(strToFind);
   while(bFound)
   {
      bFound = ff.FindNextFile();
      if(!ff.IsDots() && !ff.IsDirectory())
      {
         // get the full path and file name and add to the array
         CString strFilePath = ff.GetFilePath();
         arrFiles.Add(strFilePath);
      }
      
   }
   
   // find subfolders
   ff.Close(); 
   strToFind.Format(_T("%s\\*.*"), pszDir);
   bFound = ff.FindFile(strToFind);
   while(bFound)
   {
      bFound = ff.FindNextFile();
      if(!ff.IsDots() && ff.IsDirectory())
      {
         // get the full path
         CString strFilePath = ff.GetFilePath();
         // call recursive for each subfolder
         EnumFilesRec(strFilePath, pszWildcard, arrFiles);
      }
   }
   
   return arrFiles.GetSize();
}
Intrebare
Mai sunt si alte metode decat folosind CFileFind?

Raspuns
Da. Controalele combobox si listbox au functia de listare fisiere built-in, folosindu-se mesajele CB_DIR si respectiv LB_DIR. In MFC acestea sunt implementate de metodele CComboBox::Dir si CListBox::Dir.
Functia din exemplul urmator desi pare ciudata prin folosirea unul listbox ascuns si temporar, e destul de simpla si adauga in plus facilitatea de sortare.

Exemplu 4

Code: Select all

int CMyDialog::EnumFilesRec(LPCTSTR pszDir, LPCTSTR pszWildcard, CStringArray& arrFiles,
                            bool bSort /*=true*/)
{
   _ASSERTE(NULL != pszDir);
   arrFiles.RemoveAll();

   // create temporary hidden listbox control
   CListBox list;
   DWORD dwStyle = bSort ? (WS_CHILD|LBS_SORT) : (WS_CHILD);
   if(list.Create(dwStyle, CRect(0,0,0,0), this, 0))
   {
      CString strToFind;
      strToFind.Format(_T("%s\\%s"), pszDir, pszWildcard); 
      if(LB_ERR != list.Dir(DDL_ARCHIVE|DDL_EXCLUSIVE, strToFind))
      {
         const int nCount = list.GetCount();
         arrFiles.SetSize(nCount);
         for(int nIndex = 0; nIndex < nCount; nIndex++)
         {
            // transfer listbox contents into the array
            CString strFile;
            list.GetText(nIndex, strFile);
            arrFiles.SetAt(nIndex, strFile);
         }
      }
      list.DestroyWindow(); // thanks! we don't need you anymore.
   }
   return arrFiles.GetSize();
}
<< Back to MFC index



Post Reply