代码之家  ›  专栏  ›  技术社区  ›  btomas

VC++2010:显示打开的对话框挂起[关闭]

  •  2
  • btomas  · 技术社区  · 13 年前

    嗨,我已经将VC++6项目转换为VC++2010,在显示模式“打开文件”对话框时一直遇到错误。

    它显示了对话框的底部,但顶部缺失,过滤器也未填充。

    标头具有用于存储文件信息的公共成员:

    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处的首次机会异常: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()行748+0x26字节C++ AliEditor.exe!C主帧::OnFileOpen()行195+0xb字节C++ AliEditor.exe_AfxDispatchCmdMsg(CCmdTarget*pTarget,unsigned int nID,int nCode,void(void)*pfn,void*pExtra,unsignedint nSig,AFX_CMDHANDLERINFO*pHandlerInfo)第82行C++ AliEditor.exe!CCmdTarget::OnCmdMsg(无符号int nID,int nCode,void*pExtra,AFX_CMDHANDLERINFO*pHandlerInfo)行381+0x27字节C++ AliEditor.exe!CFrameWnd::OnCmdMsg(无符号int nID,int nCode,void*pExtra,AFX_CMDHANDLERINFO*pHandlerInfo)行973+0x18字节C++ AliEditor.exe!CWnd::OnCommand(无符号int wParam,长lParam)行2729 C++ AliEditor.exe!CFrameWnd::OnCommand(无符号int wParam,长lParam)第371行C++ AliEditor.exe!CWnd::OnWndMsg(无符号int消息,无符号int wParam,长lParam,长*pResult)行2101+0x1e字节C++ AliEditor.exe!CWnd::WindowProc(无符号int消息,无符号int wParam,长lParam)行2087+0x20字节C++ AliEditor.exe!AfxCallWndProc(CWnd*pWnd,HWND__*HWND,无符号int nMsg,无符号整数wParam,长lParam)第257行+0x1c字节C++ AliEditor.exe!AfxWndProc(HWND__*HWND,无符号int nMsg,无符号整数wParam,长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;
    }
    

    有人能帮我吗?

    [更新] 由于现阶段没有人能帮助我,我已经将项目上传到了公共场所 here 。当我点击打开文件时,有人能下载并告诉我出了什么问题吗?

    1 回复  |  直到 13 年前
        1
  •  5
  •   Guido Simone    13 年前

    我能看到的唯一问题是你的过滤器字符串看起来不正确。看起来您的代码是基于MSDN示例之一。根据该示例,您的szFilter应该如下所示:

    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()     
    KernelBase.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/w-d/dislog/commondialogs/article.php/c1863/CFileExportDialog-Class.htm 看起来OnTypeChange的实现是基于最初的开发人员对1999年实现的Microsoft CFileDialog类的细节进行反向工程。我猜VS 2010中的内部结构已经发生了变化,所以该类不再有用。

    下次运行该程序时,请在FileExportDialog.cpp的第177行设置一个断点。当您遇到断点时,单步执行代码,观察崩溃和断言,因为过时的代码试图做它本来不应该做的事情。

    建议您转储CFileExportDialog类,并使用标准MFC CFileDialog类重写程序。