I´m using this over ~2 years, and work fine for me. But I also modified / changed it a bit according to my requirements. And now changed a little bit back for this post.
Code: Select all
;FileDelete
FileDelete, % A_ScriptDir . "\Icons.DLL"
Sleep, 250
;Create
Function_CreateIconsDll("Icons.DLL", A_ScriptDir . "\ICONSETS\normal")
Sleep, 250
Return
Function_CreateIconsDll(File_Path, File_PathDir)
{
If !FileExist(File_Path)
{
Function_DllCreateEmpty(File_Path)
}
Index := 1, Counter := 0
, module := DllCall("BeginUpdateResource", "str", File_Path, "uint", 0, "ptr")
Loop, % File_PathDir "\*.ico"
{
Counter++
, Index := Function_ReplaceIcon(module, A_LoopFileLongPath, Index)
If (Counter = 20)
{
DllCall("EndUpdateResource", "ptr", module, "uint", 0)
, module := DllCall("BeginUpdateResource", "str", File_Path, "uint", 0, "ptr")
, Counter := 0
}
}
DllCall("EndUpdateResource", "ptr", module, "uint", 0)
return Index - 1
}
Function_ReplaceIcon(Text, File_Path, LoopIndex)
{
File_Content := FileOpen(File_Path, "r")
If !IsObject(File_Content)
{
Return False
}
VarSetCapacity(igh, 8)
, File_Content.RawRead(igh, 6)
If NumGet(igh, 0, "UShort") != 0 || NumGet(igh, 2, "UShort") != 1
{
Return False
}
LoopCounter := NumGet(igh, 4, "UShort")
, VarSetCapacity(rsrcIconGroup, rsrcIconGroupSize := 6 + LoopCounter * 14)
, NumPut(NumGet(igh, "Int64"), rsrcIconGroup, "Int64") ; fast copy
, ige := &rsrcIconGroup + 6
Loop, % LoopCounter
{
A_Index_2 := ( LoopIndex - 1 ) + A_Index
, File_Content.RawRead(ige + 0, 12) ; read all but the offset
, NumPut(A_Index_2, ige + 12, "UShort")
, imgOffset := File_Content.ReadUInt()
, oldPos := File_Content.Pos
, File_Content.Pos := imgOffset
, VarSetCapacity(IconData, IconDataSize := NumGet(ige + 8, "UInt"))
, File_Content.RawRead(IconData, IconDataSize)
, File_Content.Pos := oldPos
, DllCall("UpdateResource", "Ptr", Text, "Ptr", 3, "Ptr", A_Index_2, "UShort", 0x409, "Ptr", &IconData, "UInt", IconDataSize, "UInt")
, ige += 14
}
File_Content.Close()
, File_Content := ""
Return A_Index_2 + 1, DllCall("UpdateResource", "Ptr", Text, "Ptr", 14, "Ptr", LoopIndex, "UShort", 0x409, "Ptr", &rsrcIconGroup, "UInt", rsrcIconGroupSize, "UInt")
}
Function_DllCreateEmpty(Text := "DUMMY.DLL")
{
;https:;www.autohotkey.com/boards/viewtopic.php?f=6&t=140
;Creates Empty Resource-Only DLL (1536 bytes) / CD:05.09.2010 | LM:25.10.2010 - by SKAN
TS := A_NowUTC
EnvSub, TS, 1970, S
If (A_Tab != TS)
{
Src := "0X5A4DY3CXB8YB8X4550YBCX2014CYCCX210E00E0YD0X7010BYD8X400YE4X1000YE8X1000YECX78A"
. "E0000YF0X1000YF4X200YF8X10005YFCX10005Y100X4Y108X3000Y10CX200Y114X2Y118X40000Y11CX200"
. "0Y120X100000Y124X1000Y12CX10Y140X1000Y144X10Y158X2000Y15CX8Y1B0X7273722EY1B4X63Y1B8X1"
. "0Y1BCX1000Y1C0X200Y1C4X200Y1D4X40000040Y1D8X6C65722EY1DCX636FY1E0X8Y1E4X2000Y1E8X200Y"
. "1ECX400Y1FCX42000040"
, VarSetCapacity(Trg, 1536, 0)
, Numput(TS, Trg, 192)
, AC := 0x40000000
}
Loop, Parse, Src, XY
{
Mod(A_Index, 2) ? O := "0x" A_LoopField : NumPut("0x" A_LoopField, Trg, O)
}
If (hF := DllCall("CreateFile", Str, Text, UInt, AC, UInt, 2, Ptr, 0, UInt, 2, Int, 0, Int, 0)) > 0
{
B := DllCall("_lwrite", Ptr, hF, Ptr, &Trg, UInt, 1536)
, DllCall("CloseHandle", Ptr, hF)
}
Return B ? Text :
}