Fenêtre choix de répertoire.

Afficher la fenêtre standard Windows qui propose de choisir un répertoire.

SHBrowseForFolder

Voir version :

Pas de dépendances

Télécharger :

#include <windows.h>
#include <tchar.h>
#include <shlobj.h>
#include <stdio.h>

int CALLBACK BrowseForFolderCallback(HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData)
{
    TCHAR szPath[MAX_PATH+1];
    switch(uMsg)
    {
    case BFFM_INITIALIZED:
        SendMessage(hwnd, BFFM_SETSELECTION, TRUE, pData);
        break;
    case BFFM_SELCHANGED: 
        if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szPath)) 
        {
            SendMessage(hwnd, BFFM_SETSTATUSTEXT,0,(LPARAM)szPath);    
        }
        break;
    }
    return 0;
}

BOOL BrowseFolders(HWND hwnd, LPTSTR lpszFolder, LPTSTR lpszTitle)
{
    BROWSEINFO bi;
    LPITEMIDLIST pidl;
    bi.hwndOwner = hwnd;
    bi.pidlRoot = NULL;
    bi.pszDisplayName = NULL;
    bi.lpszTitle = lpszTitle;
    bi.ulFlags = BIF_STATUSTEXT;
    bi.lpfn = BrowseForFolderCallback;
    bi.lParam = (LPARAM)lpszFolder;
    pidl = SHBrowseForFolder(&bi);
    if (pidl)
    {
        if (SHGetPathFromIDList(pidl,lpszFolder)) 
        {
            return TRUE;
        }
    }
    return FALSE;
}

int main()
{
    TCHAR rep[MAX_PATH+1];
    if (!BrowseFolders(NULL,rep,_T("Choix du repertoire")))
        printf("Annule\n");
    else
        _tprintf(_T("Choisi : %s\n"),rep);
    return 0;
}



Commentaires


Voici un petit tuto pour afficher une fenetre qui choisi un repertoire.

Avant tout, essayez le. Vous choisissez le repertoire, et, soit vous appuyez sur Annuler et le programme vous le dit,
soit vous choisissez un repertoire, et le programme marque votre choix.

Regardons le code :

J'inclus shlobj.h pour la fonction SHBrowseForFolder que nous verrons plus loin.
Je cree une chaine de taille MAX_PATH+1, qui accueillera mon futur repertoire choisi. MAX_PATH est une constante définie dans windef.h (sous windows.h)

Puis j'appelle ma fonction BrowseFolders, en passant NULL, le repertoire choisi, et un titre.

Dans ma fonction BrowseFolders, je remplis une structure BROWSEINFO.
Dedans, je mets, entre autre :

bi.hwndOwner = hwnd;

Dans mon cas, j'ai passé NULL, c'est a dire que j'admet que ma fenetre de choix de repertoire n'appartiendra a personne, et pourra se ballader n'importe ou.
Si j'avais mis l'identifiant de fenetre d'une autre fenetre, la fenetre aurait été en dessous, et ne pourrait pas sortir.

bi.lpszTitle = lpszTitle;

Le titre que j'ai passé : vous retrouverez ce titre dans la fenetre de choix : si vous changez la phrase dans le main, vous voyez donc ou ça change.

Pour savoir a quoi peuvent servir les autres champs de la structure, voir cette page.
http://msdn2.microsoft.com/en-us/library/bb773205(VS.85).aspx
(vous pouvez voir qu'on peut aussi choisir une imprimante grace au flag BIF_BROWSEFORPRINTER par exemple)

Dans les flags, j'ai choisi de mettre BIF_STATUSTEXT, c'est a dire que j'active volontairement l'affichage du chemin en cours (quand vous cliquez sur un dossier,
vous voyez se mettre a jour, en dessous du titre, le chemin : c'est grace a ce flag que ce champ existe)
et c'est aussi grace a la fonction callback qu'il se met a jour.
En effet, je met également :

bi.lpfn = BrowseForFolderCallback;

Ici, ce que je donne, c'est une FONCTION callback qui sera appelée a chaque evenement sur ma fenetre de choix.

Puis je lance la fonction SHBrowseForFolder, qui va gérer le choix en question.
sa doc :
http://msdn2.microsoft.com/en-us/library/bb762115(VS.85).aspx



la fonction Callback :
**********************

Dans cette fonction d'evenements, juste au dessus, j'ai activé 2 evenements :
BFFM_INITIALIZED : evenement lancé lorsque la fenetre apparait
BFFM_SELCHANGED : evenement lancé lorsque je selectionne un repertoire.

Dans le BFFM_INITIALIZED, j'initialise la zone de texte BFFM_SETSELECTION (celle réservée pour afficher le chemin) en lui envoyant un message.
Voici les différents messages que l'on peut envoyer pour compléter :

http://msdn2.microsoft.com/fr-fr/library/ms675173(en-us,VS.85).aspx

L'event BFFM_SELCHANGED est généré quand on change de repertoire : le but est de mettre a jour l'affichage du chemin dans la fenetre.
Donc quand je reçois cet event, je vais convertir le param lp (voir la doc ci dessus), 
qui sera une LPITEMIDLIST (structure utilisée par  SHBrowseForFolder), en chaine normale, grace a la fonction SHGetPathFromIDList.
Il ne me restera plus qu'a envoyer comme mesasge a BFFM_INITIALIZED la chaine en question pour qu'il l'affiche.
-> si vous desactivez ce case de switch, l'affichage des repertoires en dessous du titre ne se fera plus.



Lorsque vous validez (ou annulez), vous sortez de la fonction SHBrowseForFolder, qui vous retourne un pointeur sur une structure ITEMIDLIST 
(LP = long pointer : LPITEMIDLIST <=> ITEMIDLIST* )
Si ce pointeur est NULL, c'est que vous avez appuyé sur annluer (d'ou le if : si vous n'entrez pas dans le if, c'est que vous avez un pointeur NULL)
Si je n'entre pas dans le if, je renvoie donc false
Si je rentre, je recupere mon chemin en tant que chaine dans mon parametre lpszFolder, qui est le rep du main, depuis le LPITEMIDLIST, via la fonction
SHGetPathFromIDList, et je retourne TRUE.

Le main est alors simplissime : si je reçois FALSE, c'est que vous avez appuyé sur annuler, sinon, j'affiche le chemin reçu.