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
 
 
 
 
 
 
TitleMake a form filled with holes
Keywordsform, shape, region, SetWindowRgn, shaped form, holes, swiss cheese
CategoriesTips and Tricks, Graphics
 

The Form_Resize event handler creates a region covering the entire form. Then it calls the CutHoles subroutine to recursively cut holes in the region.

 
Private m_FormRegion As Long

Private Sub Form_Resize()
Dim wid As Single
Dim hgt As Single
Dim border_width As Single
Dim title_height As Single

    If WindowState = vbMinimized Then Exit Sub

    ' If we already have a region, destroy it.
    If m_FormRegion <> 0 Then
        DeleteObject m_FormRegion
        m_FormRegion = 0
    End If

    ' Create the outer region.
    wid = ScaleX(Width, vbTwips, vbPixels)
    hgt = ScaleY(Height, vbTwips, vbPixels)
    m_FormRegion = CreateRectRgn(0, 0, wid, hgt)

    ' Find the client area.
    border_width = (wid - ScaleWidth) / 2
    title_height = hgt - border_width - ScaleHeight

    ' Recursively cut holes in the region.
    CutHoles m_FormRegion, 3, _
        border_width, title_height, _
        ScaleWidth, ScaleHeight

    ' Restrict the window to the region.
    SetWindowRgn hWnd, m_FormRegion, True
End Sub
 
Subroutine CutHoles divides the area it is working on into a 3x3 grid. It makes an elliptical region in the center and corner grid areas and subtracts those regions from the main region using the CombineRgn function.

When it has cut its 5 holes, the routine calls itself recursively to cut smaller holes in the other 4 grid areas.

 
' Recursively cut holes in this region.
Private Sub CutHoles(ByRef outer_rgn As Long, ByVal level _
    As Integer, ByVal xmin As Long, ByVal ymin As Long, _
    ByVal xmax As Long, ByVal ymax As Long)
Const RGN_DIFF = 4

Dim inner_rgn As Long
Dim combined_rgn As Long
Dim dx As Long
Dim x1 As Long
Dim x2 As Long
Dim dy As Long
Dim y1 As Long
Dim y2 As Long

    ' See if we should stop.
    If level < 1 Then Exit Sub

    ' Divide the area.
    dx = (xmax - xmin) / 3
    x1 = xmin + dx
    x2 = xmin + 2 * dx
    dy = (ymax - ymin) / 3
    y1 = ymin + dy
    y2 = ymin + 2 * dy

    ' Cut out regions.
    inner_rgn = CreateEllipticRgn(xmin, ymin, x1, y1)
    combined_rgn = CreateRectRgn(0, 0, 0, 0)
    CombineRgn combined_rgn, outer_rgn, inner_rgn, RGN_DIFF
    DeleteObject outer_rgn
    DeleteObject inner_rgn
    outer_rgn = combined_rgn

    inner_rgn = CreateEllipticRgn(x2, ymin, xmax, y1)
    combined_rgn = CreateRectRgn(0, 0, 0, 0)
    CombineRgn combined_rgn, outer_rgn, inner_rgn, RGN_DIFF
    DeleteObject outer_rgn
    DeleteObject inner_rgn
    outer_rgn = combined_rgn

    inner_rgn = CreateEllipticRgn(x1, y1, x2, y2)
    combined_rgn = CreateRectRgn(0, 0, 0, 0)
    CombineRgn combined_rgn, outer_rgn, inner_rgn, RGN_DIFF
    DeleteObject outer_rgn
    DeleteObject inner_rgn
    outer_rgn = combined_rgn

    inner_rgn = CreateEllipticRgn(xmin, y2, x1, ymax)
    combined_rgn = CreateRectRgn(0, 0, 0, 0)
    CombineRgn combined_rgn, outer_rgn, inner_rgn, RGN_DIFF
    DeleteObject outer_rgn
    DeleteObject inner_rgn
    outer_rgn = combined_rgn

    inner_rgn = CreateEllipticRgn(x2, y2, xmax, ymax)
    combined_rgn = CreateRectRgn(0, 0, 0, 0)
    CombineRgn combined_rgn, outer_rgn, inner_rgn, RGN_DIFF
    DeleteObject outer_rgn
    DeleteObject inner_rgn
    outer_rgn = combined_rgn

    ' Recursively cut more holes.
    CutHoles outer_rgn, level - 1, x1, ymin, x2, y1
    CutHoles outer_rgn, level - 1, xmin, y1, x1, y2
    CutHoles outer_rgn, level - 1, x2, y1, xmax, y2
    CutHoles outer_rgn, level - 1, x1, y2, x2, ymax
End Sub
 
 
Copyright © 1997-2010 Rocky Mountain Computer Consulting, Inc.   All rights reserved.
  Updated