# VBForums CodeBank > CodeBank - Visual Basic 6 and earlier >  VB6 cGdiPlusCache.cls revisited

## Schmidt

Ok, in some earlier (and smaller) CodeBank-examples I was using a cGDIPlusCache-Class, 
to provide some "non-RC5-examples" with some base-functionality for Icon- and Image-Resource-Handling (via GDIPlus-Flat-API).

I've now revisited the Code of cGdiPlusCache.cls, to make it act a bit more like I'm wont to - with the Cairo-Drawing-Classes of the RC5.
(though as the earlier examples, it is not using any references to RC5-libs)

Here a list, what it now supports:
- Load images from file or bytearray (incl. Bmp, Jpg, Png, Gif)
- Load icons or cursors from file or bytearray
- Load icons/images/thumbnails from ShellItemObjects (or alternatively Shell-FilePaths) directly
- Base64 encoding/decoding is supported (to be able to define smaller Png- or Ico- or Cursor-resources directly in a normal VB6-String-Constant)
- Simple RLE encoding/decoding to compress resources which have a reduced ColorSet (related to the Base64-String-Const-stuff)
- Image- and Icon-Rendering is done with full Alpha-Support - and support for high-quality-stretching
- Image-Rendering is also supporting the "Tile-Mode" (to support fast rendered Form-Backgrounds, no matter the Form-Size)
- support for animated Gifs is built-in
- Antialiased Drawing of Line, Rectangle, Ellipse and Polygon (incl. Spline-Tension-Parameter, Alpha-Fill, and Alpha-Stroke) is now supported
- Easy to use DrawText-like implementation for GDIPlus-TextOutputs
- support for transforms (Translate, Rotate, Scale) is now built-in ... quite analogue to Cairo
- the above transforms support all the above drawing-primitives fully:  (Line, Ellipse, Rectangle, ImageRendering, and DrawText)
- and Cairo-like support for Save- and Restore was implemented as well (usually applied in nested renderings, to isolate the transforms of sub-routines from the ones further up the callstack)


The Demo-Zip contains 4 Folders:
- 1 Basic Usage   (demonstrating the case the Class was originally developed for -  acting as a "global ImageList-Cache for Alpha-Resources")
- 2 ShellItems  (demonstrating ShellItem-Renderings, by passing normal ShellItem-Objects as the Source)
- 3 Cursors  (how to use Cursors from *.png and *.cur file-resources, which were defined as Base64-encoded String-Constants, not using any FileAccess).
- 4 Antialiased Drawings  (Polygon- and Spline-Renderings + other Primitives + rotated Unicode-TextOutput)

Hopefully that now extended functionality will help people, to use GdiPlus with less risk of handle-leaking or teardown-crashes.

Here a ScreenShot for the new ShellItem-Load-Functions (which allows, to build Explorer-like Trees or Lists without larger fiddling).


And here another one, which demonstrates the nested Transforms, along with antialiased renderings of a few Drawing-Primitives:


Here the Demo-Sources:
GDIPlusCache.zip

Have fun,

Olaf

----------


## yokesee

Hi.
very good class I hope you keep improving it I will use it also in some projects that I do not use RC5.
I found small problems in the cursors project.
In all the calls, invalid number of arguments works but when compiling it gives error.



```
GC.DrawRect hDC, x, y, dx, dy, 1, vbBlue,, True
```

also in all 


```
GC.FillElps hDC, -10, -10, 20, 20, vbMagenta, 0.5, True
```

I removed the last parameter true and it works and compiles perfectly.

a greeting and very good job

----------


## Schmidt

> In all the calls, invalid number of arguments works but when compiling it gives error.
> 
> 
> 
> ```
> GC.DrawRect hDC, x, y, dx, dy, 1, vbBlue,, True
> ```
> 
> also in all 
> ...


Ah - yes, sorry -  the Sub where these wrong-argument-counts are in is: DrawGDIPStuffAt(...) (in the Cursors-Project)  - 
and this Sub is "dead code" (called from nowhere - just a leftover from testing)...

The Sub being dead code is the reason, why the IDE did not inform me about the wrong param-count ... 
This Sub can be safely deleted from the Cursor-Project...
 (there's better demo-routines for the Drawing-Primitives in the projectfolder "4 Antialiased Drawings").

Thanks for pointing it out though, so that others don't wonder (think it's not "serious enough", to upload a new Zip for that).

Olaf

----------


## Schmidt

Ok, made an Update for the whole thing (fixing the "dead-code" issue above + some enhancements)...
- added the Pie-Drawing-Primitive 
- added a TextOut-Method (with left/center/right adjustment around the given x/y-Point - as well as optional BaseLine-Rendering of the Text)
- added two additional Demo-Folders:
- ..\5 Layered PNGs
- ..\6 Vertical TabStrip

Here the new Code-Package: GDIPlusCache.zip

Have fun...

Olaf

----------


## shagratt

Hi Schmidt. I was trying the class and there is something I dont understand.

If I a draw using standard functons to a picture box and want to paint the same image scaled into another smaller picture box I can use the code:

    Picture1.line ....
    Picture2.PaintPicture picture1, 0, 0, halfWidth, HalfHeight, 0, 0, FullWidth, FullHeight

And it works (ugly with no antialiasing). After using your class to paint something to the Picture1 I can no longer use Picture2.PaintPicture to get a copy of its content and dont understand why. 
Anyway what I really want is to have something like AlphaRenderTo but instead of Key take as a parameter another hDC (that can be a picturebox or form)
Can you add it or help me do it?
thanks

----------


## Schmidt

> ...I was trying the class and there is something I dont understand.
> 
> If I a draw using standard functons to a picture box and want to paint the same image scaled into another smaller picture box I can use the code:
> 
>     Picture1.line ....
>     Picture2.PaintPicture picture1, 0, 0, halfWidth, HalfHeight, 0, 0, FullWidth, FullHeight


Instead of Drawing to one PicBox - and then using "Bitmap-Scaling" to render its content to another one...

Why not render onto the second (downscaled) PicBox directly by using
the cGDIPlusCache-Drawing-calls in conjunction with a transform (translation, rotation, scaling)?

Here is some DemoCode for what I mean...
(into an empty Form, which is part of a project, that also contains the cGDIPlusCache-Class):


```
Option Explicit
 
Private GC As New cGDIPlusCache

Private Sub Form_Load()
  RedrawOn Me
End Sub
Private Sub Form_Resize()
  RedrawOn Me
End Sub

Private Sub RedrawOn(VBCanvas As Object)
  VBCanvas.AutoRedraw = True: VBCanvas.Cls
  
  Dim dx: dx = VBCanvas.ScaleX(VBCanvas.ScaleWidth, VBCanvas.ScaleMode, vbPixels)
  Dim dy: dy = VBCanvas.ScaleY(VBCanvas.ScaleHeight, VBCanvas.ScaleMode, vbPixels)
 
  With CreateObject("Scripting.FileSystemObject").OpenTextFile(App.Path & "\..\cGDIPlusCache.cls", 1)
    Dim Lines() As String
        Lines = Split(.ReadAll, vbCrLf): .Close
  End With
  RenderTextLines VBCanvas.hDC, Lines, 0.1 '<- use any Zoom-Factor
 
  VBCanvas.Refresh 'refresh the Form, when in AutoRedraw-Mode
End Sub

Private Sub RenderTextLines(hDC As Long, Lines() As String, Optional ByVal Zoom! = 1)
  Dim TW As Single, TH As Single, i As Long, Color As Long
  
  Font.Name = "Consolas"
  Font.Size = 10
  
  GC.Save hDC
    GC.ScaleDrawings hDC, Zoom, Zoom 'use one of the transform-calls (here: Scaling)
    
    GC.DrawString hDC, Font, "|", 0, 0, TW, TH, DT_CALCRECT
 
    For i = 0 To UBound(Lines)
      Color = vbBlack
      If InStr(Lines(i), "Private ") Then Color = vbBlue
      If InStr(Lines(i), "Public ") Then Color = vbBlue
      If InStr(Lines(i), "End ") Then Color = vbBlue
      If InStr(Lines(i), "'") Then Color = vbGreen
      
      GC.DrawString hDC, Font, Lines(i), 0, i * TH, 0, 0, DT_SINGLELINE, Color
    Next
  GC.Restore hDC
End Sub
```

I've simplified the coloring of the text-lines in the above RenderTextLines-Routine...

Here a ScreenShot, what this will produce:
 

HTH

Olaf

----------


## shagratt

> Instead of Drawing to one PicBox - and then using "Bitmap-Scaling" to render its content to another one...
> Why not render onto the second (downscaled) PicBox directly...


I thought writing graphics directly can cause tearing and wanted to use the picturebox as a buffer. Of course I know picturebox are not the best way to achieve complex graphics. 





> ```
>   GC.Save hDC
>     GC.ScaleDrawings hDC, Zoom, Zoom 'use one of the transform-calls (here: Scaling)
>     
>     GC.DrawString hDC, Font, "|", 0, 0, TW, TH, DT_CALCRECT
>  
>     For i = 0 To UBound(Lines)
>       Color = vbBlack
>       If InStr(Lines(i), "Private ") Then Color = vbBlue
> ...


Thanks!!! Your example was amazing! Loved it! Are you a mind reader or something? That's exactly what I was going to use the code for.

I have problems understanding what the SAVE/RESTORE actually do.  When you use GC.SAVE are you copying the actual image in the hDC to the class buffer , then drawing on it and later the RESTORE put back the new image stored in the class buffer into the hDC picture? If im wrong can you explain it please.

----------


## Semke

thanks schmidt for forwarding me to thread from Enhancing VB's StdPicture Object to Support GDI+

seems quit nice, what properties do i use to read/write the picture to DB

how does this class compare with the one created by LaVolpe

thanks

----------


## Semke

ok, I figured out how to read\write byte array

it seems quite fast.

although, I can see a rich amount of options in this class, but no real documentation, could you please elaborate its capabilities

----------


## Arnoutdv

Better do it the other way around.
You have the source code, so ask a specific question for something you don't understand.

----------


## Semke

if the image is too big i use *AlphaRenderTo* to display it on a smaller DC, but i the want to save it 

using this class, how would I save the image in a smaller size, using the same format as the original (I don't want to lose the transparency).

----------


## Schmidt

> using this class, how would I save the image in a smaller size, using the same format as the original (I don't want to lose the transparency).


This cache-class allows a high-quality upscaling/downscaling at *load-time*, 
so if you have a higher-res image already on disk (like e.g. the 128x128 image "\Res\Png2.png" from the Demo-Zip),
you should specify the optional DesiredWidth, DesiredHeight Params in the Load-Function...



```
  'loading
  Debug.Print "inp"; FileLen(App.Path & "\Res\Png2.png")
  GC.AddImage "Png2_64", App.Path & "\Res\Png2.png", 64, 64
  
  'saving to ByteArray
  Dim B() As Byte: B = GC.SaveImageToPngByteArray("Png2_64")
  Debug.Print "out"; UBound(B) + 1

  'saving to File
  GC.WriteBytesToFile App.Path & "\out.png", GC.SaveImageToPngByteArray("Png2_64")
  Debug.Print "out-file"; FileLen(App.Path & "\out.png")
```

HTH

Olaf

----------


## Semke

thanks olaf,

one more question, how can i convert a picture to grayscale

----------


## Schmidt

> thanks olaf,
> 
> one more question, how can i convert a picture to grayscale


There's nothing like that currently built into cGDIPlusCache.

With the RC5/RC6 cairo-wrapper (which cGDIPlusCache is modeled after to some extent) -
you can achieve something like that at render-time (just by setting another blend-operator - 
without adding an additional greyscaled ImageResource into your Cache - quite useful for enabled/disabled state of Icons in a ToolBar for example).

So, if this is for "tooling" (on your dev-machine only) - I'd suggest to use the RC6-wrapper there for "one-time-stuff" like that 
(e.g. to produce a greyscaled copy of a colored PNG-image in a separate resource-file).

Olaf

----------


## Semke

> support for animated Gifs is built-in


how do i animate the gif file

----------


## Semke

when reading a file from disk, how do i determine what format (PNG, BMP, JPG Etc...) the file is?

----------


## Steve Grant

```
Private Function GetImageType(sFileName As String) As String
    Dim bBuf(20) As Byte, FF As Integer
    
    GetImageType = "UNKNOWN"
        
    FF = FreeFile
    Open sFileName For Binary As FF
    Get #FF, 1, bBuf()
    Close FF
    
    If bBuf(0) = 0 And bBuf(1) = 0 And bBuf(2) = 1 And bBuf(3) = 0 Then GetImageType = "ICO"
    If bBuf(0) = 137 And bBuf(1) = 80 And bBuf(2) = 78 Then GetImageType = "PNG"
    If bBuf(0) = 255 And bBuf(1) = 216 And bBuf(2) = 255 Then GetImageType = "JPG"
    If bBuf(0) = 66 And bBuf(1) = 77 Then GetImageType = "BMP"
    If bBuf(0) = 71 And bBuf(1) = 73 And bBuf(2) = 70 Then GetImageType = "GIF"
    If bBuf(0) = 73 And bBuf(1) = 73 And bBuf(2) = 42 Then GetImageType = "TIF"
    If bBuf(0) = 82 And bBuf(1) = 73 And bBuf(2) = 70 And bBuf(3) = 70 And bBuf(8) = 87 And bBuf(9) = 69 And bBuf(10) = 66 And bBuf(11) = 80 Then GetImageType = "WEBP"
    If bBuf(4) = 102 And bBuf(5) = 116 And bBuf(6) = 121 And bBuf(7) = 112 Then GetImageType = "HEIF"
End Function
```

----------


## smileyoufu

Hello! Olaf, Is it possible to add png images to Krool's VBCCR17.ocx control using GdiPlusCache Class. For example "ImageList,TreeView,ToolBar,ListView..."

----------


## Schmidt

> Hello! Olaf, Is it possible to add png images to Krool's VBCCR17.ocx control using GdiPlusCache Class. For example "ImageList,TreeView,ToolBar,ListView..."


IIRC, these Controls work together with an ImageList (which Krool included in the OCX).

It should be possible, to add Images or Icons to that ImageList dynamically (maybe Krool even allows to add PNGs directly, who knows).

That said ... the cGDIPlusCache-Class can hand out (convert) an already loaded PNG-Image as a hIcon (via the Key you gave it at LoadTime):
Public Function GetHIconFromImage(Key) As Long

This hIcon can (or should) be destroyed by you afterwards, 
in case the ImageList will not take over the "ownership" of such a passed hIcon, when adding it.
The proper GDIPlusCache-method for that is:
Public Sub DestroyHIcon(ByVal hIcon As Long) 

So, since the Class offers a bit of help already (with the hIcon-conversion) - 
it's now up to you to find (with the help of Krool) some way to add it to the VBCCR17.ImageList...

Olaf

----------


## 7edm

Hi Olaf,

I create this type of graphics in my program by simply using a picture box properties and methods, is this class something I could use instead to get a higher quality, improved re-scaling for screen shots etc.? and is all this in RC6 already?  

Attachment 183962
Hmm how can I get the image to show, and not just as an url? Why does it create an attachment when I insert an image?

----------


## Schmidt

> I create this type of graphics in my program by simply using a picture box properties and methods,
> 
>  is this class something I could use instead to get a higher quality, improved re-scaling for screen shots etc.?


Sure, it supports advanced graphic-commands, which are not "built-into" the VB6-PicBox.




> and is all this in RC6 already?


The RC6 has even more advanced graphics-functionality than this cGDIPlusCache-Helper-Class (via its Cairo-wrapper).
This Class here is not dependent on the RichClient-libs - but it mimicks at least a subset of the RC6-Cairo-functionality.




> Hmm how can I get the image to show, and not just as an url? Why does it create an attachment when I insert an image?


As soon as you want to include either "an Image" or "a Zip", 
it is better to use the "Go advanced" button - and do everything from there...

HTH

Olaf

----------


## Semke

Hi! 

thanks Scmidt, this is a great lightweight class.

i am loading to two images with gc.AddImage ("pic1","Pic1file.png") and gc.AddImage ("pic2","Pic2file.png")

i would like to save it as a file with both images, would your class allow it and how?

i would also like to that the second image should not be necessarily on the top left corner of image 1

----------


## Schmidt

> i am loading to two images with gc.AddImage ("pic1","Pic1file.png") and gc.AddImage ("pic2","Pic2file.png")
> 
> i would like to save it as a file with both images, would your class allow it and how?
> 
> i would also like to that the second image should not be necessarily on the top left corner of image 1


The class supports drawing "from cached Keys" to "any hDC" ... as e.g. MyPicBox1.hDC
Meaning, you can combine multiple render-outputs "on that specific hDC" only.

So, to achieve what you want:
- resize your PicBox in the correct PixelSize (via PicBox.Move for example)
- Set AutoRedraw on that PicBox to True
- now render (multiple images + text whatever) to the PicBox.hDC
- after rendering, perform a PicBox.Refresh
- now save the PicBox-Content as a *.bmp File via: Call SavePicture (PicBox.Image, MyPath\MyFileName.bmp)
- now you can reload the just saved *.bmp-File into the GC again (under a certain Key)
- and then you could write it out as a PNG again via: 
GC.WriteBytesToFile "MyPath\My.png", GC.SaveImageToPngByteArray("MyKey")

HTH

Olaf

----------


## Semke

> The class supports drawing "from cached Keys" to "any hDC" ... as e.g. MyPicBox1.hDC
> Meaning, you can combine multiple render-outputs "on that specific hDC" only.
> 
> So, to achieve what you want:
> - resize your PicBox in the correct PixelSize (via PicBox.Move for example)
> - Set AutoRedraw on that PicBox to True
> - now render (multiple images + text whatever) to the PicBox.hDC
> - after rendering, perform a PicBox.Refresh
> - now save the PicBox-Content as a *.bmp File via: Call SavePicture (PicBox.Image, MyPath\MyFileName.bmp)
> ...


Thanks, this was my first guess. however, I lose the transparency

----------


## Schmidt

> Thanks, this was my first guess. however, I lose the transparency


Yep, this hDC-based approach draws on "canvas-surfaces" which require a "solid background in the base layer".

If you want the BaseLayer(-Surface) to support full transparency as well, you can use the RC6-Cairo-Wrapper,
with a cCairoSurface as the Main- or Base-Layer to render into...
(instead of a VB6-PictureBox as the BaseLayer, this GDI+-Class is then "rendering things on top").

Olaf

----------


## DaveDavis

For Draw (Rotate) String:

1. Can you please do me a favor to add GdipSetStringFormatTrimming and GdipSetStringFormatFlags so that I can set TrimmingNone and NoWrap flags?

2. About Alignment,  if the Rectangle width (height) is not enough, I prefer to show FIRST segment instead of Last segment. For example, We set the string Right alignment, if the width is not enough, It shows "The quick fox" instead of last "the lazy dog". Please refer to the screenshot.

----------


## Semke

> Yep, this hDC-based approach draws on "canvas-surfaces" which require a "solid background in the base layer".
> 
> If you want the BaseLayer(-Surface) to support full transparency as well, you can use the RC6-Cairo-Wrapper,
> with a cCairoSurface as the Main- or Base-Layer to render into...
> (instead of a VB6-PictureBox as the BaseLayer, this GDI+-Class is then "rendering things on top").
> 
> Olaf



After much struggling, I could not figure out how to use the RC6-Cairo-Wrapper, (i have never used it, could you please give me some pointers, to get me started

thanks

----------


## jpbro

There are 20 different example projects/demos available to get you started here:

https://vbrichclient.com/#/en/Demos/...iroDrawing.htm

If you run into trouble, I recommend starting a new thread to ask a question about a specific problem.

----------


## DaveDavis

> For Draw (Rotate) String:
> 
> 1. Can you please do me a favor to add GdipSetStringFormatTrimming and GdipSetStringFormatFlags so that I can set TrimmingNone and NoWrap flags?
> 
> 2. About Alignment,  if the Rectangle width (height) is not enough, I prefer to show FIRST segment instead of Last segment. For example, We set the string Right alignment, if the width is not enough, It shows "The quick fox" instead of last "the lazy dog". Please refer to the screenshot.


I made some experimental changes:


```
Public Function DrawString(ByVal hDC As Long, ByVal Font As stdole.IFont, ByVal S As String, x, y, dx, dy, Optional ByVal DTFlags As eDrawText = DT_SINGLELINE Or DT_VCENTER, Optional ByVal TextColor&, Optional ByVal Alpha! = 1) As Long
  Dim LFW&(0 To 22), gdipFont As Long, gdipFormat As Long, R!(0 To 3), M!(0 To 3)
  Prepare hDC, TextColor, Alpha, 0
  GetObjectW Font.hFont, 92, LFW(0): GdipCreateFontFromLogfontW hDC, LFW(0), gdipFont
  If gdipFont = 0 Then  'let's make one more attempt, falling back to Arial
    Font.Name = "Arial" 'because the passed font was probably not a TrueType-Font
    GetObjectW Font.hFont, 92, LFW(0): GdipCreateFontFromLogfontW hDC, LFW(0), gdipFont
  End If
  If gdipFont = 0 Then Err.Raise vbObjectError, , "Couldn't create GDIP-FontObject" 'we dont' try anymore

  GdipStringFormatGetGenericTypographic gdipFormat
  If gdipFormat = 0 Then Err.Raise vbObjectError, , "Couldn't create GDIP-FormatObject"
  
  GdipSetStringFormatAlign gdipFormat, 0
  GdipSetStringFormatLineAlign gdipFormat, 0
  If DTFlags And DT_CENTER Then GdipSetStringFormatAlign gdipFormat, 1
  If DTFlags And DT_RIGHT Then GdipSetStringFormatAlign gdipFormat, 2
  If DTFlags And DT_VCENTER Then GdipSetStringFormatLineAlign gdipFormat, 1
  If DTFlags And DT_BOTTOM Then GdipSetStringFormatLineAlign gdipFormat, 2
  If DTFlags And DT_SINGLELINE Then GdipSetStringFormatFlags gdipFormat, &H1000
  
  'R(0) = x: R(1) = y: R(2) = x + dx: R(3) = y + dy
  R(0) = 0: R(1) = 0: R(2) = 0: R(3) = 0
   
  If DTFlags And DT_CALCRECT Then
     GdipMeasureString mCtx, StrPtr(S), Len(S), gdipFont, R(0), gdipFormat, M(0), 0, DrawString
     CalcAscentPercentFor gdipFont
     x = M(0): y = M(1): dx = M(2): dy = M(3)
  Else
     R(0) = x: R(1) = y: R(2) = dx: R(3) = dy
     GdipDrawString mCtx, StrPtr(S), Len(S), gdipFont, R(0), gdipFormat, mBrush
  End If
  
  GdipDeleteStringFormat gdipFormat
  GdipDeleteFont gdipFont
End Function

Private Sub DrawTextStuffAt(x, y, Angle, FontSize)
  'since we use translations and rotations, we have to save/restore the GDIPlus-context-state on procedure-entry and -exit
  GC.Save hDC
    GC.TranslateDrawings hDC, x, y     'make the current Coord our new CoordSys-Origin (so, all other drawing-coords are given relative to that new 0,0)
    GC.FillElps hDC, -10, -10, 20, 20, vbMagenta, 0.5

    GC.RotateDrawingsDeg hDC, Angle 'rotate the following rectangle-output by 45?around the MousePoint (which is our new 0,0)
    GC.FillRect hDC, -5, -5, 10, 10, vbYellow, 0.5
    
    Me.FontName = "Arial": Me.FontSize = FontSize 'adjust the Fontsize before the Text-Output-Block
    Dim S: S = "The quick fox" & " jumps over the lazy dog" 'ChrW(29392) & ChrW(29432)
    Dim dx, dy: dx = 180: dy = 15: x = 0: y = 0
    GC.DrawRect hDC, x, y, dx, dy, 1, vbRed
    
    'GC.DrawString hDC, Me.Font, S, x, y, dx, dy, DT_SINGLELINE Or DT_RIGHT
    'GC.DrawString hDC, Me.Font, S, x, y, dx, dy, DT_RIGHT Or DT_SINGLELINE Or DT_CALCRECT
       
    Dim mX As Long
    Dim mY As Long
    mX = dx
    mY = dy
        
    
    Dim DTFlags As Long
    DTFlags = DT_RIGHT Or DT_SINGLELINE Or DT_BOTTOM
      
    
    GC.DrawString hDC, Me.Font, S, 0, 0, mX, mY, DTFlags Or DT_CALCRECT
        
     If (dx < mX) Then
        If DTFlags And DT_RIGHT Then DTFlags = (DTFlags And (Not DT_RIGHT)) Or DT_TOPLEFT
     End If
     If (dy < mY) Then
        If DTFlags And DT_BOTTOM Then DTFlags = (DTFlags And (Not DT_BOTTOM)) Or DT_TOPLEFT
     End If
    
     GC.DrawString hDC, Me.Font, S, x, y, dx, dy, DTFlags
     
     
    
     'GC.DrawString hDC, Me.Font, S, 0, 0, dx, dy, DTFlags Or DT_CALCRECT
     'GC.DrawRect hDC, x, y, dx, dy, 1, vbBlue
    
  GC.Restore hDC
End Sub
```

----------


## Semke

Hi!
I am trying to print Images using this class by sending to the printer.hdc, i seem not to have any success. am i missing anything

----------


## Schmidt

> Hi!
> I am trying to print Images using this class by sending to the printer.hdc, i seem not to have any success. am i missing anything


The 32Bit-Alpha-IMages are not accepted by many Printer-Drivers...

Better to use "normal 24Bit-TrueColor"-hBMPs for that.

There is already a method built-in, which gives you such a Handle: 
myBitmapHandle = GC.GetHBmpFromImage(Key)

But you can also convert such a 24Bit-hBmp-Handle into a VB6-StdPicture of course - 
which you then render via e.g. Printer.PaintPicture (or Form.PaintPicture or MyPicBox.PaintPicture...)

Just add a new Picture-Property to the cGDIPlusCache-Class, using this Code:


```
' depends on: Private Declare Function OleCreatePictureIndirect Lib "oleaut32" (lpPictDesc As Any, riid As Any, ByVal fPictureOwnsHandle As Long, ipic As IPicture) As Long
Public Property Get Picture(Key) As StdPicture
  Dim lpPictDesc(0 To 3) As Long, aGUID(0 To 3) As Long
   
  lpPictDesc(0) = 16
  lpPictDesc(1) = vbPicTypeBitmap
  lpPictDesc(2) = GetHBmpFromImage(Key)
   
  aGUID(0) = &H7BF80980
  aGUID(1) = &H101ABF32
  aGUID(2) = &HAA00BB8B
  aGUID(3) = &HAB0C3000
   
  OleCreatePictureIndirect lpPictDesc(0), aGUID(0), 1, Picture
End Property
```

It will then hand out such a 24Bit-StdPicture (via passing a Key) to you.

Usage in a Form:


```
Private Sub Form_Load()
  GC.AddImage "MyImg", "c:\temp\test.png" 'add some test-png under a certain key

  Me.AutoRedraw = True
  Me.PaintPicture GC.Picture("MyImg"), 0, 0
  
  'For "Printer-Mode" just use:
  'Printer.PaintPicture GC.Picture("MyImg"), x, y, Width, Height
End Sub
```

HTH

Olaf

----------


## Semke

> The 32Bit-Alpha-IMages are not accepted by many Printer-Drivers...
> 
> Better to use "normal 24Bit-TrueColor"-hBMPs for that.
> 
> There is already a method built-in, which gives you such a Handle: 
> myBitmapHandle = GC.GetHBmpFromImage(Key)
> 
> But you can also convert such a 24Bit-hBmp-Handle into a VB6-StdPicture of course - 
> which you then render via e.g. Printer.PaintPicture (or Form.PaintPicture or MyPicBox.PaintPicture...)
> ...


This will also help anyone who wants to use PNG in Krools Toolbar as per post #19

----------


## smileyoufu

Hello Olaf!

Please ask me how to add all the icons in shell32.dll to cGDIPlusCache.

Thank you very much!

----------


## Schmidt

> Please ask me how to add all the icons in shell32.dll to cGDIPlusCache.


Guess you meant "tell me"?
(probably having the RC6.Cairo.ImageList.AddIconFromResourceFile(...) method in mind)?

Wouldn't recommend to load "*all* icons" which are sitting in shell32.dll into the cache.

You can always do that for the "select few you need", by "storing them as PNGs" beforehand
(e.g. using RC6-Cairo ... and then loading them from these PNGs into the GdiPlusCache).

I have currently no plans, to enhance the cGdiPlusCache further (functionality-wise) -
because I consider GdiPlus is a "dead end" when it comes to 2D-graphics.

Olaf

----------

