动态生成多级菜单

以前,我是用数据表保存菜单项目及各个操作员的相应权限,并在vfp中编写了相应的程序来实现菜单、工具栏、Treeview   的生成。但由于vfp有一个叫宏替换的东东&,实现起来比较简单。  
  由于vb及.net的“对象”和“对象名称”是两种不同的数据类型,之间转换起来比较麻烦,以一直困扰了我很久了。 
经过一段时间的努力,终于实现了上述的功能。

具体做法是:

  我把系统中使用的各级菜单的信息保存在数据表中,把菜单的级次关系描述清楚(注意Bhparent字段)。
         数据表的结构如下:  
            MenBh         c   8       '菜单编号  
            MenText     c   20     '菜单项  
            Bhparent   c   8       '上级菜单编号  
            MenForm     C   20     '需要执行的窗体名称  

      数据表中记录是:  
        MenBh:   0001           MenText:   文件         Bhparent:   无  
        MenBh:   0005           MenText:   打开         Bhparent:   0001  
        MenBh:   0006           MenText:   新建         Bhparent:   0001  
        MenBh:   0011           MenText:   access数据库         Bhparent:   0006  
        MenBh:   0011           MenText:   VFP的Dbf                 Bhparent:   0006  

     这样可以定义多个级次的菜单。

我自己定义了一个类BqUMenuItem,继承于MenuItem,主要是添加了一个tag属性,以使我在编写click事件时,可以方便地调用相关的窗口.  
Public Class BqUMenuItem
    Inherits System.Windows.Forms.MenuItem

#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 窗体设计器修改此过程。
    '不要使用代码编辑器修改它。
    Private Sub InitializeComponent()
        components = New System.ComponentModel.Container
    End Sub

#End Region

    Dim lpToolsTip As String   '帮助提示
    Dim lpTag As Object       '
    Dim lpID As String        '菜单ID
    Dim lpAdd As Boolean = True '新增
    Dim lpEdi As Boolean = True '修改
    Dim lpDel As Boolean = True '删除
    Dim lpPrn As Boolean = True '打印
    Dim lpBow As Boolean = True '预览
    Dim lpOut As Boolean = True '导出
    Dim lpBhmode As String = "    " '模块编号
    Dim lpMcmode As String = "    " '模块名称
    Dim lpFrm As String = "    " '模块名称

    Public Property BqPAdd() As Boolean
        Get
            Return lpAdd
        End Get
        Set(ByVal Value As Boolean)
            lpAdd = Value
        End Set
    End Property
    Public Property BqPEdi() As Boolean
        Get
            Return lpEdi
        End Get
        Set(ByVal Value As Boolean)
            lpEdi = Value
        End Set
    End Property
    Public Property BqPDel() As Boolean
        Get
            Return lpDel
        End Get
        Set(ByVal Value As Boolean)
            lpDel = Value
        End Set
    End Property
    Public Property BqPPrn() As Boolean
        Get
            Return lpPrn
        End Get
        Set(ByVal Value As Boolean)
            lpPrn = Value
        End Set
    End Property
    Public Property BqPBow() As Boolean
        Get
            Return lpBow
        End Get
        Set(ByVal Value As Boolean)
            lpBow = Value
        End Set
    End Property
    Public Property BqPOut() As Boolean
        Get
            Return lpOut
        End Get
        Set(ByVal Value As Boolean)
            lpOut = Value
        End Set
    End Property
    Public Property BqPBhmode() As String
        Get
            Return lpBhmode
        End Get
        Set(ByVal Value As String)
            lpBhmode = Value
        End Set
    End Property
    Public Property BqPFrm() As String
        Get
            Return lpFrm
        End Get
        Set(ByVal Value As String)
            lpFrm = Value
        End Set
    End Property
    Public Property BqPMcmode() As String
        Get
            Return lpMcmode
        End Get
        Set(ByVal Value As String)
            lpMcmode = Value
        End Set
    End Property
    Public Property BqPTag()
        Get
            Return lpTag
        End Get
        Set(ByVal Value)
            lpTag = Value
        End Set
    End Property
    Public Property BqPID() As String
        Get
            Return lpID
        End Get
        Set(ByVal Value As String)
            lpID = Value
        End Set
    End Property
    Public Property BqPToolstip() As String
        Get
            Return lpToolsTip
        End Get
        Set(ByVal Value As String)
            lpToolsTip = Value
        End Set
    End Property

End Class

最后,用以下代码来生成菜单

    Public MenuNew As New System.Windows.Forms.MainMenu
    Public Function BqMmode(ByVal ltb As DataTable)
        Try
            Dim lDt As New System.Data.DataSet
            Dim tb As New DataTable
            tb = ltb.Copy    '不能直接用lTb这个表,因为,重新添加节点时,会提示“表已经在另一个数据集DataSet中
            lDt.Clear()
            lDt.Relations.Clear()
            lDt.EnforceConstraints = False
            lDt.Tables.Add(tb)
            Dim dr1 As New DataRelation("self", tb.Columns("BHmode"), tb.Columns("BHparent"))
            lDt.Relations.Add(dr1)

            Dim r1 As DataRow
            For Each r1 In lDt.Tables(0).Rows
                If r1.IsNull("BHparent") Then 'Or r1.Item("BHparent") = "0000" Then
                    mMenuAdd(r1, Nothing)
                End If
            Next
        Catch ex As Exception
        End Try
    End Function

    Private Sub mMenuAdd(ByVal r As DataRow, ByVal item As System.Windows.Forms.MenuItem)
        Try
            Dim lmBh As String, lmPa As String, lmFrm As String, lmKey As String
            Dim lmMc As String, lmBz As String, lmAt As String
            Dim lrSY As Boolean
            Dim lrAdd As Boolean, lrEdi As Boolean, lrDel As Boolean
            Dim lrPrn As Boolean, lrBow As Boolean, lrOut As Boolean
            Dim lmc As String, s As String
            Dim lk As System.Windows.Forms.Shortcut = Windows.Forms.Shortcut.None
            With r
                lmBh = "" & .Item("BHmode")     '模块编号
                lmPa = "" & .Item("BHparent")   '上级模块编号
                lmFrm = "" & .Item("FRMNAME")   '表单名称
                lmKey = "" & .Item("ModeKey")   '快捷键,以下设置与菜单相关
                lmAt = Trim("" & .Item("ModeAlt"))    '快速键
                lmMc = Trim("" & .Item("MCmode"))     '模块名称,如果名称为-号,表示分隔符
                lmBz = "" & .Item("MeM")        '备注内容
                lrSY = .Item("MarKsy")    '设置各个菜单的enabled属性
                lrAdd = .Item("blnAdd")   '读出有关的权限
                lrEdi = .Item("blnEdi")
                lrDel = .Item("blnDel")
                lrPrn = .Item("blnPrn")
                lrBow = .Item("blnBow")
                lrOut = .Item("blnOut")
            End With
            '关于快捷键的使用,要写一个转换程序,并使用Shortcut属性来设置
            lmc = lmMc
            If Microsoft.VisualBasic.Left(lmMc, 1) = "-" Then   '在菜单名称中,左边第一个字符为 - ,则表示分隔符
                lmc = "-"
            Else   '都把快速键加在左边
                '根据有无快速键,生成左边字符
                s = IIf(lmAt = "", Space(3), "(&" & Microsoft.VisualBasic.Left(lmAt, 1) & ")")
                If Trim(lmPa) = "" Then   '没有父级,表示一级菜单
                    lmc = Trim(s + lmc)  '则左边加上快速键,再去除空格
                Else
                    lmc = s + " " + lmc
                    '如果lmc不足15位(, 则在后面补空格)
                    lmc = IIf(Len(Trim(lmc)) < 18, lmc + Space(18 - Len(Trim(lmc))), lmc)
                    lk = IIf(Len(Trim(lmKey)) = 0 Or IsDBNull(lmKey), lk, MMgetShort(lmKey)) '根据表中的快捷键,得到快捷键对象
                End If
            End If

            Dim mi As New bqbass.BqUMenuItem   '自定义类,继承于MenuItem,添加了部分属性,见下
            With mi                't自定义的菜单类,分别设置有以下表示权限的属性
                .BqPAdd = lrAdd    '添加数据
                .BqPEdi = lrEdi    '修改数据
                .BqPDel = lrDel    '删除数据
                .BqPPrn = lrPrn    '打印数据
                .BqPBow = lrBow    '预览数据
                .BqPOut = lrOut    '数据输出
                .BqPBhmode = lmBh    '模块编号
                .BqPFrm = lmFrm      '表单名称
                .BqPMcmode = lmMc    '模块名称
                .BqPToolstip = lmBz  '提示信息
                .Text = lmc
                .Shortcut = lk '根据表中的快捷键,得到快捷键对象
                .ShowShortcut = True
            End With
            If item Is Nothing Then
                MenuNew.MenuItems.Add(mi)
            Else
                item.MenuItems.Add(mi)
            End If
            mi.Enabled = lrSY  '设置各菜单的权限
            AddHandler mi.Click, AddressOf mMenuClick    '定义各个菜单的click事件
            AddHandler mi.Select, AddressOf mMenuBarMouse       '添加状态栏说明
            AddHandler mi.Popup, AddressOf mMenuBarMouse        '添加状态栏说明

            Dim r2 As DataRow
            For Each r2 In r.GetChildRows("self")
                mMenuAdd(r2, mi)
            Next
        Catch ex As Exception

        End Try
    End Sub
    '我自己定义的 选择菜单后的操作,在状态栏上显示
    Public Overridable Sub mMenuClick(ByVal sender As System.Object, ByVal e As System.EventArgs)
    End Sub   '外部使用
    Private Sub mMenuBarMouse(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Me.BqBar2Cz("" & sender.BqPToolstip)
    End Sub
 

你可能感兴趣的:(动态生成多级菜单)