Question

I am trying to add an 'About' button to the System menu of my app, but the code that I found is throwing an error -

Unable to find an entry point named 'AppendMenu' in DLL 'user32'.

I wonder if someone could please take a look at the code and advise on how what I would need to do to fix it? Thanks.

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
Was it helpful?

Solution

Well, the message is accurate, there is no entry point named "AppendMenu" in user32.dll. It actually has two versions of it. One is named AppendMenuA, the A means Ansi. The legacy version that uses 8-bit encoded strings, commonly used in old C programs. And AppendMenuW, the W means Wide. It takes a Unicode string like all winapi functions do on modern Windows versions.

Your old-style Declare statement is using the legacy function. You should use the Alias keyword to give the proper entrypoint name:

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

Or just plain call it AppendMenuA. Using the legacy function isn't very pretty, although it won't have a problem converting "About" to Unicode. But do favor the modern way to declare pinvoke functions, it has many advantages beyond automatically mapping to the A or W version:

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top