AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Reference negative icon numbers

 
Reply to topic    AutoHotkey Community Forum Index -> Ask for Help
View previous topic :: View next topic  
Author Message
jaco0646



Joined: 07 Oct 2006
Posts: 3102
Location: MN, USA

PostPosted: Thu Dec 27, 2007 3:23 am    Post subject: Reference negative icon numbers Reply with quote

Icons inside DLLs are often referred to in the registry and other places using negative numbers. Is it possible to have AHK do the same (e.g. for a Picture control or inside a ListView)?

I quickly made this GUI script to show the icons in the shell32.dll file. But it won't accept negative numbers, which nicely demonstrates my problem.

Code:
#SingleInstance force
#NoTrayIcon
#NoEnv

DLL=%A_WinDir%\System32\shell32.dll
Num=0

Gui, Add, Button, w50 gUp, Up
Gui, Add, Pic, vPic Icon%Num%, %DLL%
Gui, Add, Button, w50 gDown, Down
Gui, Font, s12
Gui, Add, Edit, vNum gEdit w50, %Num%

Gui, Show
return
GuiClose:
ExitApp

Up:
Down:
Edit:
Gui, Submit, NoHide
If A_GuiControl = Up
 Num++
Else If A_GuiControl = Down
 Num--
GuiControl,,Pic, *Icon%Num% %DLL%
If A_GuiControl != Num
 GuiControl,,Num, %Num%
return


Last edited by jaco0646 on Fri Dec 28, 2007 2:58 am; edited 1 time in total
Back to top
View user's profile Send private message Visit poster's website
engunneer



Joined: 30 Aug 2005
Posts: 8255
Location: Maywood, IL

PostPosted: Thu Dec 27, 2007 9:02 pm    Post subject: Reply with quote

please give an example of something needing the negative numbers.
_________________

(Common Answers)
Back to top
View user's profile Send private message Visit poster's website
jaco0646



Joined: 07 Oct 2006
Posts: 3102
Location: MN, USA

PostPosted: Fri Dec 28, 2007 12:12 am    Post subject: Reply with quote

Well, the first example I gave was the registry, which denotes many icons using negative numbers. For example, suppose I wanted to find the default icon a computer uses to display MP3 files. I would look up the key:

Code:
HKEY_CLASSES_ROOT\mp3file\DefaultIcon


and on the PC I'm using right now, the answer is:

Code:
C:\PROGRA~1\WINDOW~2\wmplayer.exe,-120


Now, the icon being used is actually #2, but I need AHK to work with the negative number.

For a second example, the icon for a text file is shown in the registry as:
Code:
%SystemRoot%\system32\shell32.dll,-152
...this is actually icon #71.
Back to top
View user's profile Send private message Visit poster's website
Lexikos



Joined: 17 Oct 2006
Posts: 7258
Location: Australia

PostPosted: Fri Dec 28, 2007 4:28 am    Post subject: Reply with quote

The icon indices used by AutoHotkey are zero-based, never negative. The DefaultIcon registry key uses a resource id, which is different to an icon index.

If you search the forums for "LoadImage", you might find some examples of how to load an icon, given a resource id.
Back to top
View user's profile Send private message Visit poster's website
jaco0646



Joined: 07 Oct 2006
Posts: 3102
Location: MN, USA

PostPosted: Sat Dec 29, 2007 12:16 am    Post subject: Reply with quote

Thanks for the info. Is the resource ID method significantly more complicated to code for, or would this be worth a "Wish List" post?
Back to top
View user's profile Send private message Visit poster's website
Lexikos



Joined: 17 Oct 2006
Posts: 7258
Location: Australia

PostPosted: Sat Dec 29, 2007 1:02 am    Post subject: Reply with quote

It's fairly simple. Might be worth it.
Back to top
View user's profile Send private message Visit poster's website
jaco0646



Joined: 07 Oct 2006
Posts: 3102
Location: MN, USA

PostPosted: Sat Dec 29, 2007 2:15 am    Post subject: Reply with quote

It seems that the resource IDs are at least sequential, like an index number (at least for shell32.dll). So given the offset for a particular DLL, it's easy to calculate the icon number from the resource ID.

For example, the offset in shell32.dll is 223, the difference between -152 and 71 in my previous example. Resource ID number -151 is icon number 72, and so on. So, given the resource ID of the first icon in a DLL, it's simple to calculate the icon numbers for any other resource, and thus have an easy workaround.

Perhaps it wouldn't be too difficult to code a function that returns the resource ID of icon #0 in a given file. Unfortunately, I know next to nothing about DLLcall, so it's beyond my skills. Sad
Back to top
View user's profile Send private message Visit poster's website
[VxE]



Joined: 07 Oct 2006
Posts: 3234
Location: Simi Valley, CA

PostPosted: Sat Dec 29, 2007 2:57 am    Post subject: Reply with quote

It may be worthwhile for someone (other than me Laughing ) to write a script that acquires general information about a selected DLL and displays the info in a GUI. That is unless you can find the specs for the DLL somewhere like MSDN...

... Just a thought.
_________________
Ternary (a ? b : c) guide     TSV Table Manipulation Library
Post code inside [code][/code] tags!
Back to top
View user's profile Send private message
Lexikos



Joined: 17 Oct 2006
Posts: 7258
Location: Australia

PostPosted: Sat Dec 29, 2007 3:54 am    Post subject: Reply with quote

jaco0646 wrote:
It seems that the resource IDs are at least sequential, like an index number (at least for shell32.dll). So given the offset for a particular DLL, it's easy to calculate the icon number from the resource ID.
That is true for shell32.dll, but not necessarily other dlls. If you have a list of all resource ids, you could probably calculate the index. Resource IDs are not necessarily contiguous, but maybe the icon indices are in the same order.

Edit: Icons can be loaded directly by resource ID using LoadImage, but then you need to know how to use the icon handle. Since it depends on what you're using it for, it's probably easier to convert the ID to an index. You may include the following in your script, or use it once to convert a resource ID to an icon index.
Code:
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
}

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
}
The script assumes the order of the icon resources defines the icon indices. It supports only numeric resource IDs, not resource names.

Example usage:
Code:
Menu, Tray, Icon, shell32.dll, % IndexOfIconResource("shell32.dll", 324)
On XP and Vista, ID 324 = Icon211 (a blue "Question").
Back to top
View user's profile Send private message Visit poster's website
jaco0646



Joined: 07 Oct 2006
Posts: 3102
Location: MN, USA

PostPosted: Sat Dec 29, 2007 4:41 pm    Post subject: Reply with quote

Thank you.
Back to top
View user's profile Send private message Visit poster's website
Mustang



Joined: 17 May 2007
Posts: 421
Location: England

PostPosted: Mon Dec 31, 2007 5:09 am    Post subject: Reply with quote

Very helpful
Thanks lexikos
Back to top
View user's profile Send private message
Micahs



Joined: 01 Dec 2006
Posts: 460

PostPosted: Tue May 20, 2008 11:40 pm    Post subject: Reply with quote

Beautiful!
Thanks Lexikos.
I think that its worth noting that while the negative number signifies that it is an icon resource and not an icon index, the value itself should be passed as a positive. Also, the icon index used in the reg seems to be 0-based and the icon index in ahk is 1-based.

This makes sure it works either way:
Code:
If(iconNum < 0)   ;if an icon resource given
{   iconNum := IndexOfIconResource(iconSrc, Abs(iconNum))
}
Else   ;icon number given
{   iconNum++   ;convert from 0 to 1 based
}

Thanks again!
_________________
Back to top
View user's profile Send private message
MRCS



Joined: 08 Jun 2009
Posts: 2

PostPosted: Mon Jun 08, 2009 8:51 am    Post subject: Reply with quote

I have no idea whether I put together the 3 codes correctly or not, but I was not able to get the up & down buttons to work on negative numbers. I am new to AHK and my programming was many moons ago (IBM 360), so this may not be the most elegant solution, but it works.

Code:
#SingleInstance force
#NoTrayIcon
#NoEnv

DLL=C:\dl\ResourceHacker\shell32.dll
Num :=0

Gui, Add, Button, w165 gUp, Up
Gui, Add, Pic, vPic Icon%Num%, %DLL%
Gui, Add, Button, w165 gDown, Down
Gui, Font, s12
Gui, Add, Edit, vNum gEdit w50, %Num%

Gui, Show
return
GuiClose:
ExitApp

Up:
Down:
Edit:
Gui, Submit, NoHide
If A_GuiControl = Up
 Num :=Num-0
Else If A_GuiControl = Down
 Num :=Num-2
If(Num < 0)   ;if an icon resource given
{   INum :=Num
Num := IndexOfIconResource(DLL, Abs(Num))
}
Else   ;icon number given
{   Num :=Num+1   ;convert from 0 to 1 based
INum :=Num-1
}
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
}

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
}
GuiControl,,Pic, *Icon%Num% %DLL%
Num :=INum+1
If A_GuiControl != Num
 GuiControl,,Num, %Num%
return
Back to top
View user's profile Send private message
jaco0646



Joined: 07 Oct 2006
Posts: 3102
Location: MN, USA

PostPosted: Mon Jun 08, 2009 2:19 pm    Post subject: Reply with quote

Since this topic, Lexikos has made improvements to icon support in AutoHotkey_L (Lexikos' custom build) including the ability to handle resource identifiers (negative icon numbers).
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Ask for Help All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group