dirwalk.c

来自「一本已经绝版的好书」· C语言 代码 · 共 282 行

C
282
字号
/************************************************************
Module name: DirWalk.C
Written by: Jim Harkins and Jeffrey Richter
Notices: Copyright (c) 1995-1997 Jeffrey Richter
************************************************************/


#include "..\CmnHdr.H"                  /* See Appendix C. */
#include <windows.h>
#include <windowsx.h>

#include <tchar.h>
#include <stdlib.h>
#include <stdio.h>             // For sprintf
#include <string.h>
#include "Resource.H"


/////////////////////////////////////////////////////////////


static BOOL IsChildDir (WIN32_FIND_DATA *lpFindData) {

   return(
      ((lpFindData->dwFileAttributes & 
         FILE_ATTRIBUTE_DIRECTORY) != 0) &&
      (lstrcmp(lpFindData->cFileName, __TEXT("."))  != 0) &&
      (lstrcmp(lpFindData->cFileName, __TEXT("..")) != 0));
}


/////////////////////////////////////////////////////////////


static BOOL FindNextChildDir (HANDLE hFindFile,
   WIN32_FIND_DATA *lpFindData) {

   BOOL fFound = FALSE;

   do {
      fFound = FindNextFile(hFindFile, lpFindData);
   } while (fFound && !IsChildDir(lpFindData));

   return(fFound);
}


/////////////////////////////////////////////////////////////


static HANDLE FindFirstChildDir (LPTSTR szPath,
   WIN32_FIND_DATA *lpFindData) {

   BOOL fFound;
   HANDLE hFindFile = FindFirstFile(szPath, lpFindData);

   if (hFindFile != INVALID_HANDLE_VALUE) {
      fFound = IsChildDir(lpFindData);

      if (!fFound)
         fFound = FindNextChildDir(hFindFile, lpFindData);

      if (!fFound) {
         FindClose(hFindFile);
         hFindFile = INVALID_HANDLE_VALUE;
      }
   }
   return(hFindFile);
}


/////////////////////////////////////////////////////////////


// To minimize stack use, one instance of the DIRWALKDATA
// structure is created as a local variable in DirWalk,
// and a pointer to it is passed to DirWalkRecurse.

// Data used by DirWalkRecurse
typedef struct {
   HWND   hwndTreeLB;   // Handle to the output list box
   int    nDepth;       // Nesting depth
   BOOL   fRecurse;     // Set to TRUE to list subdirectories.
   TCHAR  szBuf[1000];  // Output formatting buffer
   int    nIndent;      // Indentation character count
   BOOL   fOk;          // Loop control flag
   BOOL   fIsDir;       // Loop control flag
   WIN32_FIND_DATA FindData; // File information
} DIRWALKDATA, *LPDIRWALKDATA;


/////////////////////////////////////////////////////////////


// Walk the directory structure and fill a list box with
// filenames. If pDW->fRecurse is set, list any child
// directories by recursively calling DirWalkRecurse.
static void DirWalkRecurse (LPDIRWALKDATA pDW) {
   HANDLE hFind;

   pDW->nDepth++;

   pDW->nIndent = 3 * pDW->nDepth;
   _stprintf(pDW->szBuf, __TEXT("%*s"), pDW->nIndent,
      __TEXT(""));

   GetCurrentDirectory(chDIMOF(pDW->szBuf) - pDW->nIndent,
      &pDW->szBuf[pDW->nIndent]);
   ListBox_AddString(pDW->hwndTreeLB, pDW->szBuf);

   hFind = FindFirstFile(__TEXT("*.*"), &pDW->FindData);
   pDW->fOk = (hFind != INVALID_HANDLE_VALUE);

   while (pDW->fOk) {
      pDW->fIsDir = pDW->FindData.dwFileAttributes &
         FILE_ATTRIBUTE_DIRECTORY;
      if (!pDW->fIsDir ||
         (!pDW->fRecurse && IsChildDir(&pDW->FindData))) {

         _stprintf(pDW->szBuf,
            pDW->fIsDir ? __TEXT("%*s[%s]") : __TEXT("%*s%s"),
            pDW->nIndent, __TEXT(""),
            pDW->FindData.cFileName);

         ListBox_AddString(pDW->hwndTreeLB, pDW->szBuf);
      }
      pDW->fOk = FindNextFile(hFind, &pDW->FindData);
   }
   if (hFind != INVALID_HANDLE_VALUE)
      FindClose(hFind);

   if (pDW->fRecurse) {
      // Get the first child directory.
      hFind = FindFirstChildDir(
         __TEXT("*.*"), &pDW->FindData);
      pDW->fOk = (hFind != INVALID_HANDLE_VALUE);
      while (pDW->fOk) {
         // Change into the child directory.
         if (SetCurrentDirectory(pDW->FindData.cFileName)) {

            // Perform the recursive walk into the child
            // directory.  Remember that some members of pDW 
            // will be overwritten by this call.
            DirWalkRecurse(pDW);

            // Change back to the child's parent directory.
            SetCurrentDirectory(__TEXT(".."));
         }

         pDW->fOk = FindNextChildDir(hFind, &pDW->FindData);
      }

      if (hFind != INVALID_HANDLE_VALUE)
         FindClose(hFind);
   }
   pDW->nDepth--;
}


/////////////////////////////////////////////////////////////


// Walk the directory structure and fill a list box with
// filenames. This function sets up a call to 
// DirWalkRecurse, which does the real work.

void DirWalk (
   HWND hwndTreeLB,      // List box to fill
   LPCTSTR pszRootPath,  // Starting point of the tree walk
   BOOL fRecurse) {      // Expand subdirectories.

   TCHAR szCurrDir[_MAX_DIR];
   DIRWALKDATA DW;

   // Clear out the list box.
   ListBox_ResetContent(hwndTreeLB);

   // Save the current directory so that it can 
   // be restored later.
   GetCurrentDirectory(chDIMOF(szCurrDir), szCurrDir);

   // Set the current directory to where we want
   // to start walking.
   SetCurrentDirectory(pszRootPath);

   // nDepth is used to control indenting. The value -1 will
   // cause the first level to display flush left.
   DW.nDepth = -1;

   DW.hwndTreeLB = hwndTreeLB;
   DW.fRecurse = fRecurse;

   // Call the recursive function to walk the subdirectories.
   DirWalkRecurse(&DW);

   // Restore the current directory to what it was 
   // before the function was called.
   SetCurrentDirectory(szCurrDir);
}


/////////////////////////////////////////////////////////////


BOOL Dlg_OnInitDialog (HWND hwnd, HWND hwndFocus,
   LPARAM lParam) {

   RECT rc;

   // Associate an icon with the dialog box.
   chSETDLGICONS(hwnd, IDI_DIRWALK, IDI_DIRWALK);

   DirWalk(GetDlgItem(hwnd, IDC_TREE), __TEXT("\\"), TRUE);

   GetClientRect(hwnd, &rc);
   SetWindowPos(GetDlgItem(hwnd, IDC_TREE), NULL,
      0, 0, rc.right, rc.bottom, SWP_NOZORDER);

   return(TRUE);
}


/////////////////////////////////////////////////////////////


void Dlg_OnSize (HWND hwnd, UINT state, int cx, int cy) {
   SetWindowPos(GetDlgItem(hwnd, IDC_TREE), NULL, 0, 0,
      cx, cy, SWP_NOZORDER);
}


/////////////////////////////////////////////////////////////


void Dlg_OnCommand (HWND hwnd, int id, HWND hwndCtl,
   UINT codeNotify) {

   switch (id) {
      case IDCANCEL:
         EndDialog(hwnd, id);
         break;

      case IDOK:
         // Call the recursive routine to walk the tree.
         DirWalk(GetDlgItem(hwnd, IDC_TREE), __TEXT("\\"),
            TRUE);
         break;
   }
}


/////////////////////////////////////////////////////////////


BOOL CALLBACK Dlg_Proc (HWND hwnd, UINT uMsg,
   WPARAM wParam, LPARAM lParam) {

   switch (uMsg) {
      chHANDLE_DLGMSG(hwnd, WM_INITDIALOG,  Dlg_OnInitDialog);
      chHANDLE_DLGMSG(hwnd, WM_SIZE,        Dlg_OnSize);
      chHANDLE_DLGMSG(hwnd, WM_COMMAND,     Dlg_OnCommand);
   }
   return(FALSE);
}


/////////////////////////////////////////////////////////////


int WINAPI _tWinMain (HINSTANCE hinstExe,
   HINSTANCE hinstPrev, LPTSTR pszCmdLine, int nCmdShow) {

   chWARNIFUNICODEUNDERWIN95();
   DialogBox(hinstExe, MAKEINTRESOURCE(IDD_DIRWALK),
      NULL, Dlg_Proc);

   return(0);
}


//////////////////////// End Of File ////////////////////////

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?