mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
522 lines
12 KiB
522 lines
12 KiB
// This is a part of the Microsoft Foundation Classes C++ library.
|
|
// Copyright (C) 1992-1995 Microsoft Corporation
|
|
// All rights reserved.
|
|
//
|
|
// This source code is only intended as a supplement to the
|
|
// Microsoft Foundation Classes Reference and related
|
|
// electronic documentation provided with the library.
|
|
// See these sources for detailed information regarding the
|
|
// Microsoft Foundation Classes product.
|
|
|
|
#include "stdafx.h"
|
|
#include <dlgs.h> // for standard control IDs for commdlg
|
|
|
|
#ifdef AFX_AUX_SEG
|
|
#pragma code_seg(AFX_AUX_SEG)
|
|
#endif
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#define new DEBUG_NEW
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// FileOpen/FileSaveAs common dialog helper
|
|
|
|
CFileDialog::CFileDialog(BOOL bOpenFileDialog,
|
|
LPCTSTR lpszDefExt, LPCTSTR lpszFileName, DWORD dwFlags,
|
|
LPCTSTR lpszFilter, CWnd* pParentWnd) : CCommonDialog(pParentWnd)
|
|
{
|
|
memset(&m_ofn, 0, sizeof(m_ofn)); // initialize structure to 0/NULL
|
|
m_szFileName[0] = '\0';
|
|
m_szFileTitle[0] = '\0';
|
|
m_pofnTemp = NULL;
|
|
|
|
m_bOpenFileDialog = bOpenFileDialog;
|
|
m_nIDHelp = bOpenFileDialog ? AFX_IDD_FILEOPEN : AFX_IDD_FILESAVE;
|
|
|
|
m_ofn.lStructSize = sizeof(m_ofn);
|
|
m_ofn.lpstrFile = m_szFileName;
|
|
m_ofn.nMaxFile = _countof(m_szFileName);
|
|
m_ofn.lpstrDefExt = lpszDefExt;
|
|
m_ofn.lpstrFileTitle = (LPTSTR)m_szFileTitle;
|
|
m_ofn.nMaxFileTitle = _countof(m_szFileTitle);
|
|
m_ofn.Flags |= dwFlags | OFN_ENABLEHOOK;
|
|
if (!afxData.bWin4 && AfxHelpEnabled())
|
|
m_ofn.Flags |= OFN_SHOWHELP;
|
|
if (afxData.bWin4)
|
|
{
|
|
m_ofn.Flags |= OFN_EXPLORER;
|
|
m_ofn.hInstance = AfxGetResourceHandle();
|
|
}
|
|
m_ofn.lpfnHook = (COMMDLGPROC)_AfxCommDlgProc;
|
|
|
|
// setup initial file name
|
|
if (lpszFileName != NULL)
|
|
lstrcpyn(m_szFileName, lpszFileName, _countof(m_szFileName));
|
|
|
|
// Translate filter into commdlg format (lots of \0)
|
|
if (lpszFilter != NULL)
|
|
{
|
|
m_strFilter = lpszFilter;
|
|
LPTSTR pch = m_strFilter.GetBuffer(0); // modify the buffer in place
|
|
// MFC delimits with '|' not '\0'
|
|
while ((pch = _tcschr(pch, '|')) != NULL)
|
|
*pch++ = '\0';
|
|
m_ofn.lpstrFilter = m_strFilter;
|
|
// do not call ReleaseBuffer() since the string contains '\0' characters
|
|
}
|
|
}
|
|
|
|
int CFileDialog::DoModal()
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(m_ofn.Flags & OFN_ENABLEHOOK);
|
|
ASSERT(m_ofn.lpfnHook != NULL); // can still be a user hook
|
|
#ifdef _MAC
|
|
ASSERT((m_ofn.Flags & OFN_ALLOWMULTISELECT) == 0);
|
|
#endif
|
|
|
|
// WINBUG: This is a special case for the file open/save dialog,
|
|
// which sometimes pumps while it is coming up but before it has
|
|
// disabled the main window.
|
|
HWND hWndFocus = ::GetFocus();
|
|
BOOL bEnableParent = FALSE;
|
|
m_ofn.hwndOwner = PreModal();
|
|
AfxUnhookWindowCreate();
|
|
if (m_ofn.hwndOwner != NULL && ::IsWindowEnabled(m_ofn.hwndOwner))
|
|
{
|
|
bEnableParent = TRUE;
|
|
::EnableWindow(m_ofn.hwndOwner, FALSE);
|
|
}
|
|
|
|
_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
|
|
ASSERT(pThreadState->m_pAlternateWndInit == NULL);
|
|
|
|
if (m_ofn.Flags & OFN_EXPLORER)
|
|
pThreadState->m_pAlternateWndInit = this;
|
|
else
|
|
AfxHookWindowCreate(this);
|
|
|
|
int nResult;
|
|
if (m_bOpenFileDialog)
|
|
nResult = ::GetOpenFileName(&m_ofn);
|
|
else
|
|
nResult = ::GetSaveFileName(&m_ofn);
|
|
|
|
if (nResult)
|
|
ASSERT(pThreadState->m_pAlternateWndInit == NULL);
|
|
pThreadState->m_pAlternateWndInit = NULL;
|
|
|
|
// WINBUG: Second part of special case for file open/save dialog.
|
|
if (bEnableParent)
|
|
::EnableWindow(m_ofn.hwndOwner, TRUE);
|
|
if (::IsWindow(hWndFocus))
|
|
::SetFocus(hWndFocus);
|
|
|
|
PostModal();
|
|
return nResult ? nResult : IDCANCEL;
|
|
}
|
|
|
|
CString CFileDialog::GetPathName() const
|
|
{
|
|
#ifndef _MAC
|
|
if ((m_ofn.Flags & OFN_EXPLORER) && m_hWnd != NULL)
|
|
{
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
CString strResult;
|
|
if (GetParent()->SendMessage(CDM_GETSPEC, (WPARAM)MAX_PATH,
|
|
(LPARAM)strResult.GetBuffer(MAX_PATH)) < 0)
|
|
{
|
|
strResult.Empty();
|
|
}
|
|
else
|
|
{
|
|
strResult.ReleaseBuffer();
|
|
}
|
|
|
|
if (!strResult.IsEmpty())
|
|
{
|
|
if (GetParent()->SendMessage(CDM_GETFILEPATH, (WPARAM)MAX_PATH,
|
|
(LPARAM)strResult.GetBuffer(MAX_PATH)) < 0)
|
|
strResult.Empty();
|
|
else
|
|
{
|
|
strResult.ReleaseBuffer();
|
|
return strResult;
|
|
}
|
|
}
|
|
}
|
|
return m_ofn.lpstrFile;
|
|
#else
|
|
CString strResult;
|
|
LPSTR pstr;
|
|
::GetFullPathName(m_ofn.lpstrFile, MAX_PATH, strResult.GetBuffer(MAX_PATH), &pstr);
|
|
strResult.ReleaseBuffer();
|
|
return strResult;
|
|
#endif
|
|
}
|
|
|
|
CString CFileDialog::GetFileName() const
|
|
{
|
|
#ifndef _MAC
|
|
if ((m_ofn.Flags & OFN_EXPLORER) && m_hWnd != NULL)
|
|
{
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
CString strResult;
|
|
if (GetParent()->SendMessage(CDM_GETSPEC, (WPARAM)MAX_PATH,
|
|
(LPARAM)strResult.GetBuffer(MAX_PATH)) < 0)
|
|
{
|
|
strResult.Empty();
|
|
}
|
|
else
|
|
{
|
|
strResult.ReleaseBuffer();
|
|
return strResult;
|
|
}
|
|
}
|
|
#endif
|
|
return m_ofn.lpstrFileTitle;
|
|
}
|
|
|
|
CString CFileDialog::GetFileExt() const
|
|
{
|
|
#ifndef _MAC
|
|
if ((m_ofn.Flags & OFN_EXPLORER) && m_hWnd != NULL)
|
|
{
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
CString strResult;
|
|
if (GetParent()->SendMessage(CDM_GETSPEC, (WPARAM)MAX_PATH,
|
|
(LPARAM)strResult.GetBuffer(MAX_PATH)) < 0)
|
|
strResult.Empty();
|
|
else
|
|
{
|
|
strResult.ReleaseBuffer();
|
|
int pos = strResult.ReverseFind('.');
|
|
if (pos >= 0)
|
|
return strResult.Right(strResult.GetLength() - pos - 1);
|
|
strResult.Empty();
|
|
}
|
|
return strResult;
|
|
}
|
|
#endif
|
|
|
|
if (m_pofnTemp != NULL)
|
|
if (m_pofnTemp->nFileExtension == 0)
|
|
return &afxChNil;
|
|
else
|
|
return m_pofnTemp->lpstrFile + m_pofnTemp->nFileExtension;
|
|
|
|
if (m_ofn.nFileExtension == 0)
|
|
return &afxChNil;
|
|
else
|
|
return m_ofn.lpstrFile + m_ofn.nFileExtension;
|
|
}
|
|
|
|
CString CFileDialog::GetFileTitle() const
|
|
{
|
|
#ifndef _MAC
|
|
CString strResult = GetFileName();
|
|
int pos = strResult.ReverseFind('.');
|
|
if (pos >= 0)
|
|
return strResult.Left(pos);
|
|
return strResult;
|
|
#else
|
|
return GetFileName();
|
|
#endif
|
|
}
|
|
|
|
CString CFileDialog::GetNextPathName(POSITION& pos) const
|
|
{
|
|
#ifndef _MAC
|
|
TCHAR chDelimiter;
|
|
if (afxData.bWin4)
|
|
chDelimiter = '\0';
|
|
else
|
|
chDelimiter = ' ';
|
|
|
|
LPTSTR lpsz = (LPTSTR)pos;
|
|
if (lpsz == m_ofn.lpstrFile) // first time
|
|
{
|
|
if ((m_ofn.Flags & OFN_ALLOWMULTISELECT) == 0)
|
|
{
|
|
pos = NULL;
|
|
return m_ofn.lpstrFile;
|
|
}
|
|
|
|
// find char pos after first Delimiter
|
|
while(*lpsz != chDelimiter && *lpsz != '\0')
|
|
lpsz = _tcsinc(lpsz);
|
|
lpsz = _tcsinc(lpsz);
|
|
|
|
// if single selection then return only selection
|
|
if ((lpsz - m_ofn.lpstrFile) > m_ofn.nFileOffset)
|
|
{
|
|
pos = NULL;
|
|
return m_ofn.lpstrFile;
|
|
}
|
|
}
|
|
|
|
CString strPath = m_ofn.lpstrFile;
|
|
if (!afxData.bWin4)
|
|
{
|
|
LPTSTR lpszPath = m_ofn.lpstrFile;
|
|
while(*lpszPath != chDelimiter)
|
|
lpszPath = _tcsinc(lpszPath);
|
|
strPath = strPath.Left(lpszPath - m_ofn.lpstrFile);
|
|
}
|
|
|
|
LPTSTR lpszFileName = lpsz;
|
|
CString strFileName = lpsz;
|
|
|
|
// find char pos at next Delimiter
|
|
while(*lpsz != chDelimiter && *lpsz != '\0')
|
|
lpsz = _tcsinc(lpsz);
|
|
|
|
if (!afxData.bWin4 && *lpsz == '\0')
|
|
pos = NULL;
|
|
else
|
|
{
|
|
if (!afxData.bWin4)
|
|
strFileName = strFileName.Left(lpsz - lpszFileName);
|
|
|
|
lpsz = _tcsinc(lpsz);
|
|
if (*lpsz == '\0') // if double terminated then done
|
|
pos = NULL;
|
|
else
|
|
pos = (POSITION)lpsz;
|
|
}
|
|
|
|
// only add '\\' if it is needed
|
|
if (!strPath.IsEmpty())
|
|
{
|
|
// check for last back-slash or forward slash (handles DBCS)
|
|
LPCTSTR lpsz = _tcsrchr(strPath, '\\');
|
|
if (lpsz == NULL)
|
|
lpsz = _tcsrchr(strPath, '/');
|
|
// if it is also the last character, then we don't need an extra
|
|
if (lpsz != NULL &&
|
|
(lpsz - (LPCTSTR)strPath) == strPath.GetLength()-1)
|
|
{
|
|
ASSERT(*lpsz == '\\' || *lpsz == '/');
|
|
return strPath + strFileName;
|
|
}
|
|
}
|
|
return strPath + '\\' + strFileName;
|
|
#else
|
|
pos = NULL;
|
|
return m_ofn.lpstrFile;
|
|
#endif
|
|
}
|
|
|
|
void CFileDialog::SetTemplate(LPCTSTR lpWin3ID, LPCTSTR lpWin4ID)
|
|
{
|
|
#ifndef _MAC
|
|
if (m_ofn.Flags & OFN_EXPLORER)
|
|
m_ofn.lpTemplateName = lpWin4ID;
|
|
else
|
|
m_ofn.lpTemplateName = lpWin3ID;
|
|
m_ofn.Flags |= OFN_ENABLETEMPLATE;
|
|
#else
|
|
UNUSED_ALWAYS(lpWin3ID);
|
|
UNUSED_ALWAYS(lpWin4ID);
|
|
#endif
|
|
}
|
|
|
|
#ifndef _MAC
|
|
CString CFileDialog::GetFolderPath() const
|
|
{
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
ASSERT(m_ofn.Flags & OFN_EXPLORER);
|
|
|
|
CString strResult;
|
|
if (GetParent()->SendMessage(CDM_GETFOLDERPATH, (WPARAM)MAX_PATH, (LPARAM)strResult.GetBuffer(MAX_PATH)) < 0)
|
|
strResult.Empty();
|
|
else
|
|
strResult.ReleaseBuffer();
|
|
return strResult;
|
|
}
|
|
|
|
void CFileDialog::SetControlText(int nID, LPCSTR lpsz)
|
|
{
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
ASSERT(m_ofn.Flags & OFN_EXPLORER);
|
|
GetParent()->SendMessage(CDM_SETCONTROLTEXT, (WPARAM)nID, (LPARAM)lpsz);
|
|
}
|
|
|
|
void CFileDialog::HideControl(int nID)
|
|
{
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
ASSERT(m_ofn.Flags & OFN_EXPLORER);
|
|
GetParent()->SendMessage(CDM_HIDECONTROL, (WPARAM)nID, 0);
|
|
}
|
|
|
|
void CFileDialog::SetDefExt(LPCSTR lpsz)
|
|
{
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
ASSERT(m_ofn.Flags & OFN_EXPLORER);
|
|
GetParent()->SendMessage(CDM_SETDEFEXT, 0, (LPARAM)lpsz);
|
|
}
|
|
#endif //!_MAC
|
|
|
|
UINT CFileDialog::OnShareViolation(LPCTSTR)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// Do not call Default() if you override
|
|
return OFN_SHAREWARN; // default
|
|
}
|
|
|
|
BOOL CFileDialog::OnFileNameOK()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// Do not call Default() if you override
|
|
return FALSE;
|
|
}
|
|
|
|
void CFileDialog::OnLBSelChangedNotify(UINT, UINT, UINT)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// Do not call Default() if you override
|
|
// no default processing needed
|
|
}
|
|
|
|
void CFileDialog::OnInitDone()
|
|
{
|
|
ASSERT_VALID(this);
|
|
GetParent()->CenterWindow();
|
|
|
|
// Do not call Default() if you override
|
|
// no default processing needed
|
|
}
|
|
|
|
void CFileDialog::OnFileNameChange()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// Do not call Default() if you override
|
|
// no default processing needed
|
|
}
|
|
|
|
void CFileDialog::OnFolderChange()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// Do not call Default() if you override
|
|
// no default processing needed
|
|
}
|
|
|
|
void CFileDialog::OnTypeChange()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// Do not call Default() if you override
|
|
// no default processing needed
|
|
}
|
|
|
|
BOOL CFileDialog::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
|
|
{
|
|
ASSERT(pResult != NULL);
|
|
|
|
// allow message map to override
|
|
if (CCommonDialog::OnNotify(wParam, lParam, pResult))
|
|
return TRUE;
|
|
|
|
#ifndef _MAC
|
|
OFNOTIFY* pNotify = (OFNOTIFY*)lParam;
|
|
switch(pNotify->hdr.code)
|
|
{
|
|
case CDN_INITDONE:
|
|
OnInitDone();
|
|
return TRUE;
|
|
case CDN_SELCHANGE:
|
|
OnFileNameChange();
|
|
return TRUE;
|
|
case CDN_FOLDERCHANGE:
|
|
OnFolderChange();
|
|
return TRUE;
|
|
case CDN_SHAREVIOLATION:
|
|
*pResult = OnShareViolation(pNotify->pszFile);
|
|
return TRUE;
|
|
case CDN_HELP:
|
|
if (!SendMessage(WM_COMMAND, ID_HELP))
|
|
SendMessage(WM_COMMANDHELP, 0, 0);
|
|
return TRUE;
|
|
case CDN_FILEOK:
|
|
*pResult = OnFileNameOK();
|
|
return TRUE;
|
|
case CDN_TYPECHANGE:
|
|
OnTypeChange();
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
return FALSE; // not handled
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// CFileDialog diagnostics
|
|
|
|
#ifdef _DEBUG
|
|
void CFileDialog::Dump(CDumpContext& dc) const
|
|
{
|
|
CDialog::Dump(dc);
|
|
|
|
if (m_bOpenFileDialog)
|
|
dc << "File open dialog";
|
|
else
|
|
dc << "File save dialog";
|
|
dc << "\nm_ofn.hwndOwner = " << (UINT)m_ofn.hwndOwner;
|
|
dc << "\nm_ofn.nFilterIndex = " << m_ofn.nFilterIndex;
|
|
dc << "\nm_ofn.lpstrFile = " << m_ofn.lpstrFile;
|
|
dc << "\nm_ofn.nMaxFile = " << m_ofn.nMaxFile;
|
|
dc << "\nm_ofn.lpstrFileTitle = " << m_ofn.lpstrFileTitle;
|
|
dc << "\nm_ofn.nMaxFileTitle = " << m_ofn.nMaxFileTitle;
|
|
dc << "\nm_ofn.lpstrTitle = " << m_ofn.lpstrTitle;
|
|
dc << "\nm_ofn.Flags = " << (LPVOID)m_ofn.Flags;
|
|
dc << "\nm_ofn.lpstrDefExt = " << m_ofn.lpstrDefExt;
|
|
dc << "\nm_ofn.nFileOffset = " << m_ofn.nFileOffset;
|
|
dc << "\nm_ofn.nFileExtension = " << m_ofn.nFileExtension;
|
|
|
|
dc << "\nm_ofn.lpstrFilter = ";
|
|
LPCTSTR lpstrItem = m_ofn.lpstrFilter;
|
|
LPTSTR lpszBreak = _T("|");
|
|
|
|
while (lpstrItem != NULL && *lpstrItem != '\0')
|
|
{
|
|
dc << lpstrItem << lpszBreak;
|
|
lpstrItem += lstrlen(lpstrItem) + 1;
|
|
}
|
|
if (lpstrItem != NULL)
|
|
dc << lpszBreak;
|
|
|
|
dc << "\nm_ofn.lpstrCustomFilter = ";
|
|
lpstrItem = m_ofn.lpstrCustomFilter;
|
|
while (lpstrItem != NULL && *lpstrItem != '\0')
|
|
{
|
|
dc << lpstrItem << lpszBreak;
|
|
lpstrItem += lstrlen(lpstrItem) + 1;
|
|
}
|
|
if (lpstrItem != NULL)
|
|
dc << lpszBreak;
|
|
|
|
if (m_ofn.lpfnHook == (COMMDLGPROC)_AfxCommDlgProc)
|
|
dc << "\nhook function set to standard MFC hook function";
|
|
else
|
|
dc << "\nhook function set to non-standard hook function";
|
|
|
|
dc << "\n";
|
|
}
|
|
#endif //_DEBUG
|
|
|
|
#ifdef AFX_INIT_SEG
|
|
#pragma code_seg(AFX_INIT_SEG)
|
|
#endif
|
|
|
|
IMPLEMENT_DYNAMIC(CFileDialog, CDialog)
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|