刚刚看了一个vb.net 实现动态菜单的例子。觉得很有意思。例子中用的主要技术有:

菜单树 的 操作

treeview的操作

利用堆栈实现菜单树与treeview树成员的对应

利用委托实现对象与事件的关联

因为我是初学者,所以有些词汇用得可能不恰当,另外有些理解也可能有偏差。

这个例子实现了,用户可以在当前菜单的任意一个节点上添加一个子菜单,并为添加的子菜单添加事件。

例子介绍如下:

首先创建一个 vb.net winform application

在form中添加一个菜单,取名为:MainItem,随便添加几个菜单项几项。

添加一个textbox控件, 取名为:txtNewText

添加一个listbox控件, 取名为:lstHandlers

添加一个TreeView控件,取名为:tvMenu

具体代码如下(其中有大部分代码为自动生成):

 

 

Public 
    
  Class Form1 
  Class Form1
    Inherits System.Windows.Forms.Form

Windows 窗体设计器生成的代码#Region " Windows 窗体设计器生成的代码 "

    Public Sub New()Sub New()
        MyBase.New()

        '该调用是 Windows 窗体设计器所必需的。
        InitializeComponent()

        '在 InitializeComponent() 调用之后添加任何初始化

    End Sub

    '窗体重写处置以清理组件列表。
    Protected Overloads Overrides Sub Dispose()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 窗体设计器修改此过程。
    '不要使用代码编辑器修改它。
    Friend WithEvents MainMenu As System.Windows.Forms.MainMenu
    Friend WithEvents MenuItem1 As System.Windows.Forms.MenuItem
    Friend WithEvents MenuItem2 As System.Windows.Forms.MenuItem
    Friend WithEvents MenuItem3 As System.Windows.Forms.MenuItem
    Friend WithEvents lstHandlers As System.Windows.Forms.ListBox
    Friend WithEvents Label3 As System.Windows.Forms.Label
    Friend WithEvents tvMenu As System.Windows.Forms.TreeView
    Friend WithEvents Label2 As System.Windows.Forms.Label
    Friend WithEvents Label1 As System.Windows.Forms.Label
    Friend WithEvents txtNewText As System.Windows.Forms.TextBox
    Friend WithEvents btnAddItem As System.Windows.Forms.Button
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()Sub InitializeComponent()
        Me.components = New System.ComponentModel.Container
        Me.MainMenu = New System.Windows.Forms.MainMenu(Me.components)
        Me.MenuItem1 = New System.Windows.Forms.MenuItem
        Me.MenuItem2 = New System.Windows.Forms.MenuItem
        Me.MenuItem3 = New System.Windows.Forms.MenuItem
        Me.lstHandlers = New System.Windows.Forms.ListBox
        Me.Label3 = New System.Windows.Forms.Label
        Me.tvMenu = New System.Windows.Forms.TreeView
        Me.Label2 = New System.Windows.Forms.Label
        Me.Label1 = New System.Windows.Forms.Label
        Me.txtNewText = New System.Windows.Forms.TextBox
        Me.btnAddItem = New System.Windows.Forms.Button
        Me.SuspendLayout()
        '
        'MainMenu
        '
        Me.MainMenu.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.MenuItem1, Me.MenuItem2, Me.MenuItem3})
        '
        'MenuItem1
        '
        Me.MenuItem1.Index = 0
        Me.MenuItem1.Text = "菜单1"
        '
        'MenuItem2
        '
        Me.MenuItem2.Index = 1
        Me.MenuItem2.Text = "菜单2"
        '
        'MenuItem3
        '
        Me.MenuItem3.Index = 2
        Me.MenuItem3.Text = "菜单3"
        '
        'lstHandlers
        '
        Me.lstHandlers.ItemHeight = 12
        Me.lstHandlers.Location = New System.Drawing.Point(88, 64)
        Me.lstHandlers.Name = "lstHandlers"
        Me.lstHandlers.Size = New System.Drawing.Size(136, 112)
        Me.lstHandlers.TabIndex = 13
        '
        'Label3
        '
        Me.Label3.Location = New System.Drawing.Point(56, 64)
        Me.Label3.Name = "Label3"
        Me.Label3.Size = New System.Drawing.Size(32, 16)
        Me.Label3.TabIndex = 12
        Me.Label3.Text = "事件"
        '
        'tvMenu
        '
        Me.tvMenu.Location = New System.Drawing.Point(280, 24)
        Me.tvMenu.Name = "tvMenu"
        Me.tvMenu.Size = New System.Drawing.Size(152, 152)
        Me.tvMenu.TabIndex = 11
        '
        'Label2
        '
        Me.Label2.Location = New System.Drawing.Point(232, 32)
        Me.Label2.Name = "Label2"
        Me.Label2.Size = New System.Drawing.Size(48, 16)
        Me.Label2.TabIndex = 10
        Me.Label2.Text = "添加到"
        '
        'Label1
        '
        Me.Label1.Location = New System.Drawing.Point(8, 32)
        Me.Label1.Name = "Label1"
        Me.Label1.Size = New System.Drawing.Size(80, 16)
        Me.Label1.TabIndex = 9
        Me.Label1.Text = "新菜单项文字"
        '
        'txtNewText
        '
        Me.txtNewText.Location = New System.Drawing.Point(88, 24)
        Me.txtNewText.Name = "txtNewText"
        Me.txtNewText.Size = New System.Drawing.Size(136, 21)
        Me.txtNewText.TabIndex = 8
        '
        'btnAddItem
        '
        Me.btnAddItem.Location = New System.Drawing.Point(168, 192)
        Me.btnAddItem.Name = "btnAddItem"
        Me.btnAddItem.Size = New System.Drawing.Size(80, 24)
        Me.btnAddItem.TabIndex = 7
        Me.btnAddItem.Text = "添加菜单项"
        '
        'Form1
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(6, 14)
        Me.ClientSize = New System.Drawing.Size(448, 225)
        Me.Controls.Add(Me.lstHandlers)
        Me.Controls.Add(Me.Label3)
        Me.Controls.Add(Me.tvMenu)
        Me.Controls.Add(Me.Label2)
        Me.Controls.Add(Me.Label1)
        Me.Controls.Add(Me.txtNewText)
        Me.Controls.Add(Me.btnAddItem)
        Me.Menu = Me.MainMenu
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.ResumeLayout(False)
        Me.PerformLayout()

    End Sub

#End Region

    Private eHandlers(3) As EventHandler   '定义事件方法集合
    Private Sub ShowHelloWorld()Sub ShowHelloWorld(ByVal sender As System.Object, ByVal e As System.EventArgs)
        MessageBox.Show("Hello World!")
    End Sub
    Private Sub ShowMenuItemText()Sub ShowMenuItemText(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Dim mItem As MenuItem
        mItem = CType(sender, MenuItem)
        MessageBox.Show(mItem.Text)
    End Sub
    Private Sub ShowMenuItemIndex()Sub ShowMenuItemIndex(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Dim mItem As MenuItem

        mItem = CType(sender, MenuItem)
        MessageBox.Show(mItem.Index)
    End Sub
    Private Sub ShowCurDateTime()Sub ShowCurDateTime(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Dim strDate As String = DateTime.Now.ToString()
        MessageBox.Show(strDate)
    End Sub


    Private Sub MenuItemToNode()Sub MenuItemToNode(ByVal menuItems As Menu.MenuItemCollection, ByVal targetNodes As TreeNodeCollection)
        'TreeNodeCollection 代表一个树结点集合,每一个节点下的儿子节点的集合
        'MenuItemCollection 代表一个菜单项的集合,也是菜单树中某一菜单下的一级子菜单的菜单项的集合
        Dim subItem As MenuItem
        For Each subItem In menuItems
            Dim subNode As New TreeNode(subItem.Text)
            If subItem.MenuItems.Count > 0 Then
                MenuItemToNode(subItem.MenuItems, subNode.Nodes)  '递归处理
            End If
            targetNodes.Add(subNode)
        Next
    End Sub

    Private Function FindMenuItem()Function FindMenuItem(ByVal selectedNode As TreeNode) As MenuItem
        Dim indexStack As New Collections.Stack()  '定一个堆栈对象
        '将树结点从当前节点一直到根的一条路径压入堆栈
        Do Until selectedNode Is Nothing
            indexStack.Push(selectedNode.Index)
            selectedNode = selectedNode.Parent
        Loop
        '再利用菜单与treeview树一一对应的特点.根据节点的index,找到对应的菜单项.然后沿着路径找到当前的菜单项
        Dim menuItem As MenuItem = MainMenu.MenuItems(indexStack.Pop())
        Do Until indexStack.Count = 0
            menuItem = menuItem.MenuItems(indexStack.Pop())
        Loop
        '返回当前菜单项
        Return menuItem

    End Function

    Private Sub btnAddItem_Click()Sub btnAddItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAddItem.Click
        If txtNewText.Text = "" Then Exit Sub
        If tvMenu.SelectedNode Is Nothing Then Exit Sub

        Dim correspondingMenuItem As MenuItem
        Dim newMenuItem As MenuItem
        correspondingMenuItem = FindMenuItem(tvMenu.SelectedNode)  '将节点转成菜单项

        newMenuItem = New MenuItem(txtNewText.Text)   '生成新加的菜单项
        If lstHandlers.SelectedIndex >= 0 Then
            AddHandler newMenuItem.Click, eHandlers(lstHandlers.SelectedIndex)   '建立事件的委托
        End If
        correspondingMenuItem.MenuItems.Add(newMenuItem)  '将新菜单加到菜单树中
        tvMenu.Nodes.Clear()   '清空treeview树
        MenuItemToNode(MainMenu.MenuItems, tvMenu.Nodes)   '将最新的菜单呈现成树
        tvMenu.ExpandAll()   '展开树


    End Sub

    Private Sub Form1_Load()Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        MenuItemToNode(MainMenu.MenuItems, tvMenu.Nodes)  '将菜单树呈现到treeview中
        tvMenu.ExpandAll()   '展开他

        '将三个事件方法放入集合
        eHandlers(0) = AddressOf ShowHelloWorld
        eHandlers(1) = AddressOf ShowMenuItemText
        eHandlers(2) = AddressOf ShowMenuItemIndex
        eHandlers(3) = AddressOf ShowCurDateTime
        '将事件方法名字写入列表
        Dim i As Integer
        For i = 0 To eHandlers.Length - 1
            lstHandlers.Items.Add(eHandlers(i).Method.Name)
        Next
    End Sub
End Class

 

运行的界面如下:

vb.net学习总结一(动态菜单)_vb.net