一个使用用户控件(包括组件)的演示

发表于:2007-06-30来源:作者:点击数: 标签:
1. Imports System.ComponentModel Public Class pic Inherits System.Windows.Forms.UserControl #Region " Windows 窗体设计器生成的代码 " @#UserControl1 重写 dispose 以清理组件列表。 Protected Overloads Overrides Sub Dispose(ByVal disposing As

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) @#主要是用于在piclearcase/" target="_blank" >ccontrols组件中创建实例时使用
        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





原文转自:http://www.ltesting.net