Partial Public Class FrmDesigner
    ' Variables related to selection and ctmMenu
    Private isCursorOnPicGame As Boolean = False
    Private selectionStartedOnWall As Boolean
    Private SelectionType As String

    Private isSelectionReadyToDrag As Boolean = False
    Private isDraggingSelection As Boolean = False
    Private selectionOffset As Point ' The offset between mouse position and selection rectangle origin
    Private selectionData As SelectionData
    Private selectionStartCell As Point ' The grid cell coordinates corresponding to selectionRectangle's original position

    Private isRightMouseDown As Boolean = False
    Private isLeftMouseDown As Boolean = False
    Private isMouseInsideGrid As Boolean = False

    Private isSelecting As Boolean = False
    Private isInSelectionMode As Boolean = False
    Private selectionStartPoint As Point
    Private selectionEndPoint As Point
    Private selectionRectangle As Rectangle

    Private copiedSelectionData As SelectionData
    Private copiedSelectionType As String
    Private isCopying As Boolean = False

    ' Methods related to ctmMenu
    Private Sub BtnSelect_Click(sender As Object, e As EventArgs) Handles btnSelect.Click
        If isInSelectionMode Then
            ' Exiting selection mode
            isInSelectionMode = False
            isSelecting = False
            isSelectionReadyToDrag = False
            selectionRectangle = Rectangle.Empty
            picGame.Cursor = Cursors.Default
            picGame.Invalidate()
        Else
            ' Entering selection mode
            isInSelectionMode = True
            isSelecting = False
            isSelectionReadyToDrag = False
            selectionRectangle = Rectangle.Empty
            picGame.Cursor = Cursors.Cross
        End If
    End Sub

    Private Sub MnuSelectAll_Click(sender As Object, e As EventArgs) Handles mnuSelectAll.Click
        selectionRectangle = New Rectangle(INDENT, INDENT, SQCOUNTX * (SQSizeX + WALL_THICKNESS) - WALL_THICKNESS, SQCOUNTY * (SQSizeY + WALL_THICKNESS) - WALL_THICKNESS)
        isInSelectionMode = True
        Cursor = Cursors.Cross
        picGame.Invalidate()
    End Sub

    Private Sub SelectAllItemsOfType(ParamArray itemKeys As String())
        Dim selectedPoints As New List(Of Point)

        For x As Integer = 0 To SQCOUNTX - 1
            For y As Integer = 0 To SQCOUNTY - 1
                Dim localX As Integer = x
                Dim localY As Integer = y
                If placedItems(localX)(localY) IsNot Nothing AndAlso Array.Exists(itemKeys, Function(key) placedItems(localX)(localY).ImageKey = key) Then
                    selectedPoints.Add(New Point(localX, localY))
                End If
            Next
        Next

        If selectedPoints.Count > 0 Then
            Dim minX = selectedPoints.Min(Function(p) p.X)
            Dim minY = selectedPoints.Min(Function(p) p.Y)
            Dim maxX = selectedPoints.Max(Function(p) p.X)
            Dim maxY = selectedPoints.Max(Function(p) p.Y)

            selectionRectangle = New Rectangle(
                INDENT + minX * (SQSizeX + WALL_THICKNESS),
                INDENT + minY * (SQSizeY + WALL_THICKNESS),
                (maxX - minX + 1) * (SQSizeX + WALL_THICKNESS) - WALL_THICKNESS,
                (maxY - minY + 1) * (SQSizeY + WALL_THICKNESS) - WALL_THICKNESS)

            isInSelectionMode = True
            Cursor = Cursors.Cross
            picGame.Invalidate()
        End If
    End Sub

    Private Sub ctmMenu_Opened(sender As Object, e As EventArgs) Handles ctmMenu.Opened
        AddHandler ctmMenu.Closed, AddressOf ctmMenu_Closed
    End Sub

    Private Sub ctmMenu_Closed(sender As Object, e As ToolStripDropDownClosedEventArgs)
        If isInSelectionMode Then
            Dim menuPosition = picGame.PointToClient(MousePosition)
            ctmMenu.Show(picGame, menuPosition)
        End If
    End Sub

    Private Sub mnuCancel_Click(sender As Object, e As EventArgs) Handles mnuCancel.Click
        isInSelectionMode = False
        isSelectionReadyToDrag = False
        Cursor = Cursors.Default
        picGame.Invalidate()
    End Sub

    Private Sub mnuFill_Click(sender As Object, e As EventArgs) Handles mnuFillBlocks.Click, mnuFillBlockStoppers.Click, mnuFillCoins.Click, mnuFIllEdge.Click, mnuFillKeys.Click, mnuFillWalls.Click
        If Not isRestoringState Then SaveStateForUndo()
        If selectionRectangle.IsEmpty Then
            MessageBox.Show("Please select an area before using the fill operation.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End If

        ' Extract the selection type from the sender's name
        Dim menuItem = CType(sender, ToolStripMenuItem)
        Dim selectionType = menuItem.Name.Substring(7) ' Remove the "mnuFill" prefix

        ' Call the appropriate fill method based on the selection type
        Select Case selectionType
            Case "Edge"
                FillSelectedAreaWithEdge()
            Case "Walls"
                FillSelectedAreaWithWalls()
            Case "BlockStoppers"
                FillSelectedAreaWithItems("picBlockStopper1")
            Case "Blocks"
                FillSelectedAreaWithItems("picBlock1")
            Case "Coins"
                FillSelectedAreaWithItems("picCoin")
            Case "Keys"
                FillSelectedAreaWithItems("picKey")
            Case Else
                MessageBox.Show($"Invalid selection type for fill operation: {selectionType}.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Select
    End Sub

    Private Sub mnuClear_Click(sender As Object, e As EventArgs) Handles mnuClearAll.Click, mnuClearBaddies.Click, mnuClearBlocks.Click, mnuClearBlockStoppers.Click, mnuClearCoins.Click, mnuClearEdge.Click, mnuClearKeys.Click, mnuClearWalls.Click, mnuClearWarps.Click
        If Not isRestoringState Then SaveStateForUndo()
        If selectionRectangle.IsEmpty Then
            Return
        End If

        ' Extract the selection type from the sender's name
        Dim menuItem = CType(sender, ToolStripMenuItem)
        Dim selectionType = menuItem.Name.Substring(8) ' Remove the "mnuClear" prefix

        ' Call the appropriate clear method based on the selection type
        Select Case selectionType
            Case "All"
                ClearSelectedArea()
            Case "Edge"
                ClearSelectedAreaEdge()
            Case "Walls"
                ClearSelectedAreaWalls()
            Case Else
                ClearSelectedAreaItems(GetItemKeysForType(selectionType))
        End Select
    End Sub

    Private Sub mnuCopy_Click(sender As Object, e As EventArgs) Handles mnuCopyAll.Click, mnuCopyBaddies.Click, mnuCopyBlocks.Click, mnuCopyBlockStoppers.Click, mnuCopyCoins.Click, mnuCopyEdge.Click, mnuCopyKeys.Click, mnuCopyWalls.Click, mnuCopyWarps.Click
        If Not isRestoringState Then SaveStateForUndo()
        If selectionRectangle.IsEmpty Then
            Return
        End If

        CaptureSelectionData()
        copiedSelectionData = CloneSelectionData(selectionData)
        isCopying = True

        ' Extract the selection type from the sender's name
        Dim menuItem = CType(sender, ToolStripMenuItem)
        copiedSelectionType = menuItem.Name.Substring(7) ' Remove the "mnuCopy" prefix

        ' Automatically start dragging the selection
        isSelectionReadyToDrag = True
        isDraggingSelection = True
        selectionOffset = New Point(Cursor.Position.X - picGame.PointToScreen(selectionRectangle.Location).X, Cursor.Position.Y - picGame.PointToScreen(selectionRectangle.Location).Y)
        picGame.Capture = True
        Cursor = Cursors.SizeAll
        picGame.Invalidate()
    End Sub

    Private Sub mnuMove_Click(sender As Object, e As EventArgs) Handles mnuMoveAll.Click, mnuMoveBaddies.Click, mnuMoveBlocks.Click, mnuMoveBlockStoppers.Click, mnuMoveCoins.Click, mnuMoveEdge.Click, mnuMoveKeys.Click, mnuMoveWalls.Click, mnuMoveWarps.Click
        If Not isRestoringState Then SaveStateForUndo()
        If selectionRectangle.IsEmpty Then
            Return
        End If

        CaptureSelectionData()
        isCopying = False

        ' Extract the selection type from the sender's name
        Dim menuItem = CType(sender, ToolStripMenuItem)
        copiedSelectionType = menuItem.Name.Substring(6) ' Remove the "mnuMove" prefix

        ' Automatically start dragging the selection
        isSelectionReadyToDrag = True
        isDraggingSelection = True
        selectionOffset = New Point(Cursor.Position.X - picGame.PointToScreen(selectionRectangle.Location).X, Cursor.Position.Y - picGame.PointToScreen(selectionRectangle.Location).Y)
        picGame.Capture = True
        Cursor = Cursors.SizeAll
        picGame.Invalidate()
    End Sub

    Private Sub CaptureSelectionData()
        If selectionRectangle.IsEmpty Then
            Return
        End If

        ' Get start and end cell indices from selection rectangle
        Dim startCellX As Integer = (selectionRectangle.X - INDENT + WALL_THICKNESS \ 2) \ (SQSizeX + WALL_THICKNESS)
        Dim startCellY As Integer = (selectionRectangle.Y - INDENT + WALL_THICKNESS \ 2) \ (SQSizeY + WALL_THICKNESS)
        Dim endCellX As Integer = ((selectionRectangle.Right - INDENT - WALL_THICKNESS \ 2 - 1)) \ (SQSizeX + WALL_THICKNESS)
        Dim endCellY As Integer = ((selectionRectangle.Bottom - INDENT - WALL_THICKNESS \ 2 - 1)) \ (SQSizeY + WALL_THICKNESS)

        startCellX = Math.Max(0, Math.Min(SQCOUNTX - 1, startCellX))
        startCellY = Math.Max(0, Math.Min(SQCOUNTY - 1, startCellY))
        endCellX = Math.Max(0, Math.Min(SQCOUNTX - 1, endCellX))
        endCellY = Math.Max(0, Math.Min(SQCOUNTY - 1, endCellY))

        Dim selectionWidth As Integer = endCellX - startCellX + 1
        Dim selectionHeight As Integer = endCellY - startCellY + 1

        ' Initialize selectionData
        selectionData = New SelectionData()
        selectionData.selectionWidth = selectionWidth
        selectionData.selectionHeight = selectionHeight

        ' Capture placed items and floor edge styles
        selectionData.placedItems = New PlacedItem(selectionWidth - 1)() {}
        selectionData.floorsUseEdgeStyle = New Boolean(selectionWidth - 1)() {}
        For x As Integer = 0 To selectionWidth - 1
            selectionData.placedItems(x) = New PlacedItem(selectionHeight - 1) {}
            selectionData.floorsUseEdgeStyle(x) = New Boolean(selectionHeight - 1) {}
            For y As Integer = 0 To selectionHeight - 1
                selectionData.placedItems(x)(y) = placedItems(startCellX + x)(startCellY + y)
                selectionData.floorsUseEdgeStyle(x)(y) = floorsUseEdgeStyle(startCellX + x)(startCellY + y)
            Next
        Next

        ' Capture internal vertical walls (excluding boundary walls)
        If selectionWidth > 1 Then
            Dim numVertWalls As Integer = selectionWidth - 2
            selectionData.verticalWalls = New Boolean(numVertWalls)() {}
            selectionData.verticalWallItems = New PlacedItem(numVertWalls)() {}
            For x As Integer = 0 To numVertWalls
                selectionData.verticalWalls(x) = New Boolean(selectionHeight - 1) {}
                selectionData.verticalWallItems(x) = New PlacedItem(selectionHeight - 1) {}
                For y As Integer = 0 To selectionHeight - 1
                    selectionData.verticalWalls(x)(y) = verticalWalls(startCellX + x + 1)(startCellY + y)
                    selectionData.verticalWallItems(x)(y) = verticalWallItems(startCellX + x + 1)(startCellY + y)
                Next
            Next
        Else
            ' No internal vertical walls to capture
            selectionData.verticalWalls = Nothing
            selectionData.verticalWallItems = Nothing
        End If

        ' Capture internal horizontal walls (excluding boundary walls)
        If selectionHeight > 1 Then
            Dim numHorizWalls As Integer = selectionHeight - 2
            selectionData.horizontalWalls = New Boolean(selectionWidth - 1)() {}
            selectionData.horizontalWallItems = New PlacedItem(selectionWidth - 1)() {}
            For x As Integer = 0 To selectionWidth - 1
                selectionData.horizontalWalls(x) = New Boolean(numHorizWalls) {}
                selectionData.horizontalWallItems(x) = New PlacedItem(numHorizWalls) {}
                For y As Integer = 0 To numHorizWalls
                    selectionData.horizontalWalls(x)(y) = horizontalWalls(startCellX + x)(startCellY + y + 1)
                    selectionData.horizontalWallItems(x)(y) = horizontalWallItems(startCellX + x)(startCellY + y + 1)
                Next
            Next
        Else
            ' No internal horizontal walls to capture
            selectionData.horizontalWalls = Nothing
            selectionData.horizontalWallItems = Nothing
        End If

        ' Store the selection start cell
        selectionStartCell = New Point(startCellX, startCellY)
    End Sub

    Private Function CloneSelectionData(original As SelectionData) As SelectionData
        Dim clone As New SelectionData()
        clone.selectionWidth = original.selectionWidth
        clone.selectionHeight = original.selectionHeight

        ' Clone placedItems
        If original.placedItems IsNot Nothing Then
            clone.placedItems = original.placedItems.Select(Function(row) row.ToArray()).ToArray()
        End If

        ' Clone floorsUseEdgeStyle
        If original.floorsUseEdgeStyle IsNot Nothing Then
            clone.floorsUseEdgeStyle = original.floorsUseEdgeStyle.Select(Function(row) row.ToArray()).ToArray()
        End If

        ' Clone verticalWalls and verticalWallItems
        If original.verticalWalls IsNot Nothing Then
            clone.verticalWalls = original.verticalWalls.Select(Function(row) CType(row.Clone(), Boolean())).ToArray()
        End If

        If original.verticalWallItems IsNot Nothing Then
            clone.verticalWallItems = original.verticalWallItems.Select(Function(row) row.ToArray()).ToArray()
        End If

        ' Clone horizontalWalls and horizontalWallItems
        If original.horizontalWalls IsNot Nothing Then
            clone.horizontalWalls = original.horizontalWalls.Select(Function(row) CType(row.Clone(), Boolean())).ToArray()
        End If

        If original.horizontalWallItems IsNot Nothing Then
            clone.horizontalWallItems = original.horizontalWallItems.Select(Function(row) row.ToArray()).ToArray()
        End If

        Return clone
    End Function

    Private Sub PasteSelectionDataTo(newCellX As Integer, newCellY As Integer)
        If copiedSelectionData Is Nothing Then
            Return
        End If

        ' Ensure the new position is within bounds
        newCellX = Math.Max(0, Math.Min(SQCOUNTX - copiedSelectionData.selectionWidth, newCellX))
        newCellY = Math.Max(0, Math.Min(SQCOUNTY - copiedSelectionData.selectionHeight, newCellY))

        ' Paste placed items and floor edge styles
        For x As Integer = 0 To copiedSelectionData.selectionWidth - 1
            For y As Integer = 0 To copiedSelectionData.selectionHeight - 1
                If newCellX + x < SQCOUNTX AndAlso newCellY + y < SQCOUNTY Then
                    placedItems(newCellX + x)(newCellY + y) = copiedSelectionData.placedItems(x)(y)
                    floorsUseEdgeStyle(newCellX + x)(newCellY + y) = copiedSelectionData.floorsUseEdgeStyle(x)(y)
                End If
            Next
        Next

        ' Paste internal vertical walls, if any
        If copiedSelectionData.verticalWalls IsNot Nothing Then
            For x As Integer = 0 To copiedSelectionData.verticalWalls.Length - 1
                For y As Integer = 0 To copiedSelectionData.verticalWalls(x).Length - 1
                    Dim targetX As Integer = newCellX + x + 1
                    Dim targetY As Integer = newCellY + y

                    If targetX >= 0 AndAlso targetX < verticalWalls.Length AndAlso targetY >= 0 AndAlso targetY < verticalWalls(0).Length Then
                        verticalWalls(targetX)(targetY) = copiedSelectionData.verticalWalls(x)(y)
                        verticalWallItems(targetX)(targetY) = copiedSelectionData.verticalWallItems(x)(y)
                    End If
                Next
            Next
        End If

        ' Paste internal horizontal walls, if any
        If copiedSelectionData.horizontalWalls IsNot Nothing Then
            For x As Integer = 0 To copiedSelectionData.horizontalWalls.Length - 1
                For y As Integer = 0 To copiedSelectionData.horizontalWalls(x).Length - 1
                    Dim targetX As Integer = newCellX + x
                    Dim targetY As Integer = newCellY + y + 1

                    If targetX >= 0 AndAlso targetX < horizontalWalls.Length AndAlso targetY >= 0 AndAlso targetY < horizontalWalls(0).Length Then
                        horizontalWalls(targetX)(targetY) = copiedSelectionData.horizontalWalls(x)(y)
                        horizontalWallItems(targetX)(targetY) = copiedSelectionData.horizontalWallItems(x)(y)
                    End If
                Next
            Next
        End If

        ' Update the selection rectangle to the new position
        selectionRectangle = New Rectangle(
            INDENT + newCellX * (SQSizeX + WALL_THICKNESS) + WALL_THICKNESS \ 2,
            INDENT + newCellY * (SQSizeY + WALL_THICKNESS) + WALL_THICKNESS \ 2,
            copiedSelectionData.selectionWidth * (SQSizeX + WALL_THICKNESS) - WALL_THICKNESS,
            copiedSelectionData.selectionHeight * (SQSizeY + WALL_THICKNESS) - WALL_THICKNESS
        )

        picGame.Invalidate()
    End Sub

    Private Sub MoveSelectionDataTo(newCellX As Integer, newCellY As Integer)
        ' Ensure the new position is within bounds
        newCellX = Math.Max(0, Math.Min(SQCOUNTX - selectionData.selectionWidth, newCellX))
        newCellY = Math.Max(0, Math.Min(SQCOUNTY - selectionData.selectionHeight, newCellY))

        ' Move placed items and floor edge styles
        For x As Integer = 0 To selectionData.selectionWidth - 1
            For y As Integer = 0 To selectionData.selectionHeight - 1
                Dim targetX As Integer = newCellX + x
                Dim targetY As Integer = newCellY + y
                Dim sourceX As Integer = selectionStartCell.X + x
                Dim sourceY As Integer = selectionStartCell.Y + y

                If targetX >= 0 AndAlso targetX < SQCOUNTX AndAlso targetY >= 0 AndAlso targetY < SQCOUNTY Then
                    placedItems(targetX)(targetY) = selectionData.placedItems(x)(y)
                    floorsUseEdgeStyle(targetX)(targetY) = selectionData.floorsUseEdgeStyle(x)(y)
                End If
                ' Clear original location
                placedItems(sourceX)(sourceY) = Nothing
                floorsUseEdgeStyle(sourceX)(sourceY) = False
            Next
        Next

        ' Move internal vertical walls, if any
        If selectionData.verticalWalls IsNot Nothing Then
            For x As Integer = 0 To selectionData.verticalWalls.Length - 1
                For y As Integer = 0 To selectionData.verticalWalls(x).Length - 1
                    Dim targetX As Integer = newCellX + x + 1
                    Dim targetY As Integer = newCellY + y
                    Dim sourceX As Integer = selectionStartCell.X + x + 1
                    Dim sourceY As Integer = selectionStartCell.Y + y

                    If targetX >= 0 AndAlso targetX < verticalWalls.Length AndAlso targetY >= 0 AndAlso targetY < verticalWalls(0).Length Then
                        verticalWalls(targetX)(targetY) = selectionData.verticalWalls(x)(y)
                        verticalWallItems(targetX)(targetY) = selectionData.verticalWallItems(x)(y)
                    End If
                    ' Clear original location
                    verticalWalls(sourceX)(sourceY) = True
                    verticalWallItems(sourceX)(sourceY) = Nothing
                Next
            Next
        End If

        ' Move internal horizontal walls, if any
        If selectionData.horizontalWalls IsNot Nothing Then
            For x As Integer = 0 To selectionData.horizontalWalls.Length - 1
                For y As Integer = 0 To selectionData.horizontalWalls(x).Length - 1
                    Dim targetX As Integer = newCellX + x
                    Dim targetY As Integer = newCellY + y + 1
                    Dim sourceX As Integer = selectionStartCell.X + x
                    Dim sourceY As Integer = selectionStartCell.Y + y + 1

                    If targetX >= 0 AndAlso targetX < horizontalWalls.Length AndAlso targetY >= 0 AndAlso targetY < horizontalWalls(0).Length Then
                        horizontalWalls(targetX)(targetY) = selectionData.horizontalWalls(x)(y)
                        horizontalWallItems(targetX)(targetY) = selectionData.horizontalWallItems(x)(y)
                    End If
                    ' Clear original location
                    horizontalWalls(sourceX)(sourceY) = True
                    horizontalWallItems(sourceX)(sourceY) = Nothing
                Next
            Next
        End If

        ' Update the selection rectangle to the new position
        selectionRectangle = New Rectangle(
            INDENT + newCellX * (SQSizeX + WALL_THICKNESS) + WALL_THICKNESS \ 2,
            INDENT + newCellY * (SQSizeY + WALL_THICKNESS) + WALL_THICKNESS \ 2,
            selectionData.selectionWidth * (SQSizeX + WALL_THICKNESS) - WALL_THICKNESS,
            selectionData.selectionHeight * (SQSizeY + WALL_THICKNESS) - WALL_THICKNESS
        )

        ' Update the selection start cell to the new location
        selectionStartCell = New Point(newCellX, newCellY)

        ' Invalidate the picGame control to refresh the display
        picGame.Invalidate()
    End Sub

    Private Sub DrawSelectionData(g As Graphics, baseCellX As Integer, baseCellY As Integer, data As SelectionData)
        Dim xOrigin As Integer = INDENT
        Dim yOrigin As Integer = INDENT

        Dim colorMatrix As New Imaging.ColorMatrix()
        colorMatrix.Matrix33 = 0.5F  ' Set opacity to 50%
        Dim imgAttributes As New Imaging.ImageAttributes()
        imgAttributes.SetColorMatrix(colorMatrix, Imaging.ColorMatrixFlag.Default, Imaging.ColorAdjustType.Bitmap)

        For x As Integer = 0 To data.selectionWidth - 1
            For y As Integer = 0 To data.selectionHeight - 1
                If data.placedItems(x)(y) IsNot Nothing Then
                    Dim img As Image = GetImageByKey(data.placedItems(x)(y).ImageKey)
                    If img IsNot Nothing Then
                        ImageAnimator.UpdateFrames(img)
                        Dim xPos As Integer = xOrigin + (baseCellX + x) * (SQSizeX + WALL_THICKNESS) + WALL_THICKNESS \ 2
                        Dim yPos As Integer = yOrigin + (baseCellY + y) * (SQSizeY + WALL_THICKNESS) + WALL_THICKNESS \ 2
                        Dim destRect As New Rectangle(xPos, yPos, SQSizeX, SQSizeY)
                        g.DrawImage(img, destRect, 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, imgAttributes)
                    End If
                End If
            Next
        Next
    End Sub

    Private Sub FillSelectedAreaWithEdge()
        CaptureSelectionData()
        For x As Integer = 0 To selectionData.selectionWidth - 1
            For y As Integer = 0 To selectionData.selectionHeight - 1
                If selectionStartCell.X + x < SQCOUNTX AndAlso selectionStartCell.Y + y < SQCOUNTY Then
                    floorsUseEdgeStyle(selectionStartCell.X + x)(selectionStartCell.Y + y) = True
                End If
            Next
        Next
        For x As Integer = 0 To selectionData.selectionWidth
            For y As Integer = 0 To selectionData.selectionHeight - 1
                If selectionStartCell.X + x < verticalWalls.Length AndAlso selectionStartCell.Y + y < verticalWalls(0).Length Then
                    verticalWalls(selectionStartCell.X + x)(selectionStartCell.Y + y) = True
                End If
            Next
        Next
        For x As Integer = 0 To selectionData.selectionWidth - 1
            For y As Integer = 0 To selectionData.selectionHeight
                If selectionStartCell.X + x < horizontalWalls.Length AndAlso selectionStartCell.Y + y < horizontalWalls(0).Length Then
                    horizontalWalls(selectionStartCell.X + x)(selectionStartCell.Y + y) = True
                End If
            Next
        Next
        picGame.Invalidate()
    End Sub

    Private Sub FillSelectedAreaWithWalls()
        If selectionData Is Nothing Then
            CaptureSelectionData()
        End If

        ' Fill internal vertical walls
        For x As Integer = 0 To selectionData.selectionWidth - 2
            For y As Integer = 0 To selectionData.selectionHeight - 1
                Dim wallX As Integer = selectionStartCell.X + x + 1
                Dim wallY As Integer = selectionStartCell.Y + y

                If wallX >= 0 AndAlso wallX < verticalWalls.Length AndAlso wallY >= 0 AndAlso wallY < verticalWalls(0).Length Then
                    verticalWalls(wallX)(wallY) = True
                End If
            Next
        Next

        ' Fill internal horizontal walls
        For x As Integer = 0 To selectionData.selectionWidth - 1
            For y As Integer = 0 To selectionData.selectionHeight - 2
                Dim wallX As Integer = selectionStartCell.X + x
                Dim wallY As Integer = selectionStartCell.Y + y + 1

                If wallX >= 0 AndAlso wallX < horizontalWalls.Length AndAlso wallY >= 0 AndAlso wallY < horizontalWalls(0).Length Then
                    horizontalWalls(wallX)(wallY) = True
                End If
            Next
        Next

        picGame.Invalidate()
    End Sub

    Private Sub FillSelectedAreaWithItems(itemKey As String)
        CaptureSelectionData()
        For x As Integer = 0 To selectionData.selectionWidth - 1
            For y As Integer = 0 To selectionData.selectionHeight - 1
                If selectionStartCell.X + x < placedItems.Length AndAlso selectionStartCell.Y + y < placedItems(0).Length Then
                    placedItems(selectionStartCell.X + x)(selectionStartCell.Y + y) = New PlacedItem() With {.ImageKey = itemKey}
                End If
            Next
        Next
        picGame.Invalidate()
    End Sub

    Private Sub ClearSelectedArea()
        If selectionData Is Nothing Then
            CaptureSelectionData()
        End If

        ' Clear placed items and floor edge styles
        For x As Integer = 0 To selectionData.selectionWidth - 1
            For y As Integer = 0 To selectionData.selectionHeight - 1
                placedItems(selectionStartCell.X + x)(selectionStartCell.Y + y) = Nothing
                floorsUseEdgeStyle(selectionStartCell.X + x)(selectionStartCell.Y + y) = False
            Next
        Next

        ' Clear internal vertical walls
        For x As Integer = 0 To selectionData.selectionWidth - 2
            For y As Integer = 0 To selectionData.selectionHeight - 1
                verticalWalls(selectionStartCell.X + x + 1)(selectionStartCell.Y + y) = False
                verticalWallItems(selectionStartCell.X + x + 1)(selectionStartCell.Y + y) = Nothing
            Next
        Next

        ' Clear internal horizontal walls
        For x As Integer = 0 To selectionData.selectionWidth - 1
            For y As Integer = 0 To selectionData.selectionHeight - 2
                horizontalWalls(selectionStartCell.X + x)(selectionStartCell.Y + y + 1) = False
                horizontalWallItems(selectionStartCell.X + x)(selectionStartCell.Y + y + 1) = Nothing
            Next
        Next

        picGame.Invalidate()
    End Sub

    Private Sub ClearSelectedAreaEdge()
        CaptureSelectionData()
        For x As Integer = 0 To selectionData.selectionWidth - 1
            For y As Integer = 0 To selectionData.selectionHeight - 1
                If selectionStartCell.X + x < SQCOUNTX AndAlso selectionStartCell.Y + y < SQCOUNTY Then
                    floorsUseEdgeStyle(selectionStartCell.X + x)(selectionStartCell.Y + y) = False
                End If
            Next
        Next
        picGame.Invalidate()
    End Sub

    Private Sub ClearSelectedAreaWalls()
        If selectionData Is Nothing Then
            CaptureSelectionData()
        End If

        ' Clear internal vertical walls
        For x As Integer = 0 To selectionData.selectionWidth - 2
            For y As Integer = 0 To selectionData.selectionHeight - 1
                Dim wallX As Integer = selectionStartCell.X + x + 1
                Dim wallY As Integer = selectionStartCell.Y + y

                ' Ensure indices are within bounds
                If wallX >= 0 AndAlso wallX < verticalWalls.Length AndAlso wallY >= 0 AndAlso wallY < verticalWalls(0).Length Then
                    verticalWalls(wallX)(wallY) = False
                    verticalWallItems(wallX)(wallY) = Nothing
                End If
            Next
        Next

        ' Clear internal horizontal walls
        For x As Integer = 0 To selectionData.selectionWidth - 1
            For y As Integer = 0 To selectionData.selectionHeight - 2
                Dim wallX As Integer = selectionStartCell.X + x
                Dim wallY As Integer = selectionStartCell.Y + y + 1

                ' Ensure indices are within bounds
                If wallX >= 0 AndAlso wallX < horizontalWalls.Length AndAlso wallY >= 0 AndAlso wallY < horizontalWalls(0).Length Then
                    horizontalWalls(wallX)(wallY) = False
                    horizontalWallItems(wallX)(wallY) = Nothing
                End If
            Next
        Next

        picGame.Invalidate()
    End Sub

    Private Sub ClearSelectedAreaItems(ParamArray itemKeys As String())
        CaptureSelectionData()
        For x As Integer = 0 To selectionData.selectionWidth - 1
            Dim localX As Integer = x
            For y As Integer = 0 To selectionData.selectionHeight - 1
                Dim localY As Integer = y
                If selectionStartCell.X + localX < placedItems.Length AndAlso selectionStartCell.Y + localY < placedItems(0).Length Then
                    If placedItems(selectionStartCell.X + localX)(selectionStartCell.Y + localY) IsNot Nothing AndAlso Array.Exists(itemKeys, Function(key) placedItems(selectionStartCell.X + localX)(selectionStartCell.Y + localY).ImageKey = key) Then
                        placedItems(selectionStartCell.X + localX)(selectionStartCell.Y + localY) = Nothing
                    End If
                End If
            Next
        Next
        picGame.Invalidate()
    End Sub

    Private Function GetItemKeysForType(type As String) As String()
        Select Case type
            Case "Baddies"
                Return New String() {"picBaddy1", "picBaddy2", "picBaddy3", "picBaddy4"}
            Case "BlockStoppers"
                Return New String() {"picBlockStopper1"}
            Case "Blocks"
                Return New String() {"picBlock1"}
            Case "Coins"
                Return New String() {"picCoin"}
            Case "Keys"
                Return New String() {"picKey"}
            Case "Warps"
                Return New String() {"picWarp", "picWarp2"}
            Case "Walls"
                Return New String() {}
            Case "Edge"
                Return New String() {}
            Case Else
                Return New String() {}
        End Select
    End Function
End Class


Can you help with mnuMove. 

It's very buggy. 

1 problem at a time. 

When I've finidhed moving the selected area. It moves to where my cursor is and not where the selection ends up and the selection box disappears after the move. The selection box should only go away when I either left click out of the secltion box or click cancel or click btnSelect for a second time. 

if you need the code from frmDesigner PLEASE let me know