Home
Search
 
What's New
Index
Books
Links
Q & A
Newsletter
Banners
 
Feedback
Tip Jar
 
C# Helper...
 
XML RSS Feed
Follow VBHelper on Twitter
 
 
MSDN Visual Basic Community
 
 
 
 
 
 
TitleShape a form to fit a picture
Keywordsshape form, picture, transparent, region
CategoriesTips and Tricks, Graphics
 
Use GetDIBits to get the picture's pixel information. Then examine the picture's pixels row-by-row. For each block of non-transparent pixels, make a region. Combine the regions and use SetWindowRgn to restrict the form to the combined region.

Some points worth noting:

  • The picture used in this example has a non-white bar at the top and is moved up so that bar lies under the form's title bar. That makes the program keep the piece of title bar visible so the user can grab and drag it. If you move the picture down or erase the blue bar in the picture, the user will be unable to move the form.
  • The form's Caption is " " (a space) so the title bar is present but blank. The ControlBox property is False so the buttons don't show.
  • The bright spots on the spheres look white but they are slightly gray. If they were white, the form would have holes there.
  • This program takes a little while to load. It would take longer for bigger pictures.
 
' Fir the form to the pixels that don't match the color.
Private Sub ShapeForm(ByVal pic As PictureBox, ByVal _
    transparent_color As Long)
Const RGN_OR = 2
Dim bytes_per_scanLine As Integer
Dim wid As Long
Dim hgt As Long
Dim bitmap_info As BITMAPINFO
Dim pixels() As Byte
Dim buffer() As Byte
Dim transparent_r As Byte
Dim transparent_g As Byte
Dim transparent_b As Byte
Dim border_width As Single
Dim title_height As Single
Dim x0 As Long
Dim y0 As Long
Dim start_c As Integer
Dim stop_c As Integer
Dim R As Integer
Dim C As Integer
Dim combined_rgn As Long
Dim new_rgn As Long

    ScaleMode = vbPixels
    pic.ScaleMode = vbPixels
    pic.AutoRedraw = True
    pic.Picture = pic.Image

    ' Prepare the bitmap description.
    wid = pic.ScaleWidth
    hgt = pic.ScaleHeight
    With bitmap_info.bmiHeader
        .biSize = 40
        .biWidth = wid
        ' Use negative height to scan top-down.
        .biHeight = -hgt
        .biPlanes = 1
        .biBitCount = 32
        .biCompression = BI_RGB
        bytes_per_scanLine = ((((.biWidth * .biBitCount) + _
            31) \ 32) * 4)
        .biSizeImage = bytes_per_scanLine * hgt
    End With

    ' Load the bitmap's data.
    ReDim pixels(1 To 4, 1 To wid, 1 To hgt)
    GetDIBits pic.hdc, pic.Image, _
        0, hgt, pixels(1, 1, 1), _
        bitmap_info, DIB_RGB_COLORS

    ' Process the pixels.
    ' Break the tansparent color apart.
    UnRGB transparent_color, transparent_r, transparent_g, _
        transparent_b

    ' Find the form's corner.
    border_width = (ScaleX(Width, vbTwips, vbPixels) - _
        ScaleWidth) / 2
    title_height = ScaleX(Height, vbTwips, vbPixels) - _
        border_width - ScaleHeight

    ' Find the picture's corner.
    x0 = pic.Left + border_width
    y0 = pic.Top + title_height

    ' Create the form's regions.
    For R = 1 To hgt
        ' Create a region for this row.
        C = 1
        Do While C <= wid
            start_c = 1
            stop_c = 1

            ' Find the next non-white column.
            Do While C <= wid
                If pixels(pixR, C, R) <> transparent_r Or _
                   pixels(pixG, C, R) <> transparent_g Or _
                   pixels(pixB, C, R) <> transparent_b _
                Then
                    Exit Do
                End If
                C = C + 1
            Loop
            start_c = C

            ' Find the next white column.
            Do While C <= wid
                If pixels(pixR, C, R) = transparent_r And _
                   pixels(pixG, C, R) = transparent_g And _
                   pixels(pixB, C, R) = transparent_b _
                Then
                    Exit Do
                End If
                C = C + 1
            Loop
            stop_c = C

            ' Make a region from start_c to stop_c.
            If start_c <= wid Then
                If stop_c > wid Then stop_c = wid

                ' Create the region.
                new_rgn = CreateRectRgn( _
                    start_c + x0, R + y0, _
                    stop_c + x0, R + y0 + 1)

                ' Add it to what we have so far.
                If combined_rgn = 0 Then
                    combined_rgn = new_rgn
                Else
                    CombineRgn combined_rgn, _
                        combined_rgn, new_rgn, RGN_OR
                    DeleteObject new_rgn
                End If
            End If
        Loop
    Next R

    ' Restrict the form to the region.
    SetWindowRgn hWnd, combined_rgn, True
    DeleteObject combined_rgn
End Sub
 
For more information on graphics programming in Visual Basic, see my book Visual Basic Graphics Programming.
 
 
Copyright © 1997-2010 Rocky Mountain Computer Consulting, Inc.   All rights reserved.
  Updated