Trouble Passing Banks to user32 api functions
Blitz3D Forums/Blitz3D Userlibs/Trouble Passing Banks to user32 api functions
| ||
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 |
| ||
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. |
| ||
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. |
| ||
I found the BLZmem dll and got MessageBoxIndirect working. One last question.. why +4 on the blzpeekint()? |
| ||
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. |
| ||
Thanks :) |