Results 1 to 17 of 17

Thread: [VB6] GDI Path clipping

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    21,166

    [VB6] GDI Path clipping

    I don't see a lot here on this topic. Perhaps it's a bit "forgotten" or maybe not that useful to most people. This example is a bit silly but it might be enough to get you started using GDI Paths for a certain kind of graphics effects.

    Code:
    Option Explicit
    
    Private Const OUTPUT_TEXT As String = "Some Text"
    
    Private Declare Function AbortPath Lib "gdi32" (ByVal hDC As Long) As Long
    
    Private Declare Function BeginPath Lib "gdi32" (ByVal hDC As Long) As Long
    
    Private Declare Function EndPath Lib "gdi32" (ByVal hDC As Long) As Long
    
    Private Enum CombineRgnStyles
        RGN_AND = 1     'The new clipping region includes the intersection (overlapping areas)
                        'of the current clipping region and the current path.
        RGN_OR = 2      'The new clipping region includes the union (combined areas) of the
                        'current clipping region and the current path.
        RGN_XOR = 3     'The new clipping region includes the union of the current clipping
                        'region and the current path but without the overlapping areas.
        RGN_DIFF = 4    'The new clipping region includes the areas of the current clipping
                        'region with those of the current path excluded.
        RGN_COPY = 5    'The new clipping region is the current path.
    End Enum
    
    Private Declare Function SelectClipPath Lib "gdi32" ( _
        ByVal hDC As Long, _
        ByVal Mode As CombineRgnStyles) As Long
    
    Private Sub Paint()
        Static TickTock As Integer
        Dim N As Single
    
        If TickTock = 0 Then ForeColor = vbYellow Else ForeColor = vbRed
        For N = 0 To ScaleHeight Step 12
            Line (0, N)-(ScaleWidth, N)
        Next
        If TickTock = 1 Then ForeColor = vbYellow Else ForeColor = vbRed
        For N = 4 To ScaleHeight Step 12
            Line (0, N)-(ScaleWidth, N)
        Next
        If TickTock = 2 Then ForeColor = vbYellow Else ForeColor = vbRed
        For N = 8 To ScaleHeight Step 12
            Line (0, N)-(ScaleWidth, N)
        Next
        TickTock = (TickTock + 1) Mod 3
    End Sub
    
    Private Sub Form_Load()
        AutoRedraw = True
        BeginPath hDC
        Circle (40, 30), 20
        Circle (150, 35), 10
        Circle (250, 20), 5
        CurrentX = (ScaleWidth - TextWidth(OUTPUT_TEXT)) / 2
        CurrentY = (ScaleHeight - 1.25 * TextHeight(OUTPUT_TEXT)) / 2
        Print OUTPUT_TEXT;
        Circle (260, 140), 15
        Circle (75, 160), 10
        Circle (200, 180), 5
        EndPath hDC
        SelectClipPath hDC, RGN_COPY
        DrawWidth = 4
        Paint
        Timer1.Enabled = True
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
        AbortPath hDC
    End Sub
    
    Private Sub Timer1_Timer()
        Paint
    End Sub
    Name:  sshot.png
Views: 269
Size:  1.5 KB

    Run it to see the effect animation.
    Attached Files Attached Files

  2. #2

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    21,166

    Re: [VB6] GDI Path clipping

    Another example using a photo and PaintPicture with some backdrop drawing:

    Code:
    Option Explicit
    
    Private Declare Function AbortPath Lib "gdi32" (ByVal hDC As Long) As Long
    
    Private Declare Function BeginPath Lib "gdi32" (ByVal hDC As Long) As Long
    
    Private Declare Function EndPath Lib "gdi32" (ByVal hDC As Long) As Long
    
    Private Enum CombineRgnStyles
        RGN_AND = 1     'The new clipping region includes the intersection (overlapping areas)
                        'of the current clipping region and the current path.
        RGN_OR = 2      'The new clipping region includes the union (combined areas) of the
                        'current clipping region and the current path.
        RGN_XOR = 3     'The new clipping region includes the union of the current clipping
                        'region and the current path but without the overlapping areas.
        RGN_DIFF = 4    'The new clipping region includes the areas of the current clipping
                        'region with those of the current path excluded.
        RGN_COPY = 5    'The new clipping region is the current path.
    End Enum
    
    Private Declare Function SelectClipPath Lib "gdi32" ( _
        ByVal hDC As Long, _
        ByVal Mode As CombineRgnStyles) As Long
    
    
    Private Sub Form_Load()
        Dim N As Single
    
        ScaleMode = vbPixels
        AutoRedraw = True
        DrawWidth = 5
        ForeColor = &H40C0&
        For N = 0 To ScaleHeight Step 25
            Line (0, 0)-(ScaleWidth, N)
        Next
        ForeColor = &H3060&
        For N = 0 To ScaleWidth Step 25
            Line (0, 0)-(N, ScaleHeight)
        Next
    
        BeginPath hDC
        Circle (ScaleWidth / 2, ScaleHeight / 2), _
               ScaleHeight / 2, _
               , _
               , _
               , _
               1.3
        EndPath hDC
        SelectClipPath hDC, RGN_COPY
        
        With Image1 'Visible = False, contains a photo.
            PaintPicture .Picture, _
                         (ScaleWidth - .Width * (ScaleHeight / .Height)) / 2, _
                         0, _
                         .Height * (ScaleHeight / .Height), _
                         ScaleHeight
        End With
        AbortPath hDC
    End Sub
    Name:  sshot.jpg
Views: 231
Size:  12.7 KB

  3. #3
    Hyperactive Member
    Join Date
    Aug 2016
    Posts
    411

    Re: [VB6] GDI Path clipping

    Quote Originally Posted by dilettante View Post
    Another example using a photo and PaintPicture with some backdrop drawing:

    Code:
    Option Explicit
    
    Private Declare Function AbortPath Lib "gdi32" (ByVal hDC As Long) As Long
    
    Private Declare Function BeginPath Lib "gdi32" (ByVal hDC As Long) As Long
    
    Private Declare Function EndPath Lib "gdi32" (ByVal hDC As Long) As Long
    
    Private Enum CombineRgnStyles
        RGN_AND = 1     'The new clipping region includes the intersection (overlapping areas)
                        'of the current clipping region and the current path.
        RGN_OR = 2      'The new clipping region includes the union (combined areas) of the
                        'current clipping region and the current path.
        RGN_XOR = 3     'The new clipping region includes the union of the current clipping
                        'region and the current path but without the overlapping areas.
        RGN_DIFF = 4    'The new clipping region includes the areas of the current clipping
                        'region with those of the current path excluded.
        RGN_COPY = 5    'The new clipping region is the current path.
    End Enum
    
    Private Declare Function SelectClipPath Lib "gdi32" ( _
        ByVal hDC As Long, _
        ByVal Mode As CombineRgnStyles) As Long
    
    
    Private Sub Form_Load()
        Dim N As Single
    
        ScaleMode = vbPixels
        AutoRedraw = True
        DrawWidth = 5
        ForeColor = &H40C0&
        For N = 0 To ScaleHeight Step 25
            Line (0, 0)-(ScaleWidth, N)
        Next
        ForeColor = &H3060&
        For N = 0 To ScaleWidth Step 25
            Line (0, 0)-(N, ScaleHeight)
        Next
    
        BeginPath hDC
        Circle (ScaleWidth / 2, ScaleHeight / 2), _
               ScaleHeight / 2, _
               , _
               , _
               , _
               1.3
        EndPath hDC
        SelectClipPath hDC, RGN_COPY
        
        With Image1 'Visible = False, contains a photo.
            PaintPicture .Picture, _
                         (ScaleWidth - .Width * (ScaleHeight / .Height)) / 2, _
                         0, _
                         .Height * (ScaleHeight / .Height), _
                         ScaleHeight
        End With
        AbortPath hDC
    End Sub
    Name:  sshot.jpg
Views: 231
Size:  12.7 KB
    I did not expect such a simple method to achieve such an effect. Most of them will use GDip

  4. #4

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    21,166

    Re: [VB6] GDI Path clipping

    Yeah, and with just a little bit more you can do things like color effects.

    Here I've used a sort of "faded photo" effect combined with a clip Path:

    Name:  sshot.jpg
Views: 198
Size:  12.4 KB

    SetStretchBltMode with StretchBlt to the rescue.

    This is all pretty old stuff, most of it available since Win95 and some since NT 4.0, but over time programmers don't seem to have much experience with the stuff any more.
    Attached Files Attached Files
    Last edited by dilettante; Jul 21st, 2020 at 12:44 PM.

  5. #5

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    21,166

    Re: [VB6] GDI Path clipping

    With some fiddling you can create other effects as well. And you can apply more than one as you go:

    Name:  sshot.jpg
Views: 175
Size:  21.6 KB


    Oops! Typo in the Caption of that Form.

  6. #6

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    21,166

    Re: [VB6] GDI Path clipping

    With a little more work you an also paint frames (borders) around the "holes" in your Region.

    Name:  sshot.jpg
Views: 172
Size:  14.0 KB
    Attached Files Attached Files
    Last edited by dilettante; Jul 23rd, 2020 at 12:02 AM.

  7. #7
    Member
    Join Date
    Feb 2015
    Posts
    37

    Re: [VB6] GDI Path clipping

    Wow, Thank you for this! I actually do have a couple of uses for it . I still use GDI & GDI+ quite heavily in most of my graphics projects, as well as Cairo via RC5. But mostly GDI+.
    Last edited by SomeYguy; Jul 24th, 2020 at 12:05 AM.

  8. #8

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    21,166

    Re: [VB6] GDI Path clipping

    BTW, you can use these color effects entirely separate from the clipping. Here's a small "sampler" project:

    Name:  sshot.jpg
Views: 142
Size:  16.2 KB

    Upper-left is without any effects.
    Attached Files Attached Files

  9. #9

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    21,166

    Re: [VB6] GDI Path clipping

    If you are really after photo effects and these are fancy enough for you to start with you might try building a utility with sliders for the various settings so you can work out exactly what you need.

    Perhaps with a "copy" button to write your settings to the Clipboard in VB source format, ready to paste into your real program.

  10. #10

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    21,166

    Re: [VB6] GDI Path clipping

    Here's another easy effect, though perhaps an obvious one: "pixelation."

    Code:
    Option Explicit
    
    Private Enum StretchBltModes
        [_SBMFAILED] = 0
        BLACKONWHITE = 1    'Performs a Boolean AND operation using the color values for the
                            'eliminated and existing pixels. If the bitmap is a monochrome
                            'bitmap, this mode preserves black pixels at the expense of white
                            'pixels.
        WHITEONBLACK = 2    'Performs a Boolean OR operation using the color values for the
                            'eliminated and existing pixels. If the bitmap is a monochrome
                            'bitmap, this mode preserves white pixels at the expense of black
                            'pixels.
        COLORONCOLOR = 3    'Deletes the pixels. This mode deletes all eliminated lines of
                            'pixels without trying to preserve their information.
        HALFTONE = 4        'Maps pixels from the source rectangle into blocks of pixels in
                            'the destination rectangle. The average color over the destination
                            'block of pixels approximates the color of the source pixels.
                            '
                            'After setting the HALFTONE stretching mode, an application must
                            'call the SetBrushOrgEx function to set the brush origin. If it
                            'fails to do so, brush misalignment occurs.
    End Enum
    
    Private Declare Function SetStretchBltMode Lib "gdi32" ( _
        ByVal hDC As Long, _
        ByVal StretchMode As StretchBltModes) As StretchBltModes
    
    Private Declare Function StretchBlt Lib "gdi32" ( _
        ByVal hDCDest As Long, _
        ByVal nXOriginDest As Long, _
        ByVal nYOriginDest As Long, _
        ByVal nWidthDest As Long, _
        ByVal nHeightDest As Long, _
        ByVal hdcSrc As Long, _
        ByVal nXOriginSrc As Long, _
        ByVal nYOriginSrc As Long, _
        ByVal nWidthSrc As Long, _
        ByVal nHeightSrc As Long, _
        Optional ByVal dwRop As RasterOpConstants = vbSrcCopy) As Long
    
    Private Const PXLTN_FACTOR = 10
    
    Private DrawAspect As Double
    
    Private Sub Form_Load()
        'Here we'll scale Pictire1's content down by the PXLTN_FACTOR factor into Picture2:
        Dim PrevMode As StretchBltModes
    
        With Picture1 'Visible = False, AutoRedraw = True so hDC is valid, contains a photo.
            'Picture2 is also Visible = False, AutoRedraw = True so hDC is valid.
            Picture2.Width = .Width
            Picture2.Height = .Height
            PrevMode = SetStretchBltMode(Picture2.hDC, HALFTONE)
            StretchBlt Picture2.hDC, _
                       0, _
                       0, _
                       Picture2.ScaleX(.ScaleWidth / PXLTN_FACTOR, Picture2.ScaleMode, vbPixels), _
                       Picture2.ScaleY(.ScaleHeight / PXLTN_FACTOR, Picture2.ScaleMode, vbPixels), _
                       .hDC, _
                       0, _
                       0, _
                       .ScaleX(.ScaleWidth, .ScaleMode, vbPixels), _
                       .ScaleY(.ScaleHeight, .ScaleMode, vbPixels)
            SetStretchBltMode Picture2.hDC, PrevMode
            DrawAspect = .ScaleWidth / .ScaleHeight
        End With
    End Sub
    
    Private Sub Form_Resize()
        Dim PrevMode As StretchBltModes
        Dim DrawWidth As Single
        Dim DrawHeight As Single
        Dim DrawLeft As Single
        Dim DrawTop As Single
        
        If WindowState <> vbMinimized Then
            'Draw from Picture2 into Form1 scaling to fit, stretching pixels:
            Cls
            With Picture2
                'Scale maintaining DrawAspect, draw centered on Form1:
                If ScaleWidth / DrawAspect > ScaleHeight Then
                    DrawWidth = ScaleHeight * DrawAspect
                    DrawHeight = ScaleHeight
                Else
                    DrawWidth = ScaleWidth
                    DrawHeight = ScaleWidth / DrawAspect
                End If
                DrawLeft = (ScaleWidth - DrawWidth) / 2
                DrawTop = (ScaleHeight - DrawHeight) / 2
                PrevMode = SetStretchBltMode(hDC, COLORONCOLOR)
                StretchBlt hDC, _
                           ScaleX(DrawLeft, ScaleMode, vbPixels), _
                           ScaleY(DrawTop, ScaleMode, vbPixels), _
                           ScaleX(DrawWidth, ScaleMode, vbPixels), _
                           ScaleY(DrawHeight, ScaleMode, vbPixels), _
                           Picture2.hDC, _
                           0, _
                           0, _
                           ScaleX(.ScaleWidth / PXLTN_FACTOR, .ScaleMode, vbPixels), _
                           ScaleY(.ScaleHeight / PXLTN_FACTOR, .ScaleMode, vbPixels)
                SetStretchBltMode hDC, PrevMode
            End With
        End If
    End Sub
    Name:  sshot.png
Views: 76
Size:  3.5 KB
    Attached Files Attached Files

  11. #11

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    21,166

    Re: [VB6] GDI Path clipping

    There is almost no end to the stunt effects you can accomplish, and some are quite simple to achieve:

    Code:
    Option Explicit
    
    Private Sub Form_Load()
        PaintPicture Picture1.Picture, 0, 0
        PaintPicture Picture2.Picture, 0, 0, , , , , , , vbSrcAnd
    End Sub
    Name:  sshot.jpg
Views: 56
Size:  22.0 KB

    There I combined some generic "ambitious politician" with a nuclear explosion mushroom cloud.

    No idea what such an effect is called. Perhaps some form of "compositing?"

  12. #12

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    21,166

    Re: [VB6] GDI Path clipping

    Here's another technique, based on MaskBlt().

    We have a backdrop image (large pastel bars), a star mask "hole" image, and an alligator. We put the alligator onto the backdrop "poking" through a star-shaped hole. 7/8ths of the 'gator pops out of the star with the lower 1/8th "behind" the hole.

    Name:  sshot.png
Views: 49
Size:  6.5 KB

    This trick relies on the alligator being against a solid color (cyan here) we can use as the second mask.


    I'm not much of a graphics programmer, so I can imagine many of you chuckling at my meager efforts. I just hope I've shown some basic ideas to get you started if any of this is new to you.
    Attached Files Attached Files

  13. #13

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    21,166

    Re: [VB6] GDI Path clipping

    But having the 'gator stand on his mask color is pretty tacky, isn't it? Let's give him a floor to stand on in that hole:

    Name:  sshot.png
Views: 40
Size:  7.4 KB

    Now we've combined a 4th image into the whole (no pun intended).

    Can you guess how?


    And yes, there are a few stray pixels of artifacting around the alligator guy I should correct manually. They stand out against the new dark background of the floor.

  14. #14

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    21,166

    Re: [VB6] GDI Path clipping

    Alligator on the floor? We don't want that. Put him back in the swamp!

    And the reeds stick up there so we'll want to poke those up as well:

    Name:  sshot.png
Views: 38
Size:  8.6 KB
    Attached Files Attached Files
    Last edited by dilettante; Aug 1st, 2020 at 11:38 AM.

  15. #15
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,040

    Re: [VB6] GDI Path clipping

    Quote Originally Posted by dilettante View Post
    ...
    I'm not much of a graphics programmer, so I can imagine many of you chuckling at my meager efforts. I just hope I've shown some basic ideas to get you started if any of this is new to you.
    You are correct. I almost felt like commenting sometime earlier in the thread, given how far advanced you are in so many areas that I'm not, and now these fairly basic examples of various graphical techniques, but I knew from previous posts that you didn't feel you did a lot of graphical stuff in your earlier programming efforts, and now that you've the time to explore a bit of what you may have overlooked in the past, you also take the time to share that exploration.

    If I don't want to make the effort to delve into my past and post these types of graphical explorations, I certainly have no place to deride someone who is learning and sharing, and hopefully entertaining themselves and others along the way.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  16. #16

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    21,166

    Re: [VB6] GDI Path clipping

    Yes, these are very basic operations for the most part. Even the MaskBlt() examples are pretty trivial.

    Perhaps there is a simpler way to extract a mask from an image? I'm also not sure whether one of the standard raster-ops might be more appropriate. Examples I found using those did two or more blits in sequence to achieve the cutout effect.

    You are right though, I was just playing around.

  17. #17

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    21,166

    Re: [VB6] GDI Path clipping

    Some cases like painting from an image dropping out its transparency color can more easily be accomplished using TransparentBlt() instead.

    That's not the same as using a second "cookie cutter" or "stencil" image of a different shape though.

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