您好,我已经将VC ++ 6项目转换为VC ++ 2010,并且在显示模态打开文件对话框时遇到错误。
它显示对话框的底部,但顶部缺失,filter也不填充。
标题有公共成员用于存储文件信息:
CString m_strFilePathName; CString m_strFileExtName;
我的代码显示对话框:
static TCHAR BASED_CODE szFilter[] = _T("Open Bin File(*.abs)|") _T("Default DataBase File(*.ddf)|") _T("SatCodex File(*.sdx)|") _T("Format Text File(*.txt)"); // TODO: Add your command handler code here CFileDlg fd(TRUE, NULL, "", OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter); //"Open Bin File(*.abs)|Default DataBase File(*.ddf)|SatCodex File(*.sdx)|Format Text File(*.txt)"); const int c_cMaxFiles = 1; const int c_cbBuffSize = (c_cMaxFiles * (MAX_PATH + 1)) + 1; fd.GetOFN().lpstrFile = m_strFilePathName.GetBuffer(c_cbBuffSize); fd.GetOFN().nMaxFile = c_cbBuffSize; // Dialog hangs on this line: if(fd.DoModal() != IDOK) return;
诊断返回: 在AliEditor.exe 0x006c69cc第一次机会exception:0xC0000005:访问冲突读取位置0x00000020。
在悬挂模式调用堆栈中断时返回以下信息:
user32.dll!_NtUserWaitMessage@0() + 0x15 bytes <-STOPPED HERE user32.dll!_NtUserWaitMessage@0() + 0x15 bytes user32.dll!_DialogBox2@16() + 0x109 bytes user32.dll!_InternalDialogBox@24() + 0xc9 bytes user32.dll!_DialogBoxIndirectParamAorW@24() + 0x36 bytes user32.dll!_DialogBoxIndirectParamW@20() + 0x1b bytes comdlg32.dll!CFileOpenSave::Show() + 0x146 bytes
AliEditor.exe!CFileDialog :: DoModal()Line 748 + 0x26 bytes C ++ AliEditor.exe!CMainFrame :: OnFileOpen()Line 195 + 0xb bytes C ++ AliEditor.exe!_AfxDispatchCmdMsg(CCmdTarget * pTarget,unsigned int nID,int nCode,void (无效)* pfn,void * pExtra,unsigned int nSig,AFX_CMDHANDLERINFO * pHandlerInfo) C ++ AliEditor.exe!CFrameWnd :: OnCmdMsg(unsigned int nID,int nCode,void * pExtra,AFX_CMDHANDLERINFO * pHandlerInfo)Line 973 + 0x18 bytes C ++ AliEditor.exe!CWnd :: OnCommand(unsigned int wParam,long lParam)Line 2729 C ++第一行,第一行,第二行,第一行,第二行,第三行,第三行,第三行,第三行,第三行,第三行,第三行,第三行,第三行,第三行, .exe!CWnd :: WindowProc(unsigned int message,unsigned int wParam,long lParam)行2087 + 0x20字节C ++ AliEditor .exe!!AfxCallWndProc(CWnd * pWnd,HWND__ * hWnd,unsigned int nMsg,unsigned int wParam,long lParam)行257 + 0x1c字节C ++ AliEditor.exe!AfxWndProc(HWND__ * hWnd,unsigned int nMsg,unsigned int wParam,long lParam )线420 C ++
我猜的声明(我不是C ++开发人员)覆盖(fileDlg.cpp):
#include "stdafx.h" #include "AliEditor.h" #include "FileDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CFileDlg IMPLEMENT_DYNAMIC(CFileDlg, CFileDialog) CFileDlg::CFileDlg(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName, DWORD dwFlags, LPCTSTR lpszFilter, CWnd* pParentWnd) : CFileExportDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd) { } BEGIN_MESSAGE_MAP(CFileDlg, CFileExportDialog) //{{AFX_MSG_MAP(CFileDlg) ON_WM_CLOSE() //}}AFX_MSG_MAP END_MESSAGE_MAP()
文件“dlgfile.cpp”非常大,但是这仅仅是最上面的部分:
// This is a part of the Microsoft Foundation Classes C++ library. // Copyright (C) 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 #include "afxglobals.h" #define new DEBUG_NEW //////////////////////////////////////////////////////////////////////////// // FileOpen/FileSaveAs common dialog helper CFileDialog::CFileDialog(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName, DWORD dwFlags, LPCTSTR lpszFilter, CWnd* pParentWnd, DWORD dwSize, BOOL bVistaStyle) : CCommonDialog(pParentWnd) { OSVERSIONINFO vi; ZeroMemory(&vi, sizeof(OSVERSIONINFO)); vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); ::GetVersionEx(&vi); // if running under Vista if (vi.dwMajorVersion >= 6) { m_bVistaStyle = bVistaStyle; } else { m_bVistaStyle = FALSE; } m_bPickFoldersMode = FALSE; // determine size of OPENFILENAME struct if dwSize is zero if (dwSize == 0) { dwSize = sizeof(OPENFILENAME); } // size of OPENFILENAME must be at least version 5 ASSERT(dwSize >= sizeof(OPENFILENAME)); // allocate memory for OPENFILENAME struct based on size passed in m_pOFN = static_cast<LPOPENFILENAME>(malloc(dwSize)); ASSERT(m_pOFN != NULL); if (m_pOFN == NULL) AfxThrowMemoryException(); memset(&m_ofn, 0, dwSize); // 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 = dwSize; 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 | OFN_EXPLORER; if(dwFlags & OFN_ENABLETEMPLATE) m_ofn.Flags &= ~OFN_ENABLESIZING; m_ofn.hInstance = AfxGetResourceHandle(); m_ofn.lpfnHook = (COMMDLGPROC)_AfxCommDlgProc; // setup initial file name if (lpszFileName != NULL) Checked::tcsncpy_s(m_szFileName, _countof(m_szFileName), lpszFileName, _TRUNCATE); // 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 } if (m_bVistaStyle == TRUE) { if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) { // multi-threaded is not supported IFileDialog* pIFileDialog; IFileDialogCustomize* pIFileDialogCustomize; HRESULT hr; USE_INTERFACE_PART_STD(FileDialogEvents); USE_INTERFACE_PART_STD(FileDialogControlEvents); if (m_bOpenFileDialog) { hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pIFileDialog)); } else { hr = CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pIFileDialog)); } if (FAILED(hr)) { m_bVistaStyle = FALSE; return; } hr = pIFileDialog->QueryInterface(IID_PPV_ARGS(&pIFileDialogCustomize)); ENSURE(SUCCEEDED(hr)); hr = pIFileDialog->Advise(reinterpret_cast<IFileDialogEvents*>(&m_xFileDialogEvents), &m_dwCookie); ENSURE(SUCCEEDED(hr)); m_pIFileDialog = static_cast<void*>(pIFileDialog); m_pIFileDialogCustomize = static_cast<void*>(pIFileDialogCustomize); } else { m_bVistaStyle = FALSE; } } } CFileDialog::~CFileDialog() { free(m_pOFN); if (m_bVistaStyle == TRUE) { HRESULT hr; hr = (static_cast<IFileDialog*>(m_pIFileDialog))->Unadvise(m_dwCookie); ENSURE(SUCCEEDED(hr)); (static_cast<IFileDialogCustomize*>(m_pIFileDialogCustomize))->Release(); (static_cast<IFileDialog*>(m_pIFileDialog))->Release(); CoUninitialize(); } } const OPENFILENAME& CFileDialog::GetOFN() const { return *m_pOFN; } OPENFILENAME& CFileDialog::GetOFN() { return *m_pOFN; }
一步一步来到同一个(“dlgfile.cpp”)文件中的这一点:
INT_PTR CFileDialog::DoModal() { ASSERT_VALID(this); ASSERT(m_ofn.Flags & OFN_ENABLEHOOK); ASSERT(m_ofn.lpfnHook != NULL); // can still be a user hook // 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)); // 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_bVistaStyle == TRUE) { AfxHookWindowCreate(this); } else if (m_ofn.Flags & OFN_EXPLORER) pThreadState->m_pAlternateWndInit = this; else AfxHookWindowCreate(this); INT_PTR nResult = 0; if (m_bVistaStyle == TRUE) { ApplyOFNToShellDialog(); // HERE CALLS **OPENFILENAME& CFileDialog::GetOFN()** method and then hangs HRESULT hr = (static_cast<IFileDialog*>(m_pIFileDialog))->Show(m_ofn.hwndOwner); nResult = (hr == S_OK) ? IDOK : IDCANCEL; } else if (m_bOpenFileDialog) nResult = ::AfxCtxGetOpenFileName(&m_ofn); else nResult = ::AfxCtxGetSaveFileName(&m_ofn); if (nResult) ASSERT(pThreadState->m_pAlternateWndInit == NULL); pThreadState->m_pAlternateWndInit = NULL; // 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; }
任何人都可以帮我吗?
[更新]现阶段没有人能帮到我,我已经把项目上传到了这里的公共场所。 任何人都可以下载并告诉我什么是错误的,当我点击打开文件?
我能看到的唯一问题是您的过滤器字符串看起来不正确。 它看起来像您的代码是基于MSDN示例之一。 根据这个例子,你的sFFilter应该是这样的:
static TCHAR BASED_CODE szFilter[] = _T("Open Bin File(*.abs)|*.abs|") _T("Default DataBase File(*.ddf)|*.ddf|") _T("SatCodex File(*.sdx)|*.sdx|") _T("Format Text File(*.txt)|*.txt||");
仅供参考,我用http://msdn.microsoft.com/en-US/library/wh5hz49d(v=vs.100).aspx作为参考。
[更新]
我创建了一个小的MFC应用程序并粘贴到您的代码中。 代码示例中有一个错字。 这个类是CFileDialog,而不是CFileDlg。 我修好了,然后应用上面所述的修改来修复szFilter字符串。 这个对我有用。 文件对话框显示,我输入一些数据,并关闭文件对话框。 没有访问冲突,没有断言。 我认为你需要查看你的代码中的其他地方来追踪这个问题。
[更新2]
忽略我以前所说的一切。 您的原始访问冲突在FileExportDialog.cpp的第174行左右
void CFileExportDialog::OnTypeChange() { // get current filename CWnd *fileNameBox = GetParent()->GetDlgItem(edt1); ASSERT_VALID(fileNameBox); CString fileName; fileNameBox->GetWindowText(fileName); // get current extension CWnd *typeNameBox = GetParent()->GetDlgItem(cmb1); ASSERT_VALID(typeNameBox); CString typeName; typeNameBox->GetWindowText(typeName); ...
真正的调用堆栈是:
AliEditor.exe!CWnd::GetDlgItem(int nID) Line 92 + 0x3 bytes C++ AliEditor.exe!CFileExportDialog::OnTypeChange() Line 177 + 0x14 bytes C++ AliEditor.exe!CFileDialog::XFileDialogEvents::OnTypeChange(IFileDialog * __formal) Line 619 C++ comdlg32.dll!76138057() [Frames below may be incorrect and/or missing, no symbols loaded for comdlg32.dll] comctl32.dll!731c7613() comdlg32.dll!7612bdda() comdlg32.dll!7612c5a0() coreelBase.dll!76096055() comctl32.dll!7458b575() user32.dll!767281c8() user32.dll!76728326() user32.dll!76728347() user32.dll!76730d27() user32.dll!7673794a() AliEditor.exe!_AfxActivationWndProc(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 456 + 0x1a bytes C++ user32.dll!767262fa() user32.dll!76726d3a() user32.dll!76726ce9() user32.dll!7672965e() user32.dll!7675206f() user32.dll!7674cf4b() user32.dll!7674ce8a() user32.dll!7674cc0e() comdlg32.dll!7612597b() AliEditor.exe!CFileDialog::DoModal() Line 748 + 0x26 bytes C++ ...
该程序崩溃在CWnd :: GetDlgItem,因为CWnd“this”指针是0.这是因为CFileExportDialog :: OnTypeChange的第一行是GetParent(),它是NULL,因为此对话框没有父项。
CFileExportDialog类不是Visual Studio的一部分,它似乎基于一些在1999年写成的公共领域代码http://www.codeguru.com/cpp/wd/dislog/commondialogs/article.php/c1863/CFileExportDialog-Class .htm 。 看起来像OnTypeChange的实现是基于原始的开发人员逆向工程微软CFileDialog类的细节,因为它是在1999年实施的。我猜测VS2010内部已经改变,所以类不再有用。
下次运行程序时,在FileExportDialog.cpp的第177行设置一个断点。 当你点击断点时,单步执行代码并观察崩溃并断言,过时的代码试图做一些本来不应该做的事情。
建议您转储CFileExportDialog类,并使用标准MFC CFileDialog类重写您的程序。