Calling object methods using structures
by Richard Russell, March 2007
Calling COM, OLE or ActiveX object methods generally involves the use of a rather arcane syntax, such as this example taken from the BB4W manual under Displaying GIF and JPEG images:
SYS !(!gpp%+24), gpp%, ^hmw% : REM. IPicture::get_Width SYS !(!gpp%+28), gpp%, ^hmh% : REM. IPicture::get_Height
Here it is not at all clear what methods are being called, and how, hence the need for comments.
It is possible to improve the clarity considerably by using a structure to represent the object. You can then call the object's methods as follows:
SYS IPicture.get_Width%, gpp%, ^hmw% SYS IPicture.get_Height%, gpp%, ^hmh%
To make this work you need to declare a structure containing all the object's methods in the correct order. In the case of the IPicture interface the structure needs to be declared as follows:
DIM IPicture{QueryInterface%, AddRef%, Release%, get_Handle%, get_hPal%, \
\ get_Type%, get_Width%, get_Height%, Render%, set_hPal%, get_CurDC%, \
\ SelectPicture%, get_KeepOriginalFormat%, put_KeepOriginalFormat%, \
\ PictureChanged%, SaveAsFile%, get_Attributes%}
To complete the process we must point the structure at the object's dispatch table:
PTR(IPicture{}) = !gpp%
The memory originally allocated when the structure was created is wasted, but this isn't a problem if it is declared as a LOCAL structure.
As a practical illustration of the use of this technique here is a replacement for the PROCdisplay routine listed in the BB4W manual:
DEF PROCdisplay(picture$, xpos%, ypos%, xsize%, ysize%) LOCAL iid{}, IPicture{}, oleaut32%, olpp%, gpp%, hmw%, hmh%, picture%, res% DIM iid{a%,b%,c%,d%}, picture% LOCAL 513 DIM IPicture{QueryInterface%, AddRef%, Release%, get_Handle%, get_hPal%, \ \ get_Type%, get_Width%, get_Height%, Render%, set_hPal%, get_CurDC%, \ \ SelectPicture%, get_KeepOriginalFormat%, put_KeepOriginalFormat%, \ \ PictureChanged%, SaveAsFile%, get_Attributes%} SYS "LoadLibrary", "OLEAUT32.DLL" TO oleaut32% SYS "GetProcAddress", oleaut32%, "OleLoadPicturePath" TO olpp% IF olpp%=0 ERROR 100, "Could not get address of OleLoadPicturePath" SYS "MultiByteToWideChar", 0, 0, picture$, -1, picture%, 256 iid.a% = &7BF80980 iid.b% = &101ABF32 iid.c% = &AA00BB8B iid.d% = &AB0C3000 SYS olpp%, picture%, 0, 0, 0, iid{}, ^gpp% IF gpp% = 0 ERROR 100, "OleLoadPicturePath failed" PTR(IPicture{}) = !gpp% SYS IPicture.get_Width%, gpp%, ^hmw% SYS IPicture.get_Height%, gpp%, ^hmh% SYS IPicture.Render%, gpp%, @memhdc%, xpos%, ypos%, xsize%, ysize%, 0, \ \ hmh%, hmw%, -hmh%, 0 TO res% IF res% ERROR 100, "IPicture::Render failed" SYS IPicture.Release%, gpp% SYS "InvalidateRect", @hwnd%, 0, 0 SYS "UpdateWindow", @hwnd% ENDPROC