Results 1 to 35 of 35

Thread: VB6 cGdiPlusCache.cls revisited

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,289

    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
    Fanatic Member
    Join Date
    Jun 2016
    Location
    EspaƱa
    Posts
    514

    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
    7,289

    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
    7,289

    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
    198

    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
    7,289

    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
    198

    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
    112

    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
    112

    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
    5,981

    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
    112

    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
    7,289

    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
    112

    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
    7,289

    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
    112

    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
    112

    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
    578

    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

  18. #18
    Lively Member
    Join Date
    Oct 2014
    Posts
    102

    Re: VB6 cGdiPlusCache.cls revisited

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

  19. #19

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,289

    Re: VB6 cGdiPlusCache.cls revisited

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

  20. #20
    Addicted Member
    Join Date
    Jun 2010
    Posts
    182

    Re: VB6 cGdiPlusCache.cls revisited

    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?
    Last edited by 7edm; Feb 13th, 2022 at 05:08 PM.
    M$ vs. VB6 = The biggest betrayal and strategic mistake of the century!?

  21. #21

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,289

    Re: VB6 cGdiPlusCache.cls revisited

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

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

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

  22. #22
    Lively Member
    Join Date
    Oct 2016
    Posts
    112

    Re: VB6 cGdiPlusCache.cls revisited

    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

  23. #23

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,289

    Re: VB6 cGdiPlusCache.cls revisited

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

  24. #24
    Lively Member
    Join Date
    Oct 2016
    Posts
    112

    Re: VB6 cGdiPlusCache.cls revisited

    Quote Originally Posted by Schmidt View Post
    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
    Thanks, this was my first guess. however, I lose the transparency

  25. #25

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,289

    Re: VB6 cGdiPlusCache.cls revisited

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

  26. #26
    Fanatic Member
    Join Date
    Aug 2016
    Posts
    608

    Re: VB6 cGdiPlusCache.cls revisited

    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.
    Attached Images Attached Images  
    Last edited by DaveDavis; Oct 28th, 2022 at 08:15 PM.

  27. #27
    Lively Member
    Join Date
    Oct 2016
    Posts
    112

    Re: VB6 cGdiPlusCache.cls revisited

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

  28. #28
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,466

    Re: VB6 cGdiPlusCache.cls revisited

    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.

  29. #29
    Fanatic Member
    Join Date
    Aug 2016
    Posts
    608

    Re: VB6 cGdiPlusCache.cls revisited

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

  30. #30
    Lively Member
    Join Date
    Oct 2016
    Posts
    112

    Re: VB6 cGdiPlusCache.cls revisited

    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

  31. #31

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,289

    Re: VB6 cGdiPlusCache.cls revisited

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

  32. #32
    Lively Member
    Join Date
    Oct 2016
    Posts
    112

    Re: VB6 cGdiPlusCache.cls revisited

    Quote Originally Posted by Schmidt View Post
    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:
    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:
    Code:
    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
    This will also help anyone who wants to use PNG in Krools Toolbar as per post #19
    Last edited by Semke; Dec 27th, 2022 at 09:44 PM.

  33. #33
    Lively Member
    Join Date
    Oct 2014
    Posts
    102

    Re: VB6 cGdiPlusCache.cls revisited

    Hello Olaf!

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

    Thank you very much!

  34. #34

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,289

    Re: VB6 cGdiPlusCache.cls revisited

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

  35. #35
    Addicted Member
    Join Date
    Feb 2015
    Posts
    176

    Re: VB6 cGdiPlusCache.cls revisited

    Nothing like digging up an old thread, eh?. Came across this while looking for other things and it reminded me of something that I've been meaning to do.

    And that is just to say thank you Olaf. Well written, very useful GDI+ class here. I use it in a couple of my applications. Take care.

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