Imports System.Text
Public Class ctlSelezionaNumeri
    Private mQNumeriPerRiga As Integer = 9
    Private mQNumeri As Integer = 90
    Private mFontNumeri As Font = New Font("Arial", 8)
    Private mBackColorSelected As Color = Color.Red
    Private mForeColorSelected As Color = Color.White
    Private mAttivaSelezione As Boolean = True
    ' Private aColoreNumeri() As struct_colore_numeri
    Private aChk() As clsMyChkeBox
    Event OnChange(ByVal Num As Integer)
    Event OnCheckDoubleClick(ByVal Num As Integer)
    Public Overrides Property ForeColor() As System.Drawing.Color
        Get
            Return MyBase.ForeColor
        End Get
        Set(ByVal value As System.Drawing.Color)
            MyBase.ForeColor = value
            LoadPulsanti()
        End Set
    End Property
    Public Overrides Property BackColor() As System.Drawing.Color
        Get
            Return MyBase.BackColor
        End Get
        Set(ByVal value As System.Drawing.Color)
            MyBase.BackColor = value
            LoadPulsanti()
        End Set
    End Property
    Public Property AttivaSelezione() As Boolean
        Get
            Return mAttivaSelezione
        End Get
        Set(ByVal value As Boolean)
            mAttivaSelezione = value
        End Set
    End Property
    Public Property ForeColorSelected() As Color
        Get
            Return mForeColorSelected
        End Get
        Set(ByVal value As Color)
            mForeColorSelected = value
            LoadPulsanti()
        End Set
    End Property
    Public Property BackColorSelected() As Color
        Get
            Return mBackColorSelected
        End Get
        Set(ByVal value As Color)
            mBackColorSelected = value
            LoadPulsanti()
        End Set
    End Property
    Public ReadOnly Property QNumeriSelezionati() As Integer
        Get
            Dim q As Integer = 0
            For k As Integer = 1 To mQNumeri
                If aChk(k).Checked Then q += 1
            Next
            Return q
        End Get
    End Property
    Public Property FontNumeri() As Font
        Get
            Return mFontNumeri
        End Get
        Set(ByVal value As Font)
            mFontNumeri = value
            LoadPulsanti()
        End Set
    End Property
    Public Property QNumeri() As Integer
        Get
            Return mQNumeri
        End Get
        Set(ByVal value As Integer)
            If value > 0 And value <= 90 Then
                mQNumeri = value
                LoadPulsanti()
            End If
        End Set
    End Property
    Public Property QNumeriPerRiga() As Integer
        Get
            Return mQNumeriPerRiga
        End Get
        Set(ByVal value As Integer)
            If value > 0 And value <= 10 And mQNumeri Mod value = 0 Then
                mQNumeriPerRiga = value
                LoadPulsanti()
            End If
        End Set
    End Property
    Private Sub ctlSelezionaNumeri_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
        LoadPulsanti()
    End Sub
    Private Sub LoadPulsante(ByVal Num As Integer, ByVal Value As Boolean, ByVal nIndex As Integer, ByVal nX As Integer, ByVal nY As Integer, ByVal nW As Integer, ByVal nH As Integer, ByVal nBackColor As Color, ByVal nForeColor As Color)
        aChk(Num) = New clsMyChkeBox
        aChk(Num).AutoSize = False
        aChk(Num).BorderStyle = Windows.Forms.BorderStyle.Fixed3D
        aChk(Num).Font = mFontNumeri
        aChk(Num).Top = nY
        aChk(Num).Left = nX
        aChk(Num).Width = nW
        aChk(Num).Height = nH
        aChk(Num).Parent = Me
        aChk(Num).Text = Num
        aChk(Num).Index = nIndex
        aChk(Num).BackColor = nBackColor
        aChk(Num).ForeColor = nForeColor
        aChk(Num).BackColorSelected = mBackColorSelected
        aChk(Num).ForeColorSelected = mForeColorSelected
        aChk(Num).TextAlign = ContentAlignment.MiddleCenter
        aChk(Num).Checked = Value
        aChk(Num).Visible = True
        AddHandler aChk(Num).Click, AddressOf CheckBox_CheckedChanged
        AddHandler aChk(Num).DoubleClick, AddressOf CheckBox_DoubleClik
    End Sub
    Private Sub CheckBox_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
        If mAttivaSelezione Then
            Dim c As clsMyChkeBox = DirectCast(sender, clsMyChkeBox)
            c.Checked = Not c.Checked
            RaiseEvent OnChange(DirectCast(sender, clsMyChkeBox).Index)
        End If
    End Sub
    Private Sub CheckBox_DoubleClik(ByVal sender As System.Object, ByVal e As System.EventArgs)
        RaiseEvent OnCheckDoubleClick(DirectCast(sender, clsMyChkeBox).Index)
    End Sub
    Private Sub LoadPulsanti()
        Dim N As Integer = 0
        Dim nX As Integer, nY As Integer, nH As Integer, nW As Integer
        Try
            Me.Controls.Clear()
            ReDim aChk(0)
            If mQNumeri > 0 AndAlso mQNumeriPerRiga > 0 Then
                ReDim aChk(mQNumeri)
                nW = (Me.Width / mQNumeriPerRiga)
                nH = (Me.ClientRectangle.Height / (mQNumeri / mQNumeriPerRiga))
                nX = 0
                nY = 0
                Do
                    nX = 0
                    For r As Integer = 1 To mQNumeriPerRiga
                        N += 1
                        LoadPulsante(N, False, N, nX, nY, nW, nH, Me.BackColor, Me.ForeColor)
                        nX += nW
                        If N >= mQNumeri Then Exit For
                    Next
                    nY += nH
                    If N >= mQNumeri Then Exit Do
                Loop
            End If
        Catch ex As Exception
        End Try
    End Sub
    Function GetStringaNumeri(Optional ByVal sChrSep As String = ",") As String
        Dim s As String = ""
        For k As Integer = 1 To mQNumeri
            If aChk(k).Checked Then
                s = s & k.ToString & sChrSep
            End If
        Next
        If s <> "" Then
            Return s.Substring(0, s.Length - 1)
        End If
    End Function
    Function GetValue(ByVal Num As Integer) As Boolean
        If Num > 0 AndAlso Num <= mQNumeri Then
            Return aChk(Num).Checked
        End If
    End Function
    Sub SetValue(ByVal Num As Integer, ByVal value As Boolean)
        If Num > 0 AndAlso Num <= mQNumeri Then
            aChk(Num).Checked = value
            RaiseEvent OnChange(Num)
        End If
    End Sub
    Sub SetValueFromStringaNum(ByVal sNumeri As String, Optional ByVal bValue As Boolean = True)
        Dim sValue As String = ""
        Dim sChr As String
        Dim n As Integer
        For k As Integer = 0 To sNumeri.Length - 1
            sChr = sNumeri.Substring(k, 1)
            If IsNumeric(sChr) Then
                sValue = sValue & sChr
            Else
                Try
                    n = Convert.ToInt32(sValue)
                    If n > 0 AndAlso n <= mQNumeri Then
                        SetValue(n, bValue)
                    End If
                    sValue = ""
                Catch ex As Exception
                End Try
            End If
        Next
        If sValue <> "" Then
            Try
                n = Convert.ToInt32(sValue)
                If n > 0 AndAlso n <= mQNumeri Then
                    SetValue(n, bValue)
                End If
            Catch ex As Exception
            End Try
        End If
    End Sub
    Sub SetColore(ByVal num As Integer, ByVal BackColor As Color, ByVal ForeColor As Color)
        If num > 0 AndAlso num <= mQNumeri Then
            aChk(num).BackColor = BackColor
            aChk(num).ForeColor = ForeColor
        End If
    End Sub
    Function GetColore(ByVal num As Integer, ByRef BackColor As Color, ByRef ForeColor As Color) As Boolean
        If num > 0 AndAlso num <= mQNumeri Then
            BackColor = aChk(num).BackColor
            ForeColor = aChk(num).ForeColor
            Return True
        End If
    End Function
    Function GetArrayNumSelezionati(ByRef aRetNum() As Integer) As Integer
        Dim q As Integer
        ReDim aRetNum(mQNumeri)
        For k As Integer = 1 To mQNumeri
            If aChk(k).Checked Then
                q = q + 1
                aRetNum(q) = k
            End If
        Next
        ReDim Preserve aRetNum(q)
        Return q
    End Function
    Function GetArrayNumSelezionati(ByRef aRetNum() As Boolean) As Integer
        Dim q As Integer
        ReDim aRetNum(mQNumeri)
        For k As Integer = 1 To mQNumeri
            If aChk(k).Checked Then
                q = q + 1
                aRetNum(k) = True
            End If
        Next
        Return q
    End Function
    Function GetArrayColoriWin32(ByRef aRetBackColor() As Integer, ByRef aRetForeColor() As Integer) As Boolean
        If mQNumeri > 0 Then
            ReDim aRetBackColor(mQNumeri)
            ReDim aRetForeColor(mQNumeri)
            For k As Integer = 1 To mQNumeri
                aRetBackColor(k) = System.Drawing.ColorTranslator.ToWin32(aChk(k).BackColor)
                aRetForeColor(k) = System.Drawing.ColorTranslator.ToWin32(aChk(k).ForeColor)
            Next
            Return True
        End If
    End Function
    Function SetArrayColoriWin32(ByVal aBackColor() As Integer, ByRef aForeColor() As Integer) As Boolean
        If mQNumeri > 0 Then
            Try
                For k As Integer = 1 To mQNumeri
                    aChk(k).BackColor = System.Drawing.ColorTranslator.FromWin32(aBackColor(k))
                    aChk(k).ForeColor = System.Drawing.ColorTranslator.FromWin32(aForeColor(k))
                Next
                Return True
            Catch ex As Exception
            End Try
        End If
    End Function
    Function GetStringaBackColorWin32(Optional ByVal sChrSep As Char = ";") As String
        Dim sb As New StringBuilder
        For k As Integer = 1 To mQNumeri
            sb.Append(System.Drawing.ColorTranslator.ToWin32(aChk(k).BackColor).ToString)
            sb.Append(sChrSep)
        Next
        sb.Remove(sb.Length - 1, 1)
        Return sb.ToString
    End Function
    Sub SetBackColorFromStringaColoriWin32(ByVal sColori As String, Optional ByVal sChrSep As Char = ";")
        Try
            If sColori.Trim <> "" Then
                Dim av() As String = sColori.Split(sChrSep)
                For k = 0 To UBound(av)
                    If (k + 1) <= mQNumeri Then
                        aChk(k + 1).BackColor = System.Drawing.ColorTranslator.FromWin32(Convert.ToInt32(av(k)))
                    End If
                Next
            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Errore", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub
    Function GetStringaForeColorWin32(Optional ByVal sChrSep As Char = ";") As String
        Dim sb As New StringBuilder
        For k As Integer = 1 To mQNumeri
            sb.Append(System.Drawing.ColorTranslator.ToWin32(aChk(k).ForeColor).ToString)
            sb.Append(sChrSep)
        Next
        sb.Remove(sb.Length - 1, 1)
        Return sb.ToString
    End Function
    Sub SetForeColorFromStringaColoriWin32(ByVal sColori As String, Optional ByVal sChrSep As Char = ";")
        Try
            If sColori.Trim <> "" Then
                Dim av() As String = sColori.Split(sChrSep)
                For k = 0 To UBound(av)
                    If (k + 1) <= mQNumeri Then
                        aChk(k + 1).ForeColor = System.Drawing.ColorTranslator.FromWin32(Convert.ToInt32(av(k)))
                    End If
                Next
            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Errore", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub
    Sub SelezionaTutto(Optional b As Boolean = True)
        For k As Integer = 1 To mQNumeri
            aChk(k).Checked = b
        Next
    End Sub
End Class
Public Class clsMyChkeBox
    Inherits Label
    Private mIndex As Integer
    Private mBackColorSelected As Color = Color.Red
    Private mForeColorSelected As Color = Color.White
    Private mBackColor As Color = SystemColors.Control
    Private mForeColor As Color = SystemColors.WindowText
    Private mChecked As Boolean
    Public Property Checked() As Boolean
        Get
            Return mChecked
        End Get
        Set(ByVal value As Boolean)
            mChecked = value
            If mChecked Then
                MyBase.BackColor = mBackColorSelected
                MyBase.ForeColor = mForeColorSelected
            Else
                MyBase.BackColor = mBackColor
                MyBase.ForeColor = mForeColor
            End If
        End Set
    End Property
    Public Overrides Property ForeColor() As Color
        Get
            Return MyBase.ForeColor
        End Get
        Set(ByVal value As Color)
            mForeColor = value
            MyBase.ForeColor = mForeColor
        End Set
    End Property
    Public Overrides Property BackColor() As Color
        Get
            Return MyBase.BackColor
        End Get
        Set(ByVal value As Color)
            mBackColor = value
            MyBase.BackColor = mBackColor
        End Set
    End Property
    Public Property ForeColorSelected() As Color
        Get
            Return mForeColorSelected
        End Get
        Set(ByVal value As Color)
            mForeColorSelected = value
        End Set
    End Property
    Public Property BackColorSelected() As Color
        Get
            Return mBackColorSelected
        End Get
        Set(ByVal value As Color)
            mBackColorSelected = value
        End Set
    End Property
    
    Public Property Index() As Integer
        Get
            Return mIndex
        End Get
        Set(ByVal value As Integer)
            mIndex = value
        End Set
    End Property
End Class