// ==========================================================================
// 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"
// v9.3 - update 03 - 64-bit - added for PtrToUlong
#include "UTB64Bit.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()
// ==========================================================================