-1

好的,我已经处理了两天了,我找不到解决方案。

问题:我正在尝试使用 Winapi为文件选择对话框设置过滤器。我正在使用GetOpenFileName函数来做到这一点。此函数使用结构来设置选项,例如文件扩展名过滤器。这个结构的成员调用lpstrFilter需要一定的字符串格式。我完全按照 Winapi 的指示设置该字符串,但由于某种原因,该字符串的值发生了变化。

我有这个静态 const char *

//This contains string "JPG"
static const char * extensionFilter = v->trabajo10.C_JMV_SelectFile_FileExtension7.GetString();

//This forms a filter string which applies to OPENFILENAME structure.
string sFilter;
sFilter.append("Format: ");
sFilter.append(extensionFilter);
sFilter.push_back('\0');
sFilter.append("*.");
sFilter.append(extensionFilter);
sFilter.push_back('\0');
const char * filter = sFilter.c_str();
ofn.lpstrFilter = filter; //This sets: --> Format: JPG\0*.JPG\0

//This opens the file selection dialog
if (GetOpenFileName(&ofn)==TRUE){
...

文件选择对话框看起来正确,如下所示:

在此处输入图像描述

笑话来了,我这样修改代码:

//This contains string "JPG"
static const char * extensionFilter = v->trabajo10.C_JMV_SelectFile_FileExtension7.GetString();

if(1){
   //This forms a filter string which applies to OPENFILENAME structure.
   string sFilter;
   sFilter.append("Format: ");
   sFilter.append(extensionFilter);
   sFilter.push_back('\0');
   sFilter.append("*.");
   sFilter.append(extensionFilter);
   sFilter.push_back('\0');
   const char * filter = sFilter.c_str();
   ofn.lpstrFilter = filter; //This sets: --> Format: JPG\0*.JPG\0
}

//This opens the file selection dialog
if (GetOpenFileName(&ofn)==TRUE){
...

这就是结果,问题

在此处输入图像描述

过滤器字符串被修改???

4

3 回答 3

5
if(1){
   //This forms a filter string which applies to OPENFILENAME structure.
   string sFilter;
   sFilter.append("Format: ");
   sFilter.append(extensionFilter);
   sFilter.push_back('\0');
   sFilter.append("*.");
   sFilter.append(extensionFilter);
   sFilter.push_back('\0');
   const char * filter = sFilter.c_str();
   ofn.lpstrFilter = filter; //This sets: --> Format: JPG\0*.JPG\0
}

变量的sFilter生命周期在它声明的块结束时结束。返回的指针在被修改或销毁sFilter.c_str()之前是有效的。sFilter

您在此指针失效后使用它。这与您昨天遇到的问题相同,我在对该问题的评论中猜到了。这就是为什么您需要展示完整的 MCVE。这个问题看起来也与您一周前提出的问题重复:Winapi GetOpenFileName Extension Filter not working。我建议您花一些时间来确保您完全理解c_str().

您必须确保sFilter在您使用完指针之前一直存在。sFilter在外部块中声明以确保这一点。

于 2015-12-11T12:47:19.173 回答
2

问题是您有一个超出范围的变量

if(1){
   string sFilter;

   // ... code

   // Right here
   const char * filter = sFilter.c_str();      
   ofn.lpstrFilter = filter;
}

在该块结束后filter超出范围,ofn.lpstrFilter悬空指针也是如此。

于 2015-12-11T12:47:42.447 回答
0

回答 ProtectedVoid 对声明未使用对象的担忧:想象 astd::string是一个昂贵的对象,而且这种情况不太可能发生。除非条件为真,否则您不希望构造对象。但它必须持续超出条件的范围。unique_ptr所以我们使用默认构造比默认构造便宜得多的事实string

std::unique_ptr<std::string> scope_extender;
if( something unlikely ){
       //This forms a filter string which applies to OPENFILENAME structure.
       std::string* sFilter = new std::string;
       scope_extender.reset( sFilter );
       sFilter->append("Format: ");
       sFilter->append(extensionFilter);
       sFilter->push_back('\0');
       sFilter->append("*.");
       sFilter->append(extensionFilter);
       sFilter->push_back('\0');
       const char * filter = sFilter->c_str();
       ofn.lpstrFilter = filter; //This sets: --> Format: JPG\0*.JPG\0
    }

显然,我不想暗示std::string建造成本足够昂贵,值得所有麻烦。但是在类似情况下的某些对象可能是。此外,还有一个评论是关于如果在一个条件中有许多次要对象怎么办。在这种情况下,您需要一个实用程序结构将它们全部保存在一起,并且 unique_ptr 有条件地拥有该结构。

于 2015-12-11T14:44:22.937 回答