Il y a 8 procédures, 4 pour travailler depuis un fichier sur le disque et les 4 mêmes mais pour travailler depuis les fichiers en datas ou en mémoire.
Je n'ai testé que sous Vista, les icônes Vista ne sont pas supportés ni les icônes supérieurs à 255 de côté.
Les fonctions sont les suivantes :
Code : Tout sélectionner
IconNumberFromFile(File$)
IconNumberFromMemory(AdresseMemoire.l)
EnumereIconFormatFromFile(File$, buffer.l)
EnumereIconFormatFromMemory(Memory_Add.l, buffer.l)
LoadIconEx(File$, size.l, Format.l)
LoadIconFromFile(File$, IconPos.l)
CatchIconEx(Memory_Add_1, size.l, Format.l)
CatchIcon(Memory_Add_1.l, IconPos.l)
Code : Tout sélectionner
IconNumberFromFile(File$)
File$ est le chemin complet du fichier .ico
Code : Tout sélectionner
IconNumberFromMemory(AdresseMemoire.l)
AdresseMemoire.l est l'adresse ou est située le fichier en data ou en mémoire
Ces deux fonctions retournent une valeur négative en cas d'échec
Code : Tout sélectionner
EnumereIconFormatFromFile(File$, buffer.l)
File$ est le chemin complet du fichier .ico
buffer est une zone mémoire allouée avec la fonction AllocateMemory() et typiquement on la dimensionne avant l'appel de la fonction puis on la libère ensuite comme ceci
Code : Tout sélectionner
*IconInfo.IconFormat, mem.l
*IconInfo = AllocateMemory(SizeOf(IconFormat) * Nb_Icones)
If *IconInfo
mem = *IconInfo
; on énumère les infos de chaque icône
EnumereIconFormatFromMemory(MemoryIcon, *IconInfo)
; ici la zone mémoire contient les données de chaque icône
; on fait ce que l'on a à faire avec les données
; ...
;
; on libère la mémoire
FreeMemory(mem)
EndIf
Cette Structure mémorise pour chaque icône :
- La largeur de l'icône courant (élément width.w)
- La hauteur de l'icône courant (élément height.w)
- Le Format de l'icône courant qui est une valeur ou une combinaison des valeurs de l'énumération IconFormat (élément ColorFormat.w)
- La position de l'icône dans le fichier avec le 1er icône à la position 1 (élément position.w)
Pour le format, seule la valeur #Format_Custom peut être combinée avec une des autres valeurs.
Code : Tout sélectionner
EnumereIconFormatFromMemory(Memory_Add.l, buffer.l)
Memory_Add.l est l'adresse ou est située le fichier en data ou en mémoire
C'est exactement le même fonctionnement que la fonction ci-dessus EnumereIconFormatFromFile(File$, buffer.l)
Code : Tout sélectionner
LoadIconEx(File$, size.l, Format.l)
File$ est le chemin complet du fichier .ico
size est la taille de l'icône recherchée
Format est une combinaison d'un ou de plusieurs éléments de l'énumération IconFormat, seule la valeur #Format_Custom peut être combinée avec une des autres valeurs.
Cette fonction ne fonctionne qu'avec des icônes carrés
Par exemple, on veut créer une image avec l'icône au format XP (c'est-à-dire qui supporte la transparence partielle, la couche alpha) d'une taille de 32
Si ce format existe, l'image sera crée depuis le fichier icône mais sans créer de fichier sur le disque, c'est transparent pour l'utilisateur.
La fonction retourne l'identifiant statique de la fontion PB catchImage utilisée en interne et non pas le handle de l'image.
Les commandes PureBasic des images sont utilisables, ne pas oublier FreeImage() pour détruire l'image
Pour cet exemple, voici comment utiliser la fonction
Code : Tout sélectionner
Fichier.s = "C:\MonIco.ico"
Img.l = 0
Img = LoadIconEx(Fichier, 32, #Format_XP_Colors)
If img
; ici c'est OK
; on peut utiliser ImageID(img)
Else
; ici l'icône 32x32 au format XP n'existe pas dans le fichier ico
EndIf
Code : Tout sélectionner
LoadIconFromFile(File$, IconPos.l)
File$ est le chemin complet du fichier .ico
IconPos est la position de l'icône recherchée dans le fichier
Le fonctionnement est identique à la fonction LoadIconEx(File$, size.l, Format.l)
Code : Tout sélectionner
CatchIconEx(Memory_Add_1, size.l, Format.l)
size est la taille de l'icône recherchée
Format est une combinaison d'un ou de plusieurs éléments de l'énumération IconFormat, seule la valeur #Format_Custom peut être combinée avec une des autres valeurs.
Pour le reste, Le fonctionnement est identique à la fonction LoadIconEx(File$, size.l, Format.l)
Code : Tout sélectionner
CatchIcon(Memory_Add_1.l, IconPos.l)
IconPos est la position de l'icône recherchée dans le fichier
Pour le reste, Le fonctionnement est identique à la fonction CatchIconEx(Memory_Add_1, size.l, Format.l)
************************************************************************
Il faut absolument tester le résultat des fonctions car les fonctions
utilisent des zones mémoire et des fichiers, il y a risque de plantage
************************************************************************
Voici le code des procédures :
Code : Tout sélectionner
; code PB de Franky ici --> http://www.purebasic.fr/english/viewtopic.php?t=13306
;
; Bonnes explications du format ici --> http://www.whisqu.se/per/docs/graphics52.htm
;
;
; http://www.developpez.net/forums/archive/index.php/t-370305.html
; http://www.developpez.net/forums/showthread.php?t=370305
; http://www.winmatrix.com/forums/index.php?showtopic=5461
; http://en.wikipedia.org/wiki/ICO_(icon_image_file_format)
; http://en.wikipedia.org/wiki/Windows_and_OS/2_bitmap
; http://www.codeguru.com/csharp/.net/net_general/graphics/article.php/c12787/
EnableExplicit
;- Enumeration IconFormat
Enumeration
#Format_XP_Colors = 1 ; couleurs avec couche alpha
#Format_True_Colors = 2 ; 16,8 millions de couleurs
#Format_256_Colors = 4 ; 256 couleurs indexées
#Format_16_Colors = 8 ; 16 couleurs
#Format_Monochrome = 16 ; noir et blanc
#Format_Custom = 32 ; format personnalisé, peut être combiné avec une des autres valeur
#Format_UnKnow = 64 ; ne devrait pas arriver, format inconnu
EndEnumeration
;- Structures
Structure IconDirectoryEntry
bWidth.b ; largeur de l'icône en pixels
bHeight.b ; hauteur de l'icône en pixels
bColorCount.b ; nombre de couleurs de l'icône (2, 8 ou 16 ?)
bReserved.b ; réservé, doit être à 0
wPlanes.w ;
wBitCount.w ; nombre de bits utilisé pour définir les couleurs de l'icône
dwBytesInRes.l ; Taille en octets de l'icône
dwImageOffset.l ; offset de l'icône en octets à partir du début du fichier jusqu'à l'image de l'icône
EndStructure
Structure IconDir
idReserved.w
idType.w
idCount.w
idEntries.IconDirectoryEntry[1]
EndStructure
Structure IconFormat
width.w ; largeur de l'icône
height.w ; hauteur de l'icône
ColorFormat.w ; un des formats de l'énumération IconFormat
position.w ; position de l'icône dans le fichier
EndStructure
;- declarations
Declare.l IconNumberFromFile(File$)
Declare.l IconNumberFromMemory(AdresseMemoire.l)
Declare.l EnumereIconFormatFromFile(File$, buffer.l)
Declare.l EnumereIconFormatFromMemory(Memory_Add.l, buffer.l)
Declare.l LoadIconEx(File$, size.l, Format.l)
Declare.l LoadIconFromFile(File$, IconPos.l)
Declare.l CatchIconEx(Memory_Add_1, size.l, Format.l)
Declare.l CatchIcon(Memory_Add_1.l, IconPos.l)
;- Procedures
Procedure.l IconNumberFromFile(File$)
; retourne le nombre d'icônes contenu dans le fichier ico passé en paramètre
; retourne une valeur négative en cas d'erreur
; File$ est le nom complet du fichier au format ico
Protected IconNumber.l ; mémorise le nombre d'icône
Protected FileId.l ; mémorise l'identifiant du fichier utilisé
FileId = ReadFile(#PB_Any, File$)
If FileId = 0
ProcedureReturn - 1
EndIf
; positionne le pointeur du fichier sur le bon élément
FileSeek(FileId, Loc(FileId) + OffsetOf(IconDir\idCount))
; lecture du nombre d'icônes
IconNumber = ReadWord(FileId)
; fermeture du fichier
CloseFile(FileId)
; retourne la valeur
ProcedureReturn IconNumber
EndProcedure
Procedure.l IconNumberFromMemory(AdresseMemoire.l)
; La procedure retourne le nombre d'icônes contenu dans le fichier Ico en mémoire ou en datas
; retourne une valeur négative en cas d'erreur
; AdresseMemoire est l'adresse mémoire ou est situé le fichier au format ico
Protected Img.l ; mémorise l'identifiant de l'image interne utilisée
Protected ObjectType.l ; mémorise le résultat d'une API Windows
Protected ico.ICONINFO ; variable stockant les infos de l'icône à tester
; on défini avec les fonction PB si l'image est une icône
Img = CatchImage(#PB_Any, AdresseMemoire)
If Img = 0
ProcedureReturn - 1
EndIf
ObjectType = GetIconInfo_(ImageID(Img), @ico)
If ObjectType = 0
FreeImage(Img)
ProcedureReturn - 2
EndIf
FreeImage(Img)
DeleteObject_(ico\hbmMask)
DeleteObject_(ico\hbmColor)
If ico\fIcon = #False ; curseur et pas icône
ProcedureReturn - 3
EndIf
; ici c'est bien un fichier icône, on retourne le nombre d'icônes
ProcedureReturn PeekW(AdresseMemoire + OffsetOf(IconDir\idCount))
EndProcedure
Procedure.l EnumereIconFormatFromFile(File$, buffer_1.l)
; retourne en mémoire les types de chaque icône du fichier au format ico
; retourne une valeur négative en cas d'erreur
; File$ est le nom complet du fichier au format ico
; buffer_1 est l'adresse mémoire de la zone qui recevra les infos sur chaque icône.
; chaque icône aura ses informations sosu la forme de valeur basées sur la structure IconFormat
; buffer_1 sera dimensionné par le produit du nombre d'icône et de la taille de la stucture IconFormat
; buffer_1 doit être alloué et détruit par le programmeur
; voir la fonction EnumereIconFormatFromMemory(Memory_Add.l, buffer.l) pour un exemple de dimensionnement du buffer
Protected FileId.l
; on retrouve le nombre d'icônes du fichier en mémoire
Protected FileSize.l
; on retrouve le nombre d'icônes du fichier en mémoire
Protected IconNumber.l = IconNumberFromFile(File$)
; mémoire allouée pour stocker le fichier
Protected Memory.l
; teste la quantité de données lue dans le fichier et le résultat de la fonction
Protected Result.l
If IconNumber <= 0
ProcedureReturn - 2
EndIf
FileSize = FileSize(File$)
If Filesize < SizeOf(IconDir) ; il y a au moins 1 icône
ProcedureReturn - 3
EndIf
FileId = ReadFile(#PB_Any, File$)
If FileId = 0
ProcedureReturn - 4
EndIf
Memory = AllocateMemory(Filesize)
If Memory = 0
CloseFile(FileId)
ProcedureReturn - 5
EndIf
Result = ReadData(FileId, Memory, FileSize)
If Result <> FileSize
CloseFile(FileId)
FreeMemory(Memory)
ProcedureReturn - 6
EndIf
; ici la copie est Ok, on appelle la fonction EnumereIconFormatFromMemory(Memory_Add.l, buffer.l)
Result = EnumereIconFormatFromMemory(Memory, buffer_1)
CloseFile(FileId)
FreeMemory(Memory)
ProcedureReturn Result
EndProcedure
Procedure.l EnumereIconFormatFromMemory(Memory_Add.l, buffer.l)
; Enumère les formats d'icône du fichier
; buffer doit avoir été dimensionné de manière suffisante avant l'appel de la fonction
; par le codeur et doit être détruit par le codeur lorsque ce buffer devient inutile
;
; buffer doit être dimentionné de cette manière
; d'abord, il faut retrouver le nombre d'icônes contenu dans le fichier ou en data
; Ensuite il faut allouer de la mémoire avec la taille de la structure IconFormat
; multiplié par le nombre d'icônes
; Voici un exemple d'utilisation avec le fichier en datas (tester le résultat des fonctions !)
; IconNumber = IconNumberFromMemory(?Ico)
; if IconNumber > 0
; memory = AllocateMemory(SizeOf(IconFormat) * IconNumber)
; if memory
; result = EnumereIconFormatFromMemory(?Ico, memory)
; ici on peut utiliser les résultats contenus dans memory
; FreeMemory(memory)
; else
; debug "erreur"
; endif
; endif
;
; on retrouve le nombre d'icônes du fichier en mémoire
Protected IconNumber.l = IconNumberFromMemory(Memory_Add)
; compteur de boucle
Protected i.l
; pointeur sur le fichier en mémoire à partir de la 1ere entrée dans le fichier
Protected * Pt_memory.IconDirectoryEntry = Memory_Add + OffsetOf(IconDir\idEntries)
; pointeur sur le buffer passé en paramètre
Protected * Pt_buffer.IconFormat = buffer
If IconNumber <= 0
ProcedureReturn - 1
EndIf
For i = 1 To IconNumber
; lecture de la largeur
*Pt_buffer\width = *Pt_memory\bWidth
; lecture de la hauteur
*Pt_buffer\height = *Pt_memory\bHeight
; écriture de la position de l'icône dans le fichier
*Pt_buffer\position = i
; écriture du format de l'icône
If *Pt_buffer\width <> * Pt_buffer\height
*Pt_buffer\ColorFormat = #Format_Custom
EndIf
Select *Pt_memory\wBitCount
Case 1
*Pt_buffer\ColorFormat | #Format_Monochrome
Case 4
*Pt_buffer\ColorFormat | #Format_16_Colors
Case 8
*Pt_buffer\ColorFormat | #Format_256_Colors
Case 24
*Pt_buffer\ColorFormat | #Format_True_Colors
Case 32
*Pt_buffer\ColorFormat | #Format_XP_Colors
Default
*Pt_buffer\ColorFormat | #Format_UnKnow
EndSelect
; positionnement du pointeur *Pt_memory
*Pt_memory + SizeOf(IconDirectoryEntry)
; positionnement du pointeur *Pt_buffer
*Pt_buffer + SizeOf(IconFormat)
Next
ProcedureReturn #ERROR_SUCCESS
EndProcedure
Procedure.l LoadIconEx(File$, size.l, Format.l)
; Permet de charger l'icône définie par les 2 paramètres size et Format s'il existe
; retourne -1 en cas d'échec, sinon l'identifiant statique PureBasic de l'icône choisie
; Si la fonction réussie, les commandes PB s'appliquent à l'image retournée, en particulier FreeImage()
; L'image retournée n'existe pas sur le disque
;
; Paramètres :
; ----------
; File$ --> le nom complet du fichier au format .ico
; size --> La valeur en pixel de l'icône carré :
; valeurs possible, toutes jusqu'à 128
; Format --> Une des valeur de l'énumération IconFormat ci-dessus
; on énumère les éléments jusqu'à ce que l'on trouve l'icône
; si elle est rouvée, on utilise LoadIconFromFile(File$, IconPos.l)
; sinon on retourne une erreur
Protected IconNumber.l = IconNumberFromFile(File$)
; compteur de boucle
Protected i.l
; mémoire allouée pour énumérer le fichier
Protected *Memory, *Memory1.IconFormat
If IconNumber <= 0
ProcedureReturn - 1
EndIf
*Memory = AllocateMemory(SizeOf(IconFormat) * IconNumber)
If *Memory = 0
ProcedureReturn - 2
EndIf
*Memory1 = *Memory
If EnumereIconFormatFromFile(File$, *Memory) <> #ERROR_SUCCESS
FreeMemory(*Memory)
ProcedureReturn -3
EndIf
For i = 1 To IconNumber
If (*Memory1\width = size) And (*Memory1\height = size) And (*Memory1\ColorFormat = Format)
FreeMemory(*Memory)
ProcedureReturn LoadIconFromFile(File$, i)
EndIf
; ; on incémente le pointeur
*Memory1 + SizeOf(IconFormat)
Next
FreeMemory(*Memory)
ProcedureReturn -4
EndProcedure
Procedure.l LoadIconFromFile(File$, IconPos.l)
; Permet de charger l'icône en position 'Position' qui est contenue dans le fichier disque 'File$'
; retourne -1 en cas d'échec, sinon l'identifiant statique PureBasic de l'icône choisie
; Si la fonction réussie, les commandes PB s'appliquent à l'image retournée, en particulier FreeImage()
; L'image retournée n'existe pas sur le disque
Protected FileId.l
; on retrouve le nombre d'icônes du fichier en mémoire
Protected FileSize.l
; on retrouve le nombre d'icônes du fichier en mémoire
Protected IconNumber.l = IconNumberFromFile(File$)
; mémoire allouée pour stocker le fichier
Protected Memory.l
; teste la quantité de données lue dans le fichier et le résultat de la fonction
Protected Result.l
If IconNumber <= 0
ProcedureReturn - 2
EndIf
FileSize = FileSize(File$)
If Filesize < SizeOf(IconDir) ; il y a au moins 1 icône
ProcedureReturn - 3
EndIf
FileId = ReadFile(#PB_Any, File$)
If FileId = 0
ProcedureReturn - 4
EndIf
Memory = AllocateMemory(Filesize)
If Memory = 0
CloseFile(FileId)
ProcedureReturn - 5
EndIf
Result = ReadData(FileId, Memory, FileSize)
If Result <> FileSize
CloseFile(FileId)
FreeMemory(Memory)
ProcedureReturn - 6
EndIf
; ici la copie est Ok, on appelle la fonction EnumereIconFormatFromMemory(Memory_Add.l, buffer.l)
Result = CatchIcon(Memory, IconPos.l)
CloseFile(FileId)
FreeMemory(Memory)
ProcedureReturn Result
EndProcedure
Procedure.l CatchIconEx(Memory_Add_1, size.l, Format.l)
; Permet de charger l'icône définie par les 2 paramètres size et Format s'il existe
; retourne -1 en cas d'échec, sinon l'identifiant statique PureBasic de l'icône choisie
; Si la fonction réussie, les commandes PB s'appliquent à l'image retournée, en particulier FreeImage()
; L'image retournée n'existe pas sur le disque
;
; Paramètres :
; ----------
; File$ --> le nom complet du fichier .ico
; size --> La valeur en pixel de l'icône carré :
; valeurs possible, toutes jusqu'à 128
; Format --> Une des valeur de l'énumération IconFormat ci-dessus
; on énumère les éléments jusqu'à ce que l'on trouve l'icône
; si elle est rouvée, on utilise LoadIconFromFile(File$, IconPos.l)
; sinon on retourne une erreur
Protected IconNumber.l = IconNumberFromMemory(Memory_Add_1)
; compteur de boucle
Protected i.l
; mémoire allouée pour énumérer le fichier
Protected *Memory, *Memory1.IconFormat
If IconNumber <= 0
ProcedureReturn - 1
EndIf
*Memory = AllocateMemory(SizeOf(IconFormat) * IconNumber)
If *Memory = 0
ProcedureReturn - 2
EndIf
*Memory1 = *Memory
If EnumereIconFormatFromMemory(Memory_Add_1, *Memory) <> #ERROR_SUCCESS
FreeMemory(*Memory)
ProcedureReturn -3
EndIf
For i = 1 To IconNumber
If (*Memory1\width = size) And (*Memory1\height = size) And (*Memory1\ColorFormat = Format)
FreeMemory(*Memory)
ProcedureReturn CatchIcon(Memory_Add_1, i)
EndIf
; ; on incémente le pointeur
*Memory1 + SizeOf(IconFormat)
Next
FreeMemory(*Memory)
ProcedureReturn -4
EndProcedure
Procedure.l CatchIcon(Memory_Add_1.l, IconPos.l)
; Permet de charger l'icône en position 'Position' qui est contenue dans le fichier icône en data ou mémoire
; retourne -1 en cas d'échec, sinon l'identifiant statique PureBasic de l'icône choisie
; Si la fonction réussie, les commandes PB s'appliquent à l'image retournée, en particulier FreeImage()
Protected IconNumber.l = IconNumberFromMemory(Memory_Add_1)
; taille de l'icône coureante
Protected IconSize.l
; position des données de l'icône dans le fichier
Protected IconOffset.l
; mémoire allouée pour créer l'icône
Protected *IconMemory.IconDir, Mem.l
; identifiant statique de l'image PB retournée
Protected Img.l
; pointeur sur le fichier en mémoire à partir de la 1ere entrée dans le fichier
Protected *Pt_memory.IconDirectoryEntry
If (IconNumber <= 0) Or (IconPos <= 0) Or ((IconNumber > 0) And (IconPos > IconNumber))
ProcedureReturn - 1
EndIf
IconPos - 1
; on se positionne sur la structure correspondante
*Pt_memory.IconDirectoryEntry = Memory_Add_1 + (OffsetOf(IconDir\idEntries) + (SizeOf(IconDirectoryEntry) * IconPos))
; on récupère la taille et l'offset de l'icône dans le fichier
IconSize = *Pt_memory\dwBytesInRes
IconOffset = *Pt_memory\dwImageOffset
; on alloue de la mémoire pour créer l'icône en mémoire
Mem = AllocateMemory(SizeOf(IconDir) + IconSize)
If Mem = 0
ProcedureReturn - 2
EndIf
; Mem va mémoriser l'adresse permettant de libérer la mémoire
; *IconMemory va permettre d'accéder aux données
*IconMemory = Mem
; on copie les données en mémoire, d'abord les données définissant le type du fichier
*IconMemory\idReserved = 0 ; toujours à 0
*IconMemory\idType = 1 ; resource type, toujours à 1
*IconMemory\idCount = 1 ; nombre d'icône dans le fichier --> 1 seul pour cette fonction
; ensuite les données propres définissant l'icône (la structure IconDirectoryEntry)
CopyMemory(*Pt_memory, *IconMemory\idEntries, SizeOf(IconDirectoryEntry))
; écriture en mémoire du nouvel offset des données de l'icône
; ces deonnées se trouve immédiatement après la structure IconDir qui ne contient
; qu'une seule structure IconDirectoryEntry
*IconMemory\idEntries\dwImageOffset = SizeOf(IconDir)
; positionne le pointeur de destination sur la zone des datas à écrire
*IconMemory + SizeOf(IconDir)
; écriture en mémoire des données de l'icône
CopyMemory(Memory_Add_1 + IconOffset, *IconMemory, IconSize)
Img = CatchImage(#PB_Any, Mem)
FreeMemory(Mem)
If img
ProcedureReturn Img
Else
ProcedureReturn -3 ; erreur
EndIf
EndProcedure
IncludeFile "Select_icones.pb"
L'exemple est trop long pour le forum, alors voila un lien