Grid I can paint on

前端 未结 1 1110
情歌与酒
情歌与酒 2020-12-22 02:56

So I am trying to create an application to ease creation of pixel arts (school project), what I\'ve done so far is draw a grid in a panel, next step would be to allow the us

相关标签:
1条回答
  • 2020-12-22 03:39

    This is a Grid class that allows setting the color of its cells.

    The Grid cell are referenced using a List(Of List(Of Class)).

    The Cell class Object contains is a simple Rectagle property that measures the size of the cell, and a Color property, which allows to set the color of the single cell:

    Friend Class GridCell
        Public Property Cell() As Rectangle
        Public Property CellColor() As Color
    End Class
    

    You can define:

    • The size of the Grid → ColoredGrid.GridSize = new Size(...)
    • The number of Columns and Rows → ColoredGrid.GridColumnsRows = new Size(...)
    • The position of the Grid inside the CanvasColoredGrid.GridPosition = New Point(...)
    • The color of the Grid → ColoredGrid.GridColor = Color.Gray
    • The BackGround color of the cells → ColoredGrid.CellColor = Color.FromArgb(32, 32, 32)
    • The color of a selected cell → ColoredGrid.SelectedCellColor = Color.OrangeRed


    The Grid class holds a reference to the control which will be used as the Canvas for the grid painting. This reference is set in the class contructor.
    The Grid registers the Canvas control Paint() and MouseClick() events to respond to the related actions automatically.
    When a Mouse Click is detected on the Canvas surface, the MouseEventArgs e.Location property reports the coordinates where the Click occurred.

    To identify the Grid Cell where this action is performed, the GetUpdateCell() method inspects the List(Of List(Of GridCell)) using a simple LINQ SelectMany() and identified the Cell rectangle that contains the Mouse Click coordinates (expressed as a Point() value).
    This identification is performed simply checking whether the Cell Rectangle.Contains(Point()).
    When the cell is identified, the Canvas Invalidate() method is called, specifing the area to repaint.
    This area corresponds to the Cell Rectangle, so only this section is repainted when a Cell is colored, to save resources and time.

    To test it, create a Panel and a Button in a Form:

    Imports System.Drawing
    
    'This Grid object in defined at Form Class scope 
    Public ColoredGrid As ColorGrid
    
    'Button used to trigger the Grid painting
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If ColoredGrid IsNot Nothing Then
            ColoredGrid.Dispose()
        End If
        ColoredGrid = New ColorGrid(Panel1)
        ColoredGrid.GridSize = New Size(300, 300)
        ColoredGrid.GridColumnsRows = New Size(10, 10)
        ColoredGrid.GridPosition = New Point(10, 10)
        ColoredGrid.GridColor = Color.White
        ColoredGrid.CellColor = Color.FromArgb(32, 32, 32)
        ColoredGrid.SelectedCellColor = Color.OrangeRed
        ColoredGrid.BuildGrid()
    End Sub
    

    This is a visual sample that shows how it works:


    This is the main Grid class.
    The ColorGrid Class supports IDisposable, because it registers the described events. These must be unregistered when the Class is not used anymore. Weird things can happen if you don't.

    Public Class ColorGrid
        Implements IDisposable
    
        Private Grid As List(Of List(Of GridCell))
        Private CurrentGridSize As New Size(100, 100)
        Private GridColRows As New Size(10, 10)
        Private CellSize As New Size(10, 10)
        Private MouseCell As Point = Point.Empty
        Private Canvas As Control = Nothing
        Private UpdateCell As Boolean = False
        Private NewGrid As Boolean = False
    
        Public Sub New(DrawingControl As Control)
            If DrawingControl IsNot Nothing Then
                Me.Canvas = DrawingControl
                AddHandler Me.Canvas.Paint, New PaintEventHandler(AddressOf Me.ControlPaint)
                AddHandler Me.Canvas.MouseClick, New MouseEventHandler(AddressOf Me.MouseHandler)
                Me.GridPosition = New Point(10, 10)
                Me.CellColor = Color.FromArgb(32, 32, 32)
            End If
        End Sub
    
        Public Property GridPosition() As Point
        Public Property CellColor() As Color
        Public Property SelectedCellColor() As Color
        Public Property GridColor() As Color
        Public Property GridSize() As Size
            Get
                Return Me.CurrentGridSize
            End Get
            Set(value As Size)
                Me.CurrentGridSize = value
                SetCellSize()
            End Set
        End Property
        Public Property GridColumnsRows() As Size
            Get
                Return Me.GridColRows
            End Get
            Set(value As Size)
                Me.GridColRows = value
                SetCellSize()
            End Set
        End Property
        Private Property RefreshCell() As GridCell
    
        Friend Class GridCell
            Public Property Cell() As Rectangle
            Public Property CellColor() As Color
        End Class
    
        Private Sub SetCellSize()
            Me.CellSize = New Size((Me.CurrentGridSize.Width \ Me.GridColRows.Width),
                                   (Me.CurrentGridSize.Height \ Me.GridColRows.Height))
            If Me.CellSize.Width < 4 Then Me.CellSize.Width = 4
            If Me.CellSize.Height < 4 Then Me.CellSize.Height = 4
        End Sub
    
        Public Sub BuildGrid()
            If Me.Canvas Is Nothing Then Return 
    
            Me.Grid = New List(Of List(Of GridCell))()
            For row As Integer = 0 To GridColumnsRows.Height - 1
                Dim RowCells As New List(Of GridCell)()
                For col As Integer = 0 To GridColumnsRows.Width - 1
                    RowCells.Add(New GridCell() With {
                        .Cell = New Rectangle(New Point(Me.GridPosition.X + (col * Me.CellSize.Width),
                                                        Me.GridPosition.Y + (row * Me.CellSize.Height)),
                                              Me.CellSize),
                        .CellColor = Me.CellColor})
                Next
                Me.Grid.Add(RowCells)
            Next
            Me.NewGrid = True
            Me.Canvas.Invalidate()
        End Sub
    
        Private Sub ControlPaint(o As Object, e As PaintEventArgs)
            If Me.NewGrid Then
                e.Graphics.Clear(Me.Canvas.BackColor)
                Me.NewGrid = False
            End If
    
            Me.Grid.
                SelectMany(Function(rowcells) rowcells).
                Select(Function(colcell)
                           If Me.UpdateCell Then
                               Using brush As New SolidBrush(Me.RefreshCell.CellColor)
                                   e.Graphics.FillRectangle(brush, Me.RefreshCell.Cell.X + 1, Me.RefreshCell.Cell.Y + 1,
                                                                   Me.RefreshCell.Cell.Width - 1, Me.RefreshCell.Cell.Height - 1)
                               End Using
                               Me.UpdateCell = False
                               Return Nothing
                           Else
                               Using pen As New Pen(Me.GridColor)
                                   e.Graphics.DrawRectangle(pen, colcell.Cell)
                               End Using
                               Using brush As New SolidBrush(colcell.CellColor)
                                   e.Graphics.FillRectangle(brush, colcell.Cell.X + 1, colcell.Cell.Y + 1,
                                                                   colcell.Cell.Width - 1, colcell.Cell.Height - 1)
                               End Using
                           End If
                           Return colcell
                       End Function).TakeWhile(Function(colcell) colcell IsNot Nothing).ToList()
        End Sub
    
        Private Sub MouseHandler(o As Object, e As MouseEventArgs)
            Me.RefreshCell = GetUpdateCell(e.Location)
            Me.RefreshCell.CellColor = Me.SelectedCellColor
            Dim CellColorArea As Rectangle = Me.RefreshCell.Cell
            CellColorArea.Inflate(-1, -1)
            Me.UpdateCell = True
            Me.Canvas.Invalidate(CellColorArea)
        End Sub
    
        Private Function GetUpdateCell(CellPosition As Point) As GridCell
            Return Me.Grid.
                SelectMany(Function(rowcells) rowcells).
                Select(Function(gridcell) gridcell).
                Where(Function(gridcell) gridcell.Cell.Contains(CellPosition)).
                First()
        End Function
    
        Public Sub Dispose() Implements IDisposable.Dispose
            If Me.Canvas IsNot Nothing Then
                RemoveHandler Me.Canvas.Paint, AddressOf Me.ControlPaint
                RemoveHandler Me.Canvas.MouseClick, AddressOf Me.MouseHandler
                Me.Grid = Nothing
            End If
        End Sub
    End Class
    
    0 讨论(0)
提交回复
热议问题