Results 1 to 17 of 17

Thread: VB6 cGdiPlusCache.cls revisited

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    5,569

    VB6 cGdiPlusCache.cls revisited

    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

  2. #2
    Hyperactive Member
    Join Date
    Jun 2016
    Location
    Espaņa
    Posts
    286

    Re: VB6 cGdiPlusCache.cls revisited

    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.

    Code:
    GC.DrawRect hDC, x, y, dx, dy, 1, vbBlue,, True
    also in all
    Code:
    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

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    5,569

    Re: VB6 cGdiPlusCache.cls revisited

    Quote Originally Posted by yokesee View Post
    In all the calls, invalid number of arguments works but when compiling it gives error.

    Code:
    GC.DrawRect hDC, x, y, dx, dy, 1, vbBlue,, True
    also in all
    Code:
    GC.FillElps hDC, -10, -10, 20, 20, vbMagenta, 0.5, True
    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

  4. #4

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    5,569

    Re: VB6 cGdiPlusCache.cls revisited

    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

  5. #5
    Addicted Member shagratt's Avatar
    Join Date
    Jul 2019
    Location
    Argentina
    Posts
    187

    Re: VB6 cGdiPlusCache.cls revisited

    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

  6. #6

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    5,569

    Re: VB6 cGdiPlusCache.cls revisited

    Quote Originally Posted by shagratt View Post
    ...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):
    Code:
    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

  7. #7
    Addicted Member shagratt's Avatar
    Join Date
    Jul 2019
    Location
    Argentina
    Posts
    187

    Re: VB6 cGdiPlusCache.cls revisited

    Quote Originally Posted by Schmidt View Post
    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.


    Quote Originally Posted by Schmidt View Post
    Code:
      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
    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.

  8. #8
    Lively Member
    Join Date
    Oct 2016
    Posts
    75

    Re: VB6 cGdiPlusCache.cls revisited

    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
    Last edited by Semke; Jan 6th, 2021 at 10:15 AM.

  9. #9
    Lively Member
    Join Date
    Oct 2016
    Posts
    75

    Re: VB6 cGdiPlusCache.cls revisited

    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

  10. #10
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    4,684

    Re: VB6 cGdiPlusCache.cls revisited

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

  11. #11
    Lively Member
    Join Date
    Oct 2016
    Posts
    75

    Re: VB6 cGdiPlusCache.cls revisited

    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).
    Last edited by Semke; Jan 7th, 2021 at 07:50 AM.

  12. #12

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    5,569

    Re: VB6 cGdiPlusCache.cls revisited

    Quote Originally Posted by Semke View Post
    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...

    Code:
      '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

  13. #13
    Lively Member
    Join Date
    Oct 2016
    Posts
    75

    Re: VB6 cGdiPlusCache.cls revisited

    thanks olaf,

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

  14. #14

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    5,569

    Re: VB6 cGdiPlusCache.cls revisited

    Quote Originally Posted by Semke View Post
    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

  15. #15
    Lively Member
    Join Date
    Oct 2016
    Posts
    75

    Re: VB6 cGdiPlusCache.cls revisited

    support for animated Gifs is built-in
    how do i animate the gif file

  16. #16
    Lively Member
    Join Date
    Oct 2016
    Posts
    75

    Re: VB6 cGdiPlusCache.cls revisited

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

  17. #17
    Fanatic Member
    Join Date
    Jul 2007
    Location
    Essex, UK.
    Posts
    561

    Re: VB6 cGdiPlusCache.cls revisited

    Code:
    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

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width