REAL ImageButton control!

BlitzPlus Forums/BlitzPlus Programming/REAL ImageButton control!

JoshK(Posted 2005) [#1]
One simple command:
SetButtonImage(button,image)



I chose this so that you can change the button image at any time. The function accepts a regular old Blitz image. Use SetButtonImage(button,0) to change the ImageButton back into a regular button.

win=CreateWindow("ImageButton",200,200,400,300,0,3)

i=LoadImage("blitzlogo.bmp")
w=ImageWidth(i)
h=ImageHeight(i)

button=CreateButton("",(ClientWidth(win)-w)/2,(ClientHeight(win)-h)/2,w,h,win)
SetButtonImage button,i

Repeat
Until WaitEvent()=$803


Const BM_SETIMAGE=247
Const IMAGE_BITMAP=0
Const IMAGE_ICON=1
Const BS_BITMAP=128
Const GWL_STYLE=-16
Const LR_DEFAULTSIZE=64
Const LR_LOADFROMFILE=16
Const LR_SHARED=32768

Function SetButtonImage(button,image)
hbutton=QueryObject(button,1)
flags=GetWindowLong(hbutton,GWL_STYLE)
If image
	If Not (BS_BITMAP And flags) SetWindowLong hbutton,GWL_STYLE,flags+BS_BITMAP
	Else
	If (BS_BITMAP And flags) SetWindowLong hbutton,GWL_STYLE,flags-BS_BITMAP
	Return
	EndIf
w=ImageWidth(image)
h=ImageHeight(image)
ibuffer=ImageBuffer(image)
LockBuffer ibuffer
pixels=CreateBank(w*h*4)
For y=0 To h-1
	For x=0 To w-1
		PokeInt pixels,4*(y*w+x)+0,ReadPixelFast(x,y,ibuffer)
		Next
	Next
UnlockBuffer ibuffer
i=CreateBitmap(w,h,1,32,pixels)
FreeBank pixels
If Not i Return
oldimage=SendMessage(hbutton,BM_SETIMAGE,IMAGE_BITMAP,i)
If oldimage DeleteObject(oldimage)
Return True
End Function



Beaker(Posted 2005) [#2]
CreateBitMap() function not found.


NetGamer(Posted 2005) [#3]
Function 'getwindowlong' not found


NetGamer(Posted 2005) [#4]
And I expect that SetWindowLong, SendMessage and DeleteObject will also not be found.

Could you provide decls and supporting library references?


JoshK(Posted 2005) [#5]
Those are all API functions, which you should already have installed. Get the gdi32, kernel32, and user32 decls files from the code archive.


Blaine(Posted 2005) [#6]
Cool, this works great! You should post it in the code archives (and mention that it needs those userlibs)!


NetGamer(Posted 2005) [#7]
snagged kernal32.decls, user32.decls, and gdi32.decls. All stashed with my other .decl files.

SetWindowLong, SendMessage, DeleteObject, GetWindowLong, and CreateBitmap still not found. Eyeballed the .decl files and see they all have api_ prefixes. Edited the above source into:

api_SetWindowLong,
api_SendMessage,
api_DeleteObject,
api_GetWindowLong, and
api_CreateBitmap.

It now passes the syntax check and runs before crashing. It abends at the following line:
oldimage=api_SendMessage(hbutton,BM_SETIMAGE,IMAGE_BITMAP,i)

The abend is your classic 0xc0000005

I did mod the source of the image to point to the ide_toolbar.bmp in the BlitzPlus\cfg subdirectory.

What am I missing?


NetGamer(Posted 2005) [#8]
The user32.decls needs a tweak. Per aero:

Use this:
SendMessage%(hwnd%,wMsg%,wParam%,lParam%) : "SendMessageA"

NOT this:
SendMessage%(hwnd%,wMsg%,wParam%,lParam*) : "SendMessageA"




*(Posted 2005) [#9]
crashes here too


JoshK(Posted 2005) [#10]
Use this:
SendMessage%(hwnd%,wMsg%,wParam%,lParam%) : "SendMessageA"

NOT this:
SendMessage%(hwnd%,wMsg%,wParam%,lParam*) : "SendMessageA"


*(Posted 2005) [#11]
yup changed it but still crashes


JRalha(Posted 2007) [#12]
Did all the above but the only thing i get is a blank button with width and height of the image loaded...
(Tried bmp and jpg filetypes...)

Any suggestions or advice?


Ked(Posted 2007) [#13]
OK. Create a userlib file if you don't already have one.
.lib "user32.dll"
USER32_SendMessage%(hWnd%,Msg%,wParam%,lParam%):"SendMessageA"
USER32_GetWindowLong%(hWnd%,nIndex%):"GetWindowLongA"
USER32_SetWindowLong%(hWnd%,nIndex%,dwNewLong%):"SetWindowLongA"

.lib "gdi32.dll"
GDI32_CreateBitmap%(nWidth%,nHeight%,nPlanes%,nBitCount%,lpBits*):"CreateBitmap"
GDI32_DeleteObject%(hObject%):"DeleteObject"


Change the code to this:
win=CreateWindow("ImageButton",200,200,400,300,0,3)

i=LoadImage("blitzlogo.bmp")
w=ImageWidth(i)
h=ImageHeight(i)

button=CreateButton("",(ClientWidth(win)-w)/2,(ClientHeight(win)-h)/2,w,h,win)
SetButtonImage button,i

Repeat
Until WaitEvent()=$803


Const BM_SETIMAGE=247
Const IMAGE_BITMAP=0
Const IMAGE_ICON=1
Const BS_BITMAP=128
Const GWL_STYLE=-16
Const LR_DEFAULTSIZE=64
Const LR_LOADFROMFILE=16
Const LR_SHARED=32768

Function SetButtonImage(button,image)
hbutton=QueryObject(button,1)
flags=USER32_GetWindowLong(hbutton,GWL_STYLE)
If image
	If Not (BS_BITMAP And flags) USER32_SetWindowLong hbutton,GWL_STYLE,flags+BS_BITMAP
	Else
	If (BS_BITMAP And flags) USER32_SetWindowLong hbutton,GWL_STYLE,flags-BS_BITMAP
	Return
	EndIf
w=ImageWidth(image)
h=ImageHeight(image)
ibuffer=ImageBuffer(image)
LockBuffer ibuffer
pixels=CreateBank(w*h*4)
For y=0 To h-1
	For x=0 To w-1
		PokeInt pixels,4*(y*w+x)+0,ReadPixelFast(x,y,ibuffer)
		Next
	Next
UnlockBuffer ibuffer
i=GDI32_CreateBitmap(w,h,1,32,pixels)
FreeBank pixels
If Not i Return
oldimage=USER32_SendMessage(hbutton,BM_SETIMAGE,IMAGE_BITMAP,i)
If oldimage GDI32_DeleteObject(oldimage)
Return True
End Function


Find an image or whatever and put it in the same directory as the file (if it's saved then that directory, if not then its in program files\blitzplus\tmp\). Change the above "LoadImage" part to the name of the image file.


UUICEO(Posted 2007) [#14]
I like the code.. Thanks! I hope you don't mind but I made an adjustment to it. Give this a try also:
win=CreateWindow("ImageButton",200,200,400,300,0,3)
i=LoadImage("test2.bmp"); These two images should be the same size but look different
j=LoadImage("test1.bmp"); (other image)
w=ImageWidth(i)
h=ImageHeight(i)
button=CreateButton("",(ClientWidth(win)-w)/2,(ClientHeight(win)-h)/2,w,h,win)
SetButtonImage button,i
current = i
Repeat
ID = WaitEvent(1)
	Select ID
		Case $401
			Select EventSource()
				Case button
				If current = j Then current = i Else current = j
					SetButtonImage button,current
			End Select
		Case $803
			End
	End Select
Forever
Const BM_SETIMAGE=247
Const IMAGE_BITMAP=0
Const IMAGE_ICON=1
Const BS_BITMAP=128
Const GWL_STYLE=-16
Const LR_DEFAULTSIZE=64
Const LR_LOADFROMFILE=16
Const LR_SHARED=32768

Function SetButtonImage(button,NEWimage)
hbutton=QueryObject(button,1)
flags=GetWindowLong(hbutton,GWL_STYLE)
If (Not image = NEWimage)
		If Not (BS_BITMAP And flags) SetWindowLong hbutton,GWL_STYLE,flags+BS_BITMAP
	Else
		If (BS_BITMAP And flags) SetWindowLong hbutton,GWL_STYLE,flags-BS_BITMAP
		Return
EndIf
w=ImageWidth(NEWimage)
h=ImageHeight(NEWimage)
ibuffer=ImageBuffer(NEWimage)
LockBuffer ibuffer
pixels=CreateBank(w*h*4)
For y=0 To h-1
	For x=0 To w-1
		PokeInt pixels,4*(y*w+x)+0,ReadPixelFast(x,y,ibuffer)
	Next
Next
UnlockBuffer ibuffer
tmp=CreateBitmap(w,h,1,32,pixels)
FreeBank pixels
If Not tmp Return
oldimage=SendMessage(hbutton,BM_SETIMAGE,IMAGE_BITMAP,tmp)
If oldimage DeleteObject(oldimage)
image = NEWimage
Return True
End Function



EPS(Posted 2007) [#15]
Is there any way to use transparent images on the buttons? I tried white, pink and black as transparent color but nothing works. Any ideas?