Interfaces IShellFolder & IEnumIDList
Publié : mer. 02/juin/2004 19:29
Je ne crois pas que c'est un truc ou astuce mais je ne sais pas ou poster cet exemple.
J'ai passé un certain nombre d'heure sur ce code et aussi sur la saine lecture de la dos MS (
)
Avec les interfaces, rien n'est vraiment simple de prime abord...
J'ai passé un certain nombre d'heure sur ce code et aussi sur la saine lecture de la dos MS (

Avec les interfaces, rien n'est vraiment simple de prime abord...
Code : Tout sélectionner
; Auteur : Denis
; Version de PB : 3.91
; Date : 02 juin 2004
; Testé sous WIN98 SE
;
; Explication du programme :
; Utilisation des interfaces IShellFolder et IEnumIDList pour afficher le contenu
; du dossier 'SEND TO' (envoyer vers) pour cet exemple
;- Constantes utilisateur
#Fenetre = 0
; constantes possibles utilisables par la méthode EnumObjects de l'interface IShellFolder
#SHCONTF_FOLDERS = $0020
#SHCONTF_NONFOLDERS = $0040
#SHCONTF_INCLUDEHIDDEN = $0080
#SHCONTF_INIT_ON_FIRST_NEXT = $0100
#SHCONTF_NETPRINTERSRCH = $0200
#SHCONTF_SHAREABLE = $0400
#SHCONTF_STORAGE = $0800
; constantes possibles utilisables par la méthode GetDisplayNameOf de l'interface IShellFolder
#SHGDN_NORMAL = $0000
#SHGDN_INFOLDER = $0001
#SHGDN_FOREDITING = $1000
#SHGDN_FORADDRESSBAR = $4000
#SHGDN_FORPARSING = $8000
; constantes possibles pour le paramètre uType de la structure STRRET
#STRRET_WSTR = 0
#STRRET_OFFSET = 1
#STRRET_CSTR = 2
; quelques constantes possibles pour l'API SHGetSpecialFolderLocation
#CSIDL_DESKTOP = 0
#CSIDL_PRINTERS = 4
#CSIDL_RECENT = 8
#CSIDL_SENDTO = 9
#CSIDL_STARTMENU = 11
#CSIDL_FONTS = 14
; constantes possibles pour l'API CoInitializeEx
#COINIT_MULTITHREADED = 0
#COINIT_APARTMENTTHREADED = 2
#COINIT_DISABLE_OLE1DDE = 4
#COINIT_SPEED_OVER_MEMORY = 8
;- Structure
Structure STRRET
uType.l
StructureUnion
pOleStr.l
uOffset.l
cStr.b[#MAX_PATH]
EndStructureUnion
EndStructure
;- Variables globales
Global ppMalloc.l ; pointeur sur l'interface Shell IMalloc
; ; /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
; ; \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
;- Debut prog
If OpenWindow(0, 0, 0, 600, 400, #PB_Window_ScreenCentered | #PB_Window_SystemMenu, "Explorer les dossiers avec IShellFolder")
If CreateGadgetList(WindowID())
IdListIcon = ListIconGadget(0, 10, 10, 580, 380, "Contenu du Dossier SEND TO", 575, #LVS_SHAREIMAGELISTS)
; AddGadgetColumn(0, 1, "Taille", 575 / 5)
; AddGadgetColumn(0, 2, "Type", 575 / 5 * 2)
CoInitializeEx_(0, #COINIT_SPEED_OVER_MEMORY) ; Initialise la librairie COM pour le thread courant
shlwapiDll = OpenLibrary(100, "shlwapi.dll")
SHGetMalloc_(@pMalloc)
pszDisplayName = AllocateMemory((#MAX_PATH * 2) + 2)
; l'API SHGetSpecialFolderLocation retourne #S_OK en cas de succès sinon une erreur
; Cette API est remplacée par l'API SHGetFolderLocation depuis Windows 2000, mais
; fonctionne avec les nouveaux OS
; L'API retourne dans ppidl un pointeur sur un élément identifiant une liste specifiant
; la localisation du dossier relatif à la racine du 'name space' (le bureau)
If SHGetSpecialFolderLocation_(0, #CSIDL_SENDTO, @ppidl.l) = #NOERROR And shlwapiDll
; SHGetDesktopFolder retourne dans ppshf le pointeur sur l'interface IShellFolder
; pour le dossier 'Bureau'
If SHGetDesktopFolder_(@ppshf.IShellFolder) = #NOERROR
; la méthode BindToObject de l'interface IShellFolder retrouve un object IShellFolder
; pour un sous-dossier
If ppshf\BindToObject(ppidl, 0, ?IID_IShellFolder, @ppvOut.IShellFolder) = #NOERROR
ppshf\Release() ; on libère l'interface IShellFolder retournée par
; SHGetDesktopFolder, on n'en a plus besoin
; La méthode BindToObject de l'interface IShellFolder a retourné dans ppvOut
; un pointeur sur une interface IShellFolder pour un sous-dossier
; on peut donc commencer l'énumération avec la méthode EnumObjects (interface IShellFolder)
; EnumObjects permet de déterminer le contenu d'un dossier en créant un élément
; identifiant un object 'énumeration' et retournant son interface IEnumIDList.
; Les méthodes supportée par cette interface peuvent être utilisées pour énumérer
; le contenu d'un dossier.
If ppvOut\EnumObjects(0, #SHCONTF_FOLDERS | #SHCONTF_NONFOLDERS, @ppenum.IEnumIDList) = #S_OK
; La méthode Next de l'interface IEnumIDList permet de commencer l'énumération
; La méthode Next énumère dans notre cas les éléments un par un (1er paramètre quui indique
; aussi que pidlItems est un tableau à un élément. Pour retrouver plus d'éléments à la fois,
; il faut dimensionner le tableau avec SHGetMalloc
; celtFetched retourne une valeur qui indique combien d'éléments sont retournés par
; la fonction et dans notre cas au max 1 sinon 0 si plus d'éléments
hr = ppenum\Next(1, @pidlItems, @celtFetched)
; on teste dans la boucle qu'il n'y a pas d'erreur et qu'il y a bien un élément
While ((hr = #NOERROR) And (celtFetched = 1))
; la méthopde GetDisplayNameOf de l'interface IShellFolder retrouve
; le nom d'affichage pour le dossier)fichier object spécifié.
; le 3ème paramètre est une variable basée sur la structure STRRET
strDispName.STRRET\uType = #STRRET_OFFSET
If ppvOut\GetDisplayNameOf(pidlItems, #SHGDN_INFOLDER, @strDispName.STRRET) = #NOERROR
; La chaine retournée par GetDisplayNameOf doit être formatée avant d'être
; affichée correctement avec l'API StrRetToBufA de la dll shlwapi.dll
; pszDisplayName est le buffer qui recevra la chaine à afficher
CallFunction(100, "StrRetToBufA", @strDispName, pidlItems, pszDisplayName, #MAX_PATH)
; on affiche dans la Listicon
AddGadgetItem(0, 0, PeekS(pszDisplayName))
;
hr = ppenum\Next(1, @pidlItems, @celtFetched)
EndIf
Wend
FreeLibrary_(shlwapiDll) ; ferme shlwapi.dll
EndIf
EndIf
EndIf
EndIf
EndIf
CoTaskMemFree_(ppidl) ; libère la mémoire pointée par ppidl
;- boucle evenements
While WaitWindowEvent() <> #PB_EventCloseWindow And EventWindowID() <> WindowID()
Wend
EndIf
CoUninitialize_() ; ferme la librairie COM pour le thread courant
End
DataSection
; Interface IShellFolder;
; helpstring("IShellFolder"),
; uuid(000214E6-0000-0000-C000-000000000046)
IID_IShellFolder : ; cléf du registre mise sous la forme de DATA
Data.l $000214E6
Data.w $0000, $0000
Data.b $C0, $00, $00, $00, $00, $00, $00, $46
EndDataSection