YAIG: Yet Another Icon Grabber

Programmation d'applications complexes
Mesa
Messages : 1126
Inscription : mer. 14/sept./2011 16:59

YAIG: Yet Another Icon Grabber

Message par Mesa »

Un extracteur d'icône et de curseurs.

Windows seulement, x64, x86 de Windosws Xp à Windows 10, et probablement 11 (pas testé).

[Edition 28/10/2024] Bug dans la sauvegarde, ajout d'un code de srod pour enregistrer en ico et cur et modif de "ExtractIcons.xml.dd.pbi".

YAIG.pb

Code : Tout sélectionner

;- TOP

;-
;- YAIG: Yet Another Icon Grabber
;From this original code: https://www.purebasic.fr/english/viewtopic.php?p=417143#p417143
;-

CompilerIf #PB_Compiler_IsMainFile
  EnableExplicit
CompilerEndIf

;- Include
XIncludeFile "ExtractIcons.xml.dd.pbi"

;- Global
Global iSize = 266; zoom image size
Structure Slist_listicon
  id.i
  w.i
  h.i
  bpp.i
EndStructure
Global NewList List_listicon.Slist_listicon(); list of image handles


;-
;- ########  ICON CODE  ################

; http://msdn.microsoft.com/en-us/library/ms997538.aspx

;- Constant
Enumeration
  #Icon_GetSclHdl   ; Icon might be scaled (in case a 256Pixel is requested and only 16Pixel is available, it's scaled)
  #Icon_GetCnt      ; How many different Icons are available
  #Icon_GetRealHdl  ; Get real icon - nothing is scaled! In case there's no fitting Icon you'll get nothing
  #Icon_GetSizes    ; Get List of available Icon Sizes
EndEnumeration

;- Structure
Structure Icon_Dimension
  Width.i     ; Width
  Height.i    ; Height
  BitCnt.a    ; Bits per pixel: 1=2 Colors, 2=4 Colors, 4=16 Colors, 8=256 Colors, 24=TrueColor, 32=TrueColor+Alpha
EndStructure

Structure Icon_Size
  Array Icon_Size.Icon_Dimension(1)
EndStructure

Structure Icon_EnumData
  Mode.i ; what kind of data we'd like to get
  Nr.i   ; which Icon we'd like to get (1=first, 2=second, ..)
  RetVal.i; return value with the requested information
  Array Size.Icon_Dimension(1)  ; size of the icon we want or it holds the sizes of all available icons
EndStructure

Structure ICONDIRENTRY
  bWidth.a       ; Width, in pixels, of the image
  bHeight.a      ; Height, in pixels, of the image
  bColorCount.a  ; Number of colors in image (0 if >=8bpp)
  bReserved.a    ; Reserved ( must be 0)
  wPlanes.w      ; Color Planes
  wBitCount.w    ; Bits per pixel
  dwBytesInRes.l ; How many bytes in this resource?
  dwImageOffset.l; Where in the file is this image?
EndStructure

Structure ICONDIR
  idReserved.w ; Reserved (must be 0)
  idType.w     ; Resource Type (1 for icons)
  idCount.w    ; How many images?
  Array idEntries.ICONDIRENTRY(1) ;An entry for each image (idCount of 'em)
EndStructure


;- Private Procedure
Procedure __Icon_EnumCallback(hLibrary, lpszType, lpszName, *Data.Icon_EnumData)
  ; 20130707..nalor..implemented support for icons with low BPP (1,2,4)
  Protected hIcon.i
  Protected hRsrc.i
  Protected hGlobal.i
  Protected Cnt.i
  Protected *GrpIconDir.GRPICONDIR
  Protected *IconImage.ICONIMAGE
  Protected Colors.a
  
  Select *Data\Mode
    Case #Icon_GetCnt
      *Data\RetVal + 1
      
    Case #Icon_GetSclHdl
      *Data\RetVal + 1
      If *Data\Nr = *Data\RetVal ; we've reached the requested Icon
        *Data\RetVal = LoadImage_(hLibrary, lpszName, #IMAGE_ICON, *Data\Size(0)\Width, *Data\Size(0)\Height, 0)
        ProcedureReturn #False ; no need to continue enumerating
      EndIf
      
    Case #Icon_GetSizes
      *Data\RetVal + 1
      If *Data\Nr = *Data\RetVal ; we've reached the requested Icon
                                 ;Find the group resource which lists its images
        hRsrc = FindResource_(hLibrary, lpszName, lpszType)
        If hRsrc
          ;Load And Lock To get a pointer To a GRPICONDIR
          hGlobal = LoadResource_(hLibrary, hRsrc)
          If hGlobal
            *GrpIconDir = LockResource_(hGlobal)
            If *GrpIconDir
              If *GrpIconDir\idCount
                ReDim *Data\Size(*GrpIconDir\idCount - 1)
              EndIf
              For Cnt = 0 To *GrpIconDir\idCount - 1
                *Data\Size(Cnt)\Width  = PeekA(@*GrpIconDir\idEntries[Cnt]\bWidth) ; peeka is used because 'Byte' is signed and we want an unsigned result
                *Data\Size(Cnt)\Height = PeekA(@*GrpIconDir\idEntries[Cnt]\bHeight)
                
                If *Data\Size(Cnt)\Height = 0
                  *Data\Size(Cnt)\Height = 256
                EndIf
                If *Data\Size(Cnt)\Width = 0
                  *Data\Size(Cnt)\Width = 256
                EndIf
                
                Select *GrpIconDir\idEntries[Cnt]\bColorCount
                  Case 0  ; it's an icon with at least 256 colors
                    *Data\Size(Cnt)\BitCnt = *GrpIconDir\idEntries[Cnt]\wBitCount
                  Case 2
                    *Data\Size(Cnt)\BitCnt = 1
                  Case 4
                    *Data\Size(Cnt)\BitCnt = 2
                  Case 16
                    *Data\Size(Cnt)\BitCnt = 4
                EndSelect
                
                ;Debug "Callback Cnt >"+Str(Cnt+1)+"< Size >"+Str(*Data\Size(Cnt)\Width)+" x "+Str(*Data\Size(Cnt)\Height)+"< Col >"+Str(*Data\Size(Cnt)\BitCnt)+"<"
              Next
            Else
              *Data\RetVal = - 3
            EndIf
          Else
            *Data\RetVal = - 2
          EndIf
        Else
          *Data\RetVal = - 1
        EndIf
        ProcedureReturn #False ; no need to continue enumerating
      EndIf
      
    Case #Icon_GetRealHdl
      
      Select *Data\Size(0)\BitCnt
        Case 1
          Colors = 2
        Case 2
          Colors = 4
        Case 4
          Colors = 16
        Default
          Colors = 1 ; an impossible value
      EndSelect
      
      *Data\RetVal + 1
      ; 			Debug "Current IconNr >"+Str(*Data\RetVal)+"< Dest >"+Str(*Data\Nr)+"<"
      If *Data\Nr = *Data\RetVal ; we've reached the requested Icon
                                 ; http://msdn.microsoft.com/en-us/library/ms997538.aspx
                                 ;Find the group resource which lists its images
        
        hRsrc = FindResource_(hLibrary, lpszName, lpszType)
        If hRsrc
          ;Load And Lock To get a pointer To a GRPICONDIR
          hGlobal = LoadResource_(hLibrary, hRsrc)
          If hGlobal
            *GrpIconDir = LockResource_(hGlobal)
            If *GrpIconDir
              ; Using an ID from the group, Find, Load And Lock the RT_ICON
              *Data\RetVal = 0 ; in case the requested icon is not available, "0" will be the return value
              For Cnt = 0 To *GrpIconDir\idCount - 1
                If PeekA(@*GrpIconDir\idEntries[Cnt]\bWidth) = *Data\Size(0)\Width And
                   PeekA(@*GrpIconDir\idEntries[Cnt]\bHeight) = *Data\Size(0)\Height And
                   (*GrpIconDir\idEntries[Cnt]\wBitCount = *Data\Size(0)\BitCnt Or *Data\Size(0)\BitCnt = 0 Or *GrpIconDir\idEntries[Cnt]\bColorCount = Colors)
                  
                  hRsrc = FindResource_(hLibrary, *GrpIconDir\idEntries[Cnt]\nID, #RT_ICON)
                  If hRsrc
                    hGlobal = LoadResource_(hLibrary, hRsrc)
                    If hGlobal
                      *IconImage = LockResource_(hGlobal) ;Here, *IconImage points To an ICONIMAGE Structure
                      If *IconImage
                        *Data\RetVal = CreateIconFromResourceEx_(*IconImage, SizeofResource_(hLibrary, hRsrc), #True, $30000, 0, 0, 0)
                      Else
                        *Data\RetVal = - 6
                      EndIf
                    Else
                      *Data\RetVal = - 5
                    EndIf
                  Else
                    *Data\RetVal = - 4
                  EndIf
                  ProcedureReturn #False ; we found the specific icon
                EndIf
              Next
            Else
              *Data\RetVal = - 3
            EndIf
          Else
            *Data\RetVal = - 2
          EndIf
        Else
          *Data\RetVal = - 1
        EndIf
        ProcedureReturn #False ; no need to continue enumerating
      EndIf
      
  EndSelect
  
  ProcedureReturn #True
  
EndProcedure

Procedure.i __Icon_GetRealHdlICO(File.s, Width.i, Height.i, BPP.a = 0)
  Protected pIconDir.ICONDIR ;We need an ICONDIR To hold the Data
  Protected *IconImage.ICONIMAGE
  Protected FileHdl.i
  Protected Cnt.i
  Protected Colors.a
  Protected RetVal.i = 0
  
  Select BPP
    Case 1
      Colors = 2
    Case 2
      Colors = 4
    Case 4
      Colors = 16
    Default
      Colors = 1 ; an impossible value
  EndSelect
  
  
  FileHdl = ReadFile(#PB_Any, File)
  If FileHdl
    pIconDir\idReserved = ReadWord(FileHdl) ; Read the Reserved word
    pIconDir\idType     = ReadWord(FileHdl) ; Read the Type word - make sure it is 1 For icons
    If (pIconDir\idType = #IMAGE_ICON Or pIconDir\idType = #IMAGE_CURSOR) ; it's an Icon or a Cursor
      pIconDir\idCount = ReadWord(FileHdl)                                ; Read the count - how many images in this file?
      ReDim pIconDir\idEntries(pIconDir\idCount - 1)                      ; Reallocate IconDir so that idEntries has enough room For idCount elements
      If ReadData(FileHdl, @pIconDir\idEntries(0), SizeOf(ICONDIRENTRY) * pIconDir\idCount) ; Read the ICONDIRENTRY elements
        RetVal = 0
        For Cnt = 0 To pIconDir\idCount - 1
          ;Debug "CurIcon >"+Str(pIconDir\idEntries(Cnt)\bWidth)+"<>"+Str(pIconDir\idEntries(Cnt)\bHeight)+"<>"+Str(pIconDir\idEntries(Cnt)\wBitCount)+"<"
          If PeekA(@pIconDir\idEntries(Cnt)\bWidth) = Width And
             PeekA(@pIconDir\idEntries(Cnt)\bHeight) = Height And
             (pIconDir\idEntries(Cnt)\wBitCount = BPP Or BPP = 0 Or pIconDir\idEntries(Cnt)\bColorCount = Colors)
            
            *IconImage = AllocateMemory(pIconDir\idEntries(Cnt)\dwBytesInRes) ; Allocate memory To hold the image
            If *IconImage
              FileSeek(FileHdl, pIconDir\idEntries(Cnt)\dwImageOffset) ; Seek To the location in the file that has the image
              If ReadData(FileHdl, *IconImage, pIconDir\idEntries(Cnt)\dwBytesInRes) ;Read the image Data
                RetVal = CreateIconFromResourceEx_(*IconImage, pIconDir\idEntries(Cnt)\dwBytesInRes, #True, $30000, 0, 0, 0)
              Else
                Debug "ERROR!! Reading ICONIMAGE data (__Icon_GetRealHdlICO)"
                RetVal = - 5
              EndIf
              
              FreeMemory(*IconImage)
              Break;
            Else
              Debug "ERROR!! Allocating Memory (__Icon_GetRealHdlICO)"
              RetVal = - 4
            EndIf
          EndIf
        Next
      Else
        Debug "ERROR!! Reading ICONDIRENTRY data (__Icon_GetRealHdlICO)"
        RetVal = - 3
      EndIf
    Else
      Debug "ERROR!! it's not an icon or a cursor (__Icon_GetRealHdlICO)"
      RetVal = - 2
    EndIf
    CloseFile(FileHdl)
  Else
    Debug "ERROR!! reading file (__Icon_GetRealHdlICO)"
    RetVal = - 1
  EndIf
  
  ProcedureReturn RetVal
EndProcedure

Procedure.i __Icon_GetSizesICO(File.s, *Sizes.Icon_Size)
  ; 20130707..nalor..implemented support for icons with low BPP (1,2,4)	
  Protected pIconDir.ICONDIR ;We need an ICONDIR To hold the Data
  Protected FileHdl.i
  Protected Cnt.i
  Protected RetVal.i = 0
  
  FileHdl = ReadFile(#PB_Any, File)
  If FileHdl
    pIconDir\idReserved = ReadWord(FileHdl) ; Read the Reserved word
    pIconDir\idType     = ReadWord(FileHdl) ; Read the Type word - make sure it is 1 For icons
    If (pIconDir\idType = #IMAGE_ICON Or pIconDir\idType = #IMAGE_CURSOR) ; it's an Icon or a Cursor
      pIconDir\idCount = ReadWord(FileHdl)                                ; Read the count - how many images in this file?
      ReDim pIconDir\idEntries(pIconDir\idCount - 1)                      ; Reallocate IconDir so that idEntries has enough room For idCount elements
      If ReadData(FileHdl, @pIconDir\idEntries(0), SizeOf(ICONDIRENTRY) * pIconDir\idCount) ; Read the ICONDIRENTRY elements
        
        ReDim *Sizes\Icon_Size(pIconDir\idCount - 1)
        For Cnt = 0 To pIconDir\idCount - 1
          *Sizes\Icon_Size(Cnt)\Width  = PeekA(@pIconDir\idEntries(Cnt)\bWidth) ; peeka is used because 'Byte' is signed and we want an unsigned result
          *Sizes\Icon_Size(Cnt)\Height = PeekA(@pIconDir\idEntries(Cnt)\bHeight)
          
          If *Sizes\Icon_Size(Cnt)\Width = 0
            *Sizes\Icon_Size(Cnt)\Width = 256
          EndIf
          If *Sizes\Icon_Size(Cnt)\Height = 0
            *Sizes\Icon_Size(Cnt)\Height = 256
          EndIf
          
          Select pIconDir\idEntries(Cnt)\bColorCount
            Case 0  ; it's an icon with at least 256 colors
              *Sizes\Icon_Size(Cnt)\BitCnt = pIconDir\idEntries(Cnt)\wBitCount
            Case 2
              *Sizes\Icon_Size(Cnt)\BitCnt = 1
            Case 4
              *Sizes\Icon_Size(Cnt)\BitCnt = 2
            Case 16
              *Sizes\Icon_Size(Cnt)\BitCnt = 4
          EndSelect
          
          Debug "__Icon_GetSizesICO Cnt >" + Str(Cnt + 1) + "/" + Str(pIconDir\idCount) + "< Size >" + Str(*Sizes\Icon_Size(Cnt)\Width) + " x " + Str(*Sizes\Icon_Size(Cnt)\Height) + "< BitCnt >" + Str(*Sizes\Icon_Size(Cnt)\BitCnt) + "<"
          
        Next
        RetVal = 1
      Else
        Debug "ERROR!! Reading ICONDIRENTRY data (__Icon_GetSizesICO)"
        RetVal = - 3
      EndIf
    Else
      Debug "ERROR!! it's not an icon or a cursor (__Icon_GetSizesICO)"
      RetVal = - 2
    EndIf
    CloseFile(FileHdl)
  Else
    Debug "ERROR!! reading file (__Icon_GetSizesICO)"
    RetVal = - 1
  EndIf
  
  ProcedureReturn RetVal
EndProcedure

;- Public Procedure
Procedure.i Icon_GetSizes(File.s, *Sizes.Icon_Size, IconNr.i = 1)
  Protected IconData.Icon_EnumData
  Protected hLibrary.i
  Protected ImgHdl.i
  
  IconData\RetVal = 0
  
  Select LCase(GetExtensionPart(File))
    Case "ico", "cur"
      IconData\RetVal = __Icon_GetSizesICO(File, *Sizes)
      ;       Debug "Sizes >" + ArraySize(*Sizes\Icon_Size()) + "<"
      ;       Debug "Width >" + Str(*Sizes\Icon_Size(0)\Height) + "<"
      
    Case "bmp"
      ImgHdl = LoadImage(#PB_Any, File)
      If ImgHdl
        ReDim *Sizes\Icon_Size(0)
        *Sizes\Icon_Size(0)\Height = ImageHeight(ImgHdl)
        *Sizes\Icon_Size(0)\Width  = ImageWidth(ImgHdl)
        *Sizes\Icon_Size(0)\BitCnt = ImageDepth(ImgHdl, #PB_Image_OriginalDepth)
        FreeImage(ImgHdl)
      Else
        Debug "ERROR!! Loading File (Icon_GetSizes)"
        IconData\RetVal = - 1
      EndIf
      
    Case "exe", "dll"
      hLibrary = LoadLibraryEx_(File, #Null, #LOAD_LIBRARY_AS_DATAFILE)
      If hLibrary
        IconData\Mode = #Icon_GetSizes
        IconData\Nr   = IconNr
        EnumResourceNames_(hLibrary, #RT_GROUP_ICON, @__Icon_EnumCallback(), @IconData)
        FreeLibrary_(hLibrary)
        
        If IconData\RetVal ; detection of sizes succesfull
          If CopyArray(IconData\Size(), *Sizes\Icon_Size())
            IconData\RetVal = #True
          Else
            Debug "Error CopyArray"
            IconData\RetVal = #False
          EndIf
        Else
          IconData\RetVal = #False
          Debug "Error Callback (Icon_GetSizes)"
        EndIf
      EndIf
      
  EndSelect
  
  ProcedureReturn IconData\RetVal
EndProcedure

Procedure.i Icon_GetHdl(File.s, Width.i = 16, IconNr.i = 1, Height.i = 0)
  Protected IconData.Icon_EnumData
  Protected hLibrary.i
  
  If Height = 0
    Height = Width
  EndIf
  
  Select LCase(GetExtensionPart(File))
    Case "ico"
      IconData\RetVal = LoadImage_(#Null, @File, #IMAGE_ICON, Width, Height, #LR_LOADFROMFILE)
      
    Case "cur"
      IconData\RetVal = LoadImage_(#Null, @File, #IMAGE_CURSOR, Width, Height, #LR_LOADFROMFILE)
      
    Case "bmp"
      IconData\RetVal = LoadImage_(#Null, @File, #IMAGE_BITMAP, Width, Height, #LR_LOADFROMFILE)
      
    Case "exe", "dll"
      hLibrary = LoadLibraryEx_(File, #Null, #LOAD_LIBRARY_AS_DATAFILE)
      If hLibrary
        IconData\RetVal         = 0
        IconData\Size(0)\Width  = Width
        IconData\Size(0)\Height = Height
        IconData\Nr             = IconNr
        IconData\Mode           = #Icon_GetSclHdl
        EnumResourceNames_(hLibrary, #RT_GROUP_ICON, @__Icon_EnumCallback(), @IconData)
        FreeLibrary_(hLibrary)
      EndIf
    Default
      IconData\RetVal = 0
  EndSelect
  
  ProcedureReturn IconData\RetVal
EndProcedure

Procedure.i Icon_GetRealHdl(File.s, Width.i = 16, IconNr.i = 1, Height.i = 0, BPP.a = 0)
  Protected IconData.Icon_EnumData
  Protected hLibrary.i
  Protected ImgHdl.i
  
  If Width = 256 And LCase(GetExtensionPart(File)) <> "bmp" ; this rule is not for BMP files!
    Width = 0                                               ; Width256 is stored as 0 (because it's only 1 Byte, so 255 is max.)
  EndIf
  
  If Height = 0 Or Height = 256
    Height = Width
  EndIf
  
  IconData\RetVal = 0
  
  Select LCase(GetExtensionPart(File))
    Case "ico", "cur"
      IconData\RetVal = __Icon_GetRealHdlICO(File, Width, Height, BPP)
      
    Case "bmp"
      ImgHdl = LoadImage(#PB_Any, File)
      If ImgHdl
        If ImageHeight(ImgHdl) = Height And
           ImageWidth(ImgHdl) = Width And
           (ImageDepth(ImgHdl, #PB_Image_OriginalDepth) = BPP Or BPP = 0)
          IconData\RetVal = Icon_GetHdl(File, Width, 1, Height)
        Else
          Debug "BMP size is not available"
          IconData\RetVal = 0
        EndIf
        FreeImage(ImgHdl)
      Else
        Debug "ERROR!! Loading File (Icon_GetSizes)"
        IconData\RetVal = - 1
      EndIf
      
      
    Case "exe", "dll"
      hLibrary = LoadLibraryEx_(File, #Null, #LOAD_LIBRARY_AS_DATAFILE)
      If hLibrary
        IconData\Mode           = #Icon_GetRealHdl
        IconData\Nr             = IconNr
        IconData\Size(0)\Width  = Width
        IconData\Size(0)\Height = Height
        IconData\Size(0)\BitCnt = BPP
        EnumResourceNames_(hLibrary, #RT_GROUP_ICON, @__Icon_EnumCallback(), @IconData)
        FreeLibrary_(hLibrary)
      EndIf
      
  EndSelect
  
  ProcedureReturn IconData\RetVal
EndProcedure

Procedure.i Icon_GetCnt(File.s)
  Protected IconData.Icon_EnumData
  Protected hLibrary.i
  
  Select LCase(GetExtensionPart(File))
    Case "exe", "dll"
      IconData\Mode   = #Icon_GetCnt
      IconData\RetVal = 0
      
      hLibrary = LoadLibraryEx_(File, #Null, #LOAD_LIBRARY_AS_DATAFILE)
      If hLibrary
        EnumResourceNames_(hLibrary, #RT_GROUP_ICON, @__Icon_EnumCallback(), @IconData)
        FreeLibrary_(hLibrary)
      EndIf
    Case "ico", "cur", "bmp"
      IconData\RetVal = 1
      
    Default
      IconData\RetVal = - 1 ; File not supported
  EndSelect
  
  ProcedureReturn IconData\RetVal
EndProcedure

Procedure Icon_DestroyHdl(hIcon.i)
  DestroyIcon_(hIcon)
EndProcedure

Procedure Icon_GetInfo(hIcon.i, *Size.Icon_Dimension)
  ; http://stackoverflow.com/questions/1913468/how-to-determine-the-size-of-an-icon-from-a-hicon
  Protected IconInf.ICONINFO
  Protected BMInf.BITMAP
  Protected RetVal.i = 1
  
  If (GetIconInfo_(hIcon, IconInf))
    
    If (IconInf\hbmColor) ; ' Icon has colour plane
      If (GetObject_(IconInf\hbmColor, SizeOf(BITMAP), @BMInf))
        *Size\Width  = BMInf\bmWidth
        *Size\Height = BMInf\bmHeight
        *Size\BitCnt = BMInf\bmBitsPixel
        DeleteObject_(IconInf\hbmColor)
      Else
        RetVal = - 3
        Debug "ERROR!! GetObject failed (Icon_GetInfo)"
      EndIf
    Else ;' Icon has no colour plane, image data stored in mask
      If (GetObject_(IconInf\hbmMask, SizeOf(BITMAP), @BMInf))
        *Size\Width  = BMInf\bmWidth
        *Size\Height = BMInf\bmHeight / 2
        *Size\BitCnt = 1
        DeleteObject_(IconInf\hbmMask)
      Else
        RetVal = - 2
        Debug "ERROR!! GetObject failed (Icon_GetInfo)"
      EndIf
    EndIf
  Else
    RetVal = - 1
    Debug "ERROR! GetIconInfo failed (Icon_GetInfo)"
  EndIf
  
  Debug "Width >" + Str(*Size\Width) + "< Height >" + Str(*Size\Height) + "< BPP >" + Str(*Size\BitCnt) + "<"
  
  ProcedureReturn RetVal
EndProcedure

;https://www.purebasic.fr/english/viewtopic.php?t=23387
;SaveIcon.
;By Stephen Rodriguez 2006 (Updated 2010).
;Purebasic 4.5

;This small 'include' file allows for the saving of a single icon/cursor in a .ico/.cur file.
;Extending to include multiple icons/cursors in one file would be straight forward.

;SYNTAX:  SaveIcon(hIcon, filename$)
;         where  'hIcon' is a handle of an icon/cursor either loaded from a resource file or with LoadImage_() etc.

;NOTES.

;  i)   This library can only be used with icons/cursors which are already stored in memory
;       (either loaded from disc, or created with CreateIconIndirect_() etc.) and
;       saves the icon/cursor in the same format (depth etc.) as stored internally by Windows.

;       However, this code can quite 'easily'  be adapted so that icons/cursors can be created from
;       scratch using native Purebasic commands (where images are stored in any format)
;       and then, using the code adapted from this library, saved in .ico/.cur format. It's
;       just a question of messing with colour tables etc.

;  ii)  If using this library to save an icon/cursor loaded With LoadImage_(), then it may appear that
;       the new icon/cursor is of a different size. This will be because the original .ico/.cur file has multiple
;       icons in it of different sizes. Windows explorer may report one size whilst you loaded another etc.

;TODO (maybe!)
;       -Extend the code to save multiple icons/cursors in the same .ico file.
;       -Extend to cursor .cur files  (DONE!)
;**************************************************************************************************
;Result = non-zero if no error.

;Save icon to ico
Procedure.i Icon_SaveToICO(hIcon, filename$)
  Protected result, iconinfo.ICONINFO, hbmMask, hbmColor
  Protected cbitmap.BITMAP, cwidth, cheight, cbitsperpixel, colorcount, colorplanes
  Protected mbitmap.BITMAP, mwidth, mheight, fIcon, xHotspot, yHotspot
  Protected file, imagebytecount, hdc, oldbitmap, mem, bytesinrow, temp
  Protected *bitmapinfo.BITMAPINFO
  ;Get information regarding the icon.
  If Not(GetIconInfo_(hIcon, iconinfo)) : ProcedureReturn 0 : EndIf ;Not a valid icon handle.
  fIcon = 2 - iconinfo\fIcon                                        ;icon = 1, cursor = 2,
  If fIcon = 2                                                      ;Cursor.
    xHotspot = iconinfo\xHotspot
    yHotspot = iconinfo\yHotspot
  EndIf
  ;Allocate memory for a BITMAPINFO structure + a color table with 256 entries.
  *bitmapinfo = AllocateMemory(SizeOf(BITMAPINFO) + SizeOf(RGBQUAD) << 8)
  If *bitmapinfo = 0 : ProcedureReturn 0 :EndIf
  ;Get the mask (AND) bitmap, which, if the icon is B/W monochrome, contains the colour bitmap.
  hbmMask = iconinfo\hbmMask
  GetObject_(hbmMask, SizeOf(BITMAP), mbitmap)
  mwidth  = mbitmap\bmWidth
  mheight = mbitmap\bmHeight
  ;Get the colour (XOR) bitmap.
  hbmColor = iconinfo\hbmColor
  If hbmColor
    GetObject_(hbmColor, SizeOf(BITMAP), cbitmap)
    cwidth        = cbitmap\bmWidth
    cheight       = cbitmap\bmHeight
    cbitsperpixel = cbitmap\bmBitsPixel
    If cbitsperpixel = 0 : cbitsperpixel = 1 : EndIf
    If cbitsperpixel < 8
      colorcount = Pow(2, cbitsperpixel) ;colorcount = 0 if 8 or more bpp.
    EndIf
    colorplanes = cbitmap\bmplanes
  Else ;Monochrome icon.
    cwidth        = mwidth
    cheight       = mheight / 2
    cbitsperpixel = 1
    colorcount    = 2
    colorplanes   = 1
    mheight       = cheight
  EndIf
  ;Ready to start creating the file.
  file = CreateFile(#PB_Any, filename$)
  If file
    ;Write the data.
    ;word = 0
    WriteWord(file, 0)
    ;word = 1 for icon, 2 for cursor.
    WriteWord(file, ficon) ;1 for icon, 2 for cursor.
                           ;word = number of icons in file.
    WriteWord(file, 1)     ;***CHANGE IF EXTENDING CODE TO MORE THAN ONE ICON***
                           ;16 byte ICONDIRENTRY structure, one for each icon.
    WriteByte(file, cwidth)
    WriteByte(file, cheight)
    WriteByte(file, colorcount)
    WriteByte(file, 0) ;Reserved.
    If ficon = 1       ;Icon.
      WriteWord(file, colorplanes) ;Should equal 1, -but just in case!
      WriteWord(file, cbitsperpixel)
    Else ;Cursor.
      WriteWord(file, xhotspot)
      WriteWord(file, yhotspot)
    EndIf
    WriteLong(file, 0) ;TEMPORARY! WE NEED TO RETURN WHEN WE KNOW THE EXACT QUANTITY.
                       ; Size of (InfoHeader + ANDbitmap + XORbitmap)
    WriteLong(file, Loc(file) + 4)  ;FilePos, where InfoHeader starts
                                    ;Now the image data in the form BITMAPINFOHEADER (40 bytes) + colour map for the colour bitmap
                                    ;+ bits of colour bitmap + bits of mask bitmap. Gulp! One for each icon.
                                    ;40 byte BITMAPINFOHEADER structure.
    imagebytecount = SizeOf(BITMAPINFOHEADER)
    WriteLong(file, imagebytecount) ;Should be 40.
    WriteLong(file, cwidth)
    WriteLong(file, cheight + mheight) ;Combined heights of colour + mask images.
    WriteWord(file, colorplanes)       ;Should equal 1, -but just in case!
    WriteWord(file, cbitsperpixel)
    WriteLong(file, 0) ;Compression.
    WriteLong(file, 0) ;Image size. Valid to set to zero if there's no compression.
    WriteLong(file, 0) ;Unused.
    WriteLong(file, 0) ;Unused.
    WriteLong(file, 0) ;Unused.
    WriteLong(file, 0) ;Unused.
                       ;Colour map. Only applies for <= 8 bpp.
    hdc = CreateCompatibleDC_(0) ;Needed in order to get the colour table.
    If hbmColor = 0              ;Monochrome icon.
      WriteLong(file, #Black)
      WriteLong(file, #White)
      imagebytecount + SizeOf(rgbquad) * 2
    ElseIf cbitsperpixel <= 8 ;Includes 1 bit non-monochrome icons.
                              ;Get colour table.
      temp       = Pow(2, cbitsperpixel)
      bytesinrow = SizeOf(rgbquad) * temp
      mem        = AllocateMemory(bytesinrow)
      oldbitmap  = SelectObject_(hdc, hbmColor)
      GetDIBColorTable_(hdc, 0, temp, mem)
      WriteData(file, mem, bytesinrow) ;Write color table.
      FreeMemory(mem)
      SelectObject_(hdc, oldbitmap)
      imagebytecount + bytesinrow
    EndIf
    ;Now the colour image bits. We use GetDiBits_() for this.
    bytesinrow = (cwidth * cbitsperpixel + 31) / 32 * 4  ;Aligned to a 4-byte boundary.
    bytesinrow * cheight
    mem                              = AllocateMemory(bytesinrow)
    *bitmapinfo\bmiHeader\biSize     = SizeOf(BITMAPINFOHEADER)
    *bitmapinfo\bmiHeader\biWidth    = cwidth
    *bitmapinfo\bmiHeader\biPlanes   = colorplanes
    *bitmapinfo\bmiHeader\biBitCount = cbitsperpixel
    If hbmColor
      *bitmapinfo\bmiHeader\biHeight = cheight
      GetDIBits_(hdc, hbmColor, 0, cheight, mem, *bitmapinfo, #DIB_RGB_COLORS)
    Else ;Monochrome color image is the bottom half of the mask image.
      *bitmapinfo\bmiHeader\biHeight = 2*cheight
      GetDIBits_(hdc, hbmMask, 0, cheight, mem, *bitmapinfo, #DIB_RGB_COLORS)
    EndIf
    WriteData(file, mem, bytesinrow)
    FreeMemory(mem)
    imagebytecount + bytesinrow
    ;Now the mask image bits. We use GetDiBits_() for this.
    bytesinrow = (mwidth + 31) / 32 * 4  ;Aligned to a 4-byte boundary.
    bytesinrow * mheight
    mem                              = AllocateMemory(bytesinrow)
    *bitmapinfo\bmiHeader\biWidth    = mwidth
    *bitmapinfo\bmiHeader\biPlanes   = 1
    *bitmapinfo\bmiHeader\biBitCount = 1
    If hbmColor
      *bitmapinfo\bmiHeader\biHeight = mheight
      GetDIBits_(hdc, hbmMask, 0, mheight, mem, *bitmapinfo, #DIB_RGB_COLORS)
    Else
      *bitmapinfo\bmiHeader\biHeight = 2*mheight
      GetDIBits_(hdc, hbmMask, mheight, mheight, mem, *bitmapinfo, #DIB_RGB_COLORS)
    EndIf
    WriteData(file, mem, bytesinrow)
    FreeMemory(mem)
    imagebytecount + bytesinrow
    DeleteDC_(hdc)
    ;Finally, return to the field we missed out.
    FileSeek(file, 14)
    WriteLong(file, imagebytecount)
    CloseFile(file)
    result = 1 ;Signal everything is fine.
  Else
    result = 0
  EndIf
  DeleteObject_(hbmMask) ;These are copies created as a result of GetIconInfo_() and so require deleting.
  DeleteObject_(hbmColor)
  FreeMemory(*bitmapinfo)
  ProcedureReturn result
EndProcedure

;Save icon to png, jpg, bmp, ico, cur
Procedure Icon_SaveToFile(hIcon.i, DestFile.s, plugin)
  ; http://blogs.msdn.com/b/oldnewthing/archive/2010/10/21/10078690.aspx
  ; another approach to combine image and mask:
  ; http://forums.purebasic.com/german/viewtopic.php?p=85298&sid=5a3cfda0f787dc2caec0e8834da98b0a#p85298
  
  Protected TmpImage.i
  Protected TmpMask.i
  Protected IcoInfo.Icon_Dimension
  Protected BmpHdl.i
  Protected ImageDC.i
  Protected MaskDC.i
  Protected PosX.i, PosY.i
  Protected ModeARGB.b = #False
  Protected RetVal = 1
  Protected FreeTmpImage.b = #False
  Protected FreeTmpMask.b = #False
  Protected plugins.i
  
  
  If Not Icon_GetInfo(hIcon, @IcoInfo) Or hIcon <= 0
    Debug "ERROR!! Icon_GetInfo failed!"
    RetVal = - 1
    ProcedureReturn RetVal
  EndIf
  
  
  Select plugin
      
    Case 0
      If LCase(GetExtensionPart(DestFile)) <> "png"
        DestFile + ".png"
      EndIf
      
    Case 1
      If LCase(GetExtensionPart(DestFile)) <> "jpg" Or LCase(GetExtensionPart(DestFile)) <> "jpeg"
        DestFile + ".jpg"
      EndIf
      
    Case 2
      If LCase(GetExtensionPart(DestFile)) <> "bmp"
        DestFile + ".bmp"
      EndIf
      
    Case 3
      If LCase(GetExtensionPart(DestFile)) <> "ico"
        DestFile + ".ico"
      EndIf
      
    Case 4
      If LCase(GetExtensionPart(DestFile)) <> "cur"
        DestFile + ".cur"
      EndIf
      
  EndSelect
  
  
  If RetVal
    TmpImage = CreateImage(#PB_Any, IcoInfo\Width, IcoInfo\Height, 32)
    If TmpImage
      FreeTmpImage = #True
    Else
      Debug "ERROR!! CreateImage (TmpImage) failed!"
      RetVal = - 2
    EndIf
  EndIf
  
  If RetVal
    ImageDC = StartDrawing(ImageOutput(TmpImage))
    If Not ImageDC
      Debug "ERROR!! StartDrawing failed!"
      RetVal = - 3
    EndIf
  EndIf
  
  If RetVal
    If DrawIconEx_(ImageDC, 0, 0, hIcon, 0, 0, 0, 0, #DI_IMAGE);#DI_MASK)
                                                               ;Check if Icon uses 0RGB or ARGB
      DrawingMode(#PB_2DDrawing_AlphaChannel)
      For PosY = 0 To IcoInfo\Height - 1
        For PosX = 0 To IcoInfo\Width - 1
          If (Alpha(Point(PosX, PosY)) > 0) ; ARGB detected
            ModeARGB = #True
            Break 2
          EndIf
        Next
      Next
      StopDrawing()
    Else
      Debug "ERROR!! DrawIconEx failed!"
      RetVal = - 4
    EndIf
  EndIf
  
  If RetVal
    If ModeARGB
      Debug "ARGB used"
    Else
      Debug "0RGB used"
      
      If StartDrawing(ImageOutput(TmpImage)) ;set alpha channel to "opaque"
        DrawingMode(#PB_2DDrawing_AlphaChannel)
        For PosY = 0 To IcoInfo\Height - 1
          For PosX = 0 To IcoInfo\Width - 1
            Plot(PosX, PosY, RGBA(0, 0, 0, 255))
          Next
        Next
        StopDrawing()
      Else
        Debug "ERROR!! StartDrawing (TmpImage) failed!"
        RetVal = - 5
      EndIf
      
      If RetVal
        TmpMask = CreateImage(#PB_Any, IcoInfo\Width, IcoInfo\Height, 24)
        If Not TmpMask
          Debug "ERROR!! CreateImage (TmpMask) failed!"
          RetVal = - 6
        EndIf
      EndIf
      
      If RetVal
        MaskDC = StartDrawing(ImageOutput(TmpMask))
        If MaskDC
          FreeTmpMask = #True
        Else
          Debug "ERROR!! StartDrawing (TmpMask) failed!"
          RetVal = - 7
        EndIf
      EndIf
      
      If RetVal
        If Not DrawIconEx_(MaskDC, 0, 0, hIcon, 0, 0, 0, 0, #DI_MASK)
          Debug "ERROR!! DrawIconEx failed (MaskDC)"
          RetVal = - 8
        EndIf
      EndIf
      
      If RetVal
        For PosY = 0 To IcoInfo\Height - 1
          For PosX = 0 To IcoInfo\Width - 1
            If (Point(PosX, PosY) = $FFFFFF) ; white Pixel - should be fully transparent in Image
              StopDrawing()
              If StartDrawing(ImageOutput(TmpImage))
                DrawingMode(#PB_2DDrawing_AlphaChannel)
                Plot(PosX, PosY, RGBA(0, 0, 0, 0))
                StopDrawing()
              Else
                Debug "ERROR!! StartDrawing (TmpImage) failed!"
                RetVal = - 9
                Break 2
              EndIf
              
              If Not StartDrawing(ImageOutput(TmpMask))
                Debug "ERROR!! StartDrawing (TmpMask) failed!"
                RetVal = - 10
                Break 2
              EndIf
            EndIf
          Next
        Next
        If RetVal
          StopDrawing()
        EndIf
      EndIf
    EndIf
  EndIf
  
  If FreeTmpMask
    FreeImage(TmpMask)
  EndIf
  
  If RetVal
    plugins = #PB_ImagePlugin_PNG
    Select plugin
      Case - 1
        Debug "ERROR!! SaveImage (" + DestFile + ") failed!"
        ProcedureReturn
        
      Case 0;png
        plugins = #PB_ImagePlugin_PNG
        If Not SaveImage(TmpImage, DestFile, #PB_ImagePlugin_PNG, #Null, 32)
          Debug "ERROR!! SaveImage (" + DestFile + ") failed!"
          RetVal = - 11
        EndIf
      Case 1;jpg
        plugins = #PB_ImagePlugin_JPEG
        If Not SaveImage(TmpImage, DestFile, #PB_ImagePlugin_JPEG, #Null, 32)
          Debug "ERROR!! SaveImage (" + DestFile + ") failed!"
          RetVal = - 11
        EndIf
      Case 2;bmp
        plugins = #PB_ImagePlugin_BMP
        If Not SaveImage(TmpImage, DestFile, #PB_ImagePlugin_BMP, #Null, 32)
          Debug "ERROR!! SaveImage (" + DestFile + ") failed!"
          RetVal = - 11
        EndIf
      Case 3, 4;ico & cur
        If Not Icon_SaveToICO(hIcon, DestFile)
          Debug "ERROR!! SaveImage (" + DestFile + ") failed!"
          RetVal = - 11
        EndIf
    EndSelect
    
    
  EndIf
  
  
  If FreeTmpImage
    FreeImage(TmpImage)
  EndIf
  
  ProcedureReturn RetVal
EndProcedure


;-
;- #####  CODE  ################
;- Constant
#LVM_ENABLEGROUPVIEW = #LVM_FIRST + 157
#LVM_MOVEITEMTOGROUP = #LVM_FIRST + 154
#LVM_INSERTGROUP     = #LVM_FIRST + 145

#LVIF_GROUPID = $0100

#LVGA_HEADER_LEFT   = $1
#LVGA_HEADER_CENTER = $2
#LVGA_HEADER_RIGHT  = $4

#LVGS_NORMAL    = $0
#LVGS_COLLAPSED = $1
#LVGS_HIDDEN    = $2

#LVGF_HEADER  = $1
#LVGF_FOOTER  = $2
#LVGF_STATE   = $4
#LVGF_ALIGN   = $8
#LVGF_GROUPID = $10

;- Structure
Structure LVGROUP1 Align #PB_Structure_AlignC
  cbSize.l
  mask.l
  *pszHeader
  cchHeader.l
  *pszFooter
  cchFooter.l
  iGroupId.l
  stateMask.l
  state.l
  uAlign.l
EndStructure

Structure LVITEM1 Align #PB_Structure_AlignC
  mask.l
  iItem.l
  iSubItem.l
  state.l
  stateMask.l
  *pszText
  cchTextMax.l
  iImage.l
  lParam.i
  iIndent.l
  iGroupId.l
  cColumns.l
  puColunns.l
EndStructure

;- Procedure
Procedure ListIcon_EnableGroupView(gadget.l, state.l)
  
  SendMessage_ (GadgetID(gadget), #LVM_ENABLEGROUPVIEW, state, 0)
  
EndProcedure

Procedure ListIcon_CreateImageList(cx, cy, flags = #ILC_COLOR32, cInitial = 0, cGrow = 1)
  
  ProcedureReturn ImageList_Create_(cx, cy, flags, cInitial, cGrow)
  
EndProcedure

Procedure ListIcon_AddImage(himl, hbmImage, hbmMask = 0)
  
  ProcedureReturn ImageList_Add_(himl, hbmImage, hbmMask)
  
EndProcedure

Procedure ListIcon_SetImageList(gadget, himl, iImageList = #LVSIL_SMALL)
  
  ProcedureReturn SendMessage_(GadgetID(gadget), #LVM_SETIMAGELIST, iImageList, himl)
  
EndProcedure

Procedure ListIcon_SetImage(gadget, item, index)
  
  Protected itm.LVITEM1
  
  With itm
    \mask   = #LVIF_IMAGE
    \iItem  = item
    \iImage = index
  EndWith
  
  ProcedureReturn SendMessage_ (GadgetID(gadget), #LVM_SETITEM, 0, @itm)
  
EndProcedure

Procedure ListIcon_AddGroup(gadget.l, text.s, groupid.l)
  
  Protected lvg.LVGROUP1\cbSize = SizeOf(LVGROUP1)
  lvg\mask      = #LVGF_GROUPID | #LVGF_ALIGN | #LVGF_HEADER
  lvg\iGroupId  = groupid
  lvg\uAlign    = #LVGA_HEADER_LEFT
  lvg\pszHeader = @text
  
  SendMessage_ (GadgetID(gadget), #LVM_INSERTGROUP, - 1, @lvg)
  
EndProcedure

Procedure ListIcon_AddItem(gadget.l, text.s, groupid.l, image = - 1) ; SubItems support by Maitre_Kanter
  Protected CountSubItem.i , Index, Item
  Protected itm.LVITEM1\mask
  Protected Buff.s
  CountSubItem = CountString( text , Chr(10) )
  
  Buff = StringField( text , 1 , Chr(10) )
  
  If image >= 0
    itm\mask   = #LVIF_TEXT | #LVIF_GROUPID | #LVIF_IMAGE | #LVIF_DI_SETITEM
    itm\iImage = image
  Else
    itm.LVITEM1\mask = #LVIF_TEXT | #LVIF_GROUPID | #LVIF_DI_SETITEM
  EndIf
  Item         = SendMessage_(GadgetID(gadget), #LVM_GETITEMCOUNT, 0, 0)
  itm\pszText  = @Buff
  itm\iGroupId = groupid
  itm\iItem    = Item
  SendMessage_ (GadgetID(gadget), #LVM_INSERTITEM, 0, @itm)
  
  For Index = 1 To CountSubItem
    Define subitm.LVITEM1\mask = #LVIF_TEXT | #LVIF_GROUPID | #LVIF_DI_SETITEM
    Buff                       = StringField( text , Index + 1 , Chr(10) )
    subitm\mask                = #LVIF_TEXT
    subitm\pszText             = @Buff
    subitm\iGroupId            = groupid
    subitm\iItem               = Item
    subitm\iSubItem            = Index
    SendMessage_ (GadgetID(gadget), #LVM_SETITEM, 0, @subitm)
  Next
  
EndProcedure

Procedure TreeView_ExpandAll()
  
  Protected hwndTV = GadgetID(#tree)
  Protected hRoot = SendMessage_(hwndTV, #TVM_GETNEXTITEM, #TVGN_ROOT, 0)
  Protected hItem = hRoot
  
  Repeat
    SendMessage_(hwndTV, #TVM_EXPAND, #TVE_EXPAND, hItem)
    hItem = SendMessage_(hwndTV, #TVM_GETNEXTITEM, #TVGN_NEXTVISIBLE , hItem)
  Until hItem = #Null
  
  SendMessage_(hwndTV, #TVM_ENSUREVISIBLE, 0, hRoot)
  
EndProcedure

Procedure TreeView_CollapseAll()
  
  Protected hwndTV = GadgetID(#tree)
  Protected hRoot = SendMessage_(hwndTV, #TVM_GETNEXTITEM, #TVGN_ROOT, 0)
  Protected hItem = hRoot
  
  Repeat
    SendMessage_(hwndTV, #TVM_EXPAND, #TVE_COLLAPSE, hItem)
    hItem = SendMessage_(hwndTV, #TVM_GETNEXTITEM, #TVGN_NEXTVISIBLE , hItem)
  Until hItem = #Null
  
  SendMessage_(hwndTV, #TVM_ENSUREVISIBLE, 0, hRoot)
  
EndProcedure


;Gadgets initialization
Procedure Init()
  
  ;Combo file
  ;Windows XP
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\System32\shell32.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\system32\compstui.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\system32\comres.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\system32\dmdskres.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\system32\dsuiext.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\Explorer.exe")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\System32\filemgmt.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\system32\ieframe.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\system32\mmcndmgr.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\System32\moricons.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\system32\mstscax.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\system32\mstsc.exe")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\system32\pifmgr.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\system32\setupapi.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\System32\Stobject.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\system32\wiashext.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\system32\wmploc.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\system32\wpdshext.dll")
  ;Windows 7+
  AddGadgetItem(#combobox_files, - 1, "")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\system32\accessibilitycpl.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\system32\ddores.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\System32\imageres.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\System32\imagesp1.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\system32\netcenter.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windowssystem32netshell.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\system32\networkexplorer.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\system32\pnidui.dll")
  AddGadgetItem(#combobox_files, - 1, "C:\Windows\system32\sensorscpl.dll")
  SetGadgetState(#combobox_files, 6)
  
  ;Splitters
  SetGadgetState(#splitter, 230)
  SetGadgetState(#splitter_tree, GadgetHeight(#splitter_tree) * 2 / 3)
  
  ;Combobox_saveW, H
  AddGadgetItem(#combobox_saveW, - 1, "")
  AddGadgetItem(#combobox_saveW, - 1, "16")
  AddGadgetItem(#combobox_saveW, - 1, "24")
  AddGadgetItem(#combobox_saveW, - 1, "32")
  AddGadgetItem(#combobox_saveW, - 1, "64")
  AddGadgetItem(#combobox_saveW, - 1, "128")
  AddGadgetItem(#combobox_saveW, - 1, "256")
  AddGadgetItem(#combobox_saveW, - 1, "512")
  AddGadgetItem(#combobox_saveW, - 1, "Other")
  AddGadgetItem(#combobox_saveH, - 1, "")
  AddGadgetItem(#combobox_saveH, - 1, "16")
  AddGadgetItem(#combobox_saveH, - 1, "24")
  AddGadgetItem(#combobox_saveH, - 1, "32")
  AddGadgetItem(#combobox_saveH, - 1, "64")
  AddGadgetItem(#combobox_saveH, - 1, "128")
  AddGadgetItem(#combobox_saveH, - 1, "256")
  AddGadgetItem(#combobox_saveH, - 1, "512")
  AddGadgetItem(#combobox_saveH, - 1, "Other")
  SetGadgetState(#combobox_saveW, 6)
  SetGadgetState(#combobox_saveH, 6)
  
  ;   ;#Combobox_saveformat
  ;   AddGadgetItem(#combobox_saveformat, - 1, "png")
  ;   AddGadgetItem(#combobox_saveformat, - 1, "jpg")
  ;   AddGadgetItem(#combobox_saveformat, - 1, "bmp")
  ;   AddGadgetItem(#combobox_saveformat, - 1, "ico")
  ;   AddGadgetItem(#combobox_saveformat, - 1, "cur")
  ;   SetGadgetState(#combobox_saveformat, 0)
  
  ;Image encoder/decoder
  UseJPEGImageDecoder()
  UseJPEGImageEncoder()
  UsePNGImageDecoder()
  UsePNGImageEncoder()
  
  
  
  ;Text_save 'X' vertically
  SetWindowLongPtr_(GadgetID(#text_X), #GWL_STYLE, GetWindowLongPtr_(GadgetID(2), #GWL_STYLE) & ~#SS_CENTER | #SS_CENTERIMAGE)
  SetGadgetText(#text_X, "X")
  
  ;Tree Popup menu
  If CreatePopupMenu(0)
    MenuItem(1, "Collapse All")
    MenuItem(2, "Expand All")
  EndIf
  BindMenuEvent(0, 1, @TreeView_CollapseAll())
  BindMenuEvent(0, 2, @TreeView_ExpandAll())
  
  ;Listicon
  SetWindowLongPtr_(GadgetID(#listicon), #GWL_STYLE, GetWindowLongPtr_(GadgetID(#listicon), #GWL_STYLE) | #WS_CLIPCHILDREN)
  SetGadgetAttribute(#listicon, #PB_ListIcon_DisplayMode, #PB_ListIcon_LargeIcon)
  SendMessage_(GadgetID(#listicon), #LVM_SETEXTENDEDLISTVIEWSTYLE, 0, SendMessage_(GadgetID(#listicon), #LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0) | #LVS_EX_TRACKSELECT)
  SendMessage_(GadgetID(#listicon), #LVM_SETHOVERTIME, 0, 10)
  ;Enable listicon Group view
  ListIcon_EnableGroupView(#ListIcon, 1)
  
EndProcedure

;Parse icon from file + fills the treegadget + fills the listicongadget and updates the progressbargadget
Procedure ParseIconFile(File.s = "")
  
  Protected IconSizes.Icon_Size
  Protected IconCnt.i, Cnt.i, IcCnt.i, ILwnd
  Protected ImID16.i, IconHdl.q, Text$, img, item, Width, Height, BitCnt, itemdata
  Protected group$, sLen, GroupName$, k = 0, ok, i, z
  
  ClearGadgetItems(#tree)
  ClearGadgetItems(#listicon)
  SetGadgetState(#image, 0)
  ClearList(List_listicon())
  SetGadgetState(#progressbar, 0)
  SendMessage_(GadgetID(#tree), #WM_SETREDRAW, 0, 0)
  SendMessage_(GadgetID(#listicon), #WM_SETREDRAW, 0, 0)
  
  If file = ""
    File = GetGadgetText(#combobox_files)
  Else
    SetGadgetText(#combobox_files, File)
  EndIf
  
  ILwnd = ListIcon_CreateImageList(iSize, iSize, #ILC_COLOR32 | #ILC_MASK, 0, 300)
  SendMessage_(GadgetID(#listicon), #LVM_SETIMAGELIST, #LVSIL_NORMAL, ILwnd)
  
  IconCnt = Icon_GetCnt(File)
  SetGadgetAttribute(#progressbar, #PB_ProgressBar_Maximum, IconCnt)
  For Cnt = 1 To IconCnt
    ImID16 = Icon_GetHdl(File, 16, Cnt)
    AddGadgetItem(#tree, - 1, "IconNr. " + Str(Cnt), ImID16 , 0)
    SetGadgetItemData(#tree, CountGadgetItems(#tree) - 1, Cnt)
    Icon_GetSizes(File, @IconSizes, Cnt)
    
    ListIcon_AddGroup(#ListIcon, Str(Cnt), Cnt)
    
    For IcCnt = 0 To ArraySize(IconSizes\Icon_Size())
      Width  = IconSizes\Icon_Size(IcCnt)\Width
      Height = IconSizes\Icon_Size(IcCnt)\Height
      BitCnt = IconSizes\Icon_Size(IcCnt)\BitCnt
      Text$  = Str(Width) + "x" + Str(Height) + "@" + Str(BitCnt) + "BPP"
      If ImID16
        AddGadgetItem(#tree, - 1, Text$, ImID16, 1)
        SetGadgetItemData(#tree, CountGadgetItems(#tree) - 1, Cnt)
      EndIf
      
      AddElement(List_listicon())
      List_listicon()\id  = Cnt
      List_listicon()\w   = Width
      List_listicon()\h   = Height
      List_listicon()\bpp = BitCnt
      
      File    = GetGadgetText(#combobox_files)
      IconHdl = Icon_GetRealHdl(File, Width, Cnt, Height, BitCnt)
      
      img = CreateImage(#PB_Any, iSize, iSize)
      If img And StartDrawing(ImageOutput(img))
        Box(0, 0, iSize, iSize, $B5BEB2)
        If IconHdl > 0
          DrawImage(IconHdl, iSize / 2 - Width / 2, iSize / 2 - Height / 2)
        EndIf
        Icon_DestroyHdl(IconHdl)
        StopDrawing()
        
        ListIcon_AddImage(ILwnd, ImageID(img))
        k + 1
        
      EndIf
      ListIcon_AddItem(#ListIcon, Text$, Cnt)
      SetGadgetState(#progressbar, Cnt)
    Next
    
  Next
  
  For i = 0 To k
    ListIcon_SetImage(#ListIcon, i, i)
  Next
  
  SendMessage_(GadgetID(#tree), #WM_SETREDRAW, 1, 0)
  SendMessage_(GadgetID(#listicon), #WM_SETREDRAW, 1, 0)
EndProcedure

;Change file with an OpenFileRequester
Procedure SelectFile()
  
  Protected File.s
  
  File = OpenFileRequester("Please select file", "", "FileWithIcon|*.ico;*.cur;*.exe;*.dll;*.bmp", 1)
  If File
    ParseIconFile(File)
  EndIf
  
EndProcedure

;Displays a zoomed icon when you click on a level 0 tree item, or if you hover an icon in the listicon
Procedure LoadIcon(Gadget = #tree)
  
  Protected IconNr.i
  Protected Width.i
  Protected Height.i
  Protected BitCnt.i
  Protected Text.s
  Protected IconHdl.i
  Protected OldIconHdl.i
  Protected File.s
  Protected Nr.i
  
  File = GetGadgetText(#combobox_files)
  
  Select Gadget
    Case #Tree
      Text   = GetGadgetText(#tree)
      Nr     = GetGadgetState(#tree)
      IconNr = GetGadgetItemData(#tree, Nr)
      
      If IconNr
        
        Select (GetGadgetItemAttribute(#tree, Nr, #PB_Tree_SubLevel))
          Case 0
            Width   = Val(GetGadgetText(#combobox_saveW))
            Height  = Val(GetGadgetText(#combobox_saveH))
            IconHdl = Icon_GetHdl(File, Width, IconNr, Height)
            
          Case 1
            Width  = Val(StringField(Text, 1, "x"))
            Text   = StringField(Text, 2, "x")
            Height = Val(StringField(Text, 1, "@"))
            Text   = StringField(Text, 2, "@")
            BitCnt = Val(StringField(Text, 1, "BPP"))
            
            IconHdl = Icon_GetRealHdl(File, Width, IconNr, Height, BitCnt)
        EndSelect
      EndIf
      
    Case #listicon
      Width   = List_listicon()\w
      Height  = List_listicon()\h
      BitCnt  = List_listicon()\bpp
      IconNr  = List_listicon()\id
      IconHdl = Icon_GetRealHdl(File, Width, IconNr, Height, BitCnt)
      
    Default
      ProcedureReturn
  EndSelect
  
  If IconHdl
    If IsGadget(#Image)
      OldIconHdl = GetGadgetState(#Image)
      If (OldIconHdl)
        SetGadgetState(#Image, 0)
        Icon_DestroyHdl(OldIconHdl)
      EndIf
      SetGadgetState(#Image, IconHdl)
      
    EndIf
  EndIf
  
EndProcedure




;Save on a file the icon cliked on the tree or hovered on the listicon
Procedure SaveIcon()
  
  Protected File.s, Filter$, Res.i
  
  If IsGadget(#Image)
    Filter$ = "PNG (*.png)|*.png|JPG (*.jpg)|*.jpg|BMP (*.bmp)|*.bmp|ICO (*.ico)|*.ico|CUR (*.cur)|*.cur"
    File    = SaveFileRequester("Define destination file", "", Filter$, 0)
    If File
      Res = Icon_SaveToFile(GetGadgetState(#Image), File, SelectedFilePattern())
      If Res < 1
        ;MessageRequester("ERROR", "Icon_SaveToFile failed!")
        MessageRequester("Save icon to file", "Can't Save icon to file.", #PB_MessageRequester_Ok | #PB_MessageRequester_Error)
      EndIf
      
    EndIf
  Else
    MessageRequester("Information", "Nothing to save!")
  EndIf
  
EndProcedure

;- Procedure runtime (from the Dialog window)
Runtime Procedure Onchange_combobox_files()
  
  ParseIconFile(GetGadgetText(#combobox_files))
  TreeView_ExpandAll()
  
EndProcedure

Runtime Procedure Onclick_button_openfile()
  
  SelectFile()
  TreeView_ExpandAll()
  
EndProcedure

Runtime Procedure Onclick_tree()
  
  LoadIcon()
  
EndProcedure

Runtime Procedure OnRclick_tree()
  
  DisplayPopupMenu(0, WindowID(#win))
  
EndProcedure

Runtime Procedure Onclick_button_saveimage()
  
  SaveIcon()
  
EndProcedure

Runtime Procedure Onclick_listicon()
  ;ToDo
EndProcedure

Runtime Procedure Onchange_listicon()
  
  Protected n = GetGadgetState(#listicon)
  
  If n >= 0
    SelectElement(List_listicon(), n)
    LoadIcon(#listicon)
  EndIf
  
EndProcedure

Runtime Procedure Onchange_combobox_saveW()
  Onclick_tree()
EndProcedure

Runtime Procedure Onchange_combobox_saveH()
  Onclick_tree()
EndProcedure


;- Window Dialog
Define i, R , ok
Define a$ = GetXMLString()
If ParseXML(0, a$) And XMLStatus(0) = #PB_XML_Success
  For i = 1 To #DD_WindowCount
    CreateDialog(i)
    CompilerIf #DD_UseExtraStuff
      R = DEX::InitDialog(i, 0, DD_WindowNames(i), 1)
    CompilerElse
      R = OpenXMLDialog(i, 0, DD_WindowNames(i))
    CompilerEndIf
    If R
      
      HideWindow(DialogWindow(i), 0)
      ok = #True
      
      ;- Go
      Init()
      ParseIconFile()
      TreeView_ExpandAll()
      
    Else
      Debug DialogError(i)
    EndIf
  Next i
  CompilerIf Defined(PB_OS_Web, #PB_Constant) = 0 Or #PB_Compiler_OS <> #PB_OS_Web
    If ok
      ;- Loop
      While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend
      ;Repeat
      ;Select WaitWindowEvent()
      ;Case #PB_Event_CloseWindow
      ;Break
      
      ;Case #WM_RBUTTONDOWN
      ;If EventGadget() = #...
      ;DisplayPopupMenu(0, WindowID(#mainwin))
      ; EndIf
      
      ;EndSelect
      ;ForEver
    EndIf
  CompilerEndIf
Else
  Debug XMLStatus(0)
  Debug XMLError(0)
EndIf
CompilerIf #DD_UseExtraStuff
  DEX::DeInit()
CompilerEndIf
;-

;- END


ExtractIcons.xml.dd.pbi

Code : Tout sélectionner

;
;- TOP
;
; __________________________
;|
;|  Dialog
;|
;|  Date:
;|
;|  Author: Dialog MESA
;|
;|  PB version: 6.02
;|
;|  OS: All
;|
;|  CPU: All
;|
;|  Note:
;|
;|
;|
;|___________________________


;- Constante
#DD_WindowCount   = 1
#DD_UseExtraStuff = 0

CompilerIf #DD_UseExtraStuff
  XIncludeFile "../../gadget/dialog/DialogDesign0r/DD_AddStuff.pbi"
CompilerEndIf

Runtime Enumeration Windows
  #Win
EndEnumeration


Dim DD_WindowNames.s(#DD_WindowCount)

DD_WindowNames(1) = "window"


Runtime Enumeration Gadgets
  #splitter
  #container_tree_image
  #combobox_files
  #button_openfile
  #splitter_tree
  #tree
  #scrollarea
  #image
  #frame_zoom
  #combobox_saveW
  #text_X
  #combobox_saveH
  #frame_save
  #button_saveimage
  #container_listicon
  #listicon
  #progressbar
EndEnumeration

;- Declare
Declare Onchange_combobox_files()
Declare Onclick_button_openfile()
Declare OnRclick_tree()
Declare Onclick_tree()
Declare Onchange_combobox_saveW()
Declare Onchange_combobox_saveH()
Declare Onclick_button_saveimage()
Declare Onchange_listicon()
Declare Onclick_listicon()



;- XML
Procedure.s GetXMLString()
  Protected XML$
  
  XML$ + "<?xml version='1.0' encoding='UTF-16'?>"
  XML$ + ""
  XML$ + "<dialogs><!--Created by Dialog Design0R V1.85 => get it from: https://hex0rs.coderbu.de/en/sdm_downloads/dialogdesign0r/-->"
  XML$ + "  <window flags='#PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_ScreenCentered' width='900' height='700' margin='vertical:3,horizontal:0' name='window' xpos='0' ypos='0' id='#Win'>"
  XML$ + "    <vbox spacing='3'>"
  XML$ + "      <hbox spacing='0'>"
  XML$ + "        <splitter flags='#PB_Splitter_Vertical | #PB_Splitter_Separator' id='#splitter'>"
  XML$ + "          <container margin='vertical:0,horizontal:0' id='#container_tree_image'>"
  XML$ + "            <vbox expand='item:2'>"
  XML$ + "              <hbox expand='item:1' spacing='0'>"
  XML$ + "                <combobox text='shell32.dll' flags='#PB_ComboBox_Editable' id='#combobox_files' onchange='Onchange_combobox_files()'/>"
  XML$ + "                <button text='...' id='#button_openfile' onevent='Onclick_button_openfile()'/>"
  XML$ + "              </hbox>"
  XML$ + "              <splitter flags='#PB_Splitter_Separator' id='#splitter_tree'>"
  XML$ + "                <tree width='300' height='300' id='#tree' onleftclick='Onclick_tree()' onrightclick='OnRclick_tree()'/>"
  XML$ + "                <scrollarea id='#scrollarea'>"
  XML$ + "                  <image width='300' height='300' id='#image'/> "
  XML$ + "                </scrollarea> "
  XML$ + "              </splitter>"
  XML$ + "              <hbox expand='item:6'>"
  XML$ + "                <frame text='Zoom' id='#frame_zoom'>"
  XML$ + "                  <hbox>"
  XML$ + "                    <combobox flags='#PB_ComboBox_Editable' text='256' width='60' id='#combobox_saveW' onchange='Onchange_combobox_saveW()'/>"
  XML$ + "                    <text text='X' flags='#PB_Text_Center' id='#text_X'/>"
  XML$ + "                    <combobox text='256' width='60' flags='#PB_ComboBox_Editable' id='#combobox_saveH' onchange='Onchange_combobox_saveH()'/> "
  XML$ + "                  </hbox> "
  XML$ + "                </frame>"
  XML$ + "                <frame text='Save' id='#frame_save'>"
  XML$ + "                  <hbox>"
  XML$ + "                    <button text='Save' id='#button_saveimage' onevent='Onclick_button_saveimage()'/> "
  XML$ + "                  </hbox> "
  XML$ + "                </frame> "
  XML$ + "              </hbox> "
  XML$ + "            </vbox> "
  XML$ + "          </container>"
  XML$ + "          <container margin='vertical:0,horizontal:0' id='#container_listicon'>"
  XML$ + "            <vbox expand='item:1'>"
  XML$ + "              <listicon id='#listicon' onleftclick='Onclick_listicon()' onchange='Onchange_listicon()'/>"
  XML$ + "              <progressbar height='20' min='0' max='100' value='0' id='#progressbar'/>"
  XML$ + "            </vbox> "
  XML$ + "          </container> "
  XML$ + "        </splitter> "
  XML$ + "      </hbox> "
  XML$ + "    </vbox> "
  XML$ + "  </window>"
  XML$ + "</dialogs><!--DDesign0R Definition: PureBasic|1|1|1|_04|Mesa|1-->"
  
  ProcedureReturn XML$
EndProcedure


;- Test it

CompilerIf #PB_Compiler_IsMainFile
  
  ;- Procedure runtime
  Runtime Procedure Onchange_combobox_files()
    
  EndProcedure
  
  Runtime Procedure Onclick_button_openfile()
    
  EndProcedure
  
  Runtime Procedure OnRclick_tree()
    
  EndProcedure
  
  Runtime Procedure Onclick_tree()
    
  EndProcedure
  
  Runtime Procedure Onchange_combobox_saveW()
    
  EndProcedure
  
  Runtime Procedure Onchange_combobox_saveH()
    
  EndProcedure
  
  Runtime Procedure Onclick_button_saveimage()
    
  EndProcedure
  
  Runtime Procedure Onchange_listicon()
    
  EndProcedure
  
  Runtime Procedure Onclick_listicon()
    
  EndProcedure
  
  
  
  
  
  ;- Entry point
  a$ = GetXMLString()
  If ParseXML(0, a$) And XMLStatus(0) = #PB_XML_Success
    For i = 1 To #DD_WindowCount
      CreateDialog(i)
      CompilerIf #DD_UseExtraStuff
        R = DEX::InitDialog(i, 0, DD_WindowNames(i), 1)
      CompilerElse
        R = OpenXMLDialog(i, 0, DD_WindowNames(i))
      CompilerEndIf
      If R
        HideWindow(DialogWindow(i), 0)
        ok = #True
        ;Init()
      Else
        Debug DialogError(i)
      EndIf
    Next i
    CompilerIf Defined(PB_OS_Web, #PB_Constant) = 0 Or #PB_Compiler_OS <> #PB_OS_Web
      If ok
        While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend
        ;Repeat
        ;Select WaitWindowEvent()
        ;Case #PB_Event_CloseWindow
        ;Break
        
        ;Case #WM_RBUTTONDOWN
        ;If EventGadget() = #...
        ;DisplayPopupMenu(0, WindowID(#mainwin))
        ; EndIf
        
        ;EndSelect
        ;ForEver
      EndIf
    CompilerEndIf
  Else
    Debug XMLStatus(0)
    Debug XMLError(0)
  EndIf
  CompilerIf #DD_UseExtraStuff
    DEX::DeInit()
  CompilerEndIf
  
CompilerEndIf

;- End

MESA.
Dernière modification par Mesa le lun. 28/oct./2024 16:09, modifié 4 fois.
Avatar de l’utilisateur
ZapMan
Messages : 460
Inscription : ven. 13/févr./2004 23:14
Localisation : France
Contact :

Re: YAIG: Yet Another Icon Grabber

Message par ZapMan »

Bah, je l'aurais bien testé sur Windows 11, mais il manque déjà "ExtractIcons.xml.dd.pbi" référencé dans le premier code :cry:

Tu voudrais pas faire un zip avec tout ce qu'il faut ?
Tout obstacle est un point d'appui potentiel.

Bibliothèques PureBasic et autres codes à télécharger :https://www.editions-humanis.com/downlo ... ads_FR.htm
Mesa
Messages : 1126
Inscription : mer. 14/sept./2011 16:59

Re: YAIG: Yet Another Icon Grabber

Message par Mesa »

Si, si, je l'ai mis en gros, gras, souligné et en rouge.... :lol:

M.
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: YAIG: Yet Another Icon Grabber

Message par Kwai chang caine »

Marche bien ici avec le PBI en gros, gras, souligné et en rouge :mrgreen:
Du bon travail merci pour le partage 8)
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Avatar de l’utilisateur
cage
Messages : 604
Inscription : ven. 16/oct./2015 18:22
Localisation : France
Contact :

Re: YAIG: Yet Another Icon Grabber

Message par cage »

Bonsoir,

Merci pour ce partage.

Application fonctionnelle et agréable a utiliser.
Je me suis créé un fichier projet YAIG.pbp qui me permet de compiler en 32-bit et 64-bit.
Je n'ai pas vu de différence entre l'application compilée en 32 ou 64
Mon seul regret, il n'est pas possible de sauvegarder une icône en format ico.
Le fichier YAIG.pbp

Code : Tout sélectionner

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://www.purebasic.com/namespace" version="1.0" creator="PureBasic 6.12 LTS (Windows - x64)">
  <section name="config">
    <options closefiles="1" openmode="1" name="YAIG.pbp"/>
    <buildwindow autoclose="1"/>
  </section>
  <section name="data">
    <explorer view="..\" pattern="0"/>
    <log show="1"/>
    <lastopen date="2024-10-24 20:04" user="admin" host="EBCAGE"/>
  </section>
  <section name="files">
    <file name="YAIG.pb">
      <config load="1" scan="1" panel="1" warn="1" lastopen="1" sortindex="1" panelstate="+"/>
      <fingerprint md5="b909af5363eddf2d60a4a839634a6d61"/>
    </file>
  </section>
  <section name="targets">
    <target name="Default Target" enabled="1" default="1">
      <inputfile value="YAIG.pb"/>
      <outputfile value="YAIG.exe"/>
      <compiler version="PureBasic 6.12 LTS (Windows - x64)"/>
      <executable value="YAIG.exe"/>
      <options unicode="1" thread="1" xpskin="1" dpiaware="1" dllprotection="1" debug="1" optimizer="1"/>
      <purifier enable="1"/>
      <temporaryexe value="source"/>
      <icon enable="1">icones\YAIG.ico</icon>
      <versioninfo enable="1">
        <field0 value="24,10,0,24"/>
        <field1 value="24,10,0,24"/>
        <field2 value="CAGE"/>
        <field3 value="YAIG"/>
        <field4 value="24.10.24"/>
        <field5 value="24.10.24"/>
        <field6 value="YAIG - Yet Another Icon Grabber"/>
        <field7 value="YAIG.exe"/>
        <field8 value="YAIG.exe"/>
        <field9 value="© CAGE"/>
        <field10 value="This software is the property of the author : MESA"/>
        <field11 value="0"/>
        <field12 value="0"/>
      </versioninfo>
    </target>
    <target name="Default Target (x64)" enabled="1" default="0">
      <inputfile value="YAIG.pb"/>
      <outputfile value="x64\YAIG.exe"/>
      <compiler version="PureBasic 6.12 LTS (Windows - x64)"/>
      <executable value="x64\YAIG.exe"/>
      <options unicode="1" thread="1" xpskin="1" dpiaware="1" dllprotection="1" debug="1" optimizer="1"/>
      <purifier enable="1"/>
      <temporaryexe value="source"/>
      <icon enable="1">icones\YAIG.ico</icon>
      <versioninfo enable="1">
        <field0 value="24,10,0,24"/>
        <field1 value="24,10,0,24"/>
        <field2 value="CAGE"/>
        <field3 value="YAIG"/>
        <field4 value="24.10.24"/>
        <field5 value="24.10.24"/>
        <field6 value="YAIG - Yet Another Icon Grabber"/>
        <field7 value="YAIG.exe"/>
        <field8 value="YAIG.exe"/>
        <field9 value="© CAGE"/>
        <field10 value="This software is the property of the author : MESA"/>
        <field11 value="0"/>
        <field12 value="0"/>
      </versioninfo>
    </target>
    <target name="Default Target (x86)" enabled="1" default="0">
      <inputfile value="YAIG.pb"/>
      <outputfile value="x86\YAIG.exe"/>
      <compiler version="PureBasic 6.12 LTS (Windows - x86)"/>
      <executable value="x86\YAIG.exe"/>
      <options unicode="1" thread="1" xpskin="1" dpiaware="1" dllprotection="1" debug="1" optimizer="1"/>
      <purifier enable="1"/>
      <temporaryexe value="source"/>
      <icon enable="1">icones\YAIG.ico</icon>
      <versioninfo enable="1">
        <field0 value="24,10,0,24"/>
        <field1 value="24,10,0,24"/>
        <field2 value="CAGE"/>
        <field3 value="YAIG"/>
        <field4 value="24.10.24"/>
        <field5 value="24.10.24"/>
        <field6 value="YAIG - Yet Another Icon Grabber"/>
        <field7 value="YAIG.exe"/>
        <field8 value="YAIG.exe"/>
        <field9 value="© CAGE"/>
        <field10 value="This software is the property of the author : MESA"/>
        <field11 value="0"/>
        <field12 value="0"/>
      </versioninfo>
    </target>
  </section>
</project>
Nécessite la création de 3 dossiers dans le dossier de YAIG, Icones, x64 et x86
L'icône que j'ai utilisé est disponible ici : YAIG.ico
cage
■ Win10 Pro 64-bit (Intel Celeron CPU N2920 @ 1.86GHz, 4,0GB RAM, Intel HD Graphics) & PB 6.12 LTS
■ Vivre et laisser vivre.
■ PureBasic pour le fun
■ Gérard sur le forum Anglais
■ Mes sites: http://pbcage.free.fr - http://yh.toolbox.free.fr
Mesa
Messages : 1126
Inscription : mer. 14/sept./2011 16:59

Re: YAIG: Yet Another Icon Grabber

Message par Mesa »

Petite maj, j'ai tenté d'ajouter le format ico et cur en enregistrement.
Si ça ne marche pas bien, vous pouvez changer la Procedure.i Icon_SaveToICO(hIcon, filename$) par la vôtre.

Les deux fichiers ont été modifiés.

M.
Avatar de l’utilisateur
cage
Messages : 604
Inscription : ven. 16/oct./2015 18:22
Localisation : France
Contact :

Re: YAIG: Yet Another Icon Grabber

Message par cage »

Bonjour,

Image

Je viens de tester cette nouvelle version et voila ce que j'obtiens.
Pas de possibilité de choisir le format de l'icône a sauvegarder.
Si je clique sur le bouton Save et que je choisis ICO (*.ico) j'obtiens le message suivant:

Code : Tout sélectionner

Width >32< Height >32< BPP >32<
0RGB used
cage
■ Win10 Pro 64-bit (Intel Celeron CPU N2920 @ 1.86GHz, 4,0GB RAM, Intel HD Graphics) & PB 6.12 LTS
■ Vivre et laisser vivre.
■ PureBasic pour le fun
■ Gérard sur le forum Anglais
■ Mes sites: http://pbcage.free.fr - http://yh.toolbox.free.fr
Mesa
Messages : 1126
Inscription : mer. 14/sept./2011 16:59

Re: YAIG: Yet Another Icon Grabber

Message par Mesa »

J'ai mis à jour le code et maintenant la sauvegarde en ico marche chez moi.
Pas de possibilité de choisir le format de l'icône à sauvegarder.
Oui, comme l'openrequester permet ce choix, c'était redondant.

M.
Avatar de l’utilisateur
ZapMan
Messages : 460
Inscription : ven. 13/févr./2004 23:14
Localisation : France
Contact :

Re: YAIG: Yet Another Icon Grabber

Message par ZapMan »

Mesa a écrit : jeu. 24/oct./2024 16:15 Si, si, je l'ai mis en gros, gras, souligné et en rouge.... :lol:
M.
Je te promets que je ne fais pas exprès d'être idiot. Mais, contrairement à ce que beaucoup s'imaginent, ce n'est pas la taille qui compte :mrgreen:
Si tu avais juste ajouté deux points derrière le nom du fichier, j'aurais peut-être compris qu'il fallait enregistrer le deuxième code sous ce nom là. On a plutôt l'habitude de trouver les libs en premier et les fichiers qui les utilisent ensuite. Mais, bon, bref, voilà.

Sinon, ça tourne impeccable et c'est beau comme tout. L'enregistrement en .ico marche chez moi. Le seul problème pratique que j'ai rencontré, c'est que la taille d'icone enregistrée est apparemment la dernière qui a été survolée par la souris. Du coup, si elle n'est pas proche du bouton 'Save', il faut faire du slalom avec la souris pour ne pas en survoler une autre par mégarde avant d'atteindre le bouton save. Plutôt qu'une sélection au survol, tu pourrais faire une sélection au clic, ça serait plus sûr. Mais c'est un détail.

Rien à redire sur le code : c'est clair, propre et bien présenté.
Tout obstacle est un point d'appui potentiel.

Bibliothèques PureBasic et autres codes à télécharger :https://www.editions-humanis.com/downlo ... ads_FR.htm
Avatar de l’utilisateur
SPH
Messages : 4937
Inscription : mer. 09/nov./2005 9:53

Re: YAIG: Yet Another Icon Grabber

Message par SPH »

Merci Mesa :idea:

!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.12LTS- 64 bits
Avatar de l’utilisateur
cage
Messages : 604
Inscription : ven. 16/oct./2015 18:22
Localisation : France
Contact :

Re: YAIG: Yet Another Icon Grabber

Message par cage »

Cool et fonctionnel.

J'aimais bien la sélection par le bouton Save, mais bon Le programmeur a ses raisons que la raison ne connaît point. :)

La sauvegarde ico fonctionne correctement. :D

Merci du partage.

cage
■ Win10 Pro 64-bit (Intel Celeron CPU N2920 @ 1.86GHz, 4,0GB RAM, Intel HD Graphics) & PB 6.12 LTS
■ Vivre et laisser vivre.
■ PureBasic pour le fun
■ Gérard sur le forum Anglais
■ Mes sites: http://pbcage.free.fr - http://yh.toolbox.free.fr
Répondre