Jump to content

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

ILButton() - image buttons with text, states, alignment


  • Please log in to reply
52 replies to this topic
webber
  • Members
  • 129 posts
  • Last active: Aug 13 2011 06:45 PM
  • Joined: 25 Aug 2005
v1.1 error:


Error in #include file "C:\...\ILButton_new.ahk": This line does not contain a recognized action.

Specifically: static

Line#
---> 035: {
________
Vision insurance advice

Vee_
  • Guests
  • Last active:
  • Joined: --
Probably you are using the 1.1 versione, designed for the new AHK 1.048.
Update your version of AHK, or (if like me you need the retrocompatibility) download the 1.0 version of IL_Button https://ahknet.autoh.../ILButton10.ahk

hughman
  • Members
  • 192 posts
  • Last active: Feb 14 2016 06:59 AM
  • Joined: 11 Feb 2007
It's really amazing. But there's a problem that the image can't appear unitl your mouse move over it once.

how to solve this problem? My system is xp sp2 chs , the last lin is Sleep 1

If the res file is a dll file, then the image to be loaded is icon or bitmap or else other? And is the index equal to resource identifier or not?

tkoi
  • Members
  • 56 posts
  • Last active: Feb 25 2011 02:32 AM
  • Joined: 26 Jun 2008
Hmm. I guess you could probably send a wm_mousemove message to the button, and remove the sleep (since it isn't working). I never figured out what caused that problem. Maybe I'll look into it later. But for now try wm_mousemove (0x200)

hughman
  • Members
  • 192 posts
  • Last active: Feb 14 2016 06:59 AM
  • Joined: 11 Feb 2007
Thanks, I'll try it out.

1.
I have serval bmp files, some of which can be displayed normally while other not. What's the reason for it?
I have upload two files to google picasa, the first is normal and the second not. But I think they should be the same format.
The link: http://picasaweb.goo...eat=directlink#

2.
Another problem is about that if I can use the bmp resource within a dll file? Beacause I decide to create a gui included so many buttons of bmp, I want to pack them all into one dll file to reduce file numbers.

3.
If I wrapper a function in which IL_Button() is called, It seems not work.
AddButton(hBtn, w, opt, index)
{
	local ni, pi, di, il
	ni := "res\bmp\" . (index * 3 - 2) . ".bmp"
	pi := "res\bmp\" . (index * 3 - 1) . ".bmp"
	di := "res\bmp\" . (index * 3) . ".bmp"
	il = %ni%|%ni%|%pi%|%di%|%ni%|%ni%
	Gui, Add, Button, % "w" . w . " h48" . " hwnd" . hBtn . " " . opt
	ILButton(hBtn, il, 48, 48, 4)
}


tkoi
  • Members
  • 56 posts
  • Last active: Feb 25 2011 02:32 AM
  • Joined: 26 Jun 2008
1. Those two pictures are both jpegs, which are not supported.

2. I'm sure there is a way to load a bmp contained in a dll. I would try the LoadImage() function. See MSDN: <!-- m -->http://msdn.microsof...y/ms648045.aspx<!-- m -->

3. 'index' seems to be an empty variable. Should it not just be 'res\bmp\1.bmp' 'res\bmp\2.bmp' etc?

hughman
  • Members
  • 192 posts
  • Last active: Feb 14 2016 06:59 AM
  • Joined: 11 Feb 2007
1. oops... picasa convert my bmp to jpg -_-. You can download it http://cid-95a28278a....Public/bmp.zip

2. It's a pity that this function can not support win2k. MSDN:

BCM_SETIMAGELIST Message
Minimum operating systems: Windows XP

Is there another way to realize the same effect in all windows station? AddGraphicButton can't control the button states and the button created by it always has white border which is not so pretty.

3. I have known the problem. I should add a line before calling ILButton.
_hwnd := %hBtn%
Now I can add a button without creating a global variable as below:
AddButton(1, 73, "Section ym+2 gOK")
AddButton(index, w, opt)
{
   ni := "res\bmp\" . (index * 3 - 2) . ".bmp"
   pi := "res\bmp\" . (index * 3 - 1) . ".bmp"
   di := "res\bmp\" . (index * 3) . ".bmp"
   il = %ni%|%ni%|%pi%|%di%|%ni%|%ni%
   Gui, Add, Button, % "w" . w . " h48" . " hwndhBtn " . opt
   ILButton(hBtn, il, w, 48, 4)
}


Drugwash
  • Members
  • 1078 posts
  • Last active: May 24 2016 04:20 PM
  • Joined: 07 Sep 2008
The function is contained in Windows Common Controls v6. If you can get that to install/run in Win2k, then you're a happy camper. I'm out since it won't run in Win9x. :(

Montu
  • Members
  • 142 posts
  • Last active: Jan 01 2010 03:10 AM
  • Joined: 11 Feb 2009
can it work on menu icons?

Drugwash
  • Members
  • 1078 posts
  • Last active: May 24 2016 04:20 PM
  • Joined: 07 Sep 2008
For icons in menu you don't need ComCtl v6. A pretty good example of how you can achieve it can be found here. It's been tested in Vista but works on my 98SE as well. ;)

hughman
  • Members
  • 192 posts
  • Last active: Feb 14 2016 06:59 AM
  • Joined: 11 Feb 2007

The function is contained in Windows Common Controls v6. If you can get that to install/run in Win2k, then you're a happy camper. I'm out since it won't run in Win9x. :(


Is it possible? I have a google about it and the answer seems to be not. But I will have a try tomorrow in my company.

2009-04-30:
the dll can't be registered in winwods. Should it be rebooted to safe mode? I have not tried it out as I decide to use AddGraphicButton instead in the stations prior to xp.

notbryant
  • Members
  • 48 posts
  • Last active: Apr 05 2012 05:36 AM
  • Joined: 20 Feb 2009
Wonderful script! Adds so much flair to the GUI!

Hmm. I guess you could probably send a wm_mousemove message to the button, and remove the sleep (since it isn't working). I never figured out what caused that problem. Maybe I'll look into it later. But for now try wm_mousemove (0x200)


Dunno if anyone was still have problems with this issue, but I was. I toyed with the Sleep a little bit, and I found that if you increase it, it doesn't need a mouseover. It works for me at "Sleep 37", but I just switched it five minutes ago, so I'll see if that still works, and on different computers and such.

EDIT: I'd also like to quickly suggest maybe using a different delimiter instead of a colon? (Like for "image:0"). Currently, it has to be in the working directory, because if you add the full path, the array gets messed up by the colon after the drive letter. Just a suggestion, which might be a stupid one, since I really don't understand everything in the function.

temp01
  • Members
  • 120 posts
  • Last active: May 18 2013 08:27 PM
  • Joined: 09 Jul 2009
Why didn't you use built-in ImageList functions IL_Create/IL_Add?
ILButton(hBtn, images, largeIcons=0, align=4, margin="1,1,1,1") {
	;static ;local iList, temp, v, v1, v2, v3
	iList := IL_Create(1, 5, largeIcons)
	Loop, Parse, images, |
		If RegExMatch(A_LoopField, "(.*):(\d+)", v)
			IL_Add(iList, v3:=v1 ? v1 : v3, v2+1)

	VarSetCapacity(struct, 24), temp:=iList "," margin "," align
	Loop, Parse, temp, `,
		NumPut(A_LoopField, struct, (A_Index-1)*4)
	SendMessage, 0x1602, 0, &struct,, ahk_id %hBtn%	; BCM_SETIMAGELIST
}
I removed the assume static mode; the struct var probably gets destroyed/freed-up but still it works fine here and I changed PostMessage to SendMessage and now it works without the need of Sleep 1 on XP. :D

Edit: And absolute paths work with this function ( C:\blahblah\... )

Demo script (slightly changed - iconwidth, iconheight parameters combined into one parameter: largeIcons?):
Gui, +ToolWindow +AlwaysOnTop
Loop 5 {
	Gui, Add, Button, w64 h32 xm hwndhBtn1
	Gui, Add, Button, w100 h32 x+10 hwndhBtn2, text
	ILButton(hBtn1, "user32.dll:" A_Index-1, 0, A_Index-1)
	ILButton(hBtn2, "user32.dll:" A_Index-1, 0, A_Index-1)
}
Gui, Add, Button, xm w174 h48 vStates hwndhBtn, pushbuttonstates
ILButton(hBtn, "user32.dll:0|:1|:2|:3|:4|:5", 1, 0, "16,1,-16,1")

Gui, Show,, ILButton demo
return


majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006
I modified the function. The changes are:

- Shorter code as bitmap specific part is removed (PrivateExtractIcons already handles bmps)
- Changed Aligment from numbers to string and Margin to use space instead comma
- You can omit image position entirely in which case first image will be used.
- Returns ImageList handle so you can destroy it later or reuse it.
- Image argument now accepts ImageList handle.
- Doesn't use globals (nor statics)
- You can use absolute paths.

/*
	Function:	ILButton()
				Creates an ImageList and associates it with a button.
	
	Parameters:
		HBtn   - Handle of a buttton.
		Images - A pipe delimited list of images in form "FileName[:zeroBasedIndex]" or ImageList handle.
				 Any position can be omitted in which case icon for state "normal" is used.
		Cx     - Width of the image in pixels. By default 16.
		Cy     - Height of the image in pixels. By default 16.
		Align  - One of the word: Left, Right, Top, Bottom, Center.
		Margin - Margin around the icon. A space separated list of four integers in form "left top right bottom".

	Images:
		- File must be of type exe, dll, ico, cur, ani or bmp.
		- There are 5 states: normal, hot (hover), pressed, disabled, defaulted (focused), stylushot.
		- If only one image is specified, it will be used for all the button's states
		- If fewer than six images are specified, nothing is drawn for the states without images
		- Omit "file" to use the last file specified ( "states.dll:0|:1|:2|:3|:4|:5" )
		- Omitting an index is the same as specifying 0.
	
	Returns:
		Handle of the ImageList if operation was completed or 0 otherwise.
	
	Remarks:
		Within Aero theme (WinOS >= Vista), a defaulted (focused) button fades between images 5 and 6.
		Each succesifull call to this function creates new ImageList. If you are calling this function
		more times for single button control, freeing previous ImageList is your responsibility.

	About:
		- Version 1.0 by majkinetor.
		- Original code by tkoi. See <http://www.autohotkey.com/forum/viewtopic.php?p=247168>
		- License: GNU GPLv3 <http://www.opensource.org/licenses/gpl-3.0.html>
*/

ILButton(HBtn, Images, Cx=16, Cy=16, Align="center", Margin="1 1 1 1") {
	static BCM_SETIMAGELIST=0x1602, a_right=1, a_top=2, a_bottom=3, a_center=4

	if Images is not integer
	{
		hIL := DllCall("ImageList_Create", "UInt", Cx, "UInt",Cy, "UInt", 0x20, "UInt", 1, "UInt", 6)
		Loop, Parse, Images, |, %A_Space%%A_Tab%
		{
			if (A_LoopField = "") {
				DllCall("ImageList_AddIcon", "UInt", hIL, "UInt", I)
				continue
			}
			if (k := InStr(A_LoopField, ":", 0, 0)) && ( k!=2 )
				 v1 := SubStr(A_LoopField, 1, k-1), v2 := SubStr(A_LoopField, k+1)
			else v1 := A_LoopField, v2 := 0

			ifEqual, v1,,SetEnv,v1, %prevFileName%
			else prevFileName := v1

			DllCall("PrivateExtractIcons", "Str", v1, "UInt", v2, "UInt", Cx, "UInt", Cy, "UIntP", hIcon, "UInt",0, "UInt", 1, "UInt", 0x20) ; LR_LOADTRANSPARENT = 0x20
			DllCall("ImageList_AddIcon", "UInt",hIL, "UInt",hIcon)
			ifEqual, A_Index, 1, SetEnv, I, %hIcon%
			else DllCall("DestroyIcon", "UInt", hIcon)
		}
		DllCall("DestroyIcon", "UInt", I)
	} else hIL := Images

	VarSetCapacity(BIL, 24), NumPut(hIL, BIL), NumPut(a_%Align%, BIL, 20)
	Loop, Parse, Margin, %A_Space%
		NumPut(A_LoopField, BIL, A_Index * 4)

	SendMessage, BCM_SETIMAGELIST,,&BIL,, ahk_id %HBtn%
	ifEqual, ErrorLevel, 0, return 0, DllCall("ImageList_Destroy", "Uint", hIL)

	sleep 1 ; workaround for a redrawing problem on WinXP
	return hIL
}

Sample:

#SingleInstance force 
#NoEnv 


	Gui, +ToolWindow +AlwaysOnTop 
	Loop 5 { 
	   Gui, Add, Button, w64 h32 xm hwndhBtn, %A_Index%
		  hIL := ILButton(hBtn, "user32.dll:" A_Index-1, 16, 16, "right", "0 0 10") 
	   Gui, Add, Button, w100 h32 x+10 hwndhBtn, text 
		  ILButton(hBtn, hIL, 16, 16, "", 10) 
	   } 
	Gui, Add, Button, xm h200 w200 vStates hwndhBtn, pushbuttonstates
	   ILButton(hBtn, "user32.dll|:2|:1|||", 128, 128, "top", "0 5") 
	Gui, Add, Button, w100 h26 xm+74 gToggle, Enable/disable 

	Gui, Show, , ILButton demo 
return 

Toggle: 
   GuiControlGet, s, Enabled, States 
   GuiControl, Disable%s%, States 
   return 

GuiClose: 
GuiEscape: 
   ExitApp 
return

Why didn't you use built-in ImageList functions IL_Create/IL_Add?

Because integrated IL can't be used as it limitted to 2 icon sizes. Plus it doesn't handle colors the way its good enough for all cases.

I have serval bmp files, some of which can be displayed normally while other not. What's the reason for it?

My function displays both images normally, apart from the fact that there is a small black dot in upper left corner of each image ?! When I convert them to ico format everything works OK.

Is there another way to realize the same effect in all windows station? AddGraphicButton can't control the button states and the button created by it always has white border which is not so pretty.

This could be because AGB doesn't use Transparent option I guess. Try this one:

/*
 Function:  Image
			Adds image to the Button control.

 Parameters:
			HButton	- Handle to the button.
			Image	- Path to the .BMP file or image handle. First pixel signifies transparency color.
			Width	- Width of the image, if omitted, current control width will be used.
			Height	- Height of the image, if omitted, current control height will be used.

 Returns:
		Bitmap handle.
 
 */
Ext_Image(HButton, Image, Width="", Height=""){ 
    static BM_SETIMAGE=247, IMAGE_ICON=2, BS_BITMAP=0x80, IMAGE_BITMAP=0, LR_LOADFROMFILE=16, LR_LOADTRANSPARENT=0x20

	if (Width = "" || Height = "") {
		ControlGetPos, , ,W,H, ,ahk_id %hButton%
		ifEqual, Width,, SetEnv, Width, % W-8
		ifEqual, Height,,SetEnv, Height, % H-8
	}

	if Image is not integer 
	{
		if (!hBitmap := DllCall("LoadImage", "UInt", 0, "Str", Image, "UInt", 0, "Int", Width, "Int", Height, "UInt", LR_LOADFROMFILE | LR_LOADTRANSPARENT, "UInt"))
			return 0
	} else hBitmap := Image 
    
    WinSet, Style, +%BS_BITMAP%, ahk_id %hButton% 
    SendMessage, BM_SETIMAGE, IMAGE_BITMAP, hBitmap, , ahk_id %hButton%
	return hBitmap
}

Posted Image

Montu
  • Members
  • 142 posts
  • Last active: Jan 01 2010 03:10 AM
  • Joined: 11 Feb 2009
this is not working please help.
please give example of non-dll use.
i've 8 icons in the working directory. but it only show 3 icons in every button instead of 8 icons for 8 buttons
#SingleInstance force 
#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#Include %A_ScriptDir%\icons\ILButton.ahk 
Gui, Add, Button, x6 y5 w50 h50 hwndhBtn
ILButton(hBtn,"filename:%A_workingDir%\0.ico|1.ico:0|2.ico|3.ico|4.ico|5.ico|6.ico|7.ico"0,40,40,4,"1,1,1,1")
Gui, Add, Button, x56 y5 w50 h50 hwndhBtn
ILButton(hBtn,"filename:%A_workingDir%\0.ico|1.ico:0|2.ico|3.ico|4.ico|5.ico|6.ico|7.ico"1,40,40,4,"1,1,1,1") 
Gui, Add, Button, x106 y5 w50 h50 hwndhBtn
ILButton(hBtn,"filename:%A_workingDir%\0.ico|1.ico:0|2.ico|3.ico|4.ico|5.ico|6.ico|7.ico"2,40,40,4,"1,1,1,1") 
Gui, Add, Button, x156 y5 w50 h50 hwndhBtn
ILButton(hBtn,"filename:%A_workingDir%\0.ico|1.ico:0|2.ico|3.ico|4.ico|5.ico|6.ico|7.ico"3,40,40,4,"1,1,1,1") 
Gui, Add, Button, x206 y5 w50 h50 hwndhBtn
ILButton(hBtn,"filename:%A_workingDir%\0.ico|1.ico:0|2.ico|3.ico|4.ico|5.ico|6.ico|7.ico"4,40,40,4,"1,1,1,1") 
Gui, Add, Button, x256 y5 w50 h50 hwndhBtn
ILButton(hBtn,"filename:%A_workingDir%\0.ico|1.ico:0|2.ico|3.ico|4.ico|5.ico|6.ico|7.ico"5,40,40,4,"1,1,1,1") 
Gui, Add, Button, x306 y5 w50 h50 hwndhBtn
ILButton(hBtn,"filename:%A_workingDir%\0.ico|1.ico:0|2.ico|3.ico|4.ico|5.ico|6.ico|7.ico"6,40,40,4,"1,1,1,1") 
Gui, Add, Button, x356 y5 w50 h50 hwndhBtn,
ILButton(hBtn,"filename:%A_workingDir%\0.ico|1.ico:0|2.ico|3.ico|4.ico|5.ico|6.ico|7.ico"7,40,40,4,"1,1,1,1") 
; Generated using SmartGUI Creator 4.0
Gui, Show, x342 y271 h58 w414, New GUI Window
Return

GuiClose:
ExitApp

button8:
ExitApp

even button8 doesn't do anything?