443 lines
13 KiB
C++
443 lines
13 KiB
C++
// ==========================================================================
|
|
// Class Implementation : COXDirectoryDialog
|
|
// ==========================================================================
|
|
|
|
// Source file :oxdirdlg.cpp
|
|
|
|
// Version: 9.3
|
|
|
|
// This software along with its related components, documentation and files ("The Libraries")
|
|
// is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
|
|
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
|
|
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
|
|
// to obtain this file, or directly from our office. For a copy of the license governing
|
|
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
|
|
|
|
// //////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h" // standard MFC include
|
|
#include <stdlib.h>
|
|
#include <dlgs.h>
|
|
#include <direct.h>
|
|
#include <limits.h> // For SHRT_MAX
|
|
#include "oxdirdlg.h" // class specification
|
|
#include "path.h" // To get current dir, create a dir, etc.
|
|
#include "OXMainRes.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char BASED_CODE THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Definition of static members
|
|
|
|
|
|
// Data members -------------------------------------------------------------
|
|
// protected:
|
|
// CString m_sTitle;
|
|
// --- The title text of the dialog
|
|
|
|
// CString m_sFullDir;
|
|
// --- The specified directory (may not yet exist);
|
|
|
|
// CString m_sExistingDir;
|
|
// --- That part of the specified directory that does exist
|
|
|
|
// BOOL m_bNewDirAllowed
|
|
// --- Whether the specification of a non-existing directory is allowed
|
|
|
|
// BOOL m_bAfterInit
|
|
// --- Whether the initializations in OnInitDialog executed already or not
|
|
|
|
// BOOL m_bExplorerOn95
|
|
// --- Whether the class is used in a Windows95 environment and with EXPLORER look
|
|
|
|
// private:
|
|
|
|
// Member functions ---------------------------------------------------------
|
|
// public:
|
|
|
|
COXDirectoryDialog::COXDirectoryDialog(LPCTSTR pszDefaultDir /* = NULL */,
|
|
LPCTSTR pszTitle /* = NULL */, BOOL bNewDirAllowed /* = FALSE */,
|
|
DWORD dwFlags /* = OFN_HIDEREADONLY */, CWnd* pParentWnd /* = NULL */)
|
|
:
|
|
m_sTitle(pszTitle),
|
|
m_sFullDir(pszDefaultDir),
|
|
m_sExistingDir(),
|
|
m_bNewDirAllowed(bNewDirAllowed),
|
|
m_bAfterInit(FALSE),
|
|
m_bNewCreated(FALSE),
|
|
#ifdef WIN32
|
|
m_bExplorerOn95((dwFlags & OFN_EXPLORER) && IsWin95()),
|
|
CFileDialog(TRUE, NULL, NULL, ((dwFlags & OFN_EXPLORER) && IsWin95()) ? dwFlags :
|
|
dwFlags | OFN_ENABLETEMPLATE, NULL, pParentWnd)
|
|
#else
|
|
m_bExplorerOn95(FALSE),
|
|
CFileDialog(TRUE, NULL, NULL, dwFlags | OFN_ENABLETEMPLATE, NULL, pParentWnd)
|
|
#endif
|
|
{
|
|
//{{AFX_DATA_INIT(COXDirectoryDialog)
|
|
//}}AFX_DATA_INIT
|
|
|
|
#ifdef _DEBUG
|
|
if (!m_bExplorerOn95)
|
|
// ... The new directory dialog resource must be accessable
|
|
#ifdef _AFXDLL
|
|
ASSERT(AfxFindResourceHandle(MAKEINTRESOURCE(IDD_OX_FILEOPENDUMMY), RT_DIALOG) != NULL);
|
|
#else
|
|
ASSERT(AfxGetResourceHandle() != NULL);
|
|
#endif
|
|
#endif
|
|
|
|
// ... If no directory is specified, use the current default dir
|
|
if (m_sFullDir.IsEmpty())
|
|
{
|
|
COXDirSpec currentDir;
|
|
VERIFY(currentDir.DoGetCurrentDir());
|
|
m_sFullDir = currentDir.GetDirectory();
|
|
}
|
|
|
|
// It is possible that some parts of the specified directory do not yet exist
|
|
// (E.g. When specifying C:\ONO\TWO\THREE, it is possible that
|
|
// C:\ONE\TWO exists, but C:\ONO\TWO\THREE does not)
|
|
// We will now extract the existing part
|
|
COXDirSpec realDir;
|
|
if (!realDir.SetDirectory(m_sFullDir) || realDir.GetDirectory().IsEmpty())
|
|
{
|
|
TRACE(_T("COXDirectoryDialog::COXDirectoryDialog ; Illegal or no directrory (%s) specified, using default dir\n"),
|
|
pszDefaultDir == NULL ? _T("") : pszDefaultDir);
|
|
VERIFY(realDir.DoGetCurrentDir());
|
|
m_sFullDir = m_sExistingDir = realDir.GetDirectory();
|
|
}
|
|
else
|
|
{
|
|
realDir.MakeLargestExisting();
|
|
m_sExistingDir = realDir.GetDirectory();
|
|
}
|
|
|
|
m_ofn.lpstrInitialDir = m_sExistingDir;
|
|
m_ofn.lpstrTitle = m_sTitle;
|
|
|
|
#ifdef WIN32
|
|
if (!m_bExplorerOn95)
|
|
{
|
|
// MFC CFileDialog automatically chooses EXPLORER look when in Win95
|
|
// even when the user did not pass it in the parameter dwFlags
|
|
// so eliminate it again
|
|
m_ofn.Flags &= ~OFN_EXPLORER;
|
|
#ifdef _AFXDLL
|
|
m_ofn.hInstance = AfxFindResourceHandle(MAKEINTRESOURCE(IDD_OX_FILEOPENDUMMY), RT_DIALOG);
|
|
#else
|
|
m_ofn.hInstance = AfxGetResourceHandle();
|
|
#endif // _AFXDLL
|
|
m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_OX_FILEOPENDUMMY);
|
|
ASSERT(!(m_ofn.Flags & OFN_EXPLORER));
|
|
}
|
|
#else
|
|
#ifdef _AFXDLL
|
|
m_ofn.hInstance = AfxFindResourceHandle(MAKEINTRESOURCE(IDD_OX_FILEOPENDUMMY), RT_DIALOG);
|
|
#else
|
|
m_ofn.hInstance = AfxGetResourceHandle();
|
|
#endif // _AFXDLL
|
|
m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_OX_FILEOPENDUMMY);
|
|
#endif
|
|
}
|
|
|
|
#ifdef WIN32
|
|
BOOL COXDirectoryDialog::IsWin95()
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : Determine the environment the app is executing in.
|
|
{
|
|
BOOL bWin95 = FALSE;
|
|
OSVERSIONINFO info;
|
|
|
|
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
GetVersionEx(&info);
|
|
if (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ||
|
|
(info.dwPlatformId == VER_PLATFORM_WIN32_NT && info.dwMajorVersion >= 4))
|
|
bWin95 = TRUE;
|
|
|
|
return bWin95;
|
|
}
|
|
|
|
CString COXDirectoryDialog::GetFolderPath() const
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : When in EXPLORER look ask the dialog what is the currently
|
|
// selected directory
|
|
{
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
ASSERT(m_bExplorerOn95);
|
|
|
|
CString strResult;
|
|
if (GetParent()->SendMessage(CDM_GETFOLDERPATH, (WPARAM)MAX_PATH, (LPARAM)strResult.GetBuffer(MAX_PATH)) < 0)
|
|
strResult.Empty();
|
|
else
|
|
strResult.ReleaseBuffer();
|
|
|
|
return strResult;
|
|
}
|
|
#endif
|
|
|
|
BOOL COXDirectoryDialog::OnInitDialog()
|
|
{
|
|
CFileDialog::OnInitDialog();
|
|
|
|
CenterWindow();
|
|
|
|
if (!m_bExplorerOn95)
|
|
{
|
|
// .... The directory edit control must exist within this dialog
|
|
ASSERT(GetDlgItem(IDC_OX_DIRECTORY) != NULL);
|
|
|
|
// ... Use lower case to show a dir
|
|
CString sDirectory(m_sFullDir);
|
|
#ifndef OX_FILEMNG_NOCHANGECASE
|
|
sDirectory.MakeLower();
|
|
#endif
|
|
GetDlgItem(IDC_OX_DIRECTORY)->SetWindowText(sDirectory);
|
|
|
|
// Let's hide these windows so the user cannot tab to them. Note that in
|
|
// the private template (in cddemo.dlg) the coordinates for these guys are
|
|
// *outside* the coordinates of the dlg window itself. Without the following
|
|
// ShowWindow()'s you would not see them, but could still tab to them.
|
|
GetDlgItem(stc2)->ShowWindow(SW_HIDE);
|
|
GetDlgItem(stc3)->ShowWindow(SW_HIDE);
|
|
GetDlgItem(edt1)->ShowWindow(SW_HIDE);
|
|
GetDlgItem(lst1)->ShowWindow(SW_HIDE);
|
|
GetDlgItem(cmb1)->ShowWindow(SW_HIDE);
|
|
|
|
// We must put something in this field, even though it is hidden. This is
|
|
// because if this field is empty, or has something like "*.txt" in it,
|
|
// and the user hits OK, the dlg will NOT close. We'll jam something in
|
|
// there (like "Junk") so when the user hits OK, the dlg terminates.
|
|
// Note that we'll deal with the "Junk" during return processing (see below)
|
|
SetDlgItemText(edt1, _T("Junk"));
|
|
|
|
// The directory text shown in the static control above the directory
|
|
// listbox, will always fit. When the directory text becomes to large
|
|
// full stops are automatically inserted (like "C:\..\DIR1\DIR2")
|
|
// Because we want to use this contents to show in an edit control,
|
|
// no full stops should be inserted.
|
|
// This can be done by making the static control large enough
|
|
// so full stops will never be inserted
|
|
// Because it will always be invisible, this poses no problem
|
|
|
|
CWnd* pDirStatic;
|
|
CRect staticRect;
|
|
pDirStatic = GetDlgItem(stc1);
|
|
ASSERT(pDirStatic != NULL);
|
|
// ... Get the present size
|
|
pDirStatic->GetClientRect(staticRect);
|
|
// ... Make as large as possible
|
|
staticRect.left = 0;
|
|
staticRect.right = SHRT_MAX;
|
|
pDirStatic->MoveWindow(staticRect);
|
|
// ... Hide window
|
|
pDirStatic->ShowWindow(SW_HIDE);
|
|
|
|
// Now set the focus to the directory edit control and
|
|
// select that part of the directory that does not yet exist on disk
|
|
GetDlgItem(IDC_OX_DIRECTORY)->SetFocus();
|
|
// Determine the part of the full directory, that is also in the
|
|
// existing directory
|
|
m_sFullDir.MakeLower();
|
|
m_sExistingDir.MakeLower();
|
|
LPCTSTR pszFullDir = m_sFullDir;
|
|
LPCTSTR pszExistingDir = m_sExistingDir;
|
|
// ... While neither has reached the end of the string and both
|
|
// characters are the same, continue searching
|
|
while ((*pszFullDir == *pszExistingDir) && (*pszFullDir != _T('\0')))
|
|
{
|
|
pszFullDir++;
|
|
pszExistingDir++;
|
|
}
|
|
// ... Select thet apret that does not yet exist on disk
|
|
((CEdit*)GetDlgItem(IDC_OX_DIRECTORY))->SetSel(PtrToLong(pszFullDir - (LPCTSTR)m_sFullDir),
|
|
INT_MAX);
|
|
}
|
|
#ifdef WIN32
|
|
else
|
|
{
|
|
GetParent()->SendMessage(CDM_HIDECONTROL, (WPARAM)stc3, (LPARAM)0);
|
|
GetParent()->SendMessage(CDM_HIDECONTROL, (WPARAM)edt1, (LPARAM)0);
|
|
GetParent()->SendMessage(CDM_HIDECONTROL, (WPARAM)stc2, (LPARAM)0);
|
|
GetParent()->SendMessage(CDM_HIDECONTROL, (WPARAM)cmb1, (LPARAM)0);
|
|
}
|
|
#endif
|
|
|
|
m_bAfterInit = TRUE;
|
|
// flag that specifies if picked directory was created or already existed
|
|
m_bNewCreated=FALSE;
|
|
// Focus already explicitely set
|
|
return FALSE;
|
|
}
|
|
|
|
CString COXDirectoryDialog::GetDirectory()
|
|
{
|
|
return m_sFullDir;
|
|
}
|
|
|
|
// protected:
|
|
void COXDirectoryDialog::OnLBSelChangedNotify(UINT nIDBox, UINT iCurSel, UINT nCode)
|
|
{
|
|
ASSERT(!m_bExplorerOn95);
|
|
if (m_bExplorerOn95)
|
|
return;
|
|
|
|
CFileDialog::OnLBSelChangedNotify(nIDBox, iCurSel, nCode);
|
|
// When the selection in the directory listbox changes,
|
|
// adjust the diretcory in the edit control
|
|
if (m_bAfterInit && ((nIDBox == lst2) && (nCode == CD_LBSELCHANGE) ||
|
|
(nIDBox == cmb2) && (nCode == CD_LBSELCHANGE)))
|
|
{
|
|
// Tranfer the directory spec from the hidden static control
|
|
// to the visible edit control
|
|
CString sDir;
|
|
|
|
#ifdef OX_FILEMNG_NOCHANGECASE
|
|
int nSel=GetDlgItem(lst2)->SendMessage(LB_GETCURSEL);
|
|
if(nSel!=LB_ERR)
|
|
{
|
|
sDir.Empty();
|
|
CString sPath;
|
|
for(int nIndex=0; nIndex<=nSel; nIndex++)
|
|
{
|
|
if (GetDlgItem(lst2)->SendMessage(LB_GETTEXT,(WPARAM)nIndex,
|
|
(LPARAM)sPath.GetBuffer(MAX_PATH))==LB_ERR)
|
|
{
|
|
sPath.ReleaseBuffer();
|
|
GetDlgItem(stc1)->GetWindowText(sDir);
|
|
break;
|
|
}
|
|
sPath.ReleaseBuffer();
|
|
sDir+=(nIndex>1 ? _T("\\") : _T(""))+sPath;
|
|
}
|
|
}
|
|
#else
|
|
GetDlgItem(stc1)->GetWindowText(sDir);
|
|
#endif
|
|
|
|
// ... The string should not contain double full stops within the
|
|
// directory spec (this would mean that the hidden static control
|
|
// is to small!)
|
|
ASSERT(sDir.Find(_T("..")) == -1);
|
|
GetDlgItem(IDC_OX_DIRECTORY)->SetWindowText(sDir);
|
|
}
|
|
}
|
|
|
|
#ifdef WIN32
|
|
void COXDirectoryDialog::OnFolderChange()
|
|
// Notification for Windows 95 and Windows NT 4.0
|
|
{
|
|
ASSERT(m_bExplorerOn95);
|
|
if (!m_bExplorerOn95)
|
|
return;
|
|
|
|
COXPathSpec sPath;
|
|
m_sFullDir = GetFolderPath();
|
|
sPath.SetDirectory(m_sFullDir);
|
|
sPath.SetFileName(_T("junk.xxx"));
|
|
GetParent()->SendMessage(CDM_SETCONTROLTEXT, (WPARAM)edt1, (LPARAM)(LPCTSTR)sPath.GetPath());
|
|
}
|
|
#endif
|
|
|
|
void COXDirectoryDialog::OnOK()
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : Called when the user clicks the OK button
|
|
// (the button with an ID of IDOK).
|
|
{
|
|
// .... The directory edit control must exist within this dialog
|
|
ASSERT(GetDlgItem(IDC_OX_DIRECTORY) != NULL);
|
|
GetDlgItem(IDC_OX_DIRECTORY)->GetWindowText(m_sFullDir);
|
|
|
|
BOOL bOK = TRUE;
|
|
|
|
COXDirSpec fullDir;
|
|
if (!fullDir.SetDirectory(m_sFullDir))
|
|
{
|
|
TRACE(_T("COXDirectoryDialog::OnOK : Invalid dir : %s\n"), (LPCTSTR)m_sFullDir);
|
|
CString sPrompt;
|
|
AfxFormatString1(sPrompt, IDS_OX_INVALID_DIR, (LPCTSTR)m_sFullDir);
|
|
AfxMessageBox(sPrompt, MB_ICONEXCLAMATION, IDS_OX_INVALID_DIR);
|
|
// ... Invalid dir specified
|
|
bOK = FALSE;
|
|
}
|
|
else
|
|
{
|
|
if (!fullDir.Exists() && m_bNewDirAllowed)
|
|
{
|
|
CString sPrompt;
|
|
AfxFormatString1(sPrompt, IDS_OX_CREATE_NEW_DIR, (LPCTSTR)m_sFullDir);
|
|
if (AfxMessageBox(sPrompt, MB_ICONINFORMATION | MB_YESNO, IDS_OX_CREATE_NEW_DIR) == IDYES)
|
|
{
|
|
if (fullDir.DoMakeNew())
|
|
{
|
|
m_sExistingDir = fullDir.GetDirectory();
|
|
//#ifndef OX_FILEMNG_NOCHANGECASE
|
|
m_sFullDir = m_sExistingDir;
|
|
//#endif
|
|
m_bNewCreated=TRUE;
|
|
}
|
|
else
|
|
{
|
|
AfxMessageBox(IDS_OX_FAILED_CREATE_DIR, MB_ICONEXCLAMATION, IDS_OX_FAILED_CREATE_DIR);
|
|
// .... Failed to create dir
|
|
bOK = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// ... User did not allow to create a new directory
|
|
bOK = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!fullDir.Exists() && !m_bNewDirAllowed)
|
|
{
|
|
AfxMessageBox(IDS_OX_NON_EXISTING_DIR, MB_ICONEXCLAMATION, IDS_OX_NON_EXISTING_DIR);
|
|
// .... Directory does not exist and not allowed to create
|
|
bOK = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
// ... If everything went OK, call base class implementation
|
|
if (bOK)
|
|
CFileDialog::OnOK();
|
|
else
|
|
// ... Set focus on invalid entry
|
|
GetDlgItem(IDC_OX_DIRECTORY)->SetFocus();
|
|
}
|
|
|
|
void COXDirectoryDialog::OnCancel()
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : Called when the user clicks the CANCEL button
|
|
// (the button with an ID of IDCANCEL).
|
|
{
|
|
// ... Clear the result dir
|
|
m_sFullDir.Empty();
|
|
// ... Call base class implementation
|
|
CFileDialog::OnCancel();
|
|
}
|
|
|
|
// private:
|
|
|
|
// Message handlers ---------------------------------------------------------
|
|
|
|
BEGIN_MESSAGE_MAP(COXDirectoryDialog, CFileDialog)
|
|
//{{AFX_MSG_MAP(COXDirectoryDialog)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
// ==========================================================================
|