; ; Changing icon resources in executables (the NT-API way) ; ; ; NOTE: Needs NT, 2000 or XP to work ; ; ; ; WARNING: the following code is known to fail in certain cases ; be sure to backup your data before using this! ; ; ; ; (:t)raumatic - february 2005 ; #RT_GROUP_ICON = #RT_ICON + 11 ; http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwui/html/msdn_icons.asp Structure ICONDIRENTRYCOMMON bWidth.b ; Width, in pixels, of the image bHeight.b ; Height, in pixels, of the image bColorCount.b ; Number of colors in image (0 if >=8bpp) bReserved.b ; Reserved ( must be 0) wPlanes.w ; Color Planes wBitCount.w ; Bits per pixel dwBytesInRes.l ; How many bytes in this resource? EndStructure ; Structure ICONDIRENTRY common.ICONDIRENTRYCOMMON 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? idEntries.ICONDIRENTRY[0] ; An entry for each image (idCount of 'em) EndStructure ; Structure GRPICONDIRENTRY common.ICONDIRENTRYCOMMON nId.w ; the ID EndStructure Structure GRPICONDIR idReserved.w ; Reserved (must be 0) idType.w ; Resource type (1 for icons) idCount.w ; How many images? idEntries.GRPICONDIRENTRY[0] ; The entries for each image EndStructure ; ; Change Icon-Resource in "exeFilename.s" with "iconFileName.s" ; Procedure.l ChangeIcon(iconFileName.s, exeFileName.s) *icon.ICONDIR = AllocateMemory(SizeOf(ICONDIR)) If ReadFile(0, iconFileName.s) ReadData(*icon, SizeOf(ICONDIR)) *icon = ReAllocateMemory(*icon, SizeOf(ICONDIR) + (*icon\idCount*2) *SizeOf(ICONDIRENTRY)) For i=0 To *icon\idCount-1 FileSeek(6+SizeOf(ICONDIRENTRY) * i) ; SizeOf(ICONDIR) - SizeOf(ICONDIRENTRY) = 6 ReadData(*icon\idEntries[i], SizeOf(ICONDIRENTRY) * (i+1)) Next ; hInst.l = BeginUpdateResource_(exeFileName, #False) If hInst = 0 retVal.l = #False Else ; CHANGE #RT_GROUP_ICON *iconGroup.GRPICONDIR = AllocateMemory(SizeOf(GRPICONDIR) + 6 + SizeOf(GRPICONDIRENTRY) * *icon\idCount) For i=0 To *icon\idCount-1 CopyMemory(*icon\idEntries[i]\common, *iconGroup\idEntries[i]\common, SizeOf(ICONDIRENTRYCOMMON)) *iconGroup\idEntries[i]\nId = (i+1) Next *iconGroup\idReserved = 0 *iconGroup\idType = 1 *iconGroup\idCount = *icon\idCount ; ; TODO: Error with bColorCount ; Written value is always wrong!? (e.g. 1 instead of 16) ; retVal = UpdateResource_(hInst, #RT_GROUP_ICON, 1, #LANG_NEUTRAL, *iconGroup, 6+SizeOf(GRPICONDIRENTRY)* *iconGroup\idCount) FreeMemory(*iconGroup) : *iconGroup = #Null ; CHANGE #RT_ICON For i = 0 To *icon\idCount-1 ; get the desired icon from .ico file *resData = AllocateMemory(*icon\idEntries[i]\common\dwBytesInRes) FileSeek(*icon\idEntries[i]\dwImageOffset) ReadData(*resData, *icon\idEntries[i]\common\dwBytesInRes) retVal = UpdateResource_(hInst, #RT_ICON, (i+1), #LANG_NEUTRAL, *resData, *icon\idEntries[i]\common\dwBytesInRes) Next retVal = EndUpdateResource_(hInst, #False) FreeMemory(*resData) : *resData = #Null EndIf FreeMemory(*icon) : *icon = #Null CloseFile(0) Else retVal = #False EndIf ProcedureReturn retVal EndProcedure ; Idea from Rikuk ; File specifies the file where icon is extracted ; icon = 0 to ? --> Return handle of image ; icon = -1 --> Return the count of icon Procedure IconExtract(File.s,Icon.l) ProcedureReturn ExtractIcon_(0,File,Icon) EndProcedure ;/ Test #file="shell32.dll" Count=IconExtract(#file,-1) OpenWindow(0,0,0,130,70,Str(Count)+" Icons",#PB_Window_SystemMenu|#PB_Window_ScreenCentered) CreateGadgetList(WindowID(0)) ButtonImageGadget(0,10,10,48,48,IconExtract(#file,pointer)) TextGadget(1,80,30,40,20,"n° 1") Repeat event=WaitWindowEvent() If event= #PB_Event_Gadget And EventGadget()=0 And EventType()=#PB_EventType_LeftClick pointer+1 If pointer=Count : pointer=0 : EndIf SetGadgetState(0,IconExtract(#file,pointer)) SetGadgetText(1,"n° "+Str(pointer+1)) EndIf Until event=#PB_Event_CloseWindow