EXPDIR.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:19k
源码类别:
Windows编程
开发平台:
Visual C++
- /******************************************************************************
- * This is a part of the Microsoft Source Code Samples.
- * Copyright 1996-1997 Microsoft Corporation.
- * All rights reserved.
- * This source code is only intended as a supplement to
- * Microsoft Development Tools and/or WinHelp documentation.
- * See these sources for detailed information regarding the
- * Microsoft samples programs.
- ******************************************************************************/
- // PROGRAM: EXPDIR.C
- //
- // PURPOSE: Directory Listbox expansion/collapse functions
- #define STRICT
- #include "cfiler.h"
- extern HANDLE ghModule;
- /**********************************************************************************
- * ExpDir()
- *
- * Thread Function
- * Called when directory is selected (Enter or Double-click). Expands subdirs
- * of selected directory if not expanded, indenting subdirs. If
- * already expanded, deletes all subdirs from listbox
- *
- * Returns: TRUE if successful, FALSE if error.
- ***********************************************************************************/
- BOOL ExpDir(LPCINFO lpCInfo)
- {
- HANDLE hFile = NULL; // Find file handle
- WIN32_FIND_DATA FileData; // Find file info structure
- TCHAR szFileName[BUF_SIZE];
- TCHAR szFileName2[BUF_SIZE];
- TCHAR szInsertString[DIRECTORY_STRING_SIZE << 1];
- TCHAR szBuf[BUF_SIZE];
- PTCHAR lpszHold; // Points to actual name in LB string
- BOOL fDone = FALSE; // Loop flag for finding files in dir
- DWORD dwAttrib; // Holds file attribute flags
- LONG lIndex, // Index of selected listbox member
- lDirDepth;
- INT i;
- if (!lpCInfo) {
- ErrorMsg(TEXT("ExpDir: lpCInfo is NULL."));
- return FALSE;
- }
- for (i = 0; i < BUF_SIZE; i++) {
- szFileName[i] = TEXT(' ');
- szFileName2[i] = TEXT(' ');
- }
- if( WaitForSingleObject( lpCInfo->hDirMutex, MUTEX_TIMEOUT)
- == WAIT_TIMEOUT ){
- ErrorMsg(TEXT("ExpDir: Dir LB Mutex Timeout."));
- return(0);
- }
- //
- // If the LB is empty, we insert the root, unexpanded
- //
- if( !SendMessage( lpCInfo->hDirLB, LB_GETCOUNT, 0, 0) ){
- TCHAR szHold[DIRECTORY_STRING_SIZE << 1];
- szHold[0] = TEXT('+');
- lstrcpy( &(szHold[1]), lpCInfo->lpDriveInfo->DriveName );
- //
- // Also copy the DriveName to the Caption Bar.
- //
- lstrcpy(lpCInfo->CaptionBarText, lpCInfo->lpDriveInfo->DriveName );
- SendMessage(lpCInfo->hDirLB, LB_ADDSTRING, 0,
- (LPARAM)szHold );
- if (!TableAdd(lpCInfo->DirTable, lpCInfo->lpDriveInfo->DriveName, szHold)) {
- ErrorMsg(TEXT("ExpDir: TableAdd failed."));
- return FALSE;
- }
- ReleaseMutex( lpCInfo->hDirMutex );
- return(1);
- }
- //
- // Retrieve index of selected (careted) directory.
- //
- lIndex = SendMessage( lpCInfo->hDirLB, LB_GETCARETINDEX,
- (WPARAM)NULL, (LPARAM)NULL );
- if( SendMessage( lpCInfo->hDirLB, LB_GETTEXT, (WPARAM)lIndex,
- (LPARAM)szFileName ) < 0 ){
- ErrorMsg(TEXT("Expand Directory: Get listbox text failure"));
- ExpDirExit(lpCInfo, hFile);
- return(0);
- }
- lDirDepth = GetDirDepth( szFileName, &lpszHold );
- if( lDirDepth == -1 ){
- ErrorMsg(TEXT(" Expand Directory: GetDirDepth failure"));
- ExpDirExit(lpCInfo, hFile);
- return(0);
- }
- //
- // If Directory is already expanded, collapse it, and vice versa.
- // First, change the symbol.
- //
- if( *lpszHold == TEXT('-'))
- *lpszHold = TEXT('+');
- else
- *lpszHold = TEXT('-');
- //
- // Clear WM_SETREDRAW flag, so changes will not be seen until entire
- // expansion/collapse is complete. Reset flag at end of function
- //
- if( SendMessage(lpCInfo->hDirLB, WM_SETREDRAW, (WPARAM)FALSE,
- (LPARAM)0 ) < 0){
- ErrorMsg(TEXT("Expand Directory: Clear redraw flag failure"));
- ExpDirExit(lpCInfo, hFile);
- return(0);
- }
- //
- // Delete old dir string, insert new, and reset the selection
- //
- if( SendMessage(lpCInfo->hDirLB, LB_DELETESTRING, (WPARAM)lIndex,
- (LPARAM)0 ) < 0){
- ErrorMsg(TEXT("Expand Directory: Delete dir string failure"));
- ExpDirExit(lpCInfo, hFile);
- return(0);
- }
- else {
- if (!TableGetHidden(lpCInfo->DirTable, lIndex, szBuf)) {
- ErrorMsg(TEXT("ExpDir: TableGetHidden failed."));
- return 0;
- }
- lstrcpy(szInsertString, szBuf);
- TableRemove(lpCInfo->DirTable, lIndex);
- }
- if( SendMessage(lpCInfo->hDirLB, LB_INSERTSTRING, (WPARAM)lIndex,
- (LPARAM)szFileName ) < 0){
- ErrorMsg(TEXT("Expand Directory: Insert dir string failure"));
- ExpDirExit(lpCInfo, hFile);
- return(0);
- }
- else {
- if (!TableInsert(lpCInfo->DirTable, szInsertString, szFileName, lIndex)) {
- ErrorMsg(TEXT("ExpDir: TableInsert failed."));
- return 0;
- }
- }
- if( SendMessage(lpCInfo->hDirLB, LB_SETCURSEL, (WPARAM)lIndex,
- (LPARAM)0 ) < 0){
- ErrorMsg(TEXT("Expand Directory: Insert dir string failure"));
- ExpDirExit(lpCInfo, hFile);
- return(0);
- }
- //
- // The symbol has been changed, now collapse if needed, then reset
- // redraw flag, leave critical section, and exit.
- //
- if( *lpszHold == TEXT('+') ){
- CollapseDir( lpCInfo, lIndex, lDirDepth);
- ExpDirExit(lpCInfo, hFile);
- return(1);
- }
- //
- // If we're here, directory needs to be expanded.
- // Enumerate subdirectories beneath the dir entry in the listbox.
- //
- // First, Get the full path of the directory (in szFileName)
- //
- if (!TableGetHidden(lpCInfo->DirTable, lIndex, szBuf)) {
- ErrorMsg(TEXT("ExpDir: TableGetHidden failed."));
- return FALSE;
- }
- lstrcpy(szFileName, szBuf);
- //
- // Check to see if there is a terminating backslash
- // Then append a '*' as a wildcard for FindFirstFile.
- //
- lpszHold = &szFileName[lstrlen(szFileName)];
- lpszHold--;
- if( *lpszHold != TEXT('\') ){
- lpszHold++;
- *lpszHold = TEXT('\');
- }
- lstrcpy(szFileName2, szFileName);
- lpszHold++;
- lstrcpy( lpszHold, TEXT("*"));
- //
- // Start a search on all the files within the directory
- //
- hFile = FindFirstFile( szFileName, &FileData );
- if( hFile == INVALID_HANDLE_VALUE ){
- ErrorMsg(TEXT("Expand Directory: FindFirstFile failure."));
- ExpDirExit(lpCInfo, hFile);
- return(0);
- }
- //
- // Walk all the files in the directory.
- //
- while( !fDone ){
- //
- // Check to see if the thread has been requested to kill itself.
- // This code does not clear the suicide flag for synchronization
- // reasons - it is left to the calling code.
- //
- if( lpCInfo->fSuicide ){
- ErrorMsg(TEXT("Expand Directory: killing thread per request."));
- ExpDirExit(lpCInfo, hFile);
- //
- // Post an MM_REFRESH Message if the user has re-collapsed the
- // Dir LB.
- //
- if( !lpCInfo->fDirExpand )
- if( !PostMessage(lpCInfo->hwnd, WM_COMMAND, MM_REFRESH,
- (LPARAM)0) )
- ErrorMsg(TEXT("ExpDir: MM_REFRESH call failure."));
- //
- // We must return failure (0) here, so if FullExpand is calling,
- // it will terminate.
- //
- return(0);
- }
- //
- // Append filename to path, and get attributes
- //
- lstrcpy(lpszHold, FileData.cFileName);
- dwAttrib = GetFileAttributes( szFileName );
- //
- // Check if file is a directory. If not, or if '.' or '..', fall
- // through. If so, add it to the directory listbox.
- //
- if( dwAttrib & FILE_ATTRIBUTE_DIRECTORY )
- if( lstrcmp( FileData.cFileName,TEXT(".") ) )
- if( lstrcmp( FileData.cFileName,TEXT("..") ) ){
- TCHAR szLBEntry[DIRECTORY_STRING_SIZE << 1];
- TCHAR szHidden[DIRECTORY_STRING_SIZE << 1];
- lstrcpy(szHidden, szFileName2);
- lstrcat(szHidden, FileData.cFileName);
- if (IsEncrypted(szHidden)) {
- TCHAR szDecryptedName[BUF_SIZE];
- HANDLE hFileRead;
- GetDecryptedDirName(lpCInfo->hDirLB,
- szHidden,
- szDecryptedName,
- 0,
- &hFileRead);
- CloseHandle(hFileRead);
- if (!SimplifyFileName(szDecryptedName, szBuf)) {
- ErrorMsg(TEXT("ExpDir: SimplifyFileName failed."));
- return FALSE;
- }
- lstrcpy(szDecryptedName, szBuf);
- ConstructLBEntry(lDirDepth, szDecryptedName, szLBEntry);
- }
- else
- ConstructLBEntry(lDirDepth, FileData.cFileName, szLBEntry);
- //
- // Increment index in order to add subdir after
- // dirs just inserted.
- //
- lIndex++;
- if( SendMessage(lpCInfo->hDirLB, LB_INSERTSTRING,
- (WPARAM)lIndex,
- (LPARAM)szLBEntry) < 0){
- ErrorMsg(TEXT("Expand Directory: error inserting string."));
- ExpDirExit(lpCInfo, hFile);
- return(0);
- }
- if (!TableInsert(lpCInfo->DirTable, szHidden, szLBEntry, lIndex)) {
- ErrorMsg(TEXT("ExpDir: TableInsert failed."));
- return FALSE;
- }
- }
- fDone = !FindNextFile( hFile, &FileData );
- }
- ExpDirExit(lpCInfo, hFile);
- return(1);
- }
- /***********************************************************************************
- * ExpDirExit()
- *
- * Performs clean-up operations for ExpDir, closing handles, etc.
- ***********************************************************************************/
- void ExpDirExit(LPCINFO lpCInfo, HANDLE hFile)
- {
- if (!lpCInfo) {
- ErrorMsg(TEXT("ExpDirExit: lpCInfo is NULL."));
- return;
- }
- // Reset redraw flag. Post this message, to avoid synchro problems
- if( PostMessage(lpCInfo->hDirLB, WM_SETREDRAW, (WPARAM)TRUE,
- (LPARAM)0 ) < 0)
- ErrorMsg(TEXT("Expand Directory: Clear redraw flag failure"));
- //
- // Close FindFirstFile session
- //
- if( hFile != NULL)
- FindClose(hFile);
- //
- // Release Dir LB Mutex
- //
- ReleaseMutex( lpCInfo->hDirMutex);
- }
- /***********************************************************************************
- * ConstructDirName()
- *
- * Builds the fully qualified path of the current directory, by walking back
- * through the Dir LB tree.
- *
- * Returns: TRUE if successful, FALSE if error.
- * Returns the full directory path of given directory name in
- * lpszDirName.
- ***********************************************************************************/
- BOOL ConstructDirName(LPCINFO lpCInfo, LONG lIndex, LPTSTR lpszDirName)
- {
- LONG lDirDepth, // Depth of selected directory
- lSeekDepth = LONG_MAX;
- TCHAR szFileName[DIRECTORY_STRING_SIZE << 1]; // file buffer
- LPTSTR lpszInfoPtr,
- lpszHold;
- if (!lpCInfo) {
- ErrorMsg(TEXT("ConstructDirName: lpCInfo is NULL."));
- return FALSE;
- }
- //
- // Clear the directory name buffer
- //
- *lpszDirName = TEXT(' ');
- //
- // Walk up the entries in the listbox, constructing the full path from
- // the bottom up.
- //
- while( lIndex >= 0 ){
- //
- // Get listbox text, and compute the depth of the directory
- //
- if( SendMessage( lpCInfo->hDirLB, LB_GETTEXT, (WPARAM)lIndex,
- (LPARAM)szFileName ) < 0 ){
- ErrorMsg(TEXT(" Expand Directory: Get listbox text failure"));
- return(0);
- }
- lDirDepth = GetDirDepth(szFileName, &lpszInfoPtr);
- if( lDirDepth == -1){
- ErrorMsg(TEXT("ConstructDirName: GetDirDepth failed"));
- return(0);
- }
- //
- // If we've reached the next level up, add to the directory name
- //
- if( lDirDepth < lSeekDepth ){
- lSeekDepth = lDirDepth;
- // check if we will exceed the size of our buffer
- if( lstrlen(lpszInfoPtr) + lstrlen(lpszDirName) >
- (DIRECTORY_STRING_SIZE << 1) ){
- ErrorMsg(TEXT("ConstructDirName: Exceeded Directory Size limit"));
- return(0);
- }
- // Find the end of the directory name
- lpszHold = &lpszInfoPtr[lstrlen(lpszInfoPtr)];
- // If we're not at the root, add a ''
- if( lIndex && (*lpszDirName != TEXT(' ')) )
- *lpszHold++ = TEXT('\');
- // Append the heretofore computed path to the end of the dir name
- lstrcpy( lpszHold, lpszDirName);
- // Copy the whole path so far back into the final buffer
- lstrcpy( lpszDirName, ++lpszInfoPtr);
- }
- // If the first level dir has been added, jump to the root,
- // else go up to the previous entry in the listbox.
- if( lDirDepth == 1 )
- lIndex = 0;
- else
- lIndex--;
- }
- return(TRUE);
- }
- /***********************************************************************************
- * GetDirDepth()
- *
- * Returns: -1 if error
- * otherwise, the depth of the directory (i.e. root is depth 0,
- * c:foo is depth 1, etc. This is computed in perhaps not the
- * most efficient way, by counting the ' 's proceeding the name.
- *
- * This function also returns in lpszDirName a pointer to the
- * end of the preceeding ' ' characters within the given listbox str.
- * If the function fails, this pointer value is undefined.
- *
- * The left shifted index is to skip the tab characters. See ConstructLBEntry().
- ***********************************************************************************/
- LONG GetDirDepth(LPTSTR lpszLBString, LPTSTR *lpszDirName)
- {
- TCHAR cBar;
- LONG lCount = 0;
- do{
- cBar = lpszLBString[lCount << 1];
- if( cBar == TEXT(' ') )
- lCount++;
- else
- if( cBar != TEXT('+') && cBar != TEXT('-') ){
- ErrorMsg(TEXT("GetDirDepth: string parse error"));
- return(-1);
- }
- }while( cBar != TEXT('+') && cBar != TEXT('-') );
- *lpszDirName = &(lpszLBString[lCount << 1]);
- return( lCount );
- }
- /***********************************************************************************
- * CollapseDir()
- *
- * If directory is expanded, collapses it, by deleteing any subdirectory
- * entries below it.
- *
- * Returns: TRUE if successful, FALSE if error
- ***********************************************************************************/
- BOOL CollapseDir(LPCINFO lpCInfo, LONG lIndex, LONG lDirDepth)
- {
- TCHAR szFileName[DIRECTORY_STRING_SIZE << 1]; // file name buffer
- LPTSTR lpszNamePtr;
- LONG lDepthHold;
- if (!lpCInfo) {
- ErrorMsg(TEXT("CollapseDir: lpCInfo is NULL."));
- return FALSE;
- }
- //
- // Remove any following LB entries until we return to same depth
- //
- do{
- if (lpCInfo->DirTable->iNumElems == 1)
- return 1;
- if( SendMessage( lpCInfo->hDirLB, LB_GETTEXT, (WPARAM)lIndex + 1,
- (LPARAM)szFileName ) < 0 ){
- ErrorMsg(TEXT(" Expand Directory: Get listbox text failure"));
- return(0);
- }
- lDepthHold = GetDirDepth( szFileName, &lpszNamePtr);
- if( lDirDepth == -1 ){
- ErrorMsg(TEXT(" Expand Directory: GetDirDepth failure"));
- return(0);
- }
- if( lDirDepth < lDepthHold ) {
- if( SendMessage( lpCInfo->hDirLB, LB_DELETESTRING, (WPARAM)lIndex + 1,
- (LPARAM)0 ) < 0 ){
- ErrorMsg(TEXT(" Expand Directory: Delete String failure"));
- return(0);
- }
- if (!TableRemove(lpCInfo->DirTable, lIndex + 1)) {
- ErrorMsg(TEXT("CollapseDir: TableRemove failed."));
- return 0;
- }
- }
- }while( lDirDepth < lDepthHold );
- return(1);
- }
- /***********************************************************************************
- * ConstructLBEntry()
- *
- * Given the parent's directory depth, and the subdirectory name, inserts
- * ' 's equal to the depth+1 of the parent (plus tab character), and an
- * unexpanded '+' directory marker, then the name of the subdirectory.
- *
- * The left shifted index is to skip the tab characters.
- *
- * Returns: void. the completed listbox entry is returned in szLBEntry.
- ***********************************************************************************/
- void ConstructLBEntry(LONG lDirDepth, LPTSTR szFileName, LPTSTR szLBEntry)
- {
- int i;
- for(i = 0; i <= lDirDepth; i++){
- szLBEntry[i << 1] = TEXT(' ');
- szLBEntry[(i << 1) + 1] = 9;
- }
- szLBEntry[i << 1] = TEXT('+');
- szLBEntry[(i << 1) + 1] = TEXT(' ');
- lstrcat(szLBEntry, szFileName);
- }
- /***********************************************************************************
- * FullExpand()
- *
- * From the unexpanded root, walks down directory LB, expanding each directory
- * until it reaches the end of the tree.
- ***********************************************************************************/
- BOOL FullExpand(LPCINFO lpCInfo)
- {
- LONG lIndex = 0;
- if (!lpCInfo) {
- ErrorMsg(TEXT("FullExpand: lpCInfo is NULL."));
- return FALSE;
- }
- if( WaitForSingleObject( lpCInfo->hDirMutex, MUTEX_TIMEOUT)
- == WAIT_TIMEOUT ){
- ErrorMsg(TEXT("FullExpand: Dir LB Mutex Timeout."));
- return(0);
- }
- while( SendMessage(lpCInfo->hDirLB, LB_SETCURSEL,
- (WPARAM)lIndex,
- (LPARAM)0) != LB_ERR ){
- if( !ExpDir( lpCInfo ) ){
- ErrorMsg(TEXT("Full Expand: ExpDir failure."));
- ReleaseMutex( lpCInfo->hDirMutex );
- // This is in case the ExpDir failed because a change drive
- // command caused a kill.
- if( !PostMessage(lpCInfo->hwnd, WM_COMMAND, MM_REFRESH,
- (LPARAM)0) )
- ErrorMsg(TEXT("ExpDir: MM_REFRESH call failure."));
- return(0);
- }
- lIndex++;
- }
- // Set selection in listboxes to first item.
- if( SendMessage(lpCInfo->hDirLB, LB_SETCURSEL,
- (WPARAM)0,
- (LPARAM)0) == LB_ERR ){
- ErrorMsg(TEXT("Full Expand: Dir LB Set Selection Error"));
- ReleaseMutex( lpCInfo->hDirMutex );
- return(0);
- }
- ReleaseMutex( lpCInfo->hDirMutex );
- return(1);
- }