210 lines
5.8 KiB
C++
210 lines
5.8 KiB
C++
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Crytek Engine Source File.
|
|
// Copyright (C), Crytek Studios, 2002.
|
|
// -------------------------------------------------------------------------
|
|
// File name: mfc_amd64_fix.h
|
|
// Version: v1.00
|
|
// Created: 12/9/2003 by Timur.
|
|
// Compilers: Visual Studio.NET
|
|
// Description: Fixes of problems using MFC on AMD64 machines.
|
|
// -------------------------------------------------------------------------
|
|
// History:
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef __mfc_amd64_fix_h__
|
|
#define __mfc_amd64_fix_h__
|
|
#pragma once
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// In case of AMD64 overcome crash bug when using CFileDialog.
|
|
//////////////////////////////////////////////////////////////////////////
|
|
#ifdef WIN64
|
|
class CCryFileDialog
|
|
{
|
|
public:
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// FileOpen/FileSaveAs common dialog helper
|
|
OPENFILENAME m_ofn;
|
|
BOOL m_bOpenFileDialog; // TRUE for file open, FALSE for file save
|
|
CString m_strFilter; // filter string
|
|
// separate fields with '|', terminate with '||\0'
|
|
TCHAR m_szFileTitle[64]; // contains file title after return
|
|
TCHAR m_szFileName[_MAX_PATH]; // contains full path name after return
|
|
|
|
explicit CCryFileDialog(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs
|
|
LPCTSTR lpszDefExt = NULL,
|
|
LPCTSTR lpszFileName = NULL,
|
|
DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
|
|
LPCTSTR lpszFilter = NULL,
|
|
CWnd* pParentWnd = NULL,
|
|
DWORD dwSize = sizeof(OPENFILENAME))
|
|
{
|
|
memset(&m_ofn, 0, sizeof(m_ofn)); // initialize structure to 0/NULL
|
|
m_szFileName[0] = '\0';
|
|
m_szFileTitle[0] = '\0';
|
|
m_bOpenFileDialog = bOpenFileDialog;
|
|
|
|
m_ofn.lStructSize = sizeof(m_ofn);
|
|
m_ofn.lpstrFile = m_szFileName;
|
|
m_ofn.nMaxFile = sizeof(m_szFileName);
|
|
m_ofn.lpstrDefExt = lpszDefExt;
|
|
m_ofn.lpstrFileTitle = (LPTSTR)m_szFileTitle;
|
|
m_ofn.nMaxFileTitle = sizeof(m_szFileTitle);
|
|
m_ofn.Flags |= dwFlags | OFN_ENABLESIZING;
|
|
if (pParentWnd)
|
|
m_ofn.hwndOwner = pParentWnd->GetSafeHwnd();
|
|
|
|
m_ofn.Flags |= OFN_EXPLORER;
|
|
m_ofn.hInstance = AfxGetResourceHandle();
|
|
|
|
// setup initial file name
|
|
if (lpszFileName != NULL)
|
|
lstrcpyn(m_szFileName, lpszFileName, sizeof(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_PTR DoModal()
|
|
{
|
|
|
|
// zero out the file buffer for consistent parsing later
|
|
ASSERT(AfxIsValidAddress(m_ofn.lpstrFile, m_ofn.nMaxFile));
|
|
DWORD nOffset = lstrlen(m_ofn.lpstrFile)+1;
|
|
ASSERT(nOffset <= m_ofn.nMaxFile);
|
|
memset(m_ofn.lpstrFile+nOffset, 0, (m_ofn.nMaxFile-nOffset)*sizeof(TCHAR));
|
|
|
|
// 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;
|
|
if (m_ofn.hwndOwner != NULL && ::IsWindowEnabled(m_ofn.hwndOwner))
|
|
{
|
|
bEnableParent = TRUE;
|
|
::EnableWindow(m_ofn.hwndOwner, FALSE);
|
|
}
|
|
|
|
int nResult;
|
|
if (m_bOpenFileDialog)
|
|
nResult = ::GetOpenFileName(&m_ofn);
|
|
else
|
|
nResult = ::GetSaveFileName(&m_ofn);
|
|
|
|
// WINBUG: Second part of special case for file open/save dialog.
|
|
if (bEnableParent)
|
|
::EnableWindow(m_ofn.hwndOwner, TRUE);
|
|
if (::IsWindow(hWndFocus))
|
|
::SetFocus(hWndFocus);
|
|
|
|
return nResult ? nResult : IDCANCEL;
|
|
}
|
|
|
|
CString GetPathName() const
|
|
{
|
|
return m_ofn.lpstrFile;
|
|
}
|
|
|
|
POSITION GetStartPosition() const
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
CString GetNextPathName(POSITION& pos) const
|
|
{
|
|
BOOL bExplorer = m_ofn.Flags & OFN_EXPLORER;
|
|
TCHAR chDelimiter;
|
|
if (bExplorer)
|
|
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 == 0)
|
|
{
|
|
pos = NULL;
|
|
return m_ofn.lpstrFile;
|
|
}
|
|
}
|
|
|
|
CString strPath = m_ofn.lpstrFile;
|
|
if (!bExplorer)
|
|
{
|
|
LPTSTR lpszPath = m_ofn.lpstrFile;
|
|
while(*lpszPath != chDelimiter)
|
|
lpszPath = _tcsinc(lpszPath);
|
|
strPath = strPath.Left(int(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 (!bExplorer && *lpsz == '\0')
|
|
pos = NULL;
|
|
else
|
|
{
|
|
if (!bExplorer)
|
|
strFileName = strFileName.Left(int(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;
|
|
}
|
|
};
|
|
|
|
//! Override CFileDialog with custom version.
|
|
#define CFileDialog CCryFileDialog
|
|
|
|
#endif //WIN64
|
|
|
|
#endif // __mfc_amd64_fix_h__
|