一個使用用戶控件(包括組件)的演示。

1.

Imports System.ComponentModel
Public Class pic
    Inherits System.Windows.Forms.UserControl

#Region " Windows 窗體設計器生成的代碼 "

    'UserControl1 重寫 dispose 以清理組件列表。
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Windows 窗體設計器所必需的
    Private components As System.ComponentModel.IContainer

    '注意:以下過程是 Windows 窗體設計器所必需的
    '可以使用 Windows 窗體設計器修改此過程。
    '不要使用代碼編輯器修改它。
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        '
        'pic
        '
        Me.Name = "pic"
        Me.Size = New System.Drawing.Size(48, 48)

    End Sub

#End Region

    Public Const m_maxlen As Integer = 48 '固定的寬和高
    Public Const m_maxheight As Integer = 48
    Public Sub New(ByVal m As image) '主要是用於在piccontrols組件中創建實例時使用
        MyBase.New()

        '該調用是 Windows 窗體設計器所必需的。
        InitializeComponent()

        '在 InitializeComponent() 調用之後添加任何初始化
        m_image = m
    End Sub
    Public Sub New()
        MyBase.New()

        '該調用是 Windows 窗體設計器所必需的。
        InitializeComponent()

        '在 InitializeComponent() 調用之後添加任何初始化

    End Sub

    Private m_image As image = image.FromFile("G:/練習/重要的例程/使用問題(在格子中顯示圖片)/Gounda Takeshi.ico")
    <Category("grid"), Description("設置卡片的圖片。")> _
    Public Property image() As image
        Get
            Return m_image
        End Get
        Set(ByVal Value As image)
            m_image = Value
            Me.Refresh()
        End Set
    End Property
    '繪製邊框和圖象
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        Dim g As Graphics = Me.CreateGraphics
        Me.BackColor = Color.White
        g.DrawRectangle(System.Drawing.Pens.Black, 0, 0, Me.Width - 1, Me.Height - 1)
        Dim ic As Image = CType(m_image, Image)
        g.DrawImage(ic, 0, 0)
    End Sub
    '不允許調整大小
    Protected Overrides Sub OnSizeChanged(ByVal e As System.EventArgs)
        Me.Size = New Size(m_maxlen, m_maxheight)
    End Sub
    '匹配否標誌
    Private m_double As Boolean = False
    <Category("grid"), Description("是否匹配的標誌。")> _
    Public Property doubles() As Boolean
        Get
            Return m_double
        End Get
        Set(ByVal Value As Boolean)
            m_double = Value
        End Set
    End Property
    Private m_id As Integer
    <Category("grid"), Description("區分是否來自同一圖片的標誌。")> _
    Public Property id() As Integer
        Get
            Return m_id
        End Get
        Set(ByVal Value As Integer)
            m_id = Value
        End Set
    End Property
 
End Class

2.

Imports my_namespace
Imports System.ComponentModel
Public Class piccontrols
    Inherits System.ComponentModel.Component

#Region " 組件設計器生成的代碼 "

    '組件重寫 dispose 以清理組件列表。
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    '組件設計器所必需的
    Private components As System.ComponentModel.IContainer

    '注意:以下過程是組件設計器所必需的
    '可以使用組件設計器修改此過程。
    '不要使用代碼編輯器修改它。
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        components = New System.ComponentModel.Container()
    End Sub

#End Region
    Public Sub New(ByVal Container As System.ComponentModel.IContainer)
        MyClass.New()

        'Windows.Forms 類撰寫設計器支持所必需的
        Container.Add(Me)

        changepic() '如果選擇的圖片發生了變化,那麼創建卡片集合也要相應的變化。

    End Sub

    Public Sub New()
        MyBase.New()

        '該調用是組件設計器所必需的。
        InitializeComponent()

        '在 InitializeComponent() 調用之後添加任何初始化

        changepic() '如果選擇的圖片發生了變化,那麼創建卡片集合也要相應的變化。

    End Sub
    '////////////////////////////////////////////////////////////////

    Dim m_piccontrols As New System.Collections.ArrayList()
    '總數量
    <Category("grid"), Description("集合內卡片的總數。")> _
        Public ReadOnly Property count() As Integer
        Get
            Return m_piccontrols.Count
        End Get
    End Property
    '指定位置的卡片(這個對於vb.net是比較特殊的,具有帶參數的屬性)
    Default Public ReadOnly Property items(ByVal index As Integer) As pic
        Get
            If index >= 0 And index < m_piccontrols.Count Then
                Return CType(m_piccontrols(index), pic)
            End If
        End Get
    End Property

    Public Sub shuffle() ' 混卡片,也就是生成一組隨機的卡片集合。(這裏的算法不錯!)
        Dim r As New System.Random()
        Dim d As New System.Collections.ArrayList()
        Dim p As pic
        While (m_piccontrols.Count > 0)
            Dim removeindex As Integer = r.Next(0, m_piccontrols.Count - 1)
            p = CType(m_piccontrols(removeindex), my_namespace.pic)
            m_piccontrols.RemoveAt(removeindex)
            d.Add(p)
        End While
        m_piccontrols = d
    End Sub

    Private m_image As imagelist
    <Category("grid"), Description("選擇相應的imagelist控件。")> _
    Public Property imagelist() As imagelist
        Get
            Return m_image
        End Get
        Set(ByVal Value As imagelist)
            m_image = Value
            changepic()
        End Set
    End Property
    '/////////
    '這個事件比較重要,主要是根據圖片的變動來生成不同的卡片集合。
    Private Sub changepic()
        If m_image Is Nothing Then Exit Sub
        Dim i As Integer
        For i = 0 To m_piccontrols.Count - 1
            CType(m_piccontrols(i), pic).Dispose() '注意這裏。
        Next
        m_piccontrols.Clear()
        Dim j As Integer
        For i = 0 To m_image.Images.Count - 1
            For j = 0 To 3
                Dim p As New pic(m_image.Images(i))
                p.id = i
                m_piccontrols.Add(p)
            Next
        Next
    End Sub
    '由於在排列好後,每個在集合中的卡片的doubles屬性都會被設置成true,
    '所以要在開始一次新的排序時設置所有的卡片該屬性爲false
    Public Sub setfalse()
        Dim i As Integer
        For i = 0 To m_piccontrols.Count - 1
            Dim apic As pic = CType(m_piccontrols(i), pic)
            apic.doubles = False
        Next
    End Sub

End Class

3.

Imports System.ComponentModel
Public Class picshow
    Inherits System.Windows.Forms.UserControl

#Region " Windows 窗體設計器生成的代碼 "

    Public Sub New()
        MyBase.New()

        '該調用是 Windows 窗體設計器所必需的。
        InitializeComponent()

        '在 InitializeComponent() 調用之後添加任何初始化

    End Sub

    'UserControl 重寫 dispose 以清理組件列表。
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Windows 窗體設計器所必需的
    Private components As System.ComponentModel.IContainer

    '注意:以下過程是 Windows 窗體設計器所必需的
    '可以使用 Windows 窗體設計器修改此過程。
    '不要使用代碼編輯器修改它。
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        components = New System.ComponentModel.Container()
    End Sub

#End Region
    '//                                 這個程序的原理                                                                        //
    '//先做一個pic控件,可以爲其設置相應的圖片,不允許改變大小,要重寫sizechange,onpait事件  //
    '//做一個集合組件piccontrols來容納一定數量的pic卡片,但並不顯示它,因爲是組件。只是容器  //
    '//最後做一個picshow控件,用於顯示piccontrols.count數量的卡片集合。                      //
    '//比較重要的地方就是如何對卡片進行隨機混排(piccontrols的shuffle方法)和picshow控件的   //
    '//contrains,start方法。尤其注意這裏進行排序的方法:是將卡片在集合裏就弄混(隨機),這樣//
    '//我們取得的每個卡片都是隨機的了,然後在picshow控件里根據每個卡片的doubles,id屬性來進行 //
    '//排序,把隨機和排序分開了。當然也可以把他們合併寫到picshow控件裏。不過這裏不建議這樣。 //
    '//因爲對於piccontrols組件來說,它的集合就是一個隨機產生的卡片集合。這樣比較好理解。     //

    Private Const m_spacing As Integer = 10 '間隔設置的常量

    Private m_rows As Integer = 2 ' 對於一個陣列來講,2行應該更有意義。
    <Category("grid"), Description("矩陣的行。"), DefaultValue(2)> _
        Public Property row() As Integer
        Get
            Return m_rows
        End Get
        Set(ByVal Value As Integer)
            If Value > 0 Then
                m_rows = Value
                Me.Refresh()
            End If
        End Set
    End Property
    Private m_columns As Integer = 2
    <Category("grid"), Description("矩陣的列。"), DefaultValue(2)> _
    Public Property columns() As Integer
        Get
            Return m_columns
        End Get
        Set(ByVal Value As Integer)
            If (Value > 0) And (Value Mod 2 = 0) Then
                m_columns = Value
                Me.Refresh()
            Else
                Throw New Exception("不是有效的列值!請輸入2的倍數的列值。")
            End If
        End Set
    End Property
    Private m_collection As piccontrols
    <Category("grid"), Description("指定相應的piccontrols組件。")> _
    Public Property getcontrols() As piccontrols
        Get
            Return m_collection
        End Get
        Set(ByVal Value As piccontrols)
            m_collection = Value
        End Set
    End Property
    '繪製邊框,由於還沒有將卡片加入到me.controls集合,所以只有邊框。
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        Dim height As Integer = my_namespace.pic.m_maxheight
        Dim width As Integer = my_namespace.pic.m_maxlen
        Me.Width = (width + m_spacing) * m_columns + m_spacing
        Me.Height = (height + m_spacing) * m_rows + m_spacing
        Dim g As Graphics = Me.CreateGraphics
        Dim row, column As Integer
        For row = 0 To m_rows - 1
            For column = 0 To m_columns - 1
                g.DrawRectangle(System.Drawing.Pens.Gray, column * (width + m_spacing) + m_spacing, _
                row * (height + m_spacing) + m_spacing, width, height)
            Next
        Next
    End Sub

    Private m_double As pic '記錄相同的那個卡片

    Private m_last As Integer  '記錄格子中的最後一個卡片

    '開始排列
    Public Sub start()

        Me.Controls.Clear() '先清空容器

        If Not IsNothing(m_collection) Then '判斷行列之積和卡片數量是否相等
            If (m_collection.count <> m_rows * m_columns) Then
                Throw New Exception("卡片數量爲:" & CStr(m_collection.count) & "格子數量爲:" & CStr(m_rows * m_columns))
            End If

            '///////////////////////////////////

            m_last = -2 '初始化,因爲從0開始是第一個格子,所以初始值爲-2

            m_collection.setfalse() '因爲開始一次排序就會把所有的卡片pic的double屬性全都設置爲true。所以,這裏要全都設置回false

            m_collection.shuffle() '將卡片弄混

            Dim cardcount As Integer = 0 '卡片指針
            Dim row, column As Integer

            For row = 0 To m_rows - 1
                For column = 0 To m_columns - 1
                    Dim apic As pic = CType(m_collection(cardcount), pic)
                    '加入到me的控件集合
                    Me.Controls.Add(apic)
                    '控件集合中的原有卡片進行遍歷,看是否有單個的與新加入的同一個圖片的卡片
                    Dim rint As Integer = contrains(apic)

                    Select Case rint
                        Case 0 '匹配排列
                            apic.Left = m_double.Left + m_spacing + my_namespace.pic.m_maxlen
                            apic.Top = m_double.Top
                        Case 1 '沒有匹配項,間隔排列

                            '行,注意一定要使用int進行轉化,否則會四捨五入。
                            Dim r As Integer = Int(m_last / (m_rows))
                            '列
                            Dim c As Integer = m_last Mod (m_rows)
                            '取得行列後就可以直接設置位置了。
                            apic.Left = c * (pic.m_maxlen + m_spacing) + m_spacing
                            apic.Top = r * (pic.m_maxheight + m_spacing) + m_spacing

                    End Select
                    cardcount += 1 '下一個卡片
                Next
            Next
            MessageBox.Show("排序完成!")

        End If
    End Sub
    '排序的函數
    Public Function contrains(ByVal p As pic) As Integer
        m_double = Nothing '初始值爲空,每次排序前要設置爲空。
        Dim apic As pic
        Dim i As Integer
        Dim count As Integer = Me.Controls.Count - 1
        For i = 0 To count - 1 '從0到末尾-1,把自己排除掉,自己和自己不必要去比較
            apic = CType(Me.Controls(i), pic)
            If (apic.id = p.id) And apic.doubles = False Then  'And i <> count
                apic.doubles = True '匹配
                p.doubles = True '匹配
                m_double = apic
            End If
        Next
        '找到匹配的了
        If Not (m_double Is Nothing) Then
            Return 0
        Else
            m_last += 2 '分隔開一個格子( 這裏的格子開始爲0,最後爲m_collection的count-1)
            Return 1
        End If

    End Function
End Class


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章