750 lines
30 KiB
C++
750 lines
30 KiB
C++
|
//
|
||
|
// BrowseDir.cpp
|
||
|
//
|
||
|
// Functionality for the "Browse Directory" dialog.
|
||
|
// Requires dialog resource IDD_BROWSEDIRECTORY.
|
||
|
//
|
||
|
// History:
|
||
|
//
|
||
|
// 10/04/95 KenSh Created
|
||
|
// 10/09/95 KenSh Fixed bugs, removed globals and statics
|
||
|
//
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
#include <dlgs.h>
|
||
|
#include <direct.h>
|
||
|
|
||
|
//*** Custom window messages
|
||
|
//
|
||
|
#define CM_UPDATEEDIT (WM_USER + 42) // Update text in the edit (sent to the dialog)
|
||
|
|
||
|
//*** Dialog control IDs
|
||
|
//
|
||
|
#define IDC_FILENAME edt1 // Edit box w/ current directory
|
||
|
#define IDC_FILELIST lst2 // Listbox with current directory hierarchy
|
||
|
#define IDC_DRIVECOMBO cmb2 // Combo-box with current drive
|
||
|
#define IDC_NETWORK psh14 // Network button (added at runtime)
|
||
|
|
||
|
//*** Window property names
|
||
|
//
|
||
|
const TCHAR c_szOFNProp[] = _T("OFNStruct");
|
||
|
const TCHAR c_szRedrawProp[] = _T("Redraw");
|
||
|
|
||
|
//*** Globals
|
||
|
//
|
||
|
// Note: Use of thse globals assumes that any multiple threads using
|
||
|
// our subclass at the same time always have the same original edit/
|
||
|
// combo window procs. I think this is true.
|
||
|
//
|
||
|
WNDPROC g_pfnPrevEditProc; // original edit proc (before subclass)
|
||
|
WNDPROC g_pfnPrevComboProc; // original combo proc (before subclass)
|
||
|
|
||
|
//*** Local function declarations
|
||
|
//
|
||
|
BOOL CALLBACK BrowseDirDlgHook( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );
|
||
|
BOOL BrowseDir_OnOK( HWND hwnd );
|
||
|
|
||
|
// This struct is used internally and kept as a window property,
|
||
|
// in lieu of using static variables or MFC.
|
||
|
typedef struct _OFNINFO
|
||
|
{
|
||
|
OPENFILENAME ofn; // OFN struct passed to GetOpenFileName
|
||
|
TCHAR szLastDirName[_MAX_PATH]; // last known good directory
|
||
|
BOOL fAllowSetText; // should we allow WM_SETTEXT for the Edit
|
||
|
// BOOL fNetworking; // is Connect Network Drive dialog open
|
||
|
} OFNINFO, *LPOFNINFO;
|
||
|
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Procedure BrowseForDirectory
|
||
|
//
|
||
|
// Purpose Displays a dialog that lets the user choose a directory
|
||
|
// name, either local or UNC.
|
||
|
//
|
||
|
// Parameters hwndParent Parent window for the dialog
|
||
|
// pszInitialDir Directory to use as the default
|
||
|
// pszBuf Where to store the answer
|
||
|
// cchBuf Number of characters in this buffer
|
||
|
// pszDialogTitle Title for the dialog
|
||
|
//
|
||
|
// Returns nonzero if successful, zero if not. If successful, pszBuf
|
||
|
// will be filled with the full pathname of the chosen directory.
|
||
|
//
|
||
|
// History 10/06/95 KenSh Created
|
||
|
// 10/09/95 KenSh Use lCustData member instead of global
|
||
|
//
|
||
|
|
||
|
CString strSelectDir;
|
||
|
|
||
|
BOOL BrowseForDirectory(
|
||
|
HWND hwndParent,
|
||
|
LPCTSTR pszInitialDir,
|
||
|
LPTSTR pszBuf,
|
||
|
int cchBuf,
|
||
|
LPCTSTR pszDialogTitle,
|
||
|
BOOL bRemoveTrailingBackslash )
|
||
|
{
|
||
|
TCHAR szInitialDir[MAX_PATH];
|
||
|
OFNINFO ofnInfo;
|
||
|
|
||
|
pszBuf[0] = _T('\0');
|
||
|
|
||
|
// Prepare the initial directory... add a backslash if it's
|
||
|
// a 2-character path
|
||
|
_tcscpy( szInitialDir, pszInitialDir );
|
||
|
if( !szInitialDir[2] )
|
||
|
{
|
||
|
szInitialDir[2] = _T('\\');
|
||
|
szInitialDir[3] = _T('\0');
|
||
|
}
|
||
|
|
||
|
if( pszDialogTitle )
|
||
|
{
|
||
|
ofnInfo.ofn.lpstrTitle = pszDialogTitle;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MyLoadString( IDS_SELECT_DIR, strSelectDir );
|
||
|
|
||
|
ofnInfo.ofn.lpstrTitle = (LPCTSTR)strSelectDir;
|
||
|
}
|
||
|
|
||
|
ofnInfo.ofn.lStructSize = sizeof(OPENFILENAME);
|
||
|
ofnInfo.ofn.hwndOwner = hwndParent;
|
||
|
ofnInfo.ofn.hInstance = (HINSTANCE) g_MyModuleHandle;
|
||
|
ofnInfo.ofn.lpstrFilter = NULL;
|
||
|
ofnInfo.ofn.lpstrCustomFilter = NULL;
|
||
|
ofnInfo.ofn.nMaxCustFilter = 0;
|
||
|
ofnInfo.ofn.nFilterIndex = 0;
|
||
|
ofnInfo.ofn.lpstrFile = pszBuf;
|
||
|
ofnInfo.ofn.nMaxFile = cchBuf;
|
||
|
ofnInfo.ofn.lpstrFileTitle = NULL;
|
||
|
ofnInfo.ofn.nMaxFileTitle = 0;
|
||
|
ofnInfo.ofn.lpstrInitialDir = szInitialDir;
|
||
|
ofnInfo.ofn.nFileOffset = 0;
|
||
|
ofnInfo.ofn.nFileExtension = 0;
|
||
|
ofnInfo.ofn.lpstrDefExt = NULL;
|
||
|
ofnInfo.ofn.lCustData = (LPARAM)&ofnInfo;
|
||
|
ofnInfo.ofn.lpfnHook = (LPOFNHOOKPROC)BrowseDirDlgHook;
|
||
|
ofnInfo.ofn.lpTemplateName = MAKEINTRESOURCE( IDD_BROWSEDIRECTORY );
|
||
|
ofnInfo.ofn.Flags = OFN_ENABLEHOOK | OFN_PATHMUSTEXIST |
|
||
|
OFN_NONETWORKBUTTON | OFN_ENABLETEMPLATE |
|
||
|
OFN_HIDEREADONLY;
|
||
|
|
||
|
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("comdlg32:GetOpenFileName().Start.")));
|
||
|
int nResult = ::GetOpenFileName( &ofnInfo.ofn );
|
||
|
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("comdlg32:GetOpenFileName().End.")));
|
||
|
|
||
|
DWORD dw = 0;
|
||
|
if (nResult == 0)
|
||
|
{
|
||
|
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("comdlg32:CommDlgExtendedError().Start.")));
|
||
|
dw = CommDlgExtendedError();
|
||
|
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("comdlg32:CommDlgExtendedError().End.")));
|
||
|
}
|
||
|
|
||
|
return (BOOL)( IDOK == nResult );
|
||
|
}
|
||
|
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Procedure pszSkipDriveSpec
|
||
|
//
|
||
|
// Purpose Returns a pointer to whatever comes after the drive part
|
||
|
// of a filename. For example:
|
||
|
// c:\foo\bar.bat \\server\share\file.txt
|
||
|
// ^ ^
|
||
|
//
|
||
|
// Returns Pointer to the appropriate part of the string, or a pointer
|
||
|
// to the end of the string if it's not in the right format
|
||
|
//
|
||
|
// History 10/06/95 KenSh Created
|
||
|
//
|
||
|
LPTSTR pszSkipDriveSpec( LPTSTR pszPathName )
|
||
|
{
|
||
|
LPTSTR pch = NULL;
|
||
|
|
||
|
if( pszPathName[0] == _T('\\') && pszPathName[1] == _T('\\') )
|
||
|
{
|
||
|
pch = _tcschr(pszPathName+2, _T('\\'));
|
||
|
if( NULL != pch)
|
||
|
{
|
||
|
LPTSTR pchResult;
|
||
|
pchResult = _tcschr( pch, _T('\\') );
|
||
|
|
||
|
if( pchResult )
|
||
|
{
|
||
|
pchResult = _tcschr( pchResult+1, _T('\\') );
|
||
|
}
|
||
|
|
||
|
if( pchResult )
|
||
|
{
|
||
|
return pchResult;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return _tcschr( pch, _T('\0') );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return _tcschr( pszPathName, _T('\0') );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pch = _tcschr( pszPathName, _T(':') );
|
||
|
|
||
|
if( pch )
|
||
|
{
|
||
|
return _tcsinc(pch);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return _tcschr( pszPathName, _T('\0') );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Procedure BrowseDirEditProc
|
||
|
//
|
||
|
// Purpose Subclassed window proc for the edit control in the Browse
|
||
|
// for Directory dialog. We override the WM_SETTEXT message
|
||
|
// to control when the window text can be programatically
|
||
|
// changed.
|
||
|
//
|
||
|
// Parameters standard
|
||
|
//
|
||
|
// Returns standard
|
||
|
//
|
||
|
// History 10/06/95 KenSh Created
|
||
|
// 10/09/95 KenSh Moved most code into UpdateEditText()
|
||
|
//
|
||
|
LRESULT CALLBACK BrowseDirEditProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
|
||
|
{
|
||
|
switch( message )
|
||
|
{
|
||
|
// In order to prevent default functionality from setting the Edit's text
|
||
|
// to strings like "*.*", we capture WM_SETTEXT and only allow it to occur
|
||
|
// if the fAllowSetText flag is specified in the OFNINFO struct.
|
||
|
case WM_SETTEXT:
|
||
|
{
|
||
|
LPOFNINFO lpOFNInfo = (LPOFNINFO)GetProp( GetParent(hwnd), c_szOFNProp );
|
||
|
|
||
|
if( lpOFNInfo->fAllowSetText )
|
||
|
{
|
||
|
break; // default processing
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return 0L; // suppress the urge to change the text
|
||
|
}
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return CallWindowProc( g_pfnPrevEditProc, hwnd, message, wParam, lParam );
|
||
|
}
|
||
|
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Procedure BrowseDirComboProc
|
||
|
//
|
||
|
// Purpose Subclassed window proc for the combo box in the Browse
|
||
|
// Directory dialog. We need to subclass so we can catch the
|
||
|
// change to selection after the Network button is used to
|
||
|
// switch drives.
|
||
|
//
|
||
|
// Parameters standard
|
||
|
//
|
||
|
// Returns standard
|
||
|
//
|
||
|
// History 10/09/95 KenSh Created
|
||
|
//
|
||
|
LRESULT CALLBACK BrowseDirComboProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
|
||
|
{
|
||
|
switch( message )
|
||
|
{
|
||
|
// We catch the WM_SETREDRAW message so that we ignore CB_SETCURSEL
|
||
|
// messages when the combo is not supposed to be updated. This is
|
||
|
// pretty much of a hack due to the ordering of messages after the
|
||
|
// Network button is clicked.
|
||
|
case WM_SETREDRAW:
|
||
|
{
|
||
|
if( wParam )
|
||
|
{
|
||
|
SetProp( hwnd, c_szRedrawProp, (HANDLE)1 );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if( GetProp( hwnd, c_szRedrawProp ) )
|
||
|
{
|
||
|
RemoveProp( hwnd, c_szRedrawProp );
|
||
|
}
|
||
|
}
|
||
|
break; // continue with default processing
|
||
|
}
|
||
|
|
||
|
// We catch CB_SETCURSEL and use it to update our edit box after the
|
||
|
// Network button has been pressed.
|
||
|
case CB_SETCURSEL:
|
||
|
{
|
||
|
LPOFNINFO lpOFNInfo = (LPOFNINFO)GetProp( GetParent(hwnd), c_szOFNProp );
|
||
|
|
||
|
#ifdef NEVER
|
||
|
// If "Network" was pressed and redraw has been re-enabled...
|
||
|
if( lpOFNInfo->fNetworking && GetProp( hwnd, c_szRedrawProp ) )
|
||
|
{
|
||
|
TCHAR szBuf[_MAX_PATH];
|
||
|
LRESULT lResult = CallWindowProc( g_pfnPrevComboProc, hwnd, message, wParam, lParam );
|
||
|
|
||
|
// Turn off the networking flag
|
||
|
lpOFNInfo->fNetworking = FALSE;
|
||
|
|
||
|
// Force the selected drive to be the current drive and
|
||
|
// get the current directory on that drive
|
||
|
GetWindowText( hwnd, szBuf, _MAX_PATH );
|
||
|
_chdrive( _totupper(szBuf[0]) - 'A' + 1 );
|
||
|
GetCurrentDirectory( _MAX_PATH, szBuf );
|
||
|
|
||
|
// Update the edit box with the new text.
|
||
|
lpOFNInfo->fAllowSetText = TRUE;
|
||
|
SetDlgItemText( GetParent(hwnd), IDC_FILENAME, szBuf );
|
||
|
lpOFNInfo->fAllowSetText = FALSE;
|
||
|
SendDlgItemMessage( GetParent(hwnd), IDC_FILENAME, EM_SETSEL, 0, (LPARAM)-1 );
|
||
|
|
||
|
return lResult;
|
||
|
}
|
||
|
#endif
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case WM_DESTROY:
|
||
|
{
|
||
|
if( GetProp( hwnd, c_szRedrawProp ) )
|
||
|
{
|
||
|
RemoveProp( hwnd, c_szRedrawProp );
|
||
|
}
|
||
|
break; // continue with default processing
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return CallWindowProc( g_pfnPrevComboProc, hwnd, message, wParam, lParam );
|
||
|
}
|
||
|
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Procedure UpdateEditText
|
||
|
//
|
||
|
// Purpose Based on which control has focus and the current state of
|
||
|
// the edit control, calculates the new "current directory" and
|
||
|
// sets the Edit control's text to match.
|
||
|
//
|
||
|
// Parameters hwndDlg handle to the dialog window. This function will
|
||
|
// access the lpOFNInfo window property.
|
||
|
//
|
||
|
// Returns nothing
|
||
|
//
|
||
|
// History 10/09/95 KenSh Created
|
||
|
//
|
||
|
VOID UpdateEditText( HWND hwndDlg )
|
||
|
{
|
||
|
HWND hwndLB = GetDlgItem(hwndDlg, IDC_FILELIST);
|
||
|
int nCurSel = (int)SendMessage(hwndLB, LB_GETCURSEL, 0, 0);
|
||
|
TCHAR szDirName[_MAX_PATH];
|
||
|
LPTSTR pchStart = NULL;
|
||
|
LPOFNINFO lpOFNInfo = (LPOFNINFO)GetProp( hwndDlg, c_szOFNProp );
|
||
|
int i;
|
||
|
|
||
|
HWND hwndFocus = GetFocus();
|
||
|
int idFocus = GetDlgCtrlID( hwndFocus );
|
||
|
|
||
|
if( idFocus == IDC_FILELIST )
|
||
|
// Listbox: build name up through current LB selection
|
||
|
{
|
||
|
// First get the top entry in the listbox, this will tell us
|
||
|
// if it's a connected drive or a UNC drive
|
||
|
SendMessage( hwndLB, LB_GETTEXT, 0, (LPARAM)szDirName );
|
||
|
|
||
|
// Run down the entries in the listbox appending them
|
||
|
// and stop when we get to the current selection.
|
||
|
if( szDirName[0] == _T('\\') && szDirName[1] == _T('\\') )
|
||
|
pchStart = _tcschr(szDirName+2, _T('\0'));
|
||
|
else
|
||
|
pchStart = _tcsinc(szDirName) + 1; // skip 2 chars, first may be MBCS
|
||
|
|
||
|
if (NULL != pchStart)
|
||
|
{
|
||
|
for( i = 1; i <= nCurSel; i++ )
|
||
|
{
|
||
|
if( *pchStart != _T('\\') )
|
||
|
*pchStart = _T('\\');
|
||
|
pchStart = _tcsinc(pchStart);
|
||
|
SendMessage( hwndLB, LB_GETTEXT, i, (LPARAM)pchStart );
|
||
|
pchStart = _tcschr(pchStart, _T('\0'));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if( idFocus == IDC_DRIVECOMBO )
|
||
|
// Combo box: use current working directory
|
||
|
{
|
||
|
GetCurrentDirectory( _MAX_PATH, szDirName );
|
||
|
}
|
||
|
else if( idFocus == IDC_FILENAME )
|
||
|
// Edit control: build the new path using the edit contents
|
||
|
{
|
||
|
TCHAR szBuf[_MAX_PATH];
|
||
|
|
||
|
GetDlgItemText( hwndDlg, IDC_FILENAME, szBuf, _MAX_PATH );
|
||
|
|
||
|
if( szBuf[0] == _T('\\') )
|
||
|
{
|
||
|
if( szBuf[1] == _T('\\') )
|
||
|
// full UNC path was specified
|
||
|
{
|
||
|
_tcscpy( szDirName, szBuf );
|
||
|
}
|
||
|
else
|
||
|
// new directory on the current drive
|
||
|
{
|
||
|
_tcscpy( szDirName, lpOFNInfo->szLastDirName );
|
||
|
LPTSTR pch = pszSkipDriveSpec(szDirName);
|
||
|
_tcscpy( pch, szBuf );
|
||
|
}
|
||
|
}
|
||
|
else if( *_tcsinc(szBuf) == _T(':') )
|
||
|
{
|
||
|
// Change to the requested drive and use the current directory
|
||
|
// on that drive.
|
||
|
if( 0 == _chdrive( _totupper(szBuf[0]) - 'A' + 1 ) &&
|
||
|
szBuf[2] != _T('\\') )
|
||
|
{
|
||
|
// It's a legal drive and no directory was specified,
|
||
|
// so use the current default.
|
||
|
GetCurrentDirectory( _MAX_PATH, szDirName );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// A directory was specified or the drive does not exist.
|
||
|
// Copy the text verbatim to test it and possibly display
|
||
|
// an error message.
|
||
|
_tcscpy( szDirName, szBuf );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
// Subdirectory of the current directory
|
||
|
{
|
||
|
// Start with the current directory
|
||
|
_tcscpy( szDirName, lpOFNInfo->szLastDirName );
|
||
|
|
||
|
// Append a backslash if there isn't already one there
|
||
|
LPTSTR pch = _tcsrchr( szDirName, _T('\\') );
|
||
|
if (pch)
|
||
|
{
|
||
|
if( *_tcsinc(pch) )
|
||
|
{
|
||
|
pch = _tcschr( pch, _T('\0') );
|
||
|
if (pch)
|
||
|
{
|
||
|
*pch = _T('\\');
|
||
|
}
|
||
|
}
|
||
|
pch = _tcsinc(pch);
|
||
|
|
||
|
// Append the new directory name
|
||
|
_tcscpy( pch, szBuf );
|
||
|
}
|
||
|
|
||
|
// Attempt to change into the new directory
|
||
|
if( SetCurrentDirectory(szDirName) )
|
||
|
{
|
||
|
// The directory exists, get the official name and use that
|
||
|
// instead of whatever we're using now
|
||
|
GetCurrentDirectory( _MAX_PATH, szDirName );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Some other control, likely an error message is going on
|
||
|
_tcscpy( szDirName, lpOFNInfo->szLastDirName );
|
||
|
}
|
||
|
|
||
|
lpOFNInfo->fAllowSetText = TRUE;
|
||
|
SetDlgItemText( hwndDlg, IDC_FILENAME, szDirName );
|
||
|
lpOFNInfo->fAllowSetText = FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Procedure BrowseDirDlgHook
|
||
|
//
|
||
|
// Purpose Dialog proc for the Browse for Directory subclassed common
|
||
|
// dialog. We spend most of our effort trying to get the right
|
||
|
// string into the edit control (IDC_FILENAME).
|
||
|
//
|
||
|
// Parameters standard
|
||
|
//
|
||
|
// Returns TRUE to halt further processing, FALSE to do the default.
|
||
|
//
|
||
|
// History 10/06/95 KenSh Created
|
||
|
//
|
||
|
BOOL CALLBACK BrowseDirDlgHook( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
|
||
|
{
|
||
|
switch(message)
|
||
|
{
|
||
|
case WM_INITDIALOG:
|
||
|
{
|
||
|
LPOFNINFO lpOFNInfo = (LPOFNINFO)((LPOPENFILENAME)lParam)->lCustData;
|
||
|
|
||
|
// Store the OFN struct pointer as a window property
|
||
|
SetProp( hwnd, c_szOFNProp, (HANDLE)lpOFNInfo );
|
||
|
|
||
|
// Initialize the OFNInfo struct
|
||
|
_tcscpy( lpOFNInfo->szLastDirName, lpOFNInfo->ofn.lpstrInitialDir );
|
||
|
lpOFNInfo->fAllowSetText = FALSE;
|
||
|
//lpOFNInfo->fNetworking = FALSE;
|
||
|
|
||
|
// Start our edit off with the initial directory
|
||
|
SetDlgItemText( hwnd, IDC_FILENAME, lpOFNInfo->ofn.lpstrInitialDir );
|
||
|
|
||
|
// Subclass the edit to let us display only what we want to display
|
||
|
g_pfnPrevEditProc = (WNDPROC)SetWindowLongPtr(
|
||
|
GetDlgItem(hwnd, IDC_FILENAME),
|
||
|
GWLP_WNDPROC,
|
||
|
(LONG_PTR)BrowseDirEditProc );
|
||
|
|
||
|
// Subclass the combo so we know when the Network button has been used.
|
||
|
g_pfnPrevComboProc = (WNDPROC)SetWindowLongPtr(
|
||
|
GetDlgItem(hwnd, IDC_DRIVECOMBO),
|
||
|
GWLP_WNDPROC,
|
||
|
(LONG_PTR)BrowseDirComboProc );
|
||
|
|
||
|
return TRUE; // set default focus
|
||
|
}
|
||
|
|
||
|
case WM_DESTROY:
|
||
|
{
|
||
|
// Clean up.
|
||
|
RemoveProp( hwnd, c_szOFNProp );
|
||
|
return FALSE; // continue with default processing
|
||
|
}
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
{
|
||
|
switch( LOWORD(wParam) )
|
||
|
{
|
||
|
case IDOK:
|
||
|
{
|
||
|
return BrowseDir_OnOK( hwnd );
|
||
|
}
|
||
|
|
||
|
case IDC_FILELIST: //directory listbox.
|
||
|
{
|
||
|
if( HIWORD(wParam) == LBN_DBLCLK )
|
||
|
{
|
||
|
// Post this message telling us to change the edit box.
|
||
|
PostMessage( hwnd, CM_UPDATEEDIT, 0, 0L );
|
||
|
}
|
||
|
return FALSE; // continue with default processing.
|
||
|
}
|
||
|
|
||
|
case IDC_DRIVECOMBO: // drive combo box:
|
||
|
{
|
||
|
if( HIWORD(wParam) == CBN_SELCHANGE )
|
||
|
{
|
||
|
// Post this message telling us to change the edit box.
|
||
|
PostMessage( hwnd, CM_UPDATEEDIT, 0, 0L );
|
||
|
}
|
||
|
return FALSE; // continue with default processing.
|
||
|
}
|
||
|
|
||
|
#ifdef NEVER
|
||
|
case IDC_NETWORK: // "Network..." button
|
||
|
{
|
||
|
// Set the fNetworking flag which the combo box looks for when
|
||
|
// processing CB_SETCURSEL.
|
||
|
LPOFNINFO lpOFNInfo = (LPOFNINFO)GetProp( hwnd, c_szOFNProp );
|
||
|
lpOFNInfo->fNetworking = TRUE;
|
||
|
return FALSE; // default processing.
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
default:
|
||
|
return FALSE; // default processing.
|
||
|
}
|
||
|
}
|
||
|
|
||
|
case CM_UPDATEEDIT: //update edit box with directory
|
||
|
{
|
||
|
LPOFNINFO lpOFNInfo = (LPOFNINFO)GetProp( hwnd, c_szOFNProp );
|
||
|
|
||
|
// Change the text of the edit control.
|
||
|
UpdateEditText( hwnd );
|
||
|
SendDlgItemMessage( hwnd, IDC_FILENAME, EM_SETSEL, 0, (LPARAM)(INT)-1 );
|
||
|
|
||
|
// Store this text as the "last known good" directory
|
||
|
GetDlgItemText( hwnd, IDC_FILENAME, lpOFNInfo->szLastDirName, _MAX_PATH );
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
return FALSE; //default processing
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Procedure BrowseDir_OnOK
|
||
|
//
|
||
|
// Purpose Handles a click of the OK button in the Browse Directory
|
||
|
// dialog. We have to do some sneaky stuff here with checking
|
||
|
// which control has focus, because we want the dialog to go
|
||
|
// away enter when the OK button is clicked directly (i.e. just
|
||
|
// hitting Enter doesn't count).
|
||
|
//
|
||
|
// Parameters hwnd The dialog window
|
||
|
//
|
||
|
// Returns TRUE if processing should halt, FALSE if default processing
|
||
|
// should still happen.
|
||
|
//
|
||
|
// History 10/09/95 KenSh Created
|
||
|
//
|
||
|
BOOL BrowseDir_OnOK( HWND hwnd )
|
||
|
{
|
||
|
LPOFNINFO lpOFNInfo = (LPOFNINFO)GetProp( hwnd, c_szOFNProp );
|
||
|
HWND hwndFocus = GetFocus();
|
||
|
|
||
|
int idFocus = GetDlgCtrlID(hwndFocus);
|
||
|
|
||
|
if( idFocus != IDC_FILENAME && idFocus != IDC_FILELIST && idFocus != IDC_DRIVECOMBO )
|
||
|
{
|
||
|
ASSERT( lpOFNInfo->ofn.lpstrFile != NULL );
|
||
|
//UpdateEditText( hwnd );
|
||
|
GetDlgItemText( hwnd, IDC_FILENAME, lpOFNInfo->ofn.lpstrFile, lpOFNInfo->ofn.nMaxFile );
|
||
|
|
||
|
EndDialog( hwnd, IDOK );
|
||
|
|
||
|
return TRUE; // halt processing here.
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// We don't want the dialog to go away at this point.
|
||
|
// Because the default functionality is expecting
|
||
|
// a file to be found, not a directory, we must make
|
||
|
// sure what's been typed in is actually a directory
|
||
|
// before we hand this message to the default handler.
|
||
|
|
||
|
TCHAR szBuf[_MAX_PATH];
|
||
|
|
||
|
// Calculate the new current directory and put it into the Edit
|
||
|
UpdateEditText( hwnd );
|
||
|
|
||
|
// Read the newly generated directory name
|
||
|
GetDlgItemText( hwnd, IDC_FILENAME, szBuf, _MAX_PATH );
|
||
|
|
||
|
// Update our "last good" directory
|
||
|
_tcscpy( lpOFNInfo->szLastDirName, szBuf );
|
||
|
|
||
|
// Post this message to update the edit after the default handler
|
||
|
// updates the list box
|
||
|
PostMessage( hwnd, CM_UPDATEEDIT, 0, 0 );
|
||
|
|
||
|
return FALSE; // let the original common dialog handle it.
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL BrowseForFile(
|
||
|
HWND hwndParent,
|
||
|
LPCTSTR pszInitialDir,
|
||
|
LPTSTR pszBuf,
|
||
|
int cchBuf)
|
||
|
{
|
||
|
TCHAR szInitialDir[MAX_PATH];
|
||
|
TCHAR szFileExtension[_MAX_PATH] = _T("");
|
||
|
LPTSTR p = NULL;
|
||
|
TCHAR szFileFilter[_MAX_PATH];
|
||
|
CString csTitle;
|
||
|
|
||
|
OFNINFO ofnInfo;
|
||
|
|
||
|
// Prepare the initial directory... add a backslash if it's
|
||
|
// a 2-character path
|
||
|
_tcscpy( szInitialDir, pszInitialDir );
|
||
|
if( !szInitialDir[2] )
|
||
|
{
|
||
|
szInitialDir[2] = _T('\\');
|
||
|
szInitialDir[3] = _T('\0');
|
||
|
}
|
||
|
|
||
|
// calculate file extension
|
||
|
p = _tcsrchr(pszBuf, _T('.'));
|
||
|
if (p) {
|
||
|
p = _tcsinc(p);
|
||
|
if (*p) {
|
||
|
_tcscpy(szFileExtension, _T("*."));
|
||
|
_tcscat(szFileExtension, p);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
memset( (PVOID)szFileFilter, 0, sizeof(szFileFilter));
|
||
|
p = szFileFilter;
|
||
|
if (*szFileExtension) {
|
||
|
_tcscpy(p, szFileExtension);
|
||
|
p = _tcsninc(p, _tcslen(szFileExtension) + 1);
|
||
|
_tcscpy(p, szFileExtension);
|
||
|
p = _tcsninc(p, _tcslen(szFileExtension) + 1);
|
||
|
}
|
||
|
_tcscpy(p, _T("*.*"));
|
||
|
p = _tcsninc(p, _tcslen(_T("*.*")) + 1);
|
||
|
_tcscpy(p, _T("*.*"));
|
||
|
|
||
|
// dialog title "Locate File"
|
||
|
MyLoadString(IDS_LOCATE_FILE, csTitle);
|
||
|
|
||
|
// fill in the OFNINFO struct
|
||
|
ofnInfo.ofn.lStructSize = sizeof(OPENFILENAME);
|
||
|
ofnInfo.ofn.hwndOwner = hwndParent;
|
||
|
ofnInfo.ofn.hInstance = (HINSTANCE) g_MyModuleHandle;
|
||
|
ofnInfo.ofn.lpstrFilter = szFileFilter; // extention of the file we're looking for
|
||
|
ofnInfo.ofn.lpstrCustomFilter = NULL;
|
||
|
ofnInfo.ofn.nMaxCustFilter = 0;
|
||
|
ofnInfo.ofn.nFilterIndex = 1;
|
||
|
ofnInfo.ofn.lpstrFile = pszBuf; // Buffer for file name
|
||
|
ofnInfo.ofn.nMaxFile = cchBuf;
|
||
|
ofnInfo.ofn.lpstrFileTitle = NULL;
|
||
|
ofnInfo.ofn.nMaxFileTitle = 0;
|
||
|
ofnInfo.ofn.lpstrInitialDir = szInitialDir;
|
||
|
ofnInfo.ofn.lpstrTitle = (LPCTSTR)csTitle;
|
||
|
ofnInfo.ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_EXPLORER |
|
||
|
OFN_NOCHANGEDIR | OFN_LONGNAMES | OFN_NONETWORKBUTTON;
|
||
|
ofnInfo.ofn.nFileOffset = 0;
|
||
|
ofnInfo.ofn.nFileExtension = 0;
|
||
|
ofnInfo.ofn.lpstrDefExt = NULL;
|
||
|
ofnInfo.ofn.lCustData = (LPARAM)&ofnInfo;
|
||
|
ofnInfo.ofn.lpfnHook = NULL;
|
||
|
ofnInfo.ofn.lpTemplateName = NULL;
|
||
|
|
||
|
int nResult = ::GetOpenFileName( &ofnInfo.ofn );
|
||
|
|
||
|
DWORD dw = 0;
|
||
|
if (nResult == 0) {
|
||
|
dw = CommDlgExtendedError();
|
||
|
}
|
||
|
|
||
|
if (nResult == IDOK) {
|
||
|
iisDebugOut((LOG_TYPE_TRACE, _T("pszBuf=%s\n"), pszBuf));
|
||
|
*(pszBuf + ofnInfo.ofn.nFileOffset - 1) = _T('\0');
|
||
|
}
|
||
|
|
||
|
return (BOOL)( IDOK == nResult );
|
||
|
}
|