此代码是从网上C#转换过来的.
主要是用在以下情况:给系统菜单,增加一个"关于菜单”.
Code
'SystemMenu类代码如下:
Imports System
Imports System.Windows.Forms
Imports System.Diagnostics
Imports System.Runtime.InteropServices
Public Class NoSystemMenuException
Inherits System.Exception
End Class
'这些值来自于MSDN
Public Enum ItemFlags
' The item
mfUnchecked = &H0
' is not checked
mfString = &H0
' contains a string as label
mfDisabled = &H2
' is disabled
mfGrayed = &H1
' is grayed
mfChecked = &H8
' is checked
mfPopup = &H10
' Is a popup menu. Pass the
' menu handle of the popup
' menu into the ID parameter.
mfBarBreak = &H20
' is a bar break
mfBreak = &H40
' is a break
mfByPosition = &H400
' is identified by the position
mfByCommand = &H0
' is identified by its ID
mfSeparator = &H800
End Enum
' is a seperator (String and
' ID parameters are ignored).
Public Enum WindowMessages
wmSysCommand = &H112
End Enum
'
' 帮助实现操作系统菜单的类的定义
'''.
'注意:用P/Invoke调用动态链接库中非托管函数时,应执行如下步骤:
'1,定位包含该函数的DLL。
'2,把该DLL库装载入内存。
'3,找到即将调用的函数地址,并将所有的现场压入堆栈。
'4,调用函数。
'
Public Class SystemMenu
' 提示:C#把函数声明为外部的,而且使用属性DllImport来指定DLL
'和任何其他可能需要的参数。
' 首先,我们需要GetSystemMenu() 函数
' 注意这个函数没有Unicode 版本
<DllImport("USER32", EntryPoint:="GetSystemMenu", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.Winapi)> _
Private Shared Function apiGetSystemMenu(ByVal WindowHandle As IntPtr, ByVal bReset As Integer) As IntPtr
End Function
' 还需要AppendMenu()。 既然 .NET 使用Unicode,
' 我们应该选取它的Unicode版本。
<DllImport("USER32", EntryPoint:="AppendMenuW", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.Winapi)> _
Private Shared Function apiAppendMenu(ByVal MenuHandle As IntPtr, ByVal Flags As Integer, ByVal NewID As Integer, ByVal Item As String) As Integer
End Function
'还可能需要InsertMenu()
<DllImport("USER32", EntryPoint:="InsertMenuW", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.Winapi)> _
Private Shared Function apiInsertMenu(ByVal hMenu As IntPtr, ByVal Position As Integer, ByVal Flags As Integer, ByVal NewId As Integer, ByVal Item As String) As Integer
End Function
Private m_SysMenu As IntPtr = IntPtr.Zero
' 系统菜单句柄
Public Sub New()
End Sub
' 在给定的位置(以0为索引开始值)插入一个分隔条
Public Function InsertSeparator(ByVal Pos As Integer) As Boolean
Return (InsertMenu(Pos, ItemFlags.mfSeparator Or ItemFlags.mfByPosition, 0, ""))
End Function
' 简化的InsertMenu(),前提――Pos参数是一个0开头的相对索引位置
Public Function InsertMenu(ByVal Pos As Integer, ByVal ID As Integer, ByVal Item As String) As Boolean
Return (InsertMenu(Pos, ItemFlags.mfByPosition Or ItemFlags.mfString, ID, Item))
End Function
' 在给定位置插入一个菜单项。具体插入的位置取决于Flags
Public Function InsertMenu(ByVal Pos As Integer, ByVal Flags As ItemFlags, ByVal ID As Integer, ByVal Item As String) As Boolean
' Return (apiInsertMenu(m_SysMenu, Pos, DirectCast(Flags, Int32), ID, Item) = 0)
Return (apiInsertMenu(m_SysMenu, Pos, CType(Flags, Int32), ID, Item) = 0)
End Function
' 添加一个分隔条
Public Function AppendSeparator() As Boolean
Return AppendMenu(0, "", ItemFlags.mfSeparator)
End Function
' 使用ItemFlags.mfString 作为缺省值
Public Function AppendMenu(ByVal ID As Integer, ByVal Item As String) As Boolean
Return AppendMenu(ID, Item, ItemFlags.mfString)
End Function
' 被取代的函数
Public Function AppendMenu(ByVal ID As Integer, ByVal Item As String, ByVal Flags As ItemFlags) As Boolean
Return (apiAppendMenu(m_SysMenu, CInt(Flags), ID, Item) = 0)
End Function
'从一个Form对象检索一个新对象
Public Shared Function FromForm(ByVal Frm As Form) As SystemMenu
Dim cSysMenu As New SystemMenu
cSysMenu.m_SysMenu = apiGetSystemMenu(Frm.Handle, 0)
If cSysMenu.m_SysMenu.Equals(IntPtr.Zero) Then
' 一旦失败,引发一个异常
Throw New NoSystemMenuException
End If
Return cSysMenu
End Function
' 当前窗口菜单还原
Public Shared Sub ResetSystemMenu(ByVal Frm As Form)
apiGetSystemMenu(Frm.Handle, 1)
End Sub
' 检查是否一个给定的ID在系统菜单ID范围之内
Public Shared Function VerifyItemID(ByVal ID As Integer) As Boolean
Return CBool((ID < &HF000 AndAlso ID > 0))
End Function
End Class
'调用代码如下:
Private Const m_AboutID As Integer = &H100
Private Const m_ResetID As Integer = &H101
Protected Overloads Overrides Sub WndProc(ByRef msg As Message)
' 通过截取WM_SYSCOMMAND消息并进行处理
' 注意,消息WM_SYSCOMMAND被定义在WindowMessages枚举类中
' 消息的WParam参数包含点击的项的ID
' 该值与通过上面类的InsertMenu()或AppendMenu()成员函数传递的一样
If msg.Msg = CInt(WindowMessages.wmSysCommand) Then
Select Case msg.WParam.ToInt32()
Case m_ResetID
' reset菜单项的ID
If True Then
If MessageBox.Show(Me, vbTab & "Are you sure?", "Question", MessageBoxButtons.YesNo) = DialogResult.Yes Then
' 复位系统菜单
SystemMenu.ResetSystemMenu(Me)
End If
End If
Exit Select
Case m_AboutID
If True Then
' “关于”菜单项
MessageBox.Show(Me, "关于", "关于")
End If
Exit Select
' 这里可以针对另外的菜单项设计处理过程
End Select
End If
' 调用基类函数
MyBase.WndProc(msg)
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
Try
Dim m_SystemMenu As SystemMenu = SystemMenu.FromForm(Me)
' 添加一个separator
m_SystemMenu.AppendSeparator()
' 添加"关于" 菜单项
m_SystemMenu.AppendMenu(m_AboutID, "关于")
' 在菜单顶部加上"复位"菜单项
m_SystemMenu.InsertSeparator(0)
m_SystemMenu.InsertMenu(0, m_ResetID, "复位系统菜单")
Catch generatedExceptionName As NoSystemMenuException
MsgBox(generatedExceptionName.ToString)
' err
' 建立你的错误处理器
End Try
End Sub
'SystemMenu类代码如下:
Imports System
Imports System.Windows.Forms
Imports System.Diagnostics
Imports System.Runtime.InteropServices
Public Class NoSystemMenuException
Inherits System.Exception
End Class
'这些值来自于MSDN
Public Enum ItemFlags
' The item
mfUnchecked = &H0
' is not checked
mfString = &H0
' contains a string as label
mfDisabled = &H2
' is disabled
mfGrayed = &H1
' is grayed
mfChecked = &H8
' is checked
mfPopup = &H10
' Is a popup menu. Pass the
' menu handle of the popup
' menu into the ID parameter.
mfBarBreak = &H20
' is a bar break
mfBreak = &H40
' is a break
mfByPosition = &H400
' is identified by the position
mfByCommand = &H0
' is identified by its ID
mfSeparator = &H800
End Enum
' is a seperator (String and
' ID parameters are ignored).
Public Enum WindowMessages
wmSysCommand = &H112
End Enum
'
' 帮助实现操作系统菜单的类的定义
'''.
'注意:用P/Invoke调用动态链接库中非托管函数时,应执行如下步骤:
'1,定位包含该函数的DLL。
'2,把该DLL库装载入内存。
'3,找到即将调用的函数地址,并将所有的现场压入堆栈。
'4,调用函数。
'
Public Class SystemMenu
' 提示:C#把函数声明为外部的,而且使用属性DllImport来指定DLL
'和任何其他可能需要的参数。
' 首先,我们需要GetSystemMenu() 函数
' 注意这个函数没有Unicode 版本
<DllImport("USER32", EntryPoint:="GetSystemMenu", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.Winapi)> _
Private Shared Function apiGetSystemMenu(ByVal WindowHandle As IntPtr, ByVal bReset As Integer) As IntPtr
End Function
' 还需要AppendMenu()。 既然 .NET 使用Unicode,
' 我们应该选取它的Unicode版本。
<DllImport("USER32", EntryPoint:="AppendMenuW", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.Winapi)> _
Private Shared Function apiAppendMenu(ByVal MenuHandle As IntPtr, ByVal Flags As Integer, ByVal NewID As Integer, ByVal Item As String) As Integer
End Function
'还可能需要InsertMenu()
<DllImport("USER32", EntryPoint:="InsertMenuW", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.Winapi)> _
Private Shared Function apiInsertMenu(ByVal hMenu As IntPtr, ByVal Position As Integer, ByVal Flags As Integer, ByVal NewId As Integer, ByVal Item As String) As Integer
End Function
Private m_SysMenu As IntPtr = IntPtr.Zero
' 系统菜单句柄
Public Sub New()
End Sub
' 在给定的位置(以0为索引开始值)插入一个分隔条
Public Function InsertSeparator(ByVal Pos As Integer) As Boolean
Return (InsertMenu(Pos, ItemFlags.mfSeparator Or ItemFlags.mfByPosition, 0, ""))
End Function
' 简化的InsertMenu(),前提――Pos参数是一个0开头的相对索引位置
Public Function InsertMenu(ByVal Pos As Integer, ByVal ID As Integer, ByVal Item As String) As Boolean
Return (InsertMenu(Pos, ItemFlags.mfByPosition Or ItemFlags.mfString, ID, Item))
End Function
' 在给定位置插入一个菜单项。具体插入的位置取决于Flags
Public Function InsertMenu(ByVal Pos As Integer, ByVal Flags As ItemFlags, ByVal ID As Integer, ByVal Item As String) As Boolean
' Return (apiInsertMenu(m_SysMenu, Pos, DirectCast(Flags, Int32), ID, Item) = 0)
Return (apiInsertMenu(m_SysMenu, Pos, CType(Flags, Int32), ID, Item) = 0)
End Function
' 添加一个分隔条
Public Function AppendSeparator() As Boolean
Return AppendMenu(0, "", ItemFlags.mfSeparator)
End Function
' 使用ItemFlags.mfString 作为缺省值
Public Function AppendMenu(ByVal ID As Integer, ByVal Item As String) As Boolean
Return AppendMenu(ID, Item, ItemFlags.mfString)
End Function
' 被取代的函数
Public Function AppendMenu(ByVal ID As Integer, ByVal Item As String, ByVal Flags As ItemFlags) As Boolean
Return (apiAppendMenu(m_SysMenu, CInt(Flags), ID, Item) = 0)
End Function
'从一个Form对象检索一个新对象
Public Shared Function FromForm(ByVal Frm As Form) As SystemMenu
Dim cSysMenu As New SystemMenu
cSysMenu.m_SysMenu = apiGetSystemMenu(Frm.Handle, 0)
If cSysMenu.m_SysMenu.Equals(IntPtr.Zero) Then
' 一旦失败,引发一个异常
Throw New NoSystemMenuException
End If
Return cSysMenu
End Function
' 当前窗口菜单还原
Public Shared Sub ResetSystemMenu(ByVal Frm As Form)
apiGetSystemMenu(Frm.Handle, 1)
End Sub
' 检查是否一个给定的ID在系统菜单ID范围之内
Public Shared Function VerifyItemID(ByVal ID As Integer) As Boolean
Return CBool((ID < &HF000 AndAlso ID > 0))
End Function
End Class
'调用代码如下:
Private Const m_AboutID As Integer = &H100
Private Const m_ResetID As Integer = &H101
Protected Overloads Overrides Sub WndProc(ByRef msg As Message)
' 通过截取WM_SYSCOMMAND消息并进行处理
' 注意,消息WM_SYSCOMMAND被定义在WindowMessages枚举类中
' 消息的WParam参数包含点击的项的ID
' 该值与通过上面类的InsertMenu()或AppendMenu()成员函数传递的一样
If msg.Msg = CInt(WindowMessages.wmSysCommand) Then
Select Case msg.WParam.ToInt32()
Case m_ResetID
' reset菜单项的ID
If True Then
If MessageBox.Show(Me, vbTab & "Are you sure?", "Question", MessageBoxButtons.YesNo) = DialogResult.Yes Then
' 复位系统菜单
SystemMenu.ResetSystemMenu(Me)
End If
End If
Exit Select
Case m_AboutID
If True Then
' “关于”菜单项
MessageBox.Show(Me, "关于", "关于")
End If
Exit Select
' 这里可以针对另外的菜单项设计处理过程
End Select
End If
' 调用基类函数
MyBase.WndProc(msg)
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
Try
Dim m_SystemMenu As SystemMenu = SystemMenu.FromForm(Me)
' 添加一个separator
m_SystemMenu.AppendSeparator()
' 添加"关于" 菜单项
m_SystemMenu.AppendMenu(m_AboutID, "关于")
' 在菜单顶部加上"复位"菜单项
m_SystemMenu.InsertSeparator(0)
m_SystemMenu.InsertMenu(0, m_ResetID, "复位系统菜单")
Catch generatedExceptionName As NoSystemMenuException
MsgBox(generatedExceptionName.ToString)
' err
' 建立你的错误处理器
End Try
End Sub