I have the SHBrowseForFolder to popup and work fine, but I would like to set the Title. I know it has to be a wchar_t* and when I use a const like (wchar_t*)L"My Title" the title is shown correct.
But if I try to use a String value I only get the first letter 'M', it's like the wide string has been converted to new wide string once again, pading each character with a 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();
}
}
The documentation for UnicodeString all conversion functions c_str()
,t_str()
and w_str()
all returns a wchar_t*
but the declaration shows WideChar*
.
Any ideas how to make this code work together with a String?
The fact that you are type-casting your bi
variable to a _browseinfoA*
when calling SHBrowseForFolder()
tells me that the "_TCHAR maps to" option in your Project Options is set to "char" instead of "wchar_t". That means your code is actually calling SHBrowseForFolderA()
instead of SHBrowseForFolderW()
. In XE2, the Winapi::Shlobj::BROWSEINFO
structure always maps to ::BROWSEINFOW
, regardless of the _TCHAR setting. BROWSEINFOW
is a Unicode structure, not an ANSI structure. So you are forcing Unicode data to be passed to an Ansi function. Yes, there is extra padding that is truncating the data, because you are passing the wrong data in the first place.
You need to stop using type-casts. They are hiding errors in your code that the compiler would normally have complained about. C/C++ is a strongly typed language. Using type-casts bypasses the compiler's data type validations.
To fix your code, you need to either:
1) use the generic BROWSEINFO
structure from the global namespace instead of the Winapi::Shlobj
namespace, so it matches the encoding of the generic SHBrowseForFolder()
function:
::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) continue using BROWSEINFO
from the Winapi::Shlobj
namespace but call SHBrowseForFolderW()
directly instead to match the Unicode encoding:
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);
}
On a separate note, regardless of which approach you take, you cannot use a temporary String
as the Title value. The String
will go out of scope before SHBrowseForFolder()
is called, leaving the BROWSEINFO::lpszTitle
field pointing at invalid memory. If you want to use a String
then you need to use a local variable for it, eg:
String sTitle = "My Title";
...
bi.lpszTitle = sTitle.c_str();