65.9K
CodeProject 正在变化。 阅读更多。
Home

自动流按钮面板

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.59/5 (10投票s)

2011年9月23日

CPOL

5分钟阅读

viewsIcon

34364

downloadIcon

1478

一个 .NET 控件,用于控制应用程序中分类区域的布局。

AutoFlowButtonsPanel.png

AutoFlowButtonsPanel.png AutoFlowButtonsPanel.png AutoFlowButtonsPanel.png AutoFlowButtonsPanel.png

不要忘记投票。您的投票有助于不断添加新功能。

引言

在本文中,我将向您展示如何创建一个 .NET 控件,该控件可用于对应用程序中的各个部分进行分类。此控件还可以用于许多其他方式。只需查看源代码和演示以获得对其工作原理的总体了解,然后根据需要使用它。

如果您在使用此控件时遇到任何问题,或者想添加新功能、报告错误或提交您自己的更改,都欢迎您,我将很高兴为您提供帮助。

背景

创建此控件的想法是在一年前我开发一个教阿拉伯语用户英语的应用程序时产生的,当时我需要对应用程序的各个部分进行分类(学习、词汇、测试等)。我在网上搜索了这样的控件,但没有找到任何满足我需求的控件、代码或文章。所以我决定自己实现一个控件,并将代码放在这里供大家使用。

工作原理

此控件的基石是了解按钮及其面板如何排列;这是通过特定的步骤完成的,这些步骤是:

  1. 我们知道每个按钮都有一个与之关联的面板
  2. 我们将我们控件的所有按钮放入一个list类中
  3. 我们将第一个按钮的顶部设置为 0
  4. 我们将第一个按钮的面板的顶部设置为第一个按钮的底部 + 1
  5. 每个新按钮都应放置在上一个按钮的面板底部
  6. 我们进行一个循环来检查并查看每个按钮关联的面板是否可见,如果可见,我们将下一个按钮的顶部设置为该面板的底部,如果面板不可见,我们将下一个按钮的顶部设置为按钮本身的底部。

MultiView、SingleView 样式和 ArrangeAll 方法

MultiView 样式中,用户可以浏览和查看一个或多个面板的内容;在 SingleView 样式中,用户只能浏览和查看一个面板的内容。

ArrangeAll 方法根据上述步骤排列我们列表中的所有按钮,但有一个例外,即:在 MultiView 样式中,用户可以同时浏览多个面板;在 SingleView 样式中,用户一次只能浏览一个面板,因此在 SingleView 中,我们必须创建一个变量来存储先前查看过的按钮,并使用该变量隐藏先前查看过的面板,然后再显示新的面板内容。因此,当用户单击按钮时,ArrangeAll 方法会在该按钮的 OnClick 事件上被调用,我们将该按钮发送给 ArrangeAll 方法。该方法执行以下操作:如果样式是 MultiView,并且处于 Visible 状态,如果发送按钮的面板为 false,那么

  • 将发送按钮面板的 Visible 状态设置为 true
  • 否则,将发送按钮面板的 Visible 状态设置为 false
  • 应用上面提到的第六步
    • 如果样式是 SingleView
    • 如果发送按钮面板的 Visible 状态为 false,那么
  • 将发送按钮面板的 Visible 状态设置为 true
  • 否则,将发送按钮面板的 Visible 状态设置为 false
  • 隐藏先前查看过的按钮的面板 (因为我们一次只需要显示一个面板)
  • 应用上面提到的第六步

考虑这段代码:

Friend Sub ArrangeAll(ByVal sender As YSSPButton, ByVal e As System.EventArgs)
    If PanelVariables.LayoutVeiw = LayoutView.MultiView Then
        Dim C As YSSPButton
        sender.InnerPanel.Visible = Not sender.InnerPanel.Visible
        sender.InnerPanel.Top = sender.Bottom + 1
        For I As Int16 = 1 To Buttons.Count - 1
            C = InnerFlowButtons(I - 1)
            If Not C Is Nothing Then
                If C.InnerPanel.Visible = True Then
                    InnerFlowButtons(I).Top = C.InnerPanel.Bottom + 1
                    ' put the button after the previous button's panel
                Else
                    InnerFlowButtons(I).Top = C.Bottom + 1
                    ' put the button after the previous button
                End If
            End If
            InnerFlowButtons(I).InnerPanel.Top = InnerFlowButtons(I).Bottom + 1
            ' every panel must be placed directly after its button
        Next
    Else
        If sender.InnerPanel.Visible = True Then Return
        ' in single view if current visible button is clicked
        ' there is no need to arrange all buttons

        Dim C As YSSPButton
        ' to let the user see panel contents
        sender.InnerPanel.Visible = True
        ' every panel must be placed directly after its button
        sender.InnerPanel.Top = sender.Bottom + 1
        ' hide the panel of the previous viewed button
        PreViewedButton.InnerPanel.Visible = False
        ' every panel must be placed directly after its button
        PreViewedButton.InnerPanel.Top = sender.Bottom + 1
        If PanelVariables.LayoutVeiw = _
               WindowsApplication2.YSSPAutoFlowButtonsPanel.LayoutView.SingleView Then
            If PanelVariables.ButtonsStyle = _
                  WindowsApplication2.YSSPAutoFlowButtonsPanel.ButtonsStyle.Graphical Then
                PreViewedButton.BackgroundImage = StateImages.MainImage
                ' set the image of the previous viewed button
                ' to the main state image not the seleced state image
            End If
        End If
        PreViewedButton = sender ' to be used in the next call

        For I As Int16 = 1 To Buttons.Count - 1
            C = InnerFlowButtons(I - 1)
            If Not C Is Nothing Then
                If C.InnerPanel.Visible = True Then
                    InnerFlowButtons(I).Top = C.InnerPanel.Bottom + 1
                    ' put the button after the previous button's panel
                Else
                    InnerFlowButtons(I).Top = C.Bottom + 1
                    ' put the button after the previous button
                End If
            End If
            InnerFlowButtons(I).InnerPanel.Top = InnerFlowButtons(I).Bottom + 1
            ' every panel must be placed directly after its button
        Next
    End If
End Sub

Using the Code

我们的类这里包含一些其他类来控制其样式和行为,这些类是:

  • YSSPAutoFlowButtonsPanel:这是面板本身的类。
  • PanelVariables:此类包含可应用于所有内部面板和按钮的通用信息,这些设置用于添加具有与主面板中其他按钮和面板相同样式的新按钮和内部面板。
  • Buttons:此类用于为单个按钮应用以下设置;如果您想将设置应用于所有按钮,可以使用 ButtonsSettings 类。
  • Public Sub Add(ByVal Button As YSSPButton)
    
    ' these methods are not tested or debuged yet
    Public Sub Remove(ByVal index As Integer)
    
    Public Sub Remove(ByVal Button As YSSPButton)
    
    Public Sub Hide(ByVal Index As Integer)
    
    Public ReadOnly Property Count() As Integer
    
    Public Sub SetWidth(ByVal Index As Integer, ByVal Width As Integer)
    
    Public Sub SetHeight(ByVal Index As Integer, ByVal Height As Integer)
    
    Public Sub Insert(ByVal Index As Integer, ByVal Button As YSSPButton)
    
    Public Sub InsertRange(ByVal Start As Integer, ByVal Buttons As List(Of YSSPButton))
    
    Public Sub Clear()

    此类尚未完全实现或经过测试,还需要更多工作;如果您想实现此类,欢迎您。

  • Panels:此类用于为单个面板应用以下设置;如果您想将设置应用于所有面板,可以使用 PanelsSettings 类。
  • Public Sub SetPanelWidth(ByVal Index As Integer, ByVal Width As Integer)
    Public Sub SetPanelHeight(ByVal Index As Integer, ByVal Height As Integer)

    此类尚未完全实现或经过测试,还需要更多工作;如果您想实现此类,欢迎您。

  • ButtonsSettings:此类用于将以下设置应用于所有按钮;如果您想将设置应用于单个按钮,可以使用 Buttons 类。
  • Font
    Cursor 
    ForeColor 
    BackColor 
    Width 
    Height 
    Left 
    RightToLeft 
    ImageAlign 
    ImageIndex 
    ImageKey 
    ImageList 
    TextAlign 
    TextImageRelation 
    Parent
  • PanelsSettings:此类用于将以下设置应用于所有面板;如果您想将设置应用于单个面板,可以使用 Panels 类。
  • BackgroundImage 
    BackgroundImageLayout 
    Cursor 
    ForeColor 
    BackColor 
    Height 
    width
    Left 
    RightToLeft 
    Parent
  • Settings:此类用于获取或设置主面板的常规设置。
  • StateImages:此类用于为内部按钮的不同状态提供图像。
  • LayoutView:此类用于设置或获取面板的布局视图。
  • SingleView ' only one category can be viewed 
    MultiView ' many categories can be viewed at the same time
  • ButtonsStyle:此类用于获取或设置内部按钮的样式。
  • Graphical ' graphical style
    Colors ' not implemented yet
    System ' system style
  • YSSPButton:此类是我们在控件中使用的按钮;它继承自 Button 类并重写了以下子程序。
  • Protected Overrides Sub OnParentChanged(ByVal e As System.EventArgs)
        MyBase.OnParentChanged(e)
        InnerPanel.Parent = Me.Parent
        ' change the innerpanel's parent to the button's parent
    End Sub
    Protected Overrides Sub OnLocationChanged(ByVal e As System.EventArgs)
        MyBase.OnLocationChanged(e)
        InnerPanel.Top = Me.Bottom + 1
        ' every panel must be placed directly after its button
    End Sub
    Protected Overrides Sub OnSizeChanged(ByVal e As System.EventArgs)
        MyBase.OnSizeChanged(e)
        InnerPanel.Top = Me.Bottom + 1
        ' every panel must be placed directly after its button
    End Sub
    
    Protected Overrides Sub OnMouseEnter(ByVal e As System.EventArgs)
        'return if this button is the selected one (Don't change its state)
        If PanelVariables.ButtonsStyle = ButtonsStyle.Graphical Then
            If PanelVariables.LayoutVeiw = LayoutView.SingleView Then
                If PanelVariables.ButtonsStyle = ButtonsStyle.Graphical Then
                    If Me.InnerPanel.Visible = True Then
                        Exit Sub
                    End If
                End If
            End If
            Me.BackgroundImage = StateImages.OverImage
        End If
        MyBase.OnMouseEnter(e)
    End Sub
    
    Protected Overrides Sub OnMouseLeave(ByVal e As System.EventArgs)
        MyBase.OnMouseLeave(e)
        If PanelVariables.ButtonsStyle = ButtonsStyle.Graphical Then
            'return if this button is the selected one (Don't change its state)
            If PanelVariables.ButtonsStyle = ButtonsStyle.Graphical Then
                If PanelVariables.LayoutVeiw = LayoutView.SingleView Then
                    If PanelVariables.ButtonsStyle = ButtonsStyle.Graphical Then
                        If Me.InnerPanel.Visible = True Then
                            Exit Sub
                        End If
                    End If
                End If
            End If
            Me.BackgroundImage = StateImages.MainImage
        End If
    End Sub
    
    Protected Overrides Sub OnMouseDown(ByVal mevent As System.Windows.Forms.MouseEventArgs)
        If PanelVariables.ButtonsStyle = ButtonsStyle.Graphical Then
            'return if this button is the selected one (Don't change its state)
            If PanelVariables.ButtonsStyle = ButtonsStyle.Graphical Then
                If PanelVariables.LayoutVeiw = LayoutView.SingleView Then
                    If PanelVariables.ButtonsStyle = ButtonsStyle.Graphical Then
                        If Me.InnerPanel.Visible = True Then
                            Exit Sub
                        End If
                    End If
                End If
            End If
            Me.BackgroundImage = StateImages.DownImage
        End If
        MyBase.OnMouseDown(mevent)
    End Sub
    
    Protected Overrides Sub OnMouseUp(ByVal mevent As System.Windows.Forms.MouseEventArgs)
        If PanelVariables.ButtonsStyle = ButtonsStyle.Graphical Then
            'return if this button is the selected one (Don't change its state)
            If PanelVariables.ButtonsStyle = ButtonsStyle.Graphical Then
                If PanelVariables.LayoutVeiw = LayoutView.SingleView Then
                    If PanelVariables.ButtonsStyle = ButtonsStyle.Graphical Then
                        If Me.InnerPanel.Visible = True Then
                            Exit Sub
                        End If
                    End If
                End If
            End If
            Me.BackgroundImage = StateImages.OverImage
        End If
        MyBase.OnMouseUp(mevent)
    End Sub
    
    Protected Overrides Sub OnClick(ByVal e As System.EventArgs)
        MyBase.OnClick(e)
        ' if this button is the selected one set its
        ' background image to StateImages.SelecedImage image
        If PanelVariables.LayoutVeiw = LayoutView.SingleView Then
            If PanelVariables.ButtonsStyle = ButtonsStyle.Graphical Then
                If Me.InnerPanel.Visible = True Then
                    Me.BackgroundImage = StateImages.SelecedImage
                End If
            End If
        End If
    End Sub

您可以浏览源代码以了解其工作原理。如果您想编写和测试 ButtonsPanels 类,您可以这样做,并将您的更改发送给我,以便添加到本文中并完成此控件。

关注点

您知道吗,当我决定编写这个控件时,只用了半个小时就写完了代码并进行了测试,而当我决定在这里的 CodeProject 上写它时,却花了一年时间!!!别问我为什么。

历史

  • 2011 年 9 月 27 日:修复了源代码中的两个错误(已更新文章和源代码文件)。
© . All rights reserved.