【问题标题】:Winapi GetOpenFileName Extension Filter not workingWinapi GetOpenFileName 扩展过滤器不起作用
【发布时间】:2015-12-04 16:03:11
【问题描述】:

我正在尝试将文件的扩展名过滤器应用于文件的选择对话框。

这种方式有效:

ofn.lpstrFilter =   
"(*.exe) Windows Executable\0*.exe\0"
"(*.ini) Windows Initialization file \0*.ini\0"
"(*.dll) Dynamic Link Library \0*.dll\0"
"(*.lib) Windows Library file \0*.lib\0"
"(*.conf) Windows Configuration file \0*.conf\0";

但是当我通过参数动态分配扩展过滤器时,它会失败,过滤器不会出现在组合框中:

LPCSTR filter = (LPCSTR)extFilter; //Contains string "bmp"

stringstream s;
s << "(*.exe) Windows Executable\0" << "*." << filter << "\0";
string ffilter = s.str();
ofn.lpstrFilter = ffilter.c_str();

我假设问题出在字符串转换中,但无法弄清楚。

【问题讨论】:

  • 未测试,我猜分隔符'\0' 可能会对stringstream 造成伤害。如果是这样,使用另一个字符例如$作为分隔符如何,在构建完过滤器后,将字符串复制到char的数组中并将$s转换为'\0'
  • 您是否尝试过在调试器中查看ffilter 以查看其中包含的内容?
  • 这里有什么消息吗?人们在等待...... :)

标签: c++ function winapi std getopenfilename


【解决方案1】:

这一行:

s << "(*.exe) Windows Executable\0" << "*." << filter << "\0";

正在将空终止的char* 字符串传递给operator&lt;&lt;(),因此在运行时的行为实际上与此代码相同:

s << "(*.exe) Windows Executable" << "*." << filter << "";

空值永远不会进入s

要正确插入空值,您需要将它们分配给 stringstream 作为单独的 char 值,而不是作为 char* 值:

s << "(*.exe) Windows Executable" << '\0' << "*." << filter << '\0';

此外,您正在对extFilter 进行类型转换这一事实令人怀疑。如果您必须这样做以消除编译器错误,那么extFilter 一开始就不是兼容的数据类型,类型转换隐藏了代码中的错误。摆脱类型转换:

LPCSTR filter = extFilter; //Contains string "bmp"

如果代码编译失败,那么你做错了什么,需要正确修复它。

另一方面,如果extFilter 是一个以空结尾的char 字符串开头,则无需在将其传递给operator&lt;&lt;() 之前将其分配给变量:

s << "(*.exe) Windows Executable" << '\0' << "*." << extFilter << '\0';

【讨论】:

    【解决方案2】:

    您正在使用指向某个临时字符串的指针,根据http://www.cplusplus.com/reference/string/string/c_str/,“可能会因进一步调用修改对象的其他成员函数而失效。”

    【讨论】:

    • “任何进一步的方法调用”不太可能,因为可能没有。更有可能是临时字符串流本身超出范围并被释放。
    • 暂不涉及。 stringstream 内容被分配给 string 变量,该变量在对话框关闭之前一直保持在范围内。
    • @RemyLebeau - 这是一个很好的猜测,但我没有在发布的片段中看到对对话框的调用。
    • @VladFeinstein:我们可以清楚地看到正在使用的OPENFILENAME 变量,并且我们知道它必须保持在范围内,直到对话框关闭。我们可以看到过滤器被分配给本地string 变量,然后该变量被分配给OFN 变量。因此,除非string 变量在花括号内且OFN 变量在花括号外,否则string 数据在对话调用期间在范围内。
    • @RemyLebeau - 如果问题仅出在 0 分隔符上,正如您在回答中建议的那样,OP 可能会得到一个不完整的过滤器,从 (*.exe) Windows Executable 开始,但不是垃圾第一个字节。
    【解决方案3】:

    终于找到答案了:

    const char * extensionFilter = myParamVar; //Contains "JPG" string
    
    string sFilter;
    sFilter.append("Format: ");
    sFilter.append(extensionFilter);
    sFilter.push_back('\0');
    sFilter.append("*.");
    sFilter.append(extensionFilter);
    sFilter.push_back('\0');
    
    //Current filter content --> Format: JPG\0*.JPG\0
    
    const char * filter = sFilter.c_str(); //Char string conversion
    ofn.lpstrFilter = filter; //Set the filter to the sctructure's member.
    
    //Opens the dialog and it successfully applies the filter.
    if (GetOpenFileName(&ofn)==TRUE){
    . . .
    

    【讨论】:

      【解决方案4】:

      更短的版本:

      ofn.lpstrFilter = _T("Format: XML\0*.xml\0");
      

      【讨论】:

        猜你喜欢
        • 2011-10-31
        • 1970-01-01
        • 2014-05-09
        • 2021-05-21
        • 1970-01-01
        • 1970-01-01
        • 2018-04-22
        • 2021-06-12
        • 2011-06-16
        相关资源
        最近更新 更多