SHGetPathFromIDListW Плчему получаю только один символ?

265
10 февраля 2019, 09:00

Нужно получить путь к папке. Использую структуру BROWSEINFO и функцию SHBrowseForFolder(). Но при выводе на экран полученного пути, выводится только первый символ. Как это исправить? Уже замучился искать.

//get directory of exe file
BROWSEINFO   bi;
LPITEMIDLIST folder = NULL;
LPMALLOC     shMalloc = NULL;
char         foldername[MAX_PATH];
char         folderpath[MAX_PATH];
string       path;
memset(&bi, 0, sizeof(bi));
CoInitialize(NULL);
SHGetMalloc(&shMalloc);
bi.hwndOwner = NULL;
bi.pidlRoot = NULL;
bi.pszDisplayName = (LPWSTR)foldername;
bi.lpszTitle = L"Выберите папку с базой данных:";
bi.ulFlags = BIF_NEWDIALOGSTYLE;
folder = SHBrowseForFolder(&bi);
if (folder)
{
    SHGetPathFromIDListW(folder, (LPWSTR)folderpath);
    shMalloc->Free(folder);
    shMalloc->Release();
    printf("Folder selected: %s\n", &folderpath);
}
Answer 1

Вызываемые вами функции формируют результирующую строку как "широкую" строку (массив wchar_t), а вы затем почему-то печатаете ее как "узкую" строку (массив char). Разумеется, напечатается ерунда.

Раз уж вы формируете "широкие" строки, то и печатать их надо как таковые

wprintf(L"Folder selected: %s\n", (LPWSTR) folderpath);

При этом возникает закономерный вопрос: раз уж вы собрались работать именно с "широкими" строками, то почему у вас все буферы для строк объявлены как состоящие из "узких" char? Из-за этого вам приходится замусоривать код явными приведениями к LPWSTR, не говоря уже о риске вылета за пределы массива. Зачем? Почему бы сразу не объявить все буферы как состоящие из wchar_t? Тогда и приведения к LPWSTR станут ненужными.

Answer 2

Проблема в том, что в коде используются как "широкие функции" (с w в конце), так и обычные (узкие). Широкие символы - это два байта. Если в них хранить символы латинского алфавита, то в отладчике это выглядит как нужные символы с нулевыми байтами. Естестенно, если такую строку попробовать распечатать "узкой" (анси) версией printf, то распечатается только один символ.

Что делать? нужно перейти на однотипные функции. Во первых, вместо char использовать TCHAR, а печатать тогда уже _tprintf

Или явно использовать wchar_t и подобное. Вот минимальная переделка, которая работает

//get directory of exe file
BROWSEINFO   bi;
LPITEMIDLIST folder = NULL;
LPMALLOC     shMalloc = NULL;
wchar_t         foldername[MAX_PATH];
wchar_t         folderpath[MAX_PATH];
std::wstring       path;
memset(&bi, 0, sizeof(bi));
CoInitialize(NULL);
SHGetMalloc(&shMalloc);
bi.hwndOwner = NULL;
bi.pidlRoot = NULL;
bi.pszDisplayName = (LPWSTR)foldername;
bi.lpszTitle = L"Выберите папку с базой данных:";
bi.ulFlags = BIF_NEWDIALOGSTYLE;
folder = SHBrowseForFolder(&bi);
if (folder)
{
    SHGetPathFromIDListW(folder, (LPWSTR)folderpath);
    shMalloc->Free(folder);
    shMalloc->Release();
    wprintf(L"Folder selected: %s\n", folderpath);
}
READ ALSO
Qt-QString в int

Qt-QString в int

Как конвертировать:

225
Передача полей класса в методы класса

Передача полей класса в методы класса

Для большей читабельности кода пришел к мысли что хорошо бы передавать поля класса в методы класса явноТ

267
Не могу придумать абстракцию для класса

Не могу придумать абстракцию для класса

Задание у меня следующееЕсть класс часы и в нем содержится статическое поле "часовой пояс"

247