zoukankan      html  css  js  c++  java
  • 慎用GetOpenFileName

    这两天发现了一个小问题,经过一上午的排查终于找到了问题的原因——Windows 7API函数GetOpenFileName竟然有BUG

    请参考下面的MFC代码:

    CFileDialog dlg(TRUE);

    dlg.m_ofn.lpstrInitialDir = _T("c:\");

    dlg.DoModal();

    这段代码的含义是通过"文件选择对话框"选择一个文件,并且"文件选择对话框"的初始目录是C:

    使用VC++2010编译上面的代码,在64Windows 7上的运行结果一切正常——"文件选择对话框"的初始目录一定是C:

    使用VC++6.0编译上面的代码,在64Windows 7上的运行结果为:"文件选择对话框"的初始目录并不一定是C:,而是上次选择文件的目录!

    查看MFC代码,就知道问题的所在了:VC++6.0CFileDialog会调用GetOpenFileNameGetSaveFileName打开"文件选择对话框";而VC++2010会判断Windows的版本。如果是Vista以下(不含Vista)版本则会调用GetOpenFileNameGetSaveFileName;如果是Vista以上(含Vista)版本则会通过COM接口IFileOpenDialogIFileSaveDialog打开"文件选择对话框"。

    为了验证GetOpenFileName函数的正确性,特编写了如下代码:

    TCHAR                szFile[MAX_PATH] = {''};

    OPENFILENAME    ofn;

    memset(&ofn,0,sizeof(ofn));

    ofn.lStructSize        =    sizeof(ofn);

    ofn.lpstrFile        =    szFile;

    ofn.nMaxFile        =    MAX_PATH;

    ofn.lpstrInitialDir    =    _T("c:\");

    ofn.Flags        =    OFN_HIDEREADONLY | OFN_EXPLORER

                |    OFN_ENABLESIZING;

    GetOpenFileName(&ofn);

    使用VC++2010编译上面的代码,执行结果也不正常了:"文件选择对话框"的初始目录并不一定是C:,而是上次选择文件的目录!这说明:在Windows 7操作系统下,GetOpenFileName函数未能识别参数ofn.lpstrInitialDir,这应该是一个BUG

    结论:VC++6.0MFCCFileDialog通过GetOpenFileNameGetSaveFileName显示"文件选择对话框"。但是这两个函数在Windows 7的实现有BUG,导致初始目录不是设定的值。解决这个问题有两个办法:一是舍弃VC++6.0,改用VC++2010。这样处理最简单,美中不足就是程序只能运行在Windows XP及其以上版本的Windows下,无法在Windows 98/Me/2000上运行;二是改进VC++2010CFileDialog代码,使得VC++6.0能够编译、使用。

    另一个BUG:在Windows 7上使用GetOpenFileName选择一个文件后,该文件所在目录即被锁定。目录被锁定就无法被删除了,退出整个程序后目录锁定才会被解除。

  • 相关阅读:
    Linux 常用命令
    silky微服务简介
    okhttp中的Builder模式
    Assert in C#&Java
    Abstract类中使用@Autowire
    @Scope("prototype") bean scope not creating new bean
    【转】centos系统查看cpu内存等情况
    hdu 7013 String Mod 题解
    牛客 11259 H Scholomance Academy 题解
    bzoj 2151 种树 题解
  • 原文地址:https://www.cnblogs.com/hanford/p/6164507.html
Copyright © 2011-2022 走看看