如何正确将'About'按钮添加到系统菜单?



我试图添加一个"关于"按钮到我的应用程序的系统菜单,但我发现的代码是抛出一个错误-

无法在DLL 'user32'中找到名为'AppendMenu'的入口点。

我想知道是否有人可以请看看代码和建议我需要做什么来修复它?谢谢。

Private Declare Function GetSystemMenu Lib "user32" (ByVal hWnd As IntPtr, ByVal bRevert As Boolean) As IntPtr
Private Declare Function AppendMenu Lib "user32" (ByVal hMenu As IntPtr, ByVal uFlags As Int32, ByVal uIDNewItem As IntPtr, ByVal lpNewItem As String) As Boolean
Private Const MF_STRING As Integer = &H0
Private Const MF_SEPARATOR As Integer = &H800
Private Sub AddSysMenuItems()
    'Get the System Menus Handle.
    Dim hSysMenu As IntPtr = GetSystemMenu(Me.Handle, False)
    'Add a standard Separator Item.
    AppendMenu(hSysMenu, MF_SEPARATOR, 1000, Nothing)
    'Add an About Menu Item.
    AppendMenu(hSysMenu, MF_STRING, 1001, "About")

End Sub

嗯,消息是准确的,在user32.dll中没有名为"AppendMenu"的入口点。它实际上有两个版本。一个叫做AppendMenuA, A的意思是Ansi。使用8位编码字符串的遗留版本,通常用于旧的C程序。AppendMenuW, W的意思是宽。它接受一个Unicode字符串,就像所有winapi函数在现代Windows版本上所做的那样。

旧式的Declare语句使用了遗留函数。您应该使用Alias关键字来给出正确的入口点名称:

Private Declare Function AppendMenu Lib "user32.dll" Alias "AppendMenuA" (ByVal hMenu As IntPtr, ByVal uFlags As Int32, ByVal uIDNewItem As IntPtr, ByVal lpNewItem As String) As Boolean

或者直接叫它AppendMenuA。使用遗留函数不是很美观,尽管将"About"转换为Unicode不会有问题。但是我还是倾向于使用现代的方式来声明pinvoke函数,它除了自动映射到A或W版本之外还有许多优点:

Imports System.Runtime.InteropServices
Imports System.ComponentModel
...
    <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
    Private Shared Function AppendMenu(ByVal hMenu As IntPtr, ByVal uFlags As Int32, ByVal uIDNewItem As IntPtr, ByVal lpNewItem As String) As Boolean
    End Function
...
        If Not AppendMenu(hSysMenu, MF_STRING, IntPtr.Zero, "About") Then
            Throw New Win32Exception()
        End If

最新更新