Thanks for the feedback

. The Icon index is zero based AFAIK so that would explain why it would be off by 1. I'll look into selecting a different size for icons. I made a few updates that may or may not have made it any better and started experimenting with having a function inside the dll file for extracting the images. Although it adds size to the dll file (13.5k before adding images) it might be a cleaner method... ? I also added the ability to use BMP, GIF, JPG, WMF & EMF files with this method (WMF & EMF files not currently tested) A copy of the dll file can be downloaded
<here>. Images can then be added to the dll file using
Resource Hacker. I'll likely provide the source to the dll once I clean it up a bit - there's not much to it so far.
Here is an updated version of the AGB.ahk file and another demo script for fun. The demo script uses .bmp, .ico, .gif and jpg images from the dll.
Code:
; ********************************
; Demo Script - 3.3
; ********************************
; Download sample images if necessary
IfNotExist %A_WorkingDir%\bmps.dll
{
SplashTextOn, 300, 30, !, Downloading images. Please wait...
URLDownloadToFile http://www.autohotkey.net/~corr/bmps3.dll, bmps3.dll
SplashTextOff
}
; Preload images for rollover
AGB_LoadBmpDll(sb1, A_WorkingDir . "\bmps3.dll", 601, 30, 140)
AGB_LoadBmpDll(sb1_ro, A_WorkingDir . "\bmps3.dll", 602, 80, 140)
; Load an icon instead for SampleButton2
AGB_LoadIconDll(sb2, A_WorkingDir . "\bmps3.dll", 0)
AGB_LoadImgDll(sb3, A_WorkingDir . "\bmps3.dll", 603, 30, 150)
AGB_LoadImgDll(sb4, A_WorkingDir . "\bmps3.dll", 604, 30, 150)
AGB_LoadImgDll(sb5, A_WorkingDir . "\bmps3.dll", 605)
; Create the buttons
Gui, Add, Button, h30 w140 gNbutton, Normal Button
AddGraphicButton("SampleButton1", sb1, "h30 w140 gMyButton")
AddGraphicButton("SampleButton2", sb2, "h30 w140 gMyButton")
Gui, Add, Button, h30 w140 gNbutton, Another Normal Button
AddGraphicButton("SampleButton3", sb3, "h30 w140 gMyButton")
AddGraphicButton("SampleButton4", sb4, "h30 w140 gMyButton")
AddGraphicButton("SampleButton5", sb5, "h30 w140 gMyButton")
; Show the window
Gui, Show,, Bitmap Buttons
; Image rollover for SampleButton1
OnMessage(0x200, "MouseMove")
OnMessage(0x2A3, "MouseLeave")
OnMessage(0x202, "MouseLeave") ; Restore image on LBUTTONUP
Return
MouseLeave(wParam, lParam, msg, hwnd)
{
Global
If (hwnd = SampleButton1_hwnd)
AddGraphicButton("SampleButton1", sb1, "h30 w140 gMyButton", 30, 140)
Return
}
MouseMove(wParam, lParam, msg, hwnd)
{
Global
Static _LastButtonData = true
If (hwnd = SampleButton1_hwnd)
If (_LastButtonData != SampleButton1_hwnd)
AddGraphicButton("SampleButton1", sb1_ro, "h30 w140 gMyButton", 60, 120)
_LastButtonData := hwnd
Return
}
MyButton:
MsgBox, Graphic button clicked :)
return
Nbutton:
MsgBox, Normal button Clicked :)
Return
GuiClose:
ExitApp
As before, either add these to the code above or save in your stdlib directory

Code:
; *******************************************************************
; AddGraphicButton.ahk
; *******************************************************************
; Version: 2.2 Updated: May 20, 2007
; by corrupt
; *******************************************************************
; VariableName = variable name for the button
; ImgPath = Path to the image to be displayed
; Options = AutoHotkey button options (g label, button size, etc...)
; bHeight = Image height (default = 32)
; bWidth = Image width (default = 32)
; *******************************************************************
; note:
; - calling the function again with the same variable name will
; modify the image on the button
; *******************************************************************
AddGraphicButton(VariableName, ImgPath, Options="", bHeight=32, bWidth=32)
{
Global
Local ImgType, ImgType1, ImgPath0, ImgPath1, ImgPath2, hwndmode
; BS_BITMAP := 128, IMAGE_BITMAP := 0, BS_ICON := 64, IMAGE_ICON := 1
Static LR_LOADFROMFILE := 16
Static BM_SETIMAGE := 247
Static NULL
SplitPath, ImgPath,,, ImgType1
If ImgPath is float
{
ImgType1 := (SubStr(ImgPath, 1, 1) = "0") ? "bmp" : "ico"
StringSplit, ImgPath, ImgPath,`.
%VariableName%_img := ImgPath2
hwndmode := true
}
ImgTYpe := (ImgType1 = "bmp") ? 128 : 64
If (%VariableName%_img != "") AND !(hwndmode)
DllCall("DeleteObject", "UInt", %VariableName%_img)
If (%VariableName%_hwnd = "")
Gui, Add, Button, v%VariableName% hwnd%VariableName%_hwnd +%ImgTYpe% %Options%
ImgType := (ImgType1 = "bmp") ? 0 : 1
If !(hwndmode)
%VariableName%_img := DllCall("LoadImage", "UInt", NULL, "Str", ImgPath, "UInt", ImgType, "Int", bWidth, "Int", bHeight,
"UInt", LR_LOADFROMFILE, "UInt")
DllCall("SendMessage", "UInt", %VariableName%_hwnd, "UInt", BM_SETIMAGE, "UInt", ImgType, "UInt", %VariableName%_img)
Return, %VariableName%_img ; Return the handle to the image
}
Code:
; *******************************************************************
; AGB.ahk
; updated: June 22, 2008
; by corrupt
; *******************************************************************
; - these functions can optionally be used to pre-load
; images to avoid loading them from file each time (useful for
; creating image rollovers). Specify the variable used in the
; function as ImgPath instead (note: an existing image object will
; not get deleted when a path is not specified. Use
; DllCall("DeleteObject", VariableName_img) manually first before
; using a pre-loaded image if an image path was used previously to
; free memory used by loading the image (or use the AGB_DelImage()
; function.
; *******************************************************************
;
; *******************************************************************
; Preload images for use with the AddGraphicButton() function
; Version: 2.21 Updated: June 22, 2008
; by corrupt
; *******************************************************************
; VariableName = variable name for the loaded image resource
; ImgPath = Path to the image to be displayed
; bHeight = Image height (default = 32)
; bWidth = Image width (default = 32)
; *******************************************************************
AGB_LoadImage(ByRef VariableName, ImgPath, bHeight=32, bWidth=32) {
Global
Local ImgType, ImgType1, LR_LOADFROMFILE, NULL
Static LR_LOADFROMFILE := 16
Static NULL
SplitPath, ImgPath,,, ImgType1
ImgType := (ImgType1 = "bmp") ? 0 : 1
If (%VariableName%_img != "")
DllCall("DeleteObject", "UInt", %VariableName%_img)
VariableName := ImgType . "." . DllCall("LoadImage", "UInt", NULL, "Str", ImgPath, "UInt", ImgType, "Int", bWidth, "Int", bHeight, "UInt", LR_LOADFROMFILE,
"UInt")
Return ErrorLevel
}
; *******************************************************************
; Preload bitmaps from a dll for use with the AddGraphicButton() function
; Version: 2.21 Updated: June 22, 2008
; by corrupt
; *******************************************************************
; VariableName = variable name for the loaded image resource
; dllfile = Path to the dll file that contains the image(s)
; resID = the name or ID of the bitmap (or icon? - not currently tested)
; bHeight = Image height (default = 32)
; bWidth = Image width (default = 32)
; ImgType1 = "bmp" for bitmaps, "ico" for icons
; *******************************************************************
AGB_LoadBmpDll(ByRef VariableName, dllfile, resID, bHeight=32, bWidth=32, ImgType1="bmp") {
Global
Local ImgType,LR_SHARED, NULL, bmps, IDtype
Static LR_SHARED := 32768
Static NULL
If resID is integer
IDtype = 1
bmps := DllCall("LoadLibrary", "Str", dllfile)
ImgType := (ImgType1 = "bmp") ? 0 : 1 ; future use?
If (%VariableName%_img != "")
DllCall("DeleteObject", "UInt", %VariableName%_img)
VariableName := ImgType . "." . DllCall("LoadImage", "UInt", bmps, (IDtype ? "UInt" : "Str"), resID, "UInt", ImgType, "Int", bWidth, "Int", bHeight, "UInt",
LR_SHARED, "UInt")
DllCall("FreeLibrary", "Uint", bmps)
Return ErrorLevel
}
; *******************************************************************
; Preload icons from a dll for use with the AddGraphicButton() function
; Version: 2.21 Updated: June 22, 2008
; by corrupt
; *******************************************************************
; VariableName = variable name for the loaded image resource
; dllfile = Path to the dll file that contains the image(s)
; nindex = the index of the icon to load
; *******************************************************************
AGB_LoadIconDll(ByRef VariableName, dllfile, nindex) {
Global
Local spid
spid := DllCall("GetCurrentProcessId")
If (%VariableName%_img != "")
DllCall("DeleteObject", "UInt", %VariableName%_img)
VariableName := "1." . DllCall("shell32.dll\ExtractIconA", "UInt", spid, "Str", dllfile, "UInt", nindex)
Return ErrorLevel
}
; *******************************************************************
; Preload icons from a dll for use with the AddGraphicButton() function
; uses a function in the dll to extract the images
; likely supports: BMP, GIF, JPG, WMF, EMF (does not seem to support
; .ICO at the moment for some reason)
; note: add the images using resource type: RCDATA
; Version: 2.21 Updated: June 22, 2008
; by corrupt
; *******************************************************************
; VariableName = variable name for the loaded image resource
; dllfile = Path to the dll file that contains the image(s)
; resID = the ID# of the
; nHeight = Image height (default = 32)
; nWidth = Image width (default = 32)
; *******************************************************************
AGB_LoadImgDll(ByRef VariableName, dllfile, resID, nheight=0, nwidth=0) {
Global
Local hModule
If (%VariableName%_img != "")
DllCall("DeleteObject", "UInt", %VariableName%_img)
hModule := DllCall("LoadLibrary", "Str", dllfile)
variablename := "0." . DllCall(dllfile . "\LoadDllImage", "UInt", resID, "UInt", nwidth, "UInt", nheight, "UInt")
DllCall("FreeLibrary", "UInt", hModule)
Return ErrorLevel
}
; *******************************************************************
; Destroy loaded images
; Version: 2.21 Updated: June 22, 2008
; by corrupt
; *******************************************************************
; VariableName = variable name for the loaded image resource
; *******************************************************************
AGB_DelImage(ByRef VariableName) {
Global
Local ImgPath0, ImgPath1, ImgPath2
If (%VariableName%_img != "")
DllCall("DeleteObject", "UInt", %VariableName%_img)
Else
{
StringSplit, ImgPath, ImgPath,`.
%VariableName%_img := ImgPath2
DllCall("DeleteObject", "UInt", %VariableName%_img)
}
variablename=
Return ErrorLevel
}