Page 1 sur 1

IExtractIcon - Interfaces, aie

Publié : dim. 30/janv./2005 0:50
par Le Soldat Inconnu
Salut,

je pense avoir trouvé la fonction pour résoudre mon problème avec SHGetFileInfo
voir ici : http://purebasic.hmt-forum.com/viewtopi ... 1830#21830

mais c'est des interfaces et j'ai un peu beaucoup de mal

http://msdn.microsoft.com/library/defau ... cation.asp

2 solution s'offre à moi :

- Récupérer l'adresse du fichier qui contient l'icône associé à un type de fichier avec SHGetFileInfo mais je n'y arrive pas sauf pour des dossiers et fichiers systèmes

Code : Tout sélectionner

File.s = "c:\test.txt"
Debug File
CreateFile(0, File)
CloseFile(0)

SHGetFileInfo_(@File, 0, @InfosFile.SHFILEINFO, SizeOf(SHFILEINFO), #SHGFI_ICONLOCATION)

Debug InfosFile\hIcon
Debug InfosFile\iIcon
If @InfosFile\szDisplayName
  Debug Str(@InfosFile\szDisplayName) + " : " + PeekS(@InfosFile\szDisplayName, 260)
Else
  Debug @InfosFile\szDisplayName
EndIf
If @InfosFile\szTypeName
  Debug Str(@InfosFile\szTypeName) + " : " + PeekS(@InfosFile\szTypeName, 80)
Else
  Debug @InfosFile\szTypeName
EndIf

DeleteFile(File)

Debug ""

File.s = "c:\"
Debug File

SHGetFileInfo_(@File, 0, @InfosFile.SHFILEINFO, SizeOf(SHFILEINFO), #SHGFI_ICONLOCATION)

Debug InfosFile\hIcon
Debug InfosFile\iIcon
If @InfosFile\szDisplayName
  Debug Str(@InfosFile\szDisplayName) + " : " + PeekS(@InfosFile\szDisplayName, 260)
Else
  Debug @InfosFile\szDisplayName
EndIf
If @InfosFile\szTypeName
  Debug Str(@InfosFile\szTypeName) + " : " + PeekS(@InfosFile\szTypeName, 80)
Else
  Debug @InfosFile\szTypeName
EndIf

DeleteFile(File)
ou alors passez par les interfaces cités ci dessus mais la, j'y comprend rien pour l'instant

un petit coup de main ne serait pas de refus, merci :wink:

Publié : mer. 02/févr./2005 12:21
par Le Soldat Inconnu
J'ai fais quelques essais à partir d'un code de DENIS mais il ne reconnais l'interface dont j'ai besoin.
Voir au milieu du code, entre les ===========

Un petit coup de patte, merci

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.
          
          
          ;============================================================
          ;- C'est ici que je cherche à lire une icône
          
          If ppvOut\GetUIObjectOf(WindowID(), 1, ppidl, ?IID_IExtractIcon, 0, @ppvIcon.IExtractIcon) = #S_OK
            szBuf.s = Space(#MAX_PATH)
            ppvIcon\GetIconLocation(0, @szBuf.s, #MAX_PATH, @piIndex.l, pwFlags.l)
          EndIf
          
          ;============================================================
          
          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
  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
    
  IID_IExtractIcon :
    Data.l $000214EB
    Data.w $0000, $0000
    Data.b $C0, $00, $00, $00, $00, $00, $00, $46
EndDataSection

Publié : mer. 02/févr./2005 12:45
par nico
J'ai regardé vaguement, faut pas d'abord faire une recherche sur l'objet (le fichier dont on veut récupérer l'icone) et seulement ensuite faire appel à queryinterface sur IID_IExtractIcon pour travaillé sur cette interface et l'objet en question?

Publié : mer. 02/févr./2005 13:54
par Le Soldat Inconnu
ben je ne sais pas, j'y comprends rien, alors j'essaie de faire par analogie

Publié : mer. 02/févr./2005 14:15
par Anonyme2
J'ai pas trop regardé mais le peu que j'en ai vu c'est comme le dit Nico, on récupère le pointeur sur l'ojet fichier voulu et ensuite on on extrait (comme ça ça semble simple mais ça doit être surement plus lourd à faire, rien n'est simpe avec les interfaces).

Publié : mer. 02/févr./2005 16:54
par Le Soldat Inconnu
rien n'est simpe avec les interfaces
oui, c'est certain.

J'ai finis par trouvé une solution avec la fonction SHGetFileInfo pour mon problème d'icône.

mais j'ai vu que les interfaces sont plus rapides, si c'est vrai, ça me serait fort utile.
on récupère le pointeur sur l'ojet fichier voulu et ensuite on on extrait
Ok, je vais essayer comme ça.

mais pourquoi le compilo ne reconnait pas les fonctions de l'interface ?
la :
@ppvIcon.IExtractIcon
et la :
GetIconLocation(

Publié : mer. 02/févr./2005 17:32
par nico
Cette interface n'est pas déclarer, a toi de le faire.

Publié : mer. 02/févr./2005 18:45
par Le Soldat Inconnu
OK OK, ça s'éclaircie :D

Publié : mer. 02/févr./2005 19:22
par Anonyme2
L'interface IExtractIcon est déclarée de 2 manières

IExtractIconA

et

IExtractIconW

Publié : mer. 02/févr./2005 19:25
par Le Soldat Inconnu
Tu as vu ça ou ? j'ai pas vu ça sur msdn ?

Publié : mer. 02/févr./2005 19:36
par hardy
J'ai l'impression que maintenant elles sont à peu près toutes déclarées en PB.
J'en utilise en ce moment, et c'est vrai que c'est carrément chiant.
Le plus simple, c'est quand même d'utiliser des scripts.
Y'a pas une lib pour utiliser des scripts vbs en PB?

Publié : mer. 02/févr./2005 19:40
par Anonyme2
Y a un outil dans PureBasic qui permet de voir les Interfaces, c'est tout.

Mis à part ça, dans la doc SDK de MS, fait une recherche sur IExtractIcon

Une fois la page apparue, tout en bas il y a un truc qui ressemble à ça

Interface Information

Minimum DLL Version shell32.dll version 4.0 or later
Custom Implementation Yes
Inherits from IUnknown
Header shlobj.h
Minimum operating systems Windows NT 4.0, Windows 95


La plupart du temps, on trouve toutes les infos dans le fichier ou les fichiers indiqués, ici shlobj.h

Mais pas la valeur que tu as trouvé sur Internet. Peut-être dans le fichier ou les fichiers qui sont déclarés en include files.

Dans ce fichier h, on a ceci
#undef INTERFACE
#define INTERFACE IExtractIconA

DECLARE_INTERFACE_(IExtractIconA, IUnknown) // exic
{
// *** IUnknown methods ***
STDMETHOD(QueryInterface) (THIS_ REFIID riid, void **ppv) PURE;
STDMETHOD_(ULONG,AddRef) (THIS) PURE;
STDMETHOD_(ULONG,Release) (THIS) PURE;

// *** IExtractIcon methods ***
STDMETHOD(GetIconLocation)(THIS_
UINT uFlags,
LPSTR szIconFile,
UINT cchMax,
int * piIndex,
UINT * pwFlags) PURE;

STDMETHOD(Extract)(THIS_
LPCSTR pszFile,
UINT nIconIndex,
HICON *phiconLarge,
HICON *phiconSmall,
UINT nIconSize) PURE;
};

typedef IExtractIconA * LPEXTRACTICONA;

#undef INTERFACE
#define INTERFACE IExtractIconW

DECLARE_INTERFACE_(IExtractIconW, IUnknown) // exic
{
// *** IUnknown methods ***
STDMETHOD(QueryInterface) (THIS_ REFIID riid, void **ppv) PURE;
STDMETHOD_(ULONG,AddRef) (THIS) PURE;
STDMETHOD_(ULONG,Release) (THIS) PURE;

// *** IExtractIcon methods ***
STDMETHOD(GetIconLocation)(THIS_
UINT uFlags,
LPWSTR szIconFile,
UINT cchMax,
int * piIndex,
UINT * pwFlags) PURE;

STDMETHOD(Extract)(THIS_
LPCWSTR pszFile,
UINT nIconIndex,
HICON *phiconLarge,
HICON *phiconSmall,
UINT nIconSize) PURE;
};

typedef IExtractIconW * LPEXTRACTICONW;

#ifdef UNICODE
#define IExtractIcon IExtractIconW
#define IExtractIconVtbl IExtractIconWVtbl
#define LPEXTRACTICON LPEXTRACTICONW
#else
#define IExtractIcon IExtractIconA
#define IExtractIconVtbl IExtractIconAVtbl
#define LPEXTRACTICON LPEXTRACTICONA
#endif
Je pense que Fred a utilisé son outil pour inclure cette interface

(il y a 1983 interfaces définies en standart par PB)

Publié : mer. 02/févr./2005 20:01
par Le Soldat Inconnu
Merci chef :D

Publié : dim. 06/févr./2005 12:27
par Anonyme2
J'ai fait quelques essais avec l'interface IExtractIcon, je réussi à extraire les 2 icônes, mais pas du fichier voulu. Je tourne un peu en rond.
Je n'extrait pour l'instant que l'icône (index 0) de l'explorer.exe :roll:
Je finirais par trouver (l'espoir fait vivre). :D

Ce qui me fait penser que j'ai peut-être oublié de libérer correctement la mémoire avec l'exemple que j'avais posté sur IShellFolder et IEnumIDList.
Faut que je vérifie.

Publié : dim. 06/févr./2005 23:55
par Le Soldat Inconnu
C'est encourageant :D on va triompher de ces satanés interfaces