Using VB6 and GDI+ ( aka GDIPlus )? 
Author Message
 Using VB6 and GDI+ ( aka GDIPlus )?

Tools: VB6 (SP5)
OS: Win98 SE (with GDI+ RTM)
Problem: I would really, really like to use some of the GDI+ functions, such
as Alpha, Anti-Aliasing, and Gradients, but I'm mainly interested in the
Curve and Multiple Image Encoding/Decoding right now. Is there a way to get
the GDI+ functionality (full or partial) using VB6? I can't afford
VS/VB.Net, let alone the new OS it requires, hence my need for VB6
declarations. If there isn't a "pure VB" method, what alternatives are
there? Any help, ideas, code, or downloads would be very appreciated!

Thanks,
   Avery



Thu, 13 Jan 2005 22:24:22 GMT  
 Using VB6 and GDI+ ( aka GDIPlus )?

Quote:
>Tools: VB6 (SP5)
>OS: Win98 SE (with GDI+ RTM)
>Problem: I would really, really like to use some of the GDI+ functions, such
>as Alpha, Anti-Aliasing, and Gradients, but I'm mainly interested in the
>Curve and Multiple Image Encoding/Decoding right now. Is there a way to get
>the GDI+ functionality (full or partial) using VB6? I can't afford
>VS/VB.Net, let alone the new OS it requires, hence my need for VB6
>declarations. If there isn't a "pure VB" method, what alternatives are
>there? Any help, ideas, code, or downloads would be very appreciated!

For background read the following threads at Google:

From: Andrew Mayo
Subject: Microsoft 'persuasion' to move to .NET
microsoft.public.win32.programmer.gdi
Date: 2002-05-22 05:22:46 PST

From: Andrew Mayo
Subject: HOWTO: call GDIPLUS directly from VB6
Newsgroups: comp.lang.basic.visual.misc
Date: 2002-05-28 03:11:39 PST

As you will see from the latter post you can call GdiPlus.dll directly
from VB6 but it's quite a task setting up the declares (600 plus),
constants, and structures. What you need is the Platform SDK for
documentation and .h files (they're in C of course).

Perhaps someone will produce a typelib - I'm thinking about it.

--
Richard Mason



Fri, 14 Jan 2005 15:05:57 GMT  
 Using VB6 and GDI+ ( aka GDIPlus )?
    Thanks Richard, those links were very helpful. I was hoping it wouldn't
come to this, but I suppose I'll have to ponder over those header files for
a while....Sigh....

Avery


Quote:

> >Tools: VB6 (SP5)
> >OS: Win98 SE (with GDI+ RTM)
> >Problem: I would really, really like to use some of the GDI+ functions,
such
> >as Alpha, Anti-Aliasing, and Gradients, but I'm mainly interested in the
> >Curve and Multiple Image Encoding/Decoding right now. Is there a way to
get
> >the GDI+ functionality (full or partial) using VB6? I can't afford
> >VS/VB.Net, let alone the new OS it requires, hence my need for VB6
> >declarations. If there isn't a "pure VB" method, what alternatives are
> >there? Any help, ideas, code, or downloads would be very appreciated!

> For background read the following threads at Google:

> From: Andrew Mayo
> Subject: Microsoft 'persuasion' to move to .NET
> microsoft.public.win32.programmer.gdi
> Date: 2002-05-22 05:22:46 PST

> From: Andrew Mayo
> Subject: HOWTO: call GDIPLUS directly from VB6
> Newsgroups: comp.lang.basic.visual.misc
> Date: 2002-05-28 03:11:39 PST

> As you will see from the latter post you can call GdiPlus.dll directly
> from VB6 but it's quite a task setting up the declares (600 plus),
> constants, and structures. What you need is the Platform SDK for
> documentation and .h files (they're in C of course).

> Perhaps someone will produce a typelib - I'm thinking about it.

> --
> Richard Mason



Sat, 15 Jan 2005 00:22:20 GMT  
 Using VB6 and GDI+ ( aka GDIPlus )?
    Maybe someone can help me out here...I'm having some issues converting
some of the GDI+ APIs. Currently, I don't know what the VB equivalent of
this would be:
GdipDrawCurveI(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPoint *points,
INT count);

I have this:
Public Declare Function GdipDrawCurveI Lib "gdiplus" (ByVal graphics As
Long, ByVal pen As Long, points, ByVal count As Long) As Long

...but as you can see, in the VB declaration I didn't yet define a value for
points. What should I define that parameter as? And how to make an array of
them? GpPoint seems to be a class, and in the C++ samples the points
parameter is an array of that class, but I don't know what to do with it.

    Also, I'm not too swift with converting bitwise shift operators to VB,
so maybe someone can help with this function:

    static ARGB MakeARGB(IN BYTE a,
                         IN BYTE r,
                         IN BYTE g,
                         IN BYTE b)
    {
        return (((ARGB) (b) <<  BlueShift) |
                ((ARGB) (g) << GreenShift) |
                ((ARGB) (r) <<   RedShift) |
                ((ARGB) (a) << AlphaShift));
    }

Here is what I have so far, which isn't much at all, I admit:
Note: I have declared the _Shift constants in VB

' Use this in lieu of the Color class constructor
Public Function MakeARGB(ByVal a As Byte, ByVal r As Byte, ByVal g As Byte,
ByVal b As Byte) As Long
   MakeARGB = 0
End Function


Quote:
>     Thanks Richard, those links were very helpful. I was hoping it
wouldn't
> come to this, but I suppose I'll have to ponder over those header files
for
> a while....Sigh....

> Avery




> > >Tools: VB6 (SP5)
> > >OS: Win98 SE (with GDI+ RTM)
> > >Problem: I would really, really like to use some of the GDI+ functions,
> such
> > >as Alpha, Anti-Aliasing, and Gradients, but I'm mainly interested in
the
> > >Curve and Multiple Image Encoding/Decoding right now. Is there a way to
> get
> > >the GDI+ functionality (full or partial) using VB6? I can't afford
> > >VS/VB.Net, let alone the new OS it requires, hence my need for VB6
> > >declarations. If there isn't a "pure VB" method, what alternatives are
> > >there? Any help, ideas, code, or downloads would be very appreciated!

> > For background read the following threads at Google:

> > From: Andrew Mayo
> > Subject: Microsoft 'persuasion' to move to .NET
> > microsoft.public.win32.programmer.gdi
> > Date: 2002-05-22 05:22:46 PST

> > From: Andrew Mayo
> > Subject: HOWTO: call GDIPLUS directly from VB6
> > Newsgroups: comp.lang.basic.visual.misc
> > Date: 2002-05-28 03:11:39 PST

> > As you will see from the latter post you can call GdiPlus.dll directly
> > from VB6 but it's quite a task setting up the declares (600 plus),
> > constants, and structures. What you need is the Platform SDK for
> > documentation and .h files (they're in C of course).

> > Perhaps someone will produce a typelib - I'm thinking about it.

> > --
> > Richard Mason



Sat, 15 Jan 2005 02:54:34 GMT  
 Using VB6 and GDI+ ( aka GDIPlus )?

Quote:
>    Maybe someone can help me out here...I'm having some issues converting
>some of the GDI+ APIs. Currently, I don't know what the VB equivalent of
>this would be:
>GdipDrawCurveI(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPoint *points,
>INT count);

>I have this:
>Public Declare Function GdipDrawCurveI Lib "gdiplus" (ByVal graphics As
>Long, ByVal pen As Long, points, ByVal count As Long) As Long

Public Type POINTAPI
  X As Long
  Y As Long
End Type

(ByVal graphics As Long, ByVal pen As Long, points As POINTAPI, ByVal
count As Long) As Long

Dim curvepoints(1 to 5) as POINTAPI
curvepoint(1).X = 50
curvepoint(1).Y = 100
etc.

  lstatus = GdipCreateFromHDC(picDest.hDC, graphics)
  lstatus = GdipCreatePen1(ColorARGB(255, 255, 0, 0), 2, UnitPixel,
thispen)
  lstatus = GdipDrawCurveI(graphics, thispen, curvepts(1), 5)

  picDest.Refresh

  lstatus = GdipDeletePen(thispen)

Quote:
>' Use this in lieu of the Color class constructor
>Public Function MakeARGB(ByVal a As Byte, ByVal r As Byte, ByVal g As Byte,
>ByVal b As Byte) As Long
>   MakeARGB = 0
>End Function

I prefer this:

Public Type COLORBYTES
  BlueByte As Byte
  GreenByte As Byte
  RedByte As Byte
  AlphaByte As Byte
End Type

Public Type COLORLONG
  longval As Long
End Type

Public Function ColorARGB(Alpha As Byte, Red As Byte, Green As Byte,
Blue As Byte) As Long

  Dim bytestruct As COLORBYTES
  Dim result As COLORLONG

  With bytestruct
    .AlphaByte = Alpha
    .RedByte = Red
    .GreenByte = Green
    .BlueByte = Blue
  End With

  LSet result = bytestruct
  ColorARGB = result.longval

End Function

--
Richard Mason



Sat, 15 Jan 2005 08:36:06 GMT  
 Using VB6 and GDI+ ( aka GDIPlus )?
    Thanks, that was very helpful... I never knew of the LSet statement, but
I still don't why that code works with the POINTAPI struct whereas the C++
code uses a class....why is that? I know that a C++ struct is a special
class, and I know that the MFC CPoint is derived from the POINT struct, but
why can the struct be used instead of a class not derived from the struct? I
suspect that the variables must be in the exact places as those in the
struct to make it work, but then what about functions declared ahead of the
class vars? It is very perplexing to me...

    Now, as I continue to make life difficult, I encountered another problem
when trying to get the CLSIDs of encoders and decoders. Here is the function
I brazenly tried to convert (straight from the SDK):

int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
   UINT  num = 0;          // number of image encoders
   UINT  size = 0;         // size of the image encoder array in bytes

   ImageCodecInfo* pImageCodecInfo = NULL;

   GetImageEncodersSize(&num, &size);
   if(size == 0)
      return -1;  // Failure

   pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
   if(pImageCodecInfo == NULL)
      return -1;  // Failure

   GetImageEncoders(num, size, pImageCodecInfo);

   for(UINT j = 0; j < num; ++j)
   {
      if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
      {
         *pClsid = pImageCodecInfo[j].Clsid;
         free(pImageCodecInfo);
         return j;  // Success
      }
   }

   free(pImageCodecInfo);
   return -1;  // Failure

Quote:
}

// -------END
CODE------------------------------------------------------------------

    And here is my "interpretation" that does not work (causes a GPF):

Public Declare Function GdipGetImageEncodersSize Lib "gdiplus" (numEncoders
As Long, size As Long) As GpStatus
Public Declare Function GdipGetImageEncoders Lib "gdiplus" (ByVal
numEncoders As Long, ByVal size As Long, encoders As ImageCodecInfo) As
GpStatus

Public Type CLSID
    Data1 As Long
    Data2 As Integer
    Data3 As Integer
    Data4 As String * 8
End Type

Public Type ImageCodecInfo
   ClassID As CLSID
   FormatID As CLSID
   CodecName As Long      ' String Pointer; const WCHAR*
   DllName As Long        ' String Pointer; const WCHAR*
   FormatDescription As Long ' String Pointer; const WCHAR*
   FilenameExtension As Long ' String Pointer; const WCHAR*
   MimeType As Long       ' String Pointer; const WCHAR*
   Flags As Long
   Version As Long
   SigCount As Long
   SigSize As Long
   SigPattern As Long      ' Byte Array Pointer; BYTE*
   SigMask As Long         ' Byte Array Pointer; BYTE*
End Type

Public Function GetEncoderClsid(strFormat As String, ClassID As CLSID)
   Dim num As Long, size As Long, I As Long
   Dim ICI() As ImageCodecInfo

   GetEncoderClsid = -1 'Failure flag

   ' Get the encoder array size
   Call GdipGetImageEncodersSize(num, size)
   If size = 0 Then Exit Function ' Failed!

   ' Allocate room for the array dynamically
   ReDim ICI(1 To size) As ImageCodecInfo

   ' Get the array
   Call GdipGetImageEncoders(num, size, ICI(1))

   ' **** The execution never makes it here ************
   For I = LBound(ICI) To UBound(ICI)
      If StrComp(PtrToStr(ICI(I).MimeType), strFormat, vbTextCompare) = 0
Then
         GetEncoderClsid = I
         Exit For
      End If
   Next
   Erase ICI   ' Free the array
End Function
' -------END
CODE------------------------------------------------------------------

    If I get rid of the ICI array and use a string, I get the data copied
without error, but then what?! I'm pretty sure I'm not doing something
right.... does anyone see what I'm missing or have done wrong?

Avery



Sat, 15 Jan 2005 21:09:43 GMT  
 Using VB6 and GDI+ ( aka GDIPlus )?
    Is this the correction VB declaration for this class?

Public Type PathData
   count As Long
   points As Long    ' Pointer to POINTAPIF array
   types As Long     ' Pointer to BYTE array
End Type

// C++ Original Class:
class PathData
{
public:
    PathData()
    {
        Count = 0;
        Points = NULL;
        Types = NULL;
    }

    ~PathData()
    {
        if (Points != NULL)
        {
            delete Points;
        }

        if (Types != NULL)
        {
            delete Types;
        }
    }

private:
    PathData(const PathData &);
    PathData& operator=(const PathData &);

public:
    INT Count;
    PointF* Points;
    BYTE* Types;

Quote:
};



Sun, 16 Jan 2005 21:27:14 GMT  
 Using VB6 and GDI+ ( aka GDIPlus )?

Quote:
>    Thanks, that was very helpful... I never knew of the LSet statement, but
>I still don't why that code works with the POINTAPI struct whereas the C++
>code uses a class....why is that?

I'm not a C/C++ programmer so I've no idea. I can just about manage to
translate declarations and structures to VB :-)

Quote:
>    And here is my "interpretation" that does not work (causes a GPF):

>Public Declare Function GdipGetImageEncodersSize Lib "gdiplus" (numEncoders
>As Long, size As Long) As GpStatus
>Public Declare Function GdipGetImageEncoders Lib "gdiplus" (ByVal
>numEncoders As Long, ByVal size As Long, encoders As ImageCodecInfo) As
>GpStatus

>   ' Get the encoder array size
>   Call GdipGetImageEncodersSize(num, size)
>   If size = 0 Then Exit Function ' Failed!

>   ' Allocate room for the array dynamically
>   ReDim ICI(1 To size) As ImageCodecInfo

I haven't looked at these particular functions before but I did a test
and got a value for numEncoders of 5 and a size of 1040, so you wouldn't
have an array (1 to size) of ImageCodecInfo but rather (1 to
numEncoders).

The data, as I see it, starts with num (5) headers where each header is
a ImageCodecInfo and the header data, apart from the GUID's, gives the
offset from data start of the particular info for each encoder.
I'll have a closer look at it.

--
Richard Mason



Sun, 16 Jan 2005 22:31:10 GMT  
 Using VB6 and GDI+ ( aka GDIPlus )?
    I finally figured it out. Here is what worked:

Public Function GetDecoderClsid(strMimeType As String, ClassID As CLSID)
   Dim num As Long, Size As Long, I As Long
   Dim ICI() As ImageCodecInfo
   Dim buffer() As Byte

   GetDecoderClsid = -1 'Failure flag

   ' Get the encoder array size
   Call GdipGetImageDecodersSize(num, Size)
   If Size = 0 Then Exit Function ' Failed!

   ' Allocate room for the arrays dynamically
   ReDim ICI(1 To num) As ImageCodecInfo
   ReDim buffer(1 To Size) As Byte

   ' Get the array and string data
   Call GdipGetImageDecoders(num, Size, buffer(1))
   ' Copy the class headers
   Call CopyMemory(ICI(1), buffer(1), (Len(ICI(1)) * num))

   ' Loop through all the codecs
   For I = 1 To num
      ' Must convert the pointer into a usable string
      If StrComp(PtrToStrW(ICI(I).MimeType), strMimeType, vbTextCompare) = 0
Then
         ClassID = ICI(I).ClassID   ' Save the class id
         GetDecoderClsid = I        ' return the index number for success
         Exit For
      End If
   Next
   ' Free the memory
   Erase ICI
   Erase buffer
End Function

    Thanks for helping me! Now I finally have *all* the GDI+ APIs, and their
required constants, types, and all but one of the enums translated, with
probably 99% accuracy. I even translated about 10 SDK samples to fiddle with
:)  If you'd like the entire sample project, just say so. I'm going to try
to get someone to post it on the web somewhere, either hacked apart by
others, or in its entirety - no one should have to go through what I have!

Note: If you'd like to see if you can determine how to translate this final
enum, check out my other post in microsoft.public.vb.winapi entitled: VB6
translation of malloc and free, with a bit of casting (it would seem), How?

PS: You were right - the Redim of 1 to size was wrong, but using the number
of encoders didn't allocate enough memory, but I used a workaround as you
can see above.

Avery


Quote:

> >    Thanks, that was very helpful... I never knew of the LSet statement,
but
> >I still don't why that code works with the POINTAPI struct whereas the
C++
> >code uses a class....why is that?

> I'm not a C/C++ programmer so I've no idea. I can just about manage to
> translate declarations and structures to VB :-)

> >    And here is my "interpretation" that does not work (causes a GPF):

> >Public Declare Function GdipGetImageEncodersSize Lib "gdiplus"
(numEncoders
> >As Long, size As Long) As GpStatus
> >Public Declare Function GdipGetImageEncoders Lib "gdiplus" (ByVal
> >numEncoders As Long, ByVal size As Long, encoders As ImageCodecInfo) As
> >GpStatus

> >   ' Get the encoder array size
> >   Call GdipGetImageEncodersSize(num, size)
> >   If size = 0 Then Exit Function ' Failed!

> >   ' Allocate room for the array dynamically
> >   ReDim ICI(1 To size) As ImageCodecInfo

> I haven't looked at these particular functions before but I did a test
> and got a value for numEncoders of 5 and a size of 1040, so you wouldn't
> have an array (1 to size) of ImageCodecInfo but rather (1 to
> numEncoders).

> The data, as I see it, starts with num (5) headers where each header is
> a ImageCodecInfo and the header data, apart from the GUID's, gives the
> offset from data start of the particular info for each encoder.
> I'll have a closer look at it.

> --
> Richard Mason



Mon, 17 Jan 2005 18:37:27 GMT  
 Using VB6 and GDI+ ( aka GDIPlus )?
I'm interested and like yourself I'm sure that there are many others
who would be. To get good exposure, try posting here:-

<http://www.planetsourcecode.com/vb>

Graeme

Quote:

>    I finally figured it out. Here is what worked:

>Public Function GetDecoderClsid(strMimeType As String, ClassID As CLSID)
>   Dim num As Long, Size As Long, I As Long
>   Dim ICI() As ImageCodecInfo
>   Dim buffer() As Byte

>   GetDecoderClsid = -1 'Failure flag

>   ' Get the encoder array size
>   Call GdipGetImageDecodersSize(num, Size)
>   If Size = 0 Then Exit Function ' Failed!

>   ' Allocate room for the arrays dynamically
>   ReDim ICI(1 To num) As ImageCodecInfo
>   ReDim buffer(1 To Size) As Byte

>   ' Get the array and string data
>   Call GdipGetImageDecoders(num, Size, buffer(1))
>   ' Copy the class headers
>   Call CopyMemory(ICI(1), buffer(1), (Len(ICI(1)) * num))

>   ' Loop through all the codecs
>   For I = 1 To num
>      ' Must convert the pointer into a usable string
>      If StrComp(PtrToStrW(ICI(I).MimeType), strMimeType, vbTextCompare) = 0
>Then
>         ClassID = ICI(I).ClassID   ' Save the class id
>         GetDecoderClsid = I        ' return the index number for success
>         Exit For
>      End If
>   Next
>   ' Free the memory
>   Erase ICI
>   Erase buffer
>End Function

>    Thanks for helping me! Now I finally have *all* the GDI+ APIs, and their
>required constants, types, and all but one of the enums translated, with
>probably 99% accuracy. I even translated about 10 SDK samples to fiddle with
>:)  If you'd like the entire sample project, just say so. I'm going to try
>to get someone to post it on the web somewhere, either hacked apart by
>others, or in its entirety - no one should have to go through what I have!

>Note: If you'd like to see if you can determine how to translate this final
>enum, check out my other post in microsoft.public.vb.winapi entitled: VB6
>translation of malloc and free, with a bit of casting (it would seem), How?

>PS: You were right - the Redim of 1 to size was wrong, but using the number
>of encoders didn't allocate enough memory, but I used a workaround as you
>can see above.

>Avery




>> >    Thanks, that was very helpful... I never knew of the LSet statement,
>but
>> >I still don't why that code works with the POINTAPI struct whereas the
>C++
>> >code uses a class....why is that?

>> I'm not a C/C++ programmer so I've no idea. I can just about manage to
>> translate declarations and structures to VB :-)

>> >    And here is my "interpretation" that does not work (causes a GPF):

>> >Public Declare Function GdipGetImageEncodersSize Lib "gdiplus"
>(numEncoders
>> >As Long, size As Long) As GpStatus
>> >Public Declare Function GdipGetImageEncoders Lib "gdiplus" (ByVal
>> >numEncoders As Long, ByVal size As Long, encoders As ImageCodecInfo) As
>> >GpStatus

>> >   ' Get the encoder array size
>> >   Call GdipGetImageEncodersSize(num, size)
>> >   If size = 0 Then Exit Function ' Failed!

>> >   ' Allocate room for the array dynamically
>> >   ReDim ICI(1 To size) As ImageCodecInfo

>> I haven't looked at these particular functions before but I did a test
>> and got a value for numEncoders of 5 and a size of 1040, so you wouldn't
>> have an array (1 to size) of ImageCodecInfo but rather (1 to
>> numEncoders).

>> The data, as I see it, starts with num (5) headers where each header is
>> a ImageCodecInfo and the header data, apart from the GUID's, gives the
>> offset from data start of the particular info for each encoder.
>> I'll have a closer look at it.

>> --
>> Richard Mason



Tue, 18 Jan 2005 14:40:47 GMT  
 Using VB6 and GDI+ ( aka GDIPlus )?
    Hmm, that is a good idea! I just might do that.

Thanks,
   Avery



Tue, 18 Jan 2005 19:52:35 GMT  
 
 [ 11 post ] 

 Relevant Pages 

1. Use GDI+ ( aka GDIPlus ) with VB6!

2. HOWTO: call GDIPLUS directly from VB6

3. bitblt gdi+/gdi

4. Automation Help (aka Access Modules in VB6)

5. vb6 help files AKA msdn collection

6. Using HP Printer Escape Sequences (aka Printer Passthrough Codes) in VB.Net

7. Using Word97 (aka Word 8) Spell Checker

8. Using Wake on lan aka magic packet

9. autoredraw and gdi+

10. GDI+ and VB6

11. Naive question from an outdated Techy - GDI heap status in VB6

12. GDI+ in VB6: MULTILINE and WORDBREAK

 

 
Powered by phpBB® Forum Software