Option Strict Off
Option Explicit On
Imports System.Windows.Forms
'------------------------------------ 2023/11/09 ------------------------------------
Public Class 五clsCellListBox

#Region "宣言"
    Private mCell幅, mCell高, mCell数ヨコ, mCell数タテ, mCell間タテヨコ As Integer
    Private Structure セル配列要素
        Dim セル As Rectangle
        Dim MouseChk領域 As Rectangle
        Dim 使用中 As Boolean
        Dim 選択old As Boolean
        Dim 選択new As Boolean
    End Structure
    Private mセル配列(0) As セル配列要素 '0　から始まる。
    Private mセル配列MAX As Integer = 0
    Private mセル使用MAX As Integer = 0
    Private mリスト背景色 As Integer = &HFFFFFF&
    Private m選択色 As Integer = &HFF&
    Private m図形外縁枠色 As Integer = &H0&
    Private m図形外縁枠幅 As Integer = 1 : Private Const c図形外縁枠幅 As Integer = 10
    Private WithEvents 団団 As PictureBox
    Event 選択インデックスが変わりました(ByVal rIndex As Integer)
    Event カードデーターをください(ByRef wIsOK As Boolean, ByVal rカード型IDX As Integer, ByVal rセル幅 As Integer, ByVal rセル高 As Integer, ByRef wカードRGN_呼び出し元で削除する As Integer, ByRef wカードを使用している As Boolean)
    '---------------------------------------------------
    Private WithEvents 色設定Dlg As 四frmDlgカード選択ColorSet = Nothing    'Private WithEvents カード型選択Dlg_色設定Dlg As 四frmDlgカード選択ColorSet = Nothing
    '色設定Dlg から
    Event カラーが変更されました(ByVal rIndex As Integer, ByVal rColor As Integer)
    Event カラーをすべて元に戻しなさい(ByVal rColor1stt As Integer, ByVal rColor2stt As Integer, ByVal rColor3stt As Integer, ByRef wリスト背景色 As Integer, ByRef w選択色 As Integer, ByRef w図形外縁枠色 As Integer)
    Event カラーを規定値にリセットしなさい(ByRef wリスト背景色 As Integer, ByRef w選択色 As Integer, ByRef w図形外縁枠色 As Integer)
    Event メニューのEnabledデーターをください(ByRef w元に戻す As Boolean, ByRef w規定値にリセット As Boolean, ByVal rColor1stt As Integer, ByVal rColor2stt As Integer, ByVal rColor3stt As Integer)
    '---------------------------------------------------
#End Region

#Region "初期化"
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Function セルリスト作成と初期化(ByVal rParent As Control, ByVal rBorderStyle_Value As BorderStyle, ByVal rタテtrueヨコfalse As Boolean, ByVal rCell数ヨコ As Integer, ByVal rCell数タテ As Integer, ByVal r使用個数_1_to_max As Integer, _
                                            ByVal r図形外縁枠幅 As Integer, ByVal rCell幅 As Integer, ByVal rCell高 As Integer, ByVal rCell間タテヨコ As Integer, ByVal rMouseChkInSide_0_to_03 As Single, _
                                            ByVal rリスト背景色 As Integer, ByVal r選択色 As Integer, ByVal r図形外縁枠色 As Integer, _
                                            ByVal r団団Left As Integer, ByVal r団団Top As Integer, ByRef w団団Width As Integer, ByRef w団団Height As Integer) As Boolean
        Dim タテヨコ間隔半分 As Integer = rCell間タテヨコ \ 2
        If rCell数ヨコ < 1 Or rCell数ヨコ > 100 Or rCell数タテ < 1 Or rCell数タテ > 100 Or r使用個数_1_to_max < 1 Or r使用個数_1_to_max > 1000 Or _
               r図形外縁枠幅 < 0 Or r図形外縁枠幅 > 10 Or rCell幅 < 20 Or rCell幅 > 200 Or rCell高 < 20 Or rCell高 > 200 Or タテヨコ間隔半分 < 0 Or タテヨコ間隔半分 > rCell幅 \ 3 Or タテヨコ間隔半分 > rCell高 \ 3 Then
            ⅩMsgBox_OK_情報("五clsCellListBox.SetAllSize() サイズ設定でエラーが発生") : Return False
        End If
        mCell数ヨコ = rCell数ヨコ : mCell数タテ = rCell数タテ : mCell幅 = rCell幅 : mCell高 = rCell高 : mCell間タテヨコ = rCell間タテヨコ
        mセル配列MAX = rCell数ヨコ * rCell数タテ - 1 : ReDim mセル配列(mセル配列MAX)
        m図形外縁枠幅 = Math.Max(0, Math.Min(c図形外縁枠幅, r図形外縁枠幅))
        Dim msinside As Single = Math.Max(0, Math.Min(rMouseChkInSide_0_to_03, 0.3))
        Dim msinsideX As Integer = msinside * mCell幅  'セル全体の幅に対する比率を使用する
        Dim msinsideY As Integer = msinside * mCell高
        Dim a As Integer, y As Integer, x As Integer
        For a = 0 To mセル配列MAX
            If rタテtrueヨコfalse Then
                x = (a \ mCell数タテ) : y = (a - (mCell数タテ * x))
            Else
                y = (a \ mCell数ヨコ) : x = (a - (mCell数ヨコ * y))
            End If
            With mセル配列(a)
                With .セル
                    .X = x * mCell幅 : .Y = y * mCell高 : .Width = mCell幅 : .Height = mCell高
                    .Offset(タテヨコ間隔半分, タテヨコ間隔半分)
                    .Inflate(-タテヨコ間隔半分, -タテヨコ間隔半分)
                    'qqqqq("mセル配列(" + Format(a, "00") + ").セル          " + Format(.X, "000") + "," + Format(.Y, "000") + "," + Format(.Right, "000") + "," + Format(.Bottom, "000"))
                End With
                .MouseChk領域.Location = .セル.Location
                .MouseChk領域.Size = .セル.Size
                .MouseChk領域.Inflate(-msinsideX, -msinsideY)
                'With .MouseChk領域
                '    qqqqq("mセル配列(" + Format(a, "00") + ").MouseChk領域  " + Format(.X, "000") + "," + Format(.Y, "000") + "," + Format(.Right, "000") + "," + Format(.Bottom, "000"))
                'End With
                .使用中 = (a < r使用個数_1_to_max)
                If .使用中 Then mセル使用MAX = a
                'qqqqq("使用中 = " + CStr(.使用中))
                .選択old = False
                .選択new = False
            End With
        Next
        With mセル配列(mセル配列MAX)
            w団団Width = .セル.Right + タテヨコ間隔半分 + タテヨコ間隔半分
            w団団Height = .セル.Bottom + タテヨコ間隔半分 + タテヨコ間隔半分
        End With
        '団団 に Image を作り、さいずを設定する。rPctBoxFrameWD_片側 = 0 ～ 10
        Dim 枠幅_2 As Integer
        団団 = New PictureBox
        If 団団 IsNot Nothing Then
            With 団団
                .Parent = rParent
                .BorderStyle = rBorderStyle_Value
                .Left = r団団Left
                .Top = r団団Top
                .Visible = True
                枠幅_2 = Math.Max(0, Math.Min(10, .Width - .ClientSize.Width))
            End With
            gggbol = ⅩImage_新規作成_再作成(団団.Image, w団団Width, w団団Height)
            団団.SetBounds(団団.Left, 団団.Top, w団団Width + 枠幅_2, w団団Height + 枠幅_2, BoundsSpecified.All)
        End If
        gggbol = ColorsSET(rリスト背景色, r選択色, r図形外縁枠色)
        Return True
    End Function
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Function aa色の設定ダイアログShow(ByVal rOwner As Form) As Boolean
        If gmアプリ終了する Then Return False
        色設定Dlg = New 四frmDlgカード選択ColorSet
        色設定Dlg.Owner = rOwner
        色設定Dlg.ShowDialog()
        色設定Dlg.Dispose()
        Return True
    End Function
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Function ColorsSET(ByVal rリスト背景色 As Integer, ByVal r選択色 As Integer, ByVal r図形外縁枠色 As Integer) As Boolean
        If rリスト背景色 >= 0 Then mリスト背景色 = Ⅹ色の値の検査修正値(rリスト背景色)
        If r選択色 >= 0 Then m選択色 = Ⅹ色の値の検査修正値(r選択色)
        If r図形外縁枠色 >= 0 Then m図形外縁枠色 = Ⅹ色の値の検査修正値(r図形外縁枠色)
        Return True
    End Function
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Function ColorsGET(ByRef wリスト背景色 As Integer, ByRef w選択色 As Integer, ByRef w図形外縁枠色 As Integer) As Boolean
        wリスト背景色 = mリスト背景色
        w選択色 = m選択色
        w図形外縁枠色 = m図形外縁枠色
        Return True
    End Function
#End Region

#Region "外部とのI/O関数"
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Function MouseClick_ret_Index_0_to_usingmax(ByVal e As System.Windows.Forms.MouseEventArgs, ByVal 選択newを反転する As Boolean) As Integer
        'return   0 to usingmax   /   if not catch   return -1
        Dim a As Integer, x As Integer = e.X, y As Integer = e.Y
        For a = 0 To mセル使用MAX
            If mセル配列(a).MouseChk領域.Contains(x, y) Then
                If 選択newを反転する Then gggbol = セルの選択new状態反転(a)
                'qqqqq(CStr(a))
                Return a
            End If
        Next
        Return -1
    End Function
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Function RgnOffSet_Indexセルの中心に(ByRef rgn As Integer, ByVal Index As Integer) As Boolean
        Dim rc As RECT, x As Integer, y As Integer
        gggint = GetRgnBox(rgn, rc)
        With mセル配列(Index).セル
            x = ⅩRect幅(rc) - .Width
            y = ⅩRect高(rc) - .Height
            If x <> 0 Then x = .Left - (x \ 2) Else x = .Left
            If y <> 0 Then y = .Top - (y \ 2) Else y = .Top
        End With
        gggint = OffsetRgn(rgn, x, y)
    End Function
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Function DrawRgn(ByVal img As Image, ByVal rgn As Integer, ByVal rカード型IDX As Integer, ByVal rNew選択使用 As Boolean) As Boolean
        If rgn = 0 Then Return False
        '-------------------------------------------------------
        Dim w選択old As Boolean, w選択new As Boolean
        gggbol = セルの選択newold状態GET(rカード型IDX, w選択old, w選択new)
        Dim 塗り色 As Integer = IIf(IIf(rNew選択使用, w選択new, w選択old), m選択色, mリスト背景色)
        '-------------------------------------------------------
        Dim g As Graphics
        g = Graphics.FromImage(img)
        If g IsNot Nothing Then
            Dim hdc As Integer
            hdc = g.GetHdc
            If hdc <> 0 Then
                Dim Brs塗り色 As Integer = CreateSolidBrush(塗り色)
                If Brs塗り色 <> 0 Then
                    gggint = FillRgn(hdc, rgn, Brs塗り色)
                    gggint = DeleteObject(Brs塗り色)
                    Dim brsライン As Integer = CreateSolidBrush(m図形外縁枠色)
                    If brsライン <> 0 Then
                        gggint = FrameRgn(hdc, rgn, brsライン, m図形外縁枠幅, m図形外縁枠幅)
                        gggint = DeleteObject(brsライン)
                    End If
                End If
                g.ReleaseHdc(hdc)
            End If
            g.Dispose()
        End If
        Return True
    End Function
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Function すべての選択状態チェック(ByVal mアプリ型_max As Integer, ByRef wアプリはすべて選択 As Boolean, ByRef wユーザーはすべて選択 As Boolean, ByRef wいずれかが選択 As Boolean) As Boolean
        wアプリはすべて選択 = True : wユーザーはすべて選択 = True : wいずれかが選択 = False
        Dim a As Integer
        For a = 0 To mセル使用MAX
            If mセル配列(a).選択new Then
                wいずれかが選択 = True
            Else
                If a <= mアプリ型_max Then
                    wアプリはすべて選択 = False
                Else
                    wユーザーはすべて選択 = False
                End If
            End If
            If (wアプリはすべて選択 = False) And (wユーザーはすべて選択 = False) And (wいずれかが選択 = True) Then Return True
        Next
        Return True
    End Function
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Function 選択状態は変更されている() As Boolean
        Dim a As Integer
        For a = 0 To mセル使用MAX
            If mセル配列(a).選択new <> mセル配列(a).選択old Then Return True
        Next
        Return False
    End Function
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Function 選択カード型の総数() As Integer
        Dim a As Integer, m As Integer
        m = 0
        For a = 0 To mセル使用MAX
            If mセル配列(a).選択new Then m = m + 1
        Next
        Return m
    End Function
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Function セルのサイズ(ByRef wWD As Integer, ByRef wHT As Integer) As Boolean
        With mセル配列(0).セル
            If .Width < 1 Then Return False
            wWD = .Width : wHT = .Height
        End With
        Return True
    End Function
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Function セルの選択new状態GETALL(ByRef w選択newall() As Boolean) As Boolean
        Dim a As Integer
        ReDim w選択newall(mセル使用MAX)
        For a = 0 To mセル使用MAX
            w選択newall(a) = mセル配列(a).選択new
        Next
        Return True
    End Function
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Function セルの選択newold状態SET_AllOFF_OnlyOneSelectIF(ByVal OnlyOne As Integer) As Boolean
        Dim a As Integer, bol As Boolean
        For a = 0 To mセル使用MAX
            bol = (a = OnlyOne)
            With mセル配列(a)
                .選択old = bol : .選択new = bol
            End With
        Next
        Return True
    End Function
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Function セルの選択newold状態GET(ByVal Index As Integer, ByRef w選択old As Boolean, ByRef w選択new As Boolean) As Boolean
        If Index < 0 Or Index > mセル使用MAX Then Return False
        With mセル配列(Index)
            w選択old = .選択old : w選択new = .選択new
        End With
        Return True
    End Function
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Function セルの選択状態COPY_OldToNew1_NewToOld2(ByVal Index As Integer, ByVal SetAll As Boolean, ByVal old_to_new_1__new_to_old_2 As Integer) As Boolean
        If (Not SetAll) And Index < 0 Or Index > mセル使用MAX Then Return False
        Dim a, stt, stp As Integer
        If SetAll Then
            stt = 0 : stp = mセル使用MAX
        Else
            stt = Index : stp = Index
        End If
        For a = stt To stp
            With mセル配列(a)
                If old_to_new_1__new_to_old_2 = 1 Then .選択new = .選択old Else .選択old = .選択new
            End With
        Next
        Return True
    End Function
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Function セルの選択new状態反転(ByVal Index As Integer) As Boolean
        If Index < 0 Or Index > mセル使用MAX Then Return False
        With mセル配列(Index) : .選択new = Not .選択new : End With
        Return True
    End Function
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Function セルの選択new状態SET(ByVal Index As Integer, ByVal 選択val As Boolean) As Boolean
        If Index < 0 Or Index > mセル使用MAX Then Return False
        With mセル配列(Index) : .選択new = 選択val : End With
        Return True
    End Function
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Function セルの選択old状態SET(ByVal Index As Integer, ByVal 選択val As Boolean) As Boolean
        If Index < 0 Or Index > mセル使用MAX Then Return False
        With mセル配列(Index) : .選択old = 選択val : End With
        Return True
    End Function
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Function セル使用MAX() As Integer
        Return mセル使用MAX
    End Function
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Sub Refresh()
        団団.Refresh()
    End Sub
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Private Sub 団団_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles 団団.MouseClick
        Dim idx As Integer = MouseClick_ret_Index_0_to_usingmax(e, True)
        If idx >= 0 Then gggbol = aaCardDraw(idx, True, True)
        RaiseEvent 選択インデックスが変わりました(idx)      ''gggbol = zzEnabledSet()
    End Sub
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Function aaCardDrawAll(ByVal rNew選択使用 As Boolean) As Boolean
        Dim wリスト背景色 As Integer, ccc1 As Integer, ccc2 As Integer
        gggbol = ColorsGET(wリスト背景色, ccc1, ccc2)
        gggbol = ⅩImageFillRect(団団.Image, wリスト背景色, 0, 0, 団団.Image.Width, 団団.Image.Height, False)
        For a As Integer = 0 To セル使用MAX()
            gggbol = aaCardDraw(a, rNew選択使用, False)
        Next
        団団.Refresh()
        Return True
    End Function
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
    Friend Function aaCardDraw(ByVal rカード型IDX As Integer, ByVal rNew選択使用 As Boolean, ByVal Do_pctカードリスト_Refresh As Boolean) As Boolean
        Dim wIsOK As Boolean, wカードRGN_呼び出し元で削除する As Integer = 0, wカードを使用している As Boolean = False
        Dim セル基本Width, セル基本Height As Integer
        If Not セルのサイズ(セル基本Width, セル基本Height) Then Return False
        wIsOK = False
        RaiseEvent カードデーターをください(wIsOK, rカード型IDX, セル基本Width, セル基本Height, wカードRGN_呼び出し元で削除する, wカードを使用している)
        If wIsOK = False Then Return False
        If wカードRGN_呼び出し元で削除する = 0 Then Return False
        '--------------------------------------------------
        '図形リージョンをシフトさせる。　rカード型IDX　のセル位置に移動する
        gggbol = RgnOffSet_Indexセルの中心に(wカードRGN_呼び出し元で削除する, rカード型IDX)
        '--------------------------------------------------
        gggbol = セルの選択old状態SET(rカード型IDX, wカードを使用している)
        gggbol = DrawRgn(団団.Image, wカードRGN_呼び出し元で削除する, rカード型IDX, rNew選択使用)
        '--------------------------------------------------
        DeleteObject(wカードRGN_呼び出し元で削除する)  '図形リージョンは毎回作成して使用後に破棄する。
        wカードRGN_呼び出し元で削除する = 0
        'qqqqq("Draw rgn " & CStr(wカードRGN_呼び出し元で削除する))
        '--------------------------------------------------
        If rNew選択使用 = False Then gggint = セルの選択状態COPY_OldToNew1_NewToOld2(rカード型IDX, False, 1)
        If Do_pctカードリスト_Refresh Then 団団.Refresh()
        Return True
    End Function
    '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
#End Region

#Region "イベント from 色設定Dlg"

    Private Sub 色設定Dlg_ウインドウの初期化データーをください(ByRef wIsOK As Boolean, ByRef wMe_gmDlgID As Integer, ByRef wダイアログテキスト As String, ByRef wColor1 As Integer, ByRef wColor2 As Integer, ByRef wColor3 As Integer) Handles 色設定Dlg.ウインドウの初期化データーをください
        If 色設定Dlg Is Nothing Then Return
        wIsOK = True
        wMe_gmDlgID = gmDlgカード型を設定の色設定
        'wダイアログテキスト = 色設定Dlg.Text & " - " & "カラー設定"
        wダイアログテキスト = 色設定Dlg.Text ''''''''''''''''''' & " - " & "カラー設定"
        gggbol = ColorsGET(wColor1, wColor2, wColor3)
    End Sub

    Private Sub 色設定Dlg_カラーが変更されました(ByVal rIndex As Integer, ByVal rColor As Integer) Handles 色設定Dlg.カラーが変更されました
        If 色設定Dlg Is Nothing Then Return
        RaiseEvent カラーが変更されました(rIndex, rColor)
        gggbol = ColorsSET(IIf(rIndex = 1, rColor, -1), IIf(rIndex = 2, rColor, -1), IIf(rIndex = 3, rColor, -1))
        gggbol = aaCardDrawAll(True)
    End Sub

    Private Sub 色設定Dlg_カラーの現在値をください(ByVal rIndex_1_2_3 As Integer, ByRef wColor As Integer) Handles 色設定Dlg.カラーの現在値をください
        Dim c1, c2, c3 As Integer
        gggbol = ColorsGET(c1, c2, c3)
        Select Case rIndex_1_2_3
            Case 1 : wColor = c1
            Case 2 : wColor = c2
            Case 3 : wColor = c3
            Case Else : wColor = -1
        End Select
    End Sub

    Private Sub 色設定Dlg_カラーをすべて元に戻しなさい(ByVal rColor1stt As Integer, ByVal rColor2stt As Integer, ByVal rColor3stt As Integer) Handles 色設定Dlg.カラーをすべて元に戻しなさい
        If 色設定Dlg Is Nothing Then Return
        Dim リスト背景色, 選択色, 図形外縁枠色 As Integer
        RaiseEvent カラーをすべて元に戻しなさい(rColor1stt, rColor2stt, rColor3stt, リスト背景色, 選択色, 図形外縁枠色)
        gggbol = ColorsSET(リスト背景色, 選択色, 図形外縁枠色)
        gggbol = aaCardDrawAll(True)
    End Sub

    Private Sub 色設定Dlg_カラーを規定値にリセットしなさい() Handles 色設定Dlg.カラーを規定値にリセットしなさい
        If 色設定Dlg Is Nothing Then Return
        Dim リスト背景色, 選択色, 図形外縁枠色 As Integer
        RaiseEvent カラーを規定値にリセットしなさい(リスト背景色, 選択色, 図形外縁枠色)
        gggbol = ColorsSET(リスト背景色, 選択色, 図形外縁枠色)
        gggbol = aaCardDrawAll(True)
    End Sub

    Private Sub 色設定Dlg_メニューのEnabledデーターをください(ByRef w元に戻す As Boolean, ByRef w規定値にリセット As Boolean, ByVal rColor1stt As Integer, ByVal rColor2stt As Integer, ByVal rColor3stt As Integer) Handles 色設定Dlg.メニューのEnabledデーターをください
        If 色設定Dlg Is Nothing Then Return
        RaiseEvent メニューのEnabledデーターをください(w元に戻す, w規定値にリセット, rColor1stt, rColor2stt, rColor3stt)
    End Sub

#End Region

End Class
