我维护的一个工具,有一个参考VCKbase网站上的资料,生成一个win2000风格的文件选择对话框功能。在之前使用的都是好好的。后来有人反馈会自动退出,没有任何其他反馈提示信息。我实地察看了一下,现象很奇怪。当对话框选择路径为桌面的时候,就一定会自动退出。非桌面路径选择的时候,不会出现。 我仔细观察了她的使用环境,桌面上图标很多。那么这是原因之一了。在自己机器桌面图标很少的情况下,出现异常退出的概率确实减小很多。但是这并不能表明问题解决了。开始,我怀疑是不是这个从网上拷贝下来的对话框类本身有什么问题。经过在网上查找资料和比对,确定应该代码是没有问题的。后来看到有人说是OPENFILENAMEEX变量的问题,如果设置了#define _WIN32_WINNT 0x0501后会导致异常退出。在CFileDialog 的构造函数中可以看到:
m_ofn.lStructSize = sizeof(m_ofn);
这个句话已经被编译在mfc42.dll里,也就是说,不管你定义没有定义#define _WIN32_WINNT 0x0501它的大小都是一样大的,从MSDN可看到:
typedef struct tagOFN { DWORD lStructSize; HWND hwndOwner; HINSTANCE hInstance; LPCTSTR lpstrFilter; LPTSTR lpstrCustomFilter; DWORD nMaxCustFilter; DWORD nFilterIndex; LPTSTR lpstrFile; DWORD nMaxFile; LPTSTR lpstrFileTitle; DWORD nMaxFileTitle; LPCTSTR lpstrInitialDir; LPCTSTR lpstrTitle; DWORD Flags; WORD nFileOffset; WORD nFileExtension; LPCTSTR lpstrDefExt; LPARAM lCustData; LPOFNHOOKPROC lpfnHook; LPCTSTR lpTemplateName; #if (_WIN32_WINNT >= 0x0500) void * pvReserved; DWORD dwReserved; DWORD FlagsEx; #endif // (_WIN32_WINNT >= 0x0500) } OPENFILENAME, *LPOPENFILENAME; 有可能两个大小不一致,导致内存越界发生。但是我仔细看了我的代码,和这个人所描述的情况并不相同。 继续在网上搜索相关资料。发现有人说和某些系统补丁有关,并推荐阅读此资料:http://support.microsoft.com/default.aspx?scid=kb;en-us;909486 。 看英文是件难受的事情,更难受的事情是看完后发现仍然无法解决自己的问题。在CSDN论坛上有人说用
解决了该问题,报着死马当活马医的心态我测试了一下。果然还就解决了问题。想到说,问题虽然暂时解决了,但找不到根源毕竟底气不足。 于是我继续查找相关资料。在google上用"CFileDialog和AfxOleInit"作为关键字搜索,还真让我找到了点眉目。 比较合理的解释: 是由于Adobe Reader 7.0及以上版本的pdfshell.dll文件在XP SP2的环境下需要使用COM环境。但可能因为其自身的原因或是操作系统的某个 缺陷,导致异常发生。于是程序自动退出了。而AfxOleInit的工作正式对COM环境进行一个初始化操作,避免了该问题的发生。在后面测试中 我将Adobe Reader7.0卸载后,问题不再出现。安装Adobe Reader7.0之后,在我的代码开始处加上AfxOleInit()语句,也没有再自动退出。 自此该问题应该得到解决。后面分析可能也跟我设置打开对话框风格设置为Explorer有一定的关系,但暂未验证。AfxOleInit();