Trouble Passing Banks to user32 api functions

Blitz3D Forums/Blitz3D Userlibs/Trouble Passing Banks to user32 api functions

NewtSoup(Posted 2005) [#1]
Hi all,

I'm trying to work out how to call api functions that want a struct as a parameter.

The example Im using is
.lib user32
MessageBoxIndirect% (lpMsgBoxParams*) : "MessageBoxIndirectA"

_IF_ you were using Visual basic you would create a Type as follows:

Const SHGFI_ICONLOCATION = &H1000
Const MB_ICONASTERISK = &H40&
Const MB_ICONEXCLAMATION = &H30&
Const MAX_PATH = 260
Private Type MSGBOXPARAMS
cbSize As Long
hwndOwner As Long
hInstance As Long
lpszText As String
lpszCaption As String
dwStyle As Long
lpszIcon As String
dwContextHelpId As Long
lpfnMsgBoxCallback As Long
dwLanguageId As Long
End Type

But I'm not, Im using Blitz Basic 3D. However the first thing I did was create a type in B3d and try passing that to the function directly. It sort of worked. The message box has the correct Icon but only single characters for the caption and message.

heres the code I have been experimenting with:

Type MSGBOXPARAMS
   Field cbSize
   Field hwndOwner 
   Field hInstance
   Field lpszText$
   Field lpszCaption$ 
   Field dwStyle
   Field lpszIcon$
   Field dwContextHelpId
   Field lpfnMsgBoxCallback
   Field dwLanguageId
End Type

 
Graphics3D 800,600,32,2

While Not KeyHit(1)
val = MessageBox (getActiveWindow(),"All Your Base Are Belong To Us","Warning",$10 + $3)

 mbx.msgboxparams=New msgboxparams
 mbx\hwndOwner = getActiveWindow()
 mbx\lpszText$="What foul creature wakes me from mine slumber?" +Chr(0)
 mbx\lpszCaption="Warning" + Chr(0)
 mbx\dwStyle=$30
 mbx\cbSize=83


 DoMessageBoxIndirect(mbx)

Print val

WaitKey


Wend

Function doMessageBoxIndirect(mbx.msgboxparams)
	Stop
	;mbx\cbSize=31+Len(mbx\lpszcaption)+Len(mbx\lpsztext)+Len(mbx\lpszIcon)
	
	bnk=CreateBank(mbx\cbSize)
	PokeInt (bnk,0,mbx\cbSize)
	PokeInt (bnk,4,mbx\hwndOwner)
	PokeInt (bnk,8,mbx\hInstance)
	For f=12 To Len(mbx\lpsztext)
		char$=Mid((mbx\lpsztext),f-11,1)
		
		PokeByte bnk,f,Asc(char)
	Next
	f=f+1
	PokeByte bnk,f,0
	f=f+1
	For n=f To Len(mbx\lpszCaption)
		PokeByte bnk,n,Asc(Mid(mbx\lpszCaption,n-(f-1),1))
	Next
	n=n+1
	PokeByte bnk,n,0
	n=n+1
	PokeInt(bnk,n,mbx\dwStyle)
	f=f+1
		For f=n To Len(mbx\lpszCaption)
		PokeByte bnk,f,Asc(Mid(mbx\lpszCaption,f-(n-1),1))
	Next
	f=f+1
	PokeByte bnk,f,0
	f=f+1
	PokeInt (bnk,f,mbx\dwContextHelpID)
	f=f+4
	PokeInt (bnk,f,mbx\lpfnMsgBoxCallback)
	f=f+4
	PokeInt (bnk,f,mbx\dwLanguageId)

	messageboxindirect(bnk)
	


End Function



as I said. If I call messageBoxIndirect (mbx) I get a scrambled output but at least it works a bit. If I use my function to turn the type into a bank and pass that then I get a MAV at runtime.

The method using banks is the same principle as used by Peter Sheutz in the openGLdirect code on Blitz coder:

http://www.blitzcoder.com/cgi-bin/showcase/showcase_showentry.pl?id=peter__scheutz02202003193552&comments=no

So I am pretty sure I am on the right track. I just need someone to point out what I am doing wrong here.

The VB example I found sets cbSize = Len(mbx)
however that wont work in blitz so I guessed it was the size of the whole struct including the text which is 7 ints plus 3 arbitrary null terminated strings Hence the odd formula at the front of my doMessageboxIndirect function.

Would be greatfull if an enlightened one could put me back on the path as at the moment I am face down examining the dirt :)

thanks in advance


DJWoodgate(Posted 2005) [#2]
This is in fact a bit of a pain. What you need to do is poke the address of the null terminated strings for the caption and text into the parameter block (not the strings themselves). Now you can not just poke a bank address because banks are themselves structures, and although blitz will just pass the bank data when you pass a bank directly to a userlib function, it will not know to do this if you store it in a parameter block. So you will need to poke in the address stored at the bank address + 4 which is where the data is stored. One way of getting that is to use one of those external memory functions. So you could have something like...



In this case I am using the BLZ memory DLL and decls which was posted around here some time since, probably as part of something else. I could email it to you if you do not have it or something similar.

I also came across some constants which you might find useful. I think you may find explanations for them by looking up the MessageboxEx function.


NewtSoup(Posted 2005) [#3]
I thought that might be the problem. When I passed the function an empty bank I got an empty message box. Working through, the code only failed when I reached the string. This still left me stuck as I had no idea how to pass the address of the variable storing the string.

Thanks for the help. I may well email you for that dll if I cant find it myself or another way around in the api.. just occured to me I may be able to write the dll myself quite easily by passing the string to a function in C and then returning the address as an int.


NewtSoup(Posted 2005) [#4]
I found the BLZmem dll and got MessageBoxIndirect working. One last question.. why +4 on the blzpeekint()?


DJWoodgate(Posted 2005) [#5]
That is the offset address of the bank data address. Not sure what is at bank+0, could just be a bank identifier sequence or maybe something to do with memory management, the int at bank+4 is the address of the actual bank data and the int at bank+8 is the size of the bank.


NewtSoup(Posted 2005) [#6]
Thanks :)