Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Path Icon


  • Please log in to reply
No replies to this topic
Cragaha
  • Members
  • 265 posts
  • Last active: Jan 04 2016 02:24 AM
  • Joined: 19 Nov 2010
I'm trying to make a script that returns the icon file and index for any given path (File or folder).
And it doesn't seem to be easy, specially when it comes to folders icons and shortcuts with shortcut overlay.

Here is what I have so far:
#NoEnv
#Persistent
#SingleInstance force
SetWorkingDir %A_ScriptDir%

Gui, +LastFound
Gui, Add, Text, x25 y25 w150 h150 0x1203 HWNDhPreviewPic
Gui, Show,w200 h200,PathIcon
Return

GuiDropFiles:
STM_SETIMAGE(hPreviewPic, A_GuiEvent)
Return

GuiClose:
ExitApp

STM_SETIMAGE(hControl, p_ImageFile) {
global ImagePath,IconIndex
static h_icon
DefaultFolderIdx:= 1
DefaultFileIdx:= 3
DefaultExecutableIdx:= 2
SendMessage, ( STM_SETIMAGE:=0x172 ), 0x1, 0,, ahk_id %hControl%
ImagePath:= Instr(FileExist(p_ImageFile), "D") ? A_ScriptFullPath : p_ImageFile
IconIndex:= Instr(FileExist(p_ImageFile), "D") ? 1 : 0
DLLCall("DestroyIcon", "Int", h_icon)

If Instr(FileExist(p_ImageFile), "D")
GetFolderIcon(p_ImageFile, ImagePath, IconIndex)

If (DllCall("PrivateExtractIcons", "str", ImagePath, "int", IconIndex, "int", 128, "int", 128, "uint*", h_icon, "uint*", 0, "uint", 1, "uint", 0, "int") <= 0) {
If Instr(FileExist(p_ImageFile), "D")
ImagePath:= A_ScriptFullPath, IconIndex:= DefaultFolderIdx ; default
Else {
SplitPath, ImagePath,,, OutExtension
If OutExtension {
; EXE with no icon
If (OutExtension = "exe")
ImagePath:= A_ScriptFullPath, IconIndex:= DefaultExecutableIdx

; Shortcut, look for target
Else If (OutExtension = "lnk") {
FileGetShortcut, %ImagePath%, OutTarget
SplitPath, OutTarget,,, OutExtension
If Instr(FileExist(OutTarget), "D") { ;Folder shortcut
GetFolderIcon(OutTarget, ImagePath, IconIndex)
If !ImagePath
ImagePath:= A_ScriptFullPath, IconIndex:= DefaultFolderIdx
}
Else getExtIcon(OutExtension, ImagePath, IconIndex)
}
; File type
Else {
getExtIcon(OutExtension, ImagePath, IconIndex)
If !ImagePath
ImagePath:= A_ScriptFullPath, IconIndex:= DefaultFileIdx
}
}
; File type that has no icon
Else ImagePath:= A_ScriptFullPath, IconIndex:= DefaultFileIdx
}

; MsgBox, % ImagePath "`n`n" IconIndex
DllCall("PrivateExtractIcons", "str", ImagePath, "int", IconIndex, "int", 128, "int", 128, "uint*", h_icon, "uint*", 0, "uint", 1, "uint", 0, "int")
; If (DllCall("PrivateExtractIcons", "str", ImagePath, "int", IconIndex, "int", 128, "int", 128, "uint*", h_icon, "uint*", 0, "uint", 1, "uint", 0, "int") <= 0) {
; Everything above failed :/
; }
}
SendMessage, ( STM_SETIMAGE:=0x172 ), 0x1, h_icon,, ahk_id %hControl%
}

GetFolderIcon(Folder, ByRef IconFile, ByRef IconIndex) {
IniRead, IconFile, %Folder%\desktop.ini, .ShellClassInfo, IconFile, %A_Space%
IniRead, IconIndex, %Folder%\desktop.ini, .ShellClassInfo, IconIndex, %A_Space%
If !IconFile {
IniRead, IconResource, %Folder%\desktop.ini, .ShellClassInfo, IconResource, %A_Space%
If !IconResource
Return
StringSplit, I, IconResource, `,
IconFile:= I1, IconIndex:= I2
}
StringReplace,IconFile, IconFile, `%ProgramFiles`%, %A_ProgramFiles%, All
StringReplace,IconFile, IconFile, `%windir`%, %A_WinDir%, All
If Instr(IconFile, "\")
IconFile:= GetFullPath(Folder, IconFile)
IconFile:= !FileExist(IconFile) && !FileExist(A_WinDir "\System32\" IconFile) ? "" : IconFile
}

getExtIcon(Ext, ByRef ImagePath, ByRef IconIndex) {
RegRead, from, HKEY_CLASSES_ROOT, .%Ext%
RegRead, DefaultIcon, HKEY_CLASSES_ROOT, %from%\DefaultIcon
StringReplace, DefaultIcon, DefaultIcon, `",,all ;"
StringReplace, DefaultIcon, DefaultIcon, `%SystemRoot`%, %A_WinDir%,all
StringReplace, DefaultIcon, DefaultIcon, `%ProgramFiles`%, %A_ProgramFiles%,all
StringReplace, DefaultIcon, DefaultIcon, `%windir`%, %A_WinDir%,all
I1 := I2:= ""
StringSplit, I, DefaultIcon, `,
StringReplace,I1, I1, `%ProgramFiles`%, %A_ProgramFiles%, All
StringReplace,ImagePath, I1, `%windir`%, %A_WinDir%, All
ImagePath:= !FileExist(ImagePath) && !FileExist(A_WinDir "\System32\" ImagePath) ? "" : ImagePath
IconIndex:= (I2 < 0) ? IndexOfIconResource( I1, RegExReplace(I2, "[^\d]+"))-1 : I2
IconIndex:= IconIndex < 0 ? 0 : IconIndex
}

IndexOfIconResource(Filename, ID) {
hmod := DllCall("GetModuleHandle", "str", Filename)
; If the DLL isn't already loaded, load it as a data file.
loaded := !hmod && hmod := DllCall("LoadLibraryEx", "str", Filename, "uint", 0, "uint", 0x2)
enumproc := RegisterCallback("IndexOfIconResource_EnumIconResources","F")
VarSetCapacity(param,12,0), NumPut(ID,param,0)
; Enumerate the icon group resources. (RT_GROUP_ICON=14)
DllCall("EnumResourceNames", "uint", hmod, "uint", 14, "uint", enumproc, "uint", &param)
DllCall("GlobalFree", "uint", enumproc)
; If we loaded the DLL, free it now.
if loaded
DllCall("FreeLibrary", "uint", hmod)
return NumGet(param,8) ? NumGet(param,4) : 0
} ;http://www.autohotkey.com/forum/viewtopic.php?p=168951#168951

IndexOfIconResource_EnumIconResources(hModule, lpszType, lpszName, lParam) {
NumPut(NumGet(lParam+4)+1, lParam+4)
if (lpszName = NumGet(lParam+0)) {
NumPut(1, lParam+8)
return false ; break
}
return true
}

Use compiled script for included icons.

But I believe there must be a better way using DllCall to do the job.
If anyone got an idea I appreciate that.
Thanks