DefInt A-Z

Declare Function BitBlt Lib "Gdi" (ByVal destHdc, ByVal X, ByVal Y, ByVal w, ByVal h, ByVal srcHdc, ByVal srcX, ByVal srcY, ByVal Rop As Long)
Declare Function CreateRectRgn Lib "Gdi" (ByVal X1, ByVal Y1, ByVal X2, ByVal Y2)
Declare Function SetRectRgn Lib "Gdi" (ByVal hRgn, ByVal X1, ByVal Y1, ByVal X2, ByVal Y2)
Declare Function SelectClipRgn Lib "Gdi" (ByVal Hdc, ByVal hRgn)
Declare Function CombineRgn Lib "Gdi" (ByVal hDestRgn, ByVal hSrcRgn1, ByVal hSrcRgn2, ByVal nCombineMode)

Const SRCCOPY = &HCC0020
Const SRCAND = &H8800C6
Const SRCINVERT = &H660046
Const NOTSRCCOPY = &H330008
Const SRCINVERTANDDEST = &H220B24

Const RGN_AND = 1
Const RGN_DIFF = 4
Const NULLREGION = 1

Const TRUE = -1
Const FALSE = 0
Const MODAL = 1

Const MID_OPEN = 0
Const MID_CLIPBOARD = 1
Const MID_EXIT = 3

Const MID_SCRAMMBLE = 0
Const MID_SOLVE = 1
Const MID_ANIMATE = 2
Const MID_PIECES_TO_FOREGROUND = 3
Const MID_SHOW_SCRAMMBLING = 5
Const MID_SCRAMMBLE_ON_OPEN = 6

Const MID_CIRCLES_AND_OTHERS = 1
Const MID_ELIPSES_AND_OTHERS = 2
Const MID_ANGELS_AND_STARS = 3
Const MID_CIRCLES_IN_SQUARES = 4

Dim TotalPieces  As Integer
Dim PuzzleSize   As Integer
Dim PieceHeight  As Integer
Dim PieceWidth   As Integer
Dim MovingPiece  As Integer
Dim LastMouseX   As Integer
Dim LastMouseY   As Integer
Dim MaskNeeded   As Integer
Dim Solved       As Integer

Dim Region1 As Integer
Dim Region2 As Integer
Dim Region3 As Integer
Dim Region4 As Integer

Dim Piece As PIECEINFO
Dim Pieces() As PIECEINFO
Dim Priority() As Integer


Sub Form_Load ()

    Region1 = CreateRectRgn(0, 0, 0, 0)
    Region2 = CreateRectRgn(0, 0, 0, 0)
    Region3 = CreateRectRgn(0, 0, 0, 0)
    Region4 = CreateRectRgn(0, 0, 0, 0)

    PuzzleSize = 5

    Menu_Stop.Visible = FALSE

End Sub

Sub Set_Piece_Priority (Piece As Integer)

    Temp = Priority(Piece)
    For I = Piece To 1 Step -1
        Priority(I) = Priority(I - 1)
    Next
    Priority(0) = Temp

End Sub

Sub Display_A_Piece (destHdc, Piece)
    
    DestX = Pieces(Priority(Piece)).X
    DestY = Pieces(Priority(Piece)).Y
    
    If MaskNeeded Then
        R = BitBlt(Pic_FinalPiece.Hdc, 0, 0, PieceWidth, PieceHeight, Pic_PuzzleImage.Hdc, DestX, DestY, SRCCOPY)
        R = BitBlt(Pic_FinalPiece.Hdc, 0, 0, PieceWidth, PieceHeight, Pic_PieceMask.Hdc, 0, 0, SRCAND)
        R = BitBlt(Pic_FinalPiece.Hdc, 0, 0, PieceWidth, PieceHeight, Pic_PieceImage.Hdc, 0, 0, SRCINVERT)
        R = BitBlt(destHdc, DestX, DestY, PieceWidth, PieceHeight, Pic_FinalPiece.Hdc, 0, 0, SRCCOPY)
    Else
        R = BitBlt(destHdc, DestX, DestY, PieceWidth, PieceHeight, Pic_Bitmap.Hdc, Pieces(Priority(Piece)).HomeX, Pieces(Priority(Piece)).HomeY, SRCCOPY)
    End If

End Sub


Sub Menu_OptionsSelection_Click (Index As Integer)

    Pic_Work.MousePointer = 11

    Select Case Index
        
        Case MID_SCRAMMBLE
            Scrammble_Puzzle

        Case MID_SOLVE
            Solve_Puzzle

        Case MID_ANIMATE
            Animate_Puzzle
        
        Case MID_PIECES_TO_FOREGROUND
            Bring_Pieces_To_Foreground

        Case MID_SHOW_SCRAMMBLING, MID_SCRAMMBLE_ON_OPEN
            Menu_OptionsSelection(Index).Checked = Not Menu_OptionsSelection(Index).Checked

    End Select

    Pic_Work.MousePointer = 0
    
End Sub

Sub Menu_FileSelection_Click (Index As Integer)

    Picture = LoadPicture()

    Select Case Index

        Case MID_OPEN
            OpenFile.Show MODAL
            If OpenFile.File1.ListIndex >= 0 Then Picture = LoadPicture(OpenFile.File1.FileName)

        Case MID_CLIPBOARD
            Picture = ClipBoard.GetData()

        Case MID_EXIT
            Unload JigSaw

    End Select

    If Picture Then
        Menu_Options.Enabled = TRUE
        Menu_Pieces.Enabled = TRUE
        Menu_Hint.Enabled = TRUE
        Pic_Work.Visible = TRUE
        Screen.MousePointer = 11
        Prepare_Bitmap (Menu_OptionsSelection(MID_SCRAMMBLE_ON_OPEN).Checked)
        Screen.MousePointer = 0
        Pic_Window.Refresh
    End If

End Sub

Sub Prepare_Bitmap (Scrammble)
            
    Pic_Bitmap.Picture = Picture
    Pic_Bitmap.Picture = Pic_Bitmap.Image

    PieceWidth = Pic_Bitmap.Width / PuzzleSize
    PieceHeight = Pic_Bitmap.Height / PuzzleSize

    Pic_PuzzleImage.Cls
    Pic_PuzzleImage.Move 0, 0, Pic_Bitmap.Width, Pic_Bitmap.Height
    Pic_Work.Move 0, 0, Pic_Bitmap.Width, Pic_Bitmap.Height
    Pic_Mask.Move 0, 0, Pic_Bitmap.Width, Pic_Bitmap.Height
    Pic_Mask.Cls

    Form_Resize
    Randomize Timer
    TotalPieces = 24

    If MaskNeeded Then
        
        Pic_PieceImage.Move 0, 0, PieceWidth, PieceHeight
        Pic_PieceMask.Move 0, 0, PieceWidth, PieceHeight
        Pic_FinalPiece.Move 0, 0, PieceWidth, PieceHeight
        
        Select Case MaskNeeded
            
            Case MID_CIRCLES_AND_OTHERS
                Create_Circles_Mask

            Case MID_ELIPSES_AND_OTHERS
                Create_Elipses_Mask

            Case MID_ANGELS_AND_STARS
                Create_Angel_And_Stars_Mask

            Case MID_CIRCLES_IN_SQUARES
                TotalPieces = 31
                Create_Circles_In_Squares_Mask

        End Select
    End If
    
    ReDim Pieces(TotalPieces) As PIECEINFO
    ReDim Priority(TotalPieces) As Integer

    If (MaskNeeded > 0) And (MaskNeeded <> MID_CIRCLES_IN_SQUARES) Then
        For Y = 0 To PuzzleSize - 2
            For X = 0 To PuzzleSize - 2
                I = TotalPieces - (Y * (PuzzleSize - 1) + X)
                Pieces(I).HomeX = X * PieceWidth + PieceWidth / 2
                Pieces(I).HomeY = Y * PieceHeight + PieceHeight / 2
                Pieces(I).X = Pieces(I).HomeX
                Pieces(I).Y = Pieces(I).HomeY
                Priority(I) = I
            Next X
        Next Y
    End If

    For Y = 0 To PuzzleSize - 1
        For X = 0 To PuzzleSize - 1
            I = (PuzzleSize ^ 2 - 1) - (Y * PuzzleSize + X)
            For Z = 0 To Abs(MaskNeeded = MID_CIRCLES_IN_SQUARES)
                Pieces(I + Z * 16).HomeX = X * PieceWidth
                Pieces(I + Z * 16).HomeY = Y * PieceHeight
                Pieces(I + Z * 16).X = Pieces(I).HomeX
                Pieces(I + Z * 16).Y = Pieces(I).HomeY
                Priority(I + Z * 16) = I + Z * 16
            Next Z
        Next X
    Next Y
    
    Select Case MaskNeeded
        Case 0, 4
            Outline_Circles_In_Squares
        Case 1
        Case 2
        Case 3
    End Select

    If Scrammble Then
        Scrammble_Puzzle
    Else
        Solved = TRUE
        R = BitBlt(Pic_PuzzleImage.Hdc, 0, 0, Pic_Bitmap.Width, Pic_Bitmap.Height, Pic_Bitmap.Hdc, 0, 0, SRCCOPY)
        Pic_Work.Refresh
    End If
    
End Sub

Sub Form_Unload (Cancel As Integer)

    End

End Sub

Sub Form_Resize ()

    Pic_Work.Move 0, 0
    
    HScroll1.Move 0, ScaleHeight - HScroll1.Height, ScaleWidth - VScroll1.Width
    VScroll1.Move ScaleWidth - VScroll1.Width, 0, VScroll1.Width, ScaleHeight - HScroll1.Height
    Pic_ScrollBarJoint.Move VScroll1.Left, HScroll1.Top
    Pic_Window.Move 0, 0, VScroll1.Left, HScroll1.Top

    HScroll1.Enabled = Pic_Window.Width < Pic_Bitmap.Width
    VScroll1.Enabled = Pic_Window.Height < Pic_Bitmap.Height
    
    If VScroll1.Enabled Then
        VScroll1.Value = 0
        VScroll1.Max = Abs(Pic_Window.Height - Pic_Bitmap.Height)
        VScroll1.LargeChange = VScroll1.Max \ 10
    End If
    
    If HScroll1.Enabled Then
        HScroll1.Value = 0
        HScroll1.Max = Abs(Pic_Window.Width - Pic_Bitmap.Width)
        HScroll1.LargeChange = HScroll1.Max \ 10
    End If
    
End Sub

Sub HScroll1_Change ()
  
  ' Pic_Work.Left is set to the Negative of the value since
  ' as you scroll the Scrollbar to the Right, the display
  ' should move to the Left, showing more of the right
  ' of the display, and vice-versa when scrolling to the
  ' left

  Pic_Work.Left = -HScroll1.Value

End Sub

Sub VScroll1_Change ()
  
  ' Pic_Work.Top is set to the Negative of the value since
  ' as you scroll the Scrollbar down, the display
  ' should move up, showing more of the the bottom
  ' of the display, and vice-versa when scrolling up
  
  Pic_Work.Top = -VScroll1.Value
  
End Sub

Sub Pic_Work_MouseMove (Button As Integer, Shift As Integer, X As Single, Y As Single)

    If MovingPiece And (Not Menu_Stop.Visible) Then Move_Piece X + 0, Y + 0

End Sub

Sub Pic_Work_MouseUp (Button As Integer, Shift As Integer, X As Single, Y As Single)

    If MovingPiece And (Not Menu_Stop.Visible) Then
        
        If CombineRgn(Region3, Region4, Region2, RGN_AND) <> NULLREGION Then
            R = BitBlt(Pic_Work.Hdc, Pieces(Priority(0)).X, Pieces(Priority(0)).Y, PieceWidth, PieceHeight, Pic_PuzzleImage.Hdc, Pieces(Priority(0)).X, Pieces(Priority(0)).Y, SRCCOPY)
            Pieces(Priority(0)).X = Pieces(Priority(I)).HomeX
            Pieces(Priority(0)).Y = Pieces(Priority(I)).HomeY
            Display_A_Piece (Pic_Work.Hdc), 0
            Beep
        End If
        Display_A_Piece (Pic_PuzzleImage.Hdc), 0

        For I = 0 To TotalPieces
            If (Pieces(I).X <> Pieces(I).HomeX) Or (Pieces(I).Y <> Pieces(I).HomeY) Then Exit For
        Next
        If I > TotalPieces Then
            Restore_Bitmap
            MsgBox "You have solved the puzzle", 16, "VB JigSaw"
        End If
        Menu_Hint.Enabled = (Pieces(Priority(0)).X <> Pieces(Priority(0)).HomeX) Or (Pieces(Priority(0)).Y <> Pieces(Priority(0)).HomeY)
        
    End If
    MovingPiece = FALSE
    Pic_Work.MousePointer = 0

End Sub

Sub Pic_Work_MouseDown (Button As Integer, Shift As Integer, X As Single, Y As Single)

    If (Button = 1) And (Not Menu_Stop.Visible) Then
        If Solved Then
            Solved = FALSE
            Pic_PuzzleImage.Picture = Pic_Bitmap.Image
            Pic_Work_Paint
        End If
        For I = 0 To TotalPieces
            Piece = Pieces(Priority(I))
            If (X >= Piece.X) And (X <= Piece.X + PieceWidth - 1) Then
                If (Y >= Piece.Y) And (Y <= Piece.Y + PieceHeight - 1) Then
                    If Pic_Mask.Point(Piece.HomeX + (X - Piece.X), Piece.HomeY + (Y - Piece.Y)) = (Priority(I) < (PuzzleSize ^ 2) And &HFFFFFF) Then
                        Set_Piece_Priority I
                        Prepare_To_Move_Piece X + 0, Y + 0
                        Pic_Work.MousePointer = 5
                        Exit For
                    End If
                End If
            End If
        Next I
    ElseIf (Button = 2) And Solved Then
        Pic_PuzzleImage.Picture = Pic_Bitmap.Image
        Pic_Work_Paint
    End If

End Sub

Sub Pic_Work_Paint ()

    R = BitBlt(Pic_Work.Hdc, 0, 0, Pic_Bitmap.Width, Pic_Bitmap.Height, Pic_PuzzleImage.Hdc, 0, 0, SRCCOPY)

End Sub

Sub Menu_PiecesSelection_Click (Index As Integer)

    Menu_PiecesSelection(MaskNeeded).Checked = FALSE
    Menu_PiecesSelection(Index).Checked = TRUE
    MaskNeeded = Index
    If MaskNeeded Then PuzzleSize = 4 Else PuzzleSize = 5
    Prepare_Bitmap TRUE
        
End Sub

Sub Menu_Stop_Click ()

    Menu_File.Enabled = TRUE
    Menu_Options.Enabled = TRUE
    Menu_Pieces.Enabled = TRUE
    Menu_Hint.Enabled = TRUE
    Menu_Stop.Visible = FALSE

End Sub

Sub Move_Piece (X, Y)
        
    LastX = Pieces(Priority(0)).X
    LastY = Pieces(Priority(0)).Y

    Pieces(Priority(0)).X = Pieces(Priority(0)).X + (X - LastMouseX)
    Pieces(Priority(0)).Y = Pieces(Priority(0)).Y + (Y - LastMouseY)
    Display_A_Piece (Pic_Work.Hdc), 0

    R = SetRectRgn(Region1, LastX, LastY, LastX + PieceWidth, LastY + PieceHeight)
    R = SetRectRgn(Region2, Pieces(Priority(0)).X, Pieces(Priority(0)).Y, Pieces(Priority(0)).X + PieceWidth, Pieces(Priority(0)).Y + PieceHeight)
    R = CombineRgn(Region3, Region1, Region2, RGN_DIFF)
    R = SelectClipRgn(Pic_Work.Hdc, Region3)
    R = BitBlt(Pic_Work.Hdc, LastX, LastY, PieceWidth, PieceHeight, Pic_PuzzleImage.Hdc, LastX, LastY, SRCCOPY)
    R = SelectClipRgn(Pic_Work.Hdc, 0)

    LastMouseX = X
    LastMouseY = Y

End Sub

Sub Prepare_To_Move_Piece (X, Y)
    
    Piece = Pieces(Priority(0))
    If MaskNeeded Then Get_Mask_And_Image 0
    Display_A_Piece (Pic_Work.Hdc), 0
                    
    R = SetRectRgn(Region2, Piece.X, Piece.Y, Piece.X + PieceWidth, Piece.Y + PieceHeight)
    R = SelectClipRgn(Pic_PuzzleImage.Hdc, Region2)
    Pic_PuzzleImage.Line (Piece.X, Piece.Y)-(Piece.X + PieceWidth, Piece.Y + PieceHeight), Pic_PuzzleImage.Backcolor, BF
    For N = TotalPieces To 1 Step -1
        R = SetRectRgn(Region1, Pieces(Priority(N)).X, Pieces(Priority(N)).Y, Pieces(Priority(N)).X + PieceWidth, Pieces(Priority(N)).Y + PieceHeight)
        If CombineRgn(Region3, Region2, Region1, RGN_AND) <> NULLREGION Then
            If MaskNeeded Then
                Get_Mask_And_Image N
                R = BitBlt(Pic_PuzzleImage.Hdc, Pieces(Priority(N)).X, Pieces(Priority(N)).Y, PieceWidth, PieceHeight, Pic_PieceMask.Hdc, 0, 0, SRCAND)
                R = BitBlt(Pic_PuzzleImage.Hdc, Pieces(Priority(N)).X, Pieces(Priority(N)).Y, PieceWidth, PieceHeight, Pic_PieceImage.Hdc, 0, 0, SRCINVERT)
            Else
                Display_A_Piece (Pic_PuzzleImage.Hdc), N
            End If
        End If
    Next N
    R = SelectClipRgn(Pic_PuzzleImage.Hdc, 0)

    If MaskNeeded Then Get_Mask_And_Image 0

    X1 = Piece.HomeX + 3 * (PieceWidth \ 8)
    Y1 = Piece.HomeY + 3 * (PieceHeight \ 8)
    X2 = X1 + PieceWidth \ 4
    Y2 = Y1 + PieceHeight \ 4
    R = SetRectRgn(Region4, X1, Y1, X2, Y2)

    LastMouseX = X
    LastMouseY = Y
    MovingPiece = TRUE
    
End Sub

Sub Menu_Hint_Click ()

    For I = 1 To 6
        Pic_Work.Line (Pieces(Priority(0)).X, Pieces(Priority(0)).Y)-(Pieces(Priority(0)).X + PieceWidth, Pieces(Priority(0)).Y + PieceHeight), , BF
        Pic_Work.Line (Pieces(Priority(0)).HomeX, Pieces(Priority(0)).HomeY)-(Pieces(Priority(0)).HomeX + PieceWidth, Pieces(Priority(0)).HomeY + PieceHeight), , BF
    Next

End Sub

Sub Get_Mask_And_Image (Piece)
Dim MaskROP As Long

    If Priority(Piece) < 16 Then MaskROP = NOTSRCCOPY Else MaskROP = SRCCOPY
    R = BitBlt(Pic_PieceMask.Hdc, 0, 0, PieceWidth, PieceHeight, Pic_Mask.Hdc, Pieces(Priority(Piece)).HomeX, Pieces(Priority(Piece)).HomeY, MaskROP)
    R = BitBlt(Pic_PieceImage.Hdc, 0, 0, PieceWidth, PieceHeight, Pic_Bitmap.Hdc, Pieces(Priority(Piece)).HomeX, Pieces(Priority(Piece)).HomeY, SRCCOPY)
    R = BitBlt(Pic_PieceImage.Hdc, 0, 0, PieceWidth, PieceHeight, Pic_PieceMask.Hdc, 0, 0, SRCINVERTANDDEST)

End Sub

Sub Scrammble_Puzzle ()
            
    Solved = FALSE
    Pic_Work.Cls
    Pic_PuzzleImage.Picture = LoadPicture()
    
    Randomize Timer
    For I = TotalPieces To 0 Step -1
        Pieces(Priority(I)).X = Int(Rnd * (Pic_Work.Width - PieceWidth) + 1)
        Pieces(Priority(I)).Y = Int(Rnd * (Pic_Work.Height - PieceHeight) + 1)
        If MaskNeeded Then
            Get_Mask_And_Image I
            R = BitBlt(Pic_PuzzleImage.Hdc, Pieces(Priority(I)).X, Pieces(Priority(I)).Y, PieceWidth, PieceHeight, Pic_PieceMask.Hdc, 0, 0, SRCAND)
            R = BitBlt(Pic_PuzzleImage.Hdc, Pieces(Priority(I)).X, Pieces(Priority(I)).Y, PieceWidth, PieceHeight, Pic_PieceImage.Hdc, 0, 0, SRCINVERT)
        Else
            Display_A_Piece (Pic_PuzzleImage.Hdc), I
        End If
        If Menu_OptionsSelection(MID_SHOW_SCRAMMBLING).Checked Then R = BitBlt(Pic_Work.Hdc, Pieces(Priority(I)).X, Pieces(Priority(I)).Y, PieceWidth, PieceHeight, Pic_PuzzleImage.Hdc, Pieces(Priority(I)).X, Pieces(Priority(I)).Y, SRCCOPY)
    Next I
    If Not Menu_OptionsSelection(MID_SHOW_SCRAMMBLING).Checked Then Pic_Work.Refresh

End Sub

Sub Solve_Puzzle ()
    
    Menu_Hint.Enabled = FALSE
    For I = 0 To TotalPieces
        Priority(I) = I
        Pieces(I).X = Pieces(I).HomeX
        Pieces(I).Y = Pieces(I).HomeY
    Next I
    Restore_Bitmap

End Sub

Sub Animate_Puzzle ()
            
    Menu_Hint.Enabled = FALSE
    Menu_File.Enabled = FALSE
    Menu_Options.Enabled = FALSE
    Menu_Pieces.Enabled = FALSE
    Menu_Hint.Enabled = FALSE
    Menu_Stop.Visible = TRUE

    For I = 0 To TotalPieces
        If (Pieces(Priority(0)).X <> Pieces(Priority(0)).HomeX) Or (Pieces(Priority(0)).Y <> Pieces(Priority(0)).HomeY) Then
            XInc = Sgn(Pieces(Priority(0)).X - Pieces(Priority(0)).HomeX) * 14
            YInc = Sgn(Pieces(Priority(0)).Y - Pieces(Priority(0)).HomeY) * 14
            Prepare_To_Move_Piece Pieces(Priority(0)).X, Pieces(Priority(0)).Y
            While (Pieces(Priority(0)).X <> Pieces(Priority(0)).HomeX) Or (Pieces(Priority(0)).Y <> Pieces(Priority(0)).HomeY)
                If Pieces(Priority(0)).X = Pieces(Priority(0)).HomeX Then XInc = 0
                If Pieces(Priority(0)).Y = Pieces(Priority(0)).HomeY Then YInc = 0
                X = Pieces(Priority(0)).X - XInc
                Y = Pieces(Priority(0)).Y - YInc
                If Sgn(X - Pieces(Priority(0)).HomeX) <> Sgn(XInc) Then X = Pieces(Priority(0)).HomeX
                If Sgn(Y - Pieces(Priority(0)).HomeY) <> Sgn(YInc) Then Y = Pieces(Priority(0)).HomeY
                Move_Piece X, Y
            Wend
            Display_A_Piece (Pic_PuzzleImage.Hdc), 0
        End If
        X = DoEvents()
        If Not Menu_Stop.Visible Then Exit For
        Set_Piece_Priority TotalPieces
    Next I
    MovingPiece = FALSE
    Menu_Stop_Click

    Restore_Bitmap

End Sub

Sub Bring_Pieces_To_Foreground ()
            
    For I = TotalPieces To 0 Step -1
        If (Pieces(Priority(I)).X <> Pieces(Priority(I)).HomeX) Or (Pieces(Priority(I)).Y <> Pieces(Priority(I)).HomeY) Then
            Set_Piece_Priority I
            If MaskNeeded Then Get_Mask_And_Image I
            Display_A_Piece (Pic_PuzzleImage.Hdc), I
        End If
        R = BitBlt(Pic_Work.Hdc, Pieces(Priority(I)).X, Pieces(Priority(I)).Y, PieceWidth, PieceHeight, Pic_PuzzleImage.Hdc, Pieces(Priority(I)).X, Pieces(Priority(I)).Y, SRCCOPY)
    Next I

End Sub

Sub Pic_Window_Paint ()

    If Pic_Work.Visible Then Pic_Window.Line (0, 0)-(Pic_Work.Left + Pic_Work.Width + 2, Pic_Work.Top + Pic_Work.Height + 2), (Not Pic_Window.Backcolor) And &HFFFFFF, B
    
End Sub

Sub Outline_Circles_In_Squares ()
Dim Radius As Single

    If PieceWidth < PieceHeight Then Radius = PieceWidth / 2 - 5 Else Radius = PieceHeight / 2 - 5
    For Y = 0 To PuzzleSize - 1
        For X = 0 To PuzzleSize - 1
            Pic_Bitmap.Line (X * PieceWidth, Y * PieceHeight)-(X * PieceWidth + PieceWidth - 1, Y * PieceHeight + PieceHeight - 1), , B
            If MaskNeeded <> MID_CIRCELS_IN_SQUARES Then
                Pic_Bitmap.Circle (X * PieceWidth + PieceWidth / 2, Y * PieceHeight + PieceHeight / 2), Radius
                Pic_Bitmap.Circle (X * PieceWidth + PieceWidth / 2, Y * PieceHeight + PieceHeight / 2), Radius + 1
            End If
        Next X
    Next Y

End Sub

Sub Create_Circles_In_Squares_Mask ()
Dim Radius As Single

    If PieceWidth < PieceHeight Then Radius = PieceWidth / 2 - 5 Else Radius = PieceHeight / 2 - 5
    For Y = 0 To PuzzleSize - 1
        For X = 0 To PuzzleSize - 1
            Pic_Mask.Circle (X * PieceWidth + PieceWidth / 2, Y * PieceHeight + PieceHeight / 2), Radius
        Next X
    Next Y

End Sub

Sub Create_Angel_And_Stars_Mask ()
    
    For Y = 1 To 3
        For X = 1 To 3
            If Y = 2 Then Half = 1 Else Half = 2
            Pic_Mask.Circle (X * PieceWidth, Y * PieceHeight), PieceHeight / Half, , , , 2.5
            Pic_Mask.Circle (X * PieceWidth, Y * PieceHeight), PieceWidth / 2, , , , .2
        Next X
    Next Y

    For X = 1 To 3
        Pic_Mask.fillstyle = 1
        Pic_Mask.Line (X * PieceWidth - PieceWidth / 2, 2 * PieceHeight - PieceHeight / 2)-(X * PieceWidth + PieceWidth / 2, 2 * PieceHeight + PieceHeight / 2), &HFFFFFF, BF
        Pic_Mask.fillstyle = 0
        Pic_Mask.Circle (X * PieceWidth, 2 * PieceHeight), PieceHeight / 2, , , , 4.5
        Pic_Mask.Circle (X * PieceWidth, 2 * PieceHeight), PieceWidth / 2, , , , .1
    Next X

End Sub

Sub Create_Elipses_Mask ()

    For Y = 1 To 3
        For X = 1 To 3
            If ((X * Y) Mod 2) Or (X * Y) = 4 Then
                Pic_Mask.Circle (X * PieceWidth, Y * PieceHeight), PieceHeight / 2 - 1, , , , 2.5
            Else
                Pic_Mask.Circle (X * PieceWidth, Y * PieceHeight), PieceWidth / 2 - 1, , , , .3
            End If
        Next X
    Next Y

End Sub

Sub Create_Circles_Mask ()
Dim Radius As Single

    If PieceWidth < PieceHeight Then Radius = PieceWidth / 2 - 1 Else Radius = PieceHeight / 2 - 1
    For Y = 1 To PuzzleSize - 1
        For X = 1 To PuzzleSize - 1
            Pic_Mask.Circle (X * PieceWidth, Y * PieceHeight), Radius
        Next X
    Next Y
    
End Sub

Sub Restore_Bitmap ()
    
    Solved = TRUE
    AutoRedraw = TRUE
    Pic_PuzzleImage.Picture = Image
    AutoRedraw = FALSE
    Pic_Work_Paint

End Sub

Sub Menu_OutlineSelection_Click (Index As Integer)
    
    Menu_OutlineSelection(Index).Checked = TRUE
    Menu_OutlineSelection(Abs(1 - Index)).Checked = FALSE

    Pic_Bitmap.ForeColor = (-Index) And &HFFFFFF
    Prepare_Bitmap FALSE

End Sub

Sub Menu_BackgroundSelection_Click (Index As Integer)

    Menu_BackgroundSelection(Index).Checked = TRUE
    Menu_BackgroundSelection(Abs(1 - Index)).Checked = FALSE

    Pic_Work.Backcolor = Pic_Window.Backcolor
    Pic_PuzzleImage.Backcolor = Pic_Window.Backcolor
    Pic_Window.Backcolor = (Not Pic_Work.Backcolor) And &HFFFFFF
    
    Prepare_Bitmap FALSE
    Pic_Window.Refresh

End Sub

Sub Menu_File_Click ()

    Menu_FileSelection(MID_CLIPBOARD).Enabled = ClipBoard.GetFormat(2)

End Sub

Sub Menu_HelpSelection_Click (Index As Integer)

    AboutBox.Show MODAL

End Sub

