PUM IconExtract: adding icon associated with file extension (improvements)

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
ahk7
Posts: 577
Joined: 06 Nov 2013, 16:35

PUM IconExtract: adding icon associated with file extension (improvements)

Post by ahk7 » 05 Nov 2023, 08:08

I only recently had a look at good old PUM, a very nice class to build prettier menus.
By default it can only show the icons of an Exe file in the menu. It would of course be nicer to have more options automatically which I've managed to do by butchering some code from an example from the ListView documentation.

PUM info:

PUM - owner drawn object based popup menu
Forum: https://www.autohotkey.com/board/topic/73599-ahk-l-pum-owner-drawn-object-based-popup-menu/

Download: http://apathysoftworks.com/ahk/PUM.zip
Documentation: http://apathysoftworks.com/ahk/index.html

AutoHotkey docs:

Get the high-quality small-icon associated with this file extension - https://www.autohotkey.com/docs/v1/lib/ListView.htm#ExAdvanced

In PUM_API.ahk there is a IconExtract, note the If (Ext = "Exe"):

PUM_API.ahk -- class pumAPI extends pumAPI_base

Code: Select all

...
  IconExtract( icoPath, size = 32 ) {
      pPath := this.IconGetPath( icoPath )
      pNum := this.IconGetIndex( icoPath )
      pNum := pNum = "" ? 0 : pNum
      ;http://msdn.microsoft.com/en-us/library/ms648075%28v=VS.85%29.aspx
      DllCall( this.pPrivateExtractIconsW, "Str", pPath, "UInt", pNum, "UInt", size, "UInt", size, "Ptr*", handle, "Ptr", 0,"UInt",1, "UInt", 0 )
      if !handle
      {
          SplitPath, pPath,,,Ext
          if (Ext = "exe")
              DllCall( this.pPrivateExtractIconsW, "Str", "shell32.dll", "UInt", 2, "UInt", size, "UInt", size, "Ptr*", handle, "Ptr", 0,"UInt",1, "UInt", 0 )
      }
      return handle
  }
...
I've modified it like so, the 'else' beneath the If (Ext = "Exe") which seems to work for 16 and 32 size icons

Code: Select all

...
  IconExtract( icoPath, size = 32 ) {
      pPath := this.IconGetPath( icoPath )
      pNum := this.IconGetIndex( icoPath )
      pNum := pNum = "" ? 0 : pNum
      ;http://msdn.microsoft.com/en-us/library/ms648075%28v=VS.85%29.aspx
      DllCall( this.pPrivateExtractIconsW, "Str", pPath, "UInt", pNum, "UInt", size, "UInt", size, "Ptr*", handle, "Ptr", 0,"UInt",1, "UInt", 0 )
      if !handle
      {
          SplitPath, pPath,,,Ext
          if (Ext = "exe")
              DllCall( this.pPrivateExtractIconsW, "Str", "shell32.dll", "UInt", 2, "UInt", size, "UInt", size, "Ptr*", handle, "Ptr", 0,"UInt",1, "UInt", 0 )
          else ; Get the high-quality small-icon associated with this file extension -- source: https://www.autohotkey.com/docs/v1/lib/ListView.htm#ExAdvanced
          {
              sfi_size := A_PtrSize + 8 + (A_IsUnicode ? 680 : 340)
              VarSetCapacity(sfi, sfi_size)
              ; 0x101 is SHGFI_ICON+SHGFI_SMALLICON; 102 large icon?
              if (size = 16)
                iconsize:=0x101
              if (size = 32) 
                iconsize:=0x102 ; seems to work for 32x32, I suspect this is by accident
              DllCall("Shell32\SHGetFileInfo" . (A_IsUnicode ? "W":"A"), "str", pPath, "uint", 0, "ptr", &sfi, "uint", sfi_size, "uint", iconsize)
              handle:=NumGet(sfi, 0)
          }
      }
      return handle
  }
...
My questions:

1. as you can see the DllCalls differ quite a bit, it would nice to have the associated DllCall be similar to the Exe DllCall. Would someone be able to improve the associated DllCall?

2. By using "0x101" for 16 and "0x102" for 32 the DllCall works, but for 48, 64 and other sizes it doesn't seem to work. This could either be the DllCall or what I suspect how other functions in the class handle and display the iconsize. It would be nice to have support for all sizes (16,32,48,64,128,256).

Return to “Ask for Help (v1)”