0

我有 SHBrowseForFolder 弹出并工作正常,但我想设置标题。我知道它必须是 wchar_t* 并且当我使用像 (wchar_t*)L"My Title" 这样的 const 时,标题显示正确。

但是如果我尝试使用字符串值,我只会得到第一个字母“M”,就像宽字符串再次转换为新的宽字符串一样,用 nul 填充每个字符。

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()返回一个wchar_t*但声明显示WideChar*

任何想法如何使此代码与字符串一起工作?

4

1 回答 1

2

您在调用时将bi变量类型转换为 a 的事实告诉我,您的项目选项中的“_TCHAR 映射到”选项设置为“char”而不是“wchar_t”。这意味着您的代码实际上是在调用而不是. 在 XE2中,无论 _TCHAR 设置如何, 结构总是映射到。是Unicode结构,而不是ANSI结构。因此,您强制将 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命名Winapi::Shlobj空间,但SHBrowseForFolderW()直接调用以匹配 Unicode 编码:

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 值。将在调用String之前超出范围SHBrowseForFolder(),使BROWSEINFO::lpszTitle字段指向无效内存。如果你想使用 aString那么你需要为它使用一个局部变量,例如:

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