filechng.c
来自「一本已经绝版的好书」· C语言 代码 · 共 512 行
C
512 行
/************************************************************
Module name: FileChng.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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Resource.H"
/////////////////////////////////////////////////////////////
// The following functions are taken directly from DirWalk.C.
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.
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);
}
/////////////////////////////////////////////////////////////
HANDLE g_hChange = INVALID_HANDLE_VALUE;
int g_nCount = 0;
/////////////////////////////////////////////////////////////
void Dlg_ErrorBox (LPCTSTR pszSource) {
TCHAR szBuf[100]; // Output formatting buffer.
_stprintf(szBuf, __TEXT("%s reported error %lu"),
pszSource, GetLastError());
chMB(szBuf);
}
/////////////////////////////////////////////////////////////
DWORD Dlg_GetFilter (HWND hwnd) {
DWORD fdwFilter = 0;
if (IsDlgButtonChecked(hwnd, IDC_FILENAME))
fdwFilter |= FILE_NOTIFY_CHANGE_FILE_NAME;
if (IsDlgButtonChecked(hwnd, IDC_DIRNAME))
fdwFilter |= FILE_NOTIFY_CHANGE_DIR_NAME;
if (IsDlgButtonChecked(hwnd, IDC_ATTRIBS))
fdwFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
if (IsDlgButtonChecked(hwnd, IDC_SIZEFLTR))
fdwFilter |= FILE_NOTIFY_CHANGE_SIZE;
if (IsDlgButtonChecked(hwnd, IDC_LASTWRITE))
fdwFilter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
if (IsDlgButtonChecked(hwnd, IDC_LASTACCESS))
fdwFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
if (IsDlgButtonChecked(hwnd, IDC_CREATION))
fdwFilter |= FILE_NOTIFY_CHANGE_CREATION;
if (IsDlgButtonChecked(hwnd, IDC_SECURITY))
fdwFilter |= FILE_NOTIFY_CHANGE_SECURITY;
return(fdwFilter);
}
/////////////////////////////////////////////////////////////
// Validate the dialog box controls and configure a
// valid call to FindFirstChangeNotification:
// At least one filter flag must be set, and
// the path must be valid.
BOOL Dlg_Validate (HWND hwnd) {
BOOL fValid = FALSE;
TCHAR szPath[_MAX_DIR];
// Test to see whether at least one flag is set.
if (0 != Dlg_GetFilter(hwnd)) {
// Verify that the path exists.
GetDlgItemText(hwnd, IDC_PATH, szPath,
chDIMOF(szPath));
fValid = SetCurrentDirectory(szPath);
}
return(fValid);
}
/////////////////////////////////////////////////////////////
// Stop close change notification.
void Dlg_CloseChange (HWND hwnd) {
BOOL fDisableFocus =
(GetFocus() == GetDlgItem(hwnd, IDC_STOP));
EnableWindow(GetDlgItem(hwnd, IDC_STOP), FALSE);
if (Dlg_Validate(hwnd)) {
EnableWindow(GetDlgItem(hwnd, IDC_START), TRUE);
if (fDisableFocus) {
SetFocus(GetDlgItem(hwnd, IDC_START));
}
} else {
fDisableFocus = fDisableFocus ||
(GetFocus() == GetDlgItem(hwnd, IDC_START));
EnableWindow(GetDlgItem(hwnd, IDC_START), FALSE);
if (fDisableFocus) {
SetFocus(GetDlgItem(hwnd, IDC_INCSUBDIRS));
}
}
if (INVALID_HANDLE_VALUE != g_hChange) {
if (!FindCloseChangeNotification(g_hChange)) {
Dlg_ErrorBox(__TEXT("FindCloseChangeNotification"));
}
g_hChange = INVALID_HANDLE_VALUE;
}
}
/////////////////////////////////////////////////////////////
// Start close change notification.
void Dlg_OpenChange (HWND hwnd) {
TCHAR szPath[_MAX_DIR];
BOOL fDisableFocus =
(GetFocus() == GetDlgItem(hwnd, IDC_START));
Dlg_CloseChange(hwnd);
g_nCount = 0;
SetDlgItemInt(hwnd, IDC_NCOUNT, g_nCount, FALSE);
GetDlgItemText(hwnd, IDC_PATH, szPath, chDIMOF(szPath));
g_hChange = FindFirstChangeNotification(szPath,
IsDlgButtonChecked(hwnd, IDC_INCSUBDIRS),
Dlg_GetFilter(hwnd));
if (INVALID_HANDLE_VALUE == g_hChange) {
Dlg_ErrorBox(__TEXT("FindFirstChangeNotification"));
g_hChange = INVALID_HANDLE_VALUE;
} else {
EnableWindow(GetDlgItem(hwnd, IDC_START), FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_STOP), TRUE);
if (fDisableFocus) {
SetFocus(GetDlgItem(hwnd, IDC_STOP));
}
DirWalk(GetDlgItem(hwnd, IDC_TREE), szPath,
IsDlgButtonChecked(hwnd, IDC_INCSUBDIRS));
}
}
/////////////////////////////////////////////////////////////
BOOL Dlg_OnInitDialog (HWND hwnd, HWND hwndFocus,
LPARAM lParam) {
TCHAR szPath[_MAX_DIR];
// Associate an icon with the dialog box.
chSETDLGICONS(hwnd, IDI_FILECHNG, IDI_FILECHNG);
// Path defaults to the current path
GetCurrentDirectory(chDIMOF(szPath), szPath);
SetDlgItemText(hwnd, IDC_PATH, szPath);
Dlg_CloseChange(hwnd);
return(TRUE);
}
/////////////////////////////////////////////////////////////
void Dlg_OnCommand (HWND hwnd, int id, HWND hwndCtl,
UINT codeNotify) {
switch (id) {
case IDC_PATH:
// If change notification is started and
// the user updates the path,
// stop notifications.
if (EN_CHANGE == codeNotify) {
Dlg_CloseChange(hwnd);
}
break;
case IDC_INCSUBDIRS:
case IDC_FILENAME:
case IDC_DIRNAME:
case IDC_ATTRIBS:
case IDC_SIZEFLTR:
case IDC_LASTWRITE:
case IDC_LASTACCESS:
case IDC_CREATION:
case IDC_SECURITY:
case IDC_STOP:
Dlg_CloseChange(hwnd);
break;
case IDC_START:
Dlg_OpenChange(hwnd);
break;
case IDCANCEL:
Dlg_CloseChange(hwnd);
PostQuitMessage(0);
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_COMMAND, Dlg_OnCommand);
}
return(FALSE);
}
/////////////////////////////////////////////////////////////
int WINAPI _tWinMain (HINSTANCE hinstExe,
HINSTANCE hinstPrev, LPTSTR pszCmdLine, int nCmdShow) {
HWND hwnd;
MSG msg;
DWORD dwResult;
BOOL fQuit = FALSE, fWait4FileChanges;
TCHAR szPath[_MAX_DIR];
chWARNIFUNICODEUNDERWIN95();
// Create a modeless dialog box instead of a modal
// dialog box because we need to have more control over
// the message loop processing.
hwnd = CreateDialog(hinstExe,
MAKEINTRESOURCE(IDD_FILECHNG), NULL, Dlg_Proc);
// Continue to loop until a WM_QUIT
// message comes out of the queue.
while (!fQuit) {
// Do we have a valid file change notification handle?
fWait4FileChanges = (INVALID_HANDLE_VALUE != g_hChange);
// If we do, wait until a file change occurs OR until
// a message shows up in our queue.
dwResult = MsgWaitForMultipleObjects(
(fWait4FileChanges) ? 1 : 0,
&g_hChange, FALSE, INFINITE, QS_ALLEVENTS);
if (fWait4FileChanges && (WAIT_OBJECT_0 == dwResult)) {
// We awoke because of a file change notification.
// Let's update the list box.
// Increment the counter indicating the number
// of notifications we have received.
SetDlgItemInt(hwnd, IDC_NCOUNT, ++g_nCount, FALSE);
// Get the root path and fill the list box with the
// list of files in the path and the root
// directory's subdirectories if the Include
// Subdirectories check box is checked.
GetDlgItemText(hwnd, IDC_PATH, szPath,
chDIMOF(szPath));
DirWalk(GetDlgItem(hwnd, IDC_TREE), szPath,
IsDlgButtonChecked(hwnd, IDC_INCSUBDIRS));
// Tell the system that we processed the
// notification.
FindNextChangeNotification(g_hChange);
} else {
// We awoke because there is at least one message in
// the queue. Let's dispatch all the queued messages.
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
// Call IsDialogMessage so that the keyboard can
// be used to control focus in the dialog box.
if (!IsDialogMessage(hwnd, &msg)) {
if (msg.message == WM_QUIT) {
// If we have a WM_QUIT message,
// set the flag so that the
// loop terminates.
fQuit = TRUE;
} else {
// Not a WM_QUIT message. Translate it
// and dispatch it.
TranslateMessage(&msg);
DispatchMessage(&msg);
}
} // if (!IsDialogMessage())
} // while messages are still in the queue
} // if file change notification OR message
} // while (!fQuit)
// The application is terminating. Destroy the modeless
// dialog box.
DestroyWindow(hwnd);
return(0);
}
//////////////////////// End Of File ////////////////////////
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?