Files
FC1/Editor/MFC_AMD64_Fix.h
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

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__