0

SHBrowseForFolder をポップアップして正常に動作させていますが、タイトルを設定したいと思います。wchar_t* でなければならないことはわかっていますが、(wchar_t*)L"My Title" のような const を使用すると、タイトルが正しく表示されます。

しかし、文字列値を使用しようとすると、最初の文字「M」しか得られません。これは、ワイド文字列が新しいワイド文字列に再度変換され、各文字がヌルで埋められたようなものです。

Winapi::Shlobj::BROWSEINFO bi = {0};
bi.hwndOwner = Handle;
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_EDITBOX | BIF_BROWSEFORCOMPUTER;
bi.lpszTitle = String("My Title").w_str(); // This only shows the 'M'
//bi.lpszTitle = (wchar_t*)"My Title";       // This shows the full string 'My Title'
LPITEMIDLIST pidl = SHBrowseForFolder((_browseinfoA*)&bi);

if ( pidl != 0 ) {

  // free memory used
  IMalloc *imalloc = 0;
  if (SUCCEEDED(SHGetMalloc(&imalloc))) {
    imalloc->Free(pidl);
    imalloc->Release();
  }
}

UnicodeStringのドキュメントには、すべての変換関数c_str()t_str()あり、w_str()すべてが a を返しますwchar_t*が、宣言にはWideChar*.

このコードを文字列と連携させる方法はありますか?

4

1 に答える 1

2

呼び出し時にbi変数を aに型キャストしているという事実は、プロジェクト オプションの「_TCHAR マップ先」オプションが「wchar_t」ではなく「char」に設定されていることを示しています。これは、コードが実際にの代わりに呼び出していることを意味します。XE2 では、_TCHAR の設定に関係なく 、構造体は常に にマップされます。ANSI構造ではなく、Unicode構造です。したがって、Unicode データを強制的に Ansi 関数に渡す必要があります。はい、そもそも間違ったデータを渡しているため、データを切り捨てる余分なパディングがあります。_browseinfoA*SHBrowseForFolder()SHBrowseForFolderA()SHBrowseForFolderW()Winapi::Shlobj::BROWSEINFO::BROWSEINFOWBROWSEINFOW

型キャストの使用をやめる必要があります。これらは、コンパイラーが通常文句を言うであろうコード内のエラーを隠しています。C/C++ は厳密に型指定された言語です。型キャストを使用すると、コンパイラのデータ型の検証がバイパスされます。

コードを修正するには、次のいずれかを行う必要があります。

1)BROWSEINFO名前空間の代わりにグローバル名前空間のジェネリック構造を使用して、ジェネリック関数Winapi::Shlobjのエンコーディングと一致させます。SHBrowseForFolder()

::BROWSEINFO bi = {0}; 
bi.hwndOwner = Handle; 
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_EDITBOX | BIF_BROWSEFORCOMPUTER; 
bi.lpszTitle = TEXT("My Title");
LPITEMIDLIST pidl = SHBrowseForFolder(&bi); 
if ( pidl != NULL ) { 
    // free memory used 
    CoTaskMemFree(pidl); 
} 

2)名前空間BROWSEINFOから引き続き使用しますが、代わりに直接呼び出して Unicode エンコーディングに一致させます。Winapi::ShlobjSHBrowseForFolderW()

Winapi::Shlobj::BROWSEINFO bi = {0};  
bi.hwndOwner = Handle;  
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_EDITBOX | BIF_BROWSEFORCOMPUTER;  
bi.lpszTitle = L"My Title";
LPITEMIDLIST pidl = SHBrowseForFolderW(&bi);  
if ( pidl != NULL) {  
    // free memory used  
    CoTaskMemFree(pidl);  
}

String別の注意として、どちらの方法を使用しても、一時を Title 値として使用することはできません。StringwillSHBrowseForFolder()が呼び出される前に範囲外になり、フィールドBROWSEINFO::lpszTitleが無効なメモリを指すようになります。a を使用するString場合は、ローカル変数を使用する必要があります。たとえば、次のようになります。

String sTitle = "My Title";
...
bi.lpszTitle = sTitle.c_str();
于 2012-09-10T22:19:05.170 に答える