2012-01-13 215 views
2

在Windows 7或Vista上运行的MFC Windows应用程序中使用Common Item对话框时,我面临一些奇怪的问题(至少对我而言)。在Windows 7上使用IFileDialog的问题

按照MSDN http://msdn.microsoft.com/en-us/library/windows/desktop/bb776913(v=vs.85).aspx我使用新接口来显示文件打开和保存对话框:

bool OpenFileDialog(CString& strFile, CString strTitle, CStringArray& astrFilter, CStringArray& astrFilterExtension, ULONG nFlags, HWND hParentWnd) 
{ 
USES_CONVERSION; 

INT_PTR nResult = 0; 
INT_PTR nFilterCount = astrFilter.GetCount(); 

IFileDialog* pfod = 0; 
HRESULT hr = ::CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfod)); 

if(SUCCEEDED(hr)) 
{ 
    // New dialog starting with Vista/Windows 7 
    COMDLG_FILTERSPEC* pOpenTypes = 0; 

    if((nFilterCount > 0) && (nFilterCount == astrFilterExtension.GetCount())) 
    { 
     pOpenTypes = new COMDLG_FILTERSPEC[nFilterCount]; 

     for(int nIdx = 0; nIdx < nFilterCount; nIdx++) 
     { 
      pOpenTypes[nIdx].pszName = astrFilter[nIdx].GetBuffer(); 
      pOpenTypes[nIdx].pszSpec = astrFilterExtension[nIdx].GetBuffer(); 
     } 
    } 

    // Set the file types to display. 
    if(pOpenTypes) 
    { 
     hr = pfod->SetFileTypes(nFilterCount, pOpenTypes); 

     if(SUCCEEDED(hr)) 
      hr = pfod->SetFileTypeIndex(0); 
    } 

    if(!strFile.IsEmpty()) 
     pfod->SetFileName(strFile); 

    if(!strTitle.IsEmpty()) 
     pfod->SetTitle(strTitle); 

    if(SUCCEEDED(hr)) 
    { 
     // Ensure the dialog only returns file system paths. 
     DWORD dwFlags; 
     hr = pfod->GetOptions(&dwFlags); 

     if(SUCCEEDED(hr)) 
     { 
      dwFlags |= FOS_FORCEFILESYSTEM; 

      if(nFlags & OFN_FILEMUSTEXIST) 
       dwFlags |= FOS_FILEMUSTEXIST; 

      if(nFlags & OFN_PATHMUSTEXIST) 
       dwFlags |= FOS_PATHMUSTEXIST; 

      hr = pfod->SetOptions(dwFlags); 

      if(SUCCEEDED(hr)) 
      { 
       // Create an event handling object, and hook it up to the dialog. 
       IFileDialogEvents* pfde = NULL; 
       DWORD dwCookie; 

       // Actually only added for debugging purposes 

       /*hr = CDialogEventHandler_CreateInstance(IID_PPV_ARGS(&pfde)); 

       if(SUCCEEDED(hr)) 
       { 
        // Hook up the event handler. 
        hr = pfod->Advise(pfde, &dwCookie); 

        if(!SUCCEEDED(hr)) 
        { 
         pfde->Release(); 
         pfde = 0; 
        } 
       }*/ 

       // Now show the dialog. Usually called with hParent == 0 
       if(hParentWnd) 
        hr = pfod->Show(::GetWindow(hParentWnd, GW_OWNER)); 
       else 
        hr = pfod->Show(0); 

       // do something with the path when the dialog was closed... 

所以出现的对话框中,如果我要选择一个正常的驱动文件工作正常。我可以浏览文件夹并选择任何我想要的文件。在离开对话框时我也会得到正确的文件信息。

但它不适用于左侧导航窗格中的某个库。每当我尝试选择文档,视频或图片等库时,对话框不会更新显示文件夹/库内容的右窗格。

我注意到,在文件打开/保存对话框中单击库时,IFileDialogEvents接口的OnFolderChanging()事件被触发,但OnFolderChange()和OnSelectionChange()不是。如果我点击并导航像“C”这样的“普通”驱动器,则会触发这些事件。我也尝试在InitInstance方法的早期调用对话框以避免可能的副作用,但是这并不能帮助您无论是。

有没有人有同样的行为,并能够解决这个问题?

非常感谢!

+0

你准确设置了哪些选项?你可以在'CoCreateInstance()'和'Show()'之间显示你的完整代码吗? – 2012-01-13 21:09:48

+0

@ RemyLebeau-TeamB嗨,我在调用Show()之前添加了代码,感谢您的关注! – Fluffi1974 2012-01-14 12:33:40

+0

自从至少VS2008以来,这在MFC中已得到很好的支持,其中包括来自OFN标志的映射。保持你的工具更新,以避免编写这样的代码。 – 2012-01-14 13:30:03

回答

1

所以我终于找到了这个问题的答案。为应用程序创建新的MFC项目是解决此问题的实际提示。原因是“堆栈储备规模”太大。旧VS6.0项目中的设置将堆栈大小增加到100MB以上。显然,当保留的堆栈大小太大时,基于IFileDialog的对话框不能正常工作(其他的东西也可能无法按预期工作)。所以我不得不将它重新设置为15MB。