AnsweredAssumed Answered

vrf VARIANT of VT_BSTR or VT_ARRAY

Question asked by VRFuser on Jul 21, 2003
Martin,

This is another of those things where you're going to see how VEE does stuff
behind the curtain. I don't want to turn this into another one of these big
tutorial deals, but it goes like this: all this happens automatically if you
happen to be going through an IDispatch interface, but since you're not you
have to do-it-yourself. Type the input parameter (the one they say is
supposed to be a VT_ARRAY) to your dll as long.

Reading the bitmap data is the first challenge. Different bitmaps are stored
in different formats, and you have to read it correctly to get it straight.
I'm assuming that the bitmap is of the 8-bpp variety. If it's not, then some
of the constants and data sizes and parameter type specifications below have
to change. A 256-color BMP is one of the easiest to handle. At the end, I'll
explain how to change this.

I uploaded a program to the VRF back in the beginning of June called
ChgBmp3.vee that can read all sorts of different bitmaps correctly. Look for
the subject "Bitmap manipulation with VEE". The function ReadBmp is what you
need.

I kinda lied a couple months ago when I said that VEE 5 can't deal with
Variants. It's true that it can't deal with Variants as a native type, but
that doesn't stop you from using the API to do-it-yourself. There are only a
few steps you need to take to create and use a VT_ARRAY in a Variant.

1) Create a SafeArray and fill it with data.
2) Allocate memory for a Variant.
3) Initialize the Variant with the SafeArray.

The calls you need are (in order):

1) long __stdcall SafeArrayCreateVector(short vtVarType, long lLBound,
    int cElements); //From oleaut32.dll

3) long __stdcall SafeArrayPutElement(long pSafeArray, long *pIndex,
    char *pValue); //From oleaut32.dll

2) long __stdcall GlobalAlloc(int uFlags, long dwBytes);
    //From kernel32.dll

3a) V2W2.RtlMoveMemory(long pDst, short pSrc, int iBytes);
3b) V2W4.RtlMoveMemory(long pDst, long pSrc, int iBytes);
     // Need to put these two in two different imports so VEE can keep
     // them straight. RtlMoveMemory is in ntdll.dll.

4) void __stdcall VariantInit(long pVariant); //From oleaut32.dll

5) long __stdcall GlobalFree(long pMem); //From kernel32.dll

In pseudocode, it looks something like this:

VT_UI1 = 17
VT_ARRAY = 0x200
NUMPIX = Number of pixels in BMP
psa = SafeArrayCreateVector(VT_UI1, 0, NUMPIX)
for i = 0 to each pixel in BMP
  hr = SafeArrayPutElement(psa, &i, &BMP[i])
next byte
pMem = GlobalAlloc(0x40, 16)          //Alloc VARIANT.
V2W2.RtlMoveMemory(pMem, VT_ARRAY, 2) //Set VARIANT type.
V2W4.RtlMoveMemory(pMem + 8, psa, 4)  //Set VARIANT value.
(call your dll function here - the input param is pMem)
GlobalFree(pMem)

When you set the variant type, you might have to make it VT_ARRAY + VT_UI1,
I'm not sure - but the safe array already has VT_UI1 type, so I don't think
so. GlobalAlloc is not really the correct function to use for this purpose,
but you can't use the correct one so this will have to do. Just make sure to
call GlobalFree after using the memory.

There are three other formats of bitmaps that you'll probably run across.
They are 16-bpp, 24-bpp and 32-bpp. These are unpalettized bitmaps, where
the color of each pixel is directly specified by 16, 24 and 32 bits
respectively - not an index into a palette that specifies the color values.
In the case of 16-bpp bitmaps, the variant type of the SafeArray will be
VT_UI2 (18) and the third parameter of SafeArrayPutElement will be short
*pValue. For 24-bpp, it's VT_UI4 (19) and long *pValue. For 32-bpp, it's the
same as 24-bpp. The ReadBmp function in ChgBmp2.vee will deal with these
bitmaps correctly.

If all this is Greek to you, let me know and I'll try to work up an example
in the next few days. I need to finish up VPP though and I'm starting to get
real work in too, so I won't be able to do much for the next few weeks.
-SHAWN-


---
You are currently subscribed to vrf as: rsb@soco.agilent.com
To subscribe send a blank email to "join-vrf@it.lists.it.agilent.com".
To unsubscribe send a blank email to "leave-vrf@it.lists.it.agilent.com".
To send messages to this mailing list,  email "vrf@it.lists.it.agilent.com". 
If you need help with the mailing list send a message to "owner-vrf@it.lists.it.agilent.com".

Outcomes