2010-06-29 13 views
3

J'utilise la fonction API SHGetSpecialFolderLocation. Mon application est définie sur "Utiliser un jeu de caractères Unicode".C++: utilisation de std :: wstring dans la fonction API

Voici ce que j'ai jusqu'à présent:

int main (int, char **) 
{ 
    LPITEMIDLIST pidl; 
    HRESULT hr = SHGetSpecialFolderLocation(NULL, CSIDL_PERSONAL, &pidl); 


    /* Confused at this point */ 
    wstring wstrPath; 

    wstrPath.resize (_MAX_PATH); 
    BOOL f = SHGetPathFromIDList(pidl, wstrPath.c_str()); 
    /* End confusion */ 

L'erreur que je reçois est:

error C2664: 'SHGetPathFromIDListW' : cannot convert parameter 2 from 'const wchar_t *' to 'LPWSTR' 

Quelqu'un peut-il aider? Quelle est la bonne façon de faire cela en C++?

Merci!

+1

Pas vraiment lié à la question, mais 'SHGetSpecialFolderLocation' /' SHGetSpecialFolderPath' est obsolète. Microsoft suggère 'SHGetKnownFolderPath' (http://msdn.microsoft.com/en-us/library/bb762188.aspx) ou, si vous voulez rester compatible avec Windows XP,' SHGetFolderPath' (http://msdn.microsoft .com/fr-fr/library/bb762181.aspx). – Philipp

Répondre

6

Le second paramètre est un sur paramètre, de sorte que vous ne pouvez pas passer c_str (qui est const) directement. Il serait probablement plus simple simplement à faire:

wchar_t wstrPath[MAX_PATH]; 
BOOL f = SHGetPathFromIDList(pidl, wstrPath); 

MAX_PATH est actuellement 260 caractères.

+1

+1. on peut aussi utiliser std :: vector pour cela et utiliser & v [0], mais quand il est assez facile d'allouer le buffer char sur la pile avec un MAX_PATH avec lequel on peut travailler, c'est la solution la plus simple et la plus rapide. – stinky472

+0

@Stinky: Vous pouvez aussi faire & wstrPath [0] aussi. Aucune raison pour laquelle vous êtes obligé d'utiliser un vecteur sur une chaîne ici. –

+0

Merci beaucoup. :) Je suis encore en train d'apprendre le C++. –

1

std::basic_string::c_str() renvoie une constante mémoire tampon à sa mémoire. Si vous souhaitez modifier la chaîne, vous auriez à faire quelque chose comme ceci:

wstring wstrPath; 
wstrPath.resize(MAX_PATH); 
BOOL f = SHGetPathFromIDList(pidl, &wstrPath[0]); 
wstrPath.erase(
    std::find(wstrPath.begin(), wstrPath.end(), L'\0'), wstrPath.end() 
); //Throw away unused buffer space 

EDIT: Cette devrait travailler aussi si vous n'êtes pas peur des bibliothèques C (bien que je ne l'ai pas testé comme je l'ai testé la mise en œuvre ci-dessus):

wstring wstrPath; 
wstrPath.resize(MAX_PATH); 
BOOL f = SHGetPathFromIDList(pidl, &wstrPath[0]); 
wstrPath.resize(wcslen(wstrPath.c_str())); 
1

wstring::c_str() retours const wchar_t* et est lecture seule. LPWSTR n'est pas un type const et ce paramètre est un paramètre de sortie. Vous devrez allouer le tampon vous-même. Vous pouvez faire quelque chose comme ceci:

wchar_t buf[MAX_PATH] = {0}; 
BOOL f = SHGetPathFromIDList(pidl, buf); 
wstring wstrPath = buf; 
+1

Pourquoi le zéro dans {} s? –

+0

Il initialise tous les éléments du tableau buf à zéro. Si la longueur de la liste d'initialisation est inférieure à la taille du tableau, les éléments restants sont initialisés à zéro, donc l'initialisation du premier élément à zéro met à zéro l'ensemble du tableau buf. –

+0

Ainsi, les accolades vides '{}' pour la même raison. (Ressuscitant un très vieux fil, je sais, n'hésitez pas à ignorer :)) –

0

wstring :: c_str() ne vous permet pas de modifier son tampon interne de cette façon. Votre meilleure solution consiste à créer un wchar_t vous-même tampon, et le passage au constructeur qui wstring:

wchar_t buf[MAX_PATH]; 
BOOL f = SHGetPathFromIDList(pidl, buf); 
wstring wstrPath(buf); 
+0

Le seul inconvénient ici est que vous finissez par copier le tampon deux fois. –

0

Vous pouvez obtenir l'adresse du 1er élément du tableau dans basic_string comme pointeur sur les données de chaîne inscriptibles. Bien que le standard C++ ne garantisse pas que ce bloc de mémoire doit être continu, il est sûr dans toutes les implémentations connues (How bad is code using std::basic_string as a contiguous buffer).

std::wstring path(_MAX_PATH, L'\0'); 
BOOL f = SHGetPathFromIDList(pidl, &path[0]);