-1

さて、私はこれに 2 日間対処してきましたが、解決策が見つかりません。

問題: Winapi を使用してファイル選択ダイアログにフィルターを設定しようとしています。GetOpenFileNameこれを行うために関数を使用しています。この関数は、構造体を使用して、ファイル拡張子フィルターなどのオプションを設定します。呼び出されるこの構造体のメンバーにlpstrFilterは、特定の文字列形式が必要です。Winapi が示すとおりにその文字列を設定していますが、何らかの理由でこの文字列の値が変更されます。

私はこのstatic 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 を表示する必要がある理由です。この質問も、あなたが 1 週間前に尋ねた質問と重複しているようです: 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 に答える