以前,我是用数据表保存菜单项目及各个操作员的相应权限,并在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 窗体设计器修改此过程。
'不要使用代码编辑器修改它。
<System.Diagnostics.DebuggerStepThrough()> 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