1

我正在尝试调用TrackPopupMenu函数以在运行时从托管的 VB.NET 代码显示菜单。以下是我得到的错误:

检测到 PInvokeStackImbalance 消息:对 PInvoke 函数“UeWIPopupX!UeWIPopupX.mDeclares:: TrackPopupMenu ”的调用使堆栈不平衡。这可能是因为托管 PInvoke 签名与非托管目标签名不匹配。检查 PInvoke 签名的调用约定和参数是否与目标非托管签名匹配。

下面是我用于 TrackPopupMenu 函数的声明:

 <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True, CallingConvention:=CallingConvention.StdCall)> _
Friend Function TrackPopupMenu(ByVal hMenu As Long, ByVal wFlags As Integer, ByVal x As Integer, ByVal y As Integer, ByVal nReserved As Integer, ByVal hWnd As IntPtr, ByVal lprc As RECT) As Integer

End Function

下面是调用TrackPopupMenu函数的代码:

 dim lpRc as RECT
 Dim tP As POINTAPI
 Dim lR as Integer  
 Dim lUn as Integer

 lUn = TPM_RIGHTBUTTON Or TPM_TOPALIGN Or TPM_LEFTALIGN Or TPM_RETURNCMD   
  tP.x = 50
  tP.y = 100
 'Here I am getting the error
 lR = TrackPopupMenu(m_ppMenu.Tools(1).hMenu, lUn, tP.x, tP.y, 0, m_hWndOwner, lpRC)

以下是 rectangle 的声明RECT

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Structure RECT
    Dim Left As Integer
    Dim Top As Integer
    Dim Right As Integer
    Dim Bottom As Integer
End Structure

TrackPopupMenu 调用期间的所有参数都有一些值。我尝试了不同的 callConvention 但仍然收到错误。

我无法解决这个问题。有谁知道如何解决这个问题?

4

1 回答 1

2

你的声明是错误的。第一个参数是菜单句柄,因此它必须是 IntPtr。最后一个参数是一个指向RECT 的指针。VB.NET 中的 ByRef。由于它实际上并未使用,因此最好将其声明为 ByVal IntPtr,这样就不需要 RECT 声明。在您的通话中传递 IntPtr.Zero。返回值是布尔值,而不是整数。如果返回 False,则抛出 Win32Exception。使固定:

<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Friend Function TrackPopupMenu(ByVal hMenu As IntPtr, ByVal wFlags As Integer, _
    ByVal x As Integer, ByVal y As Integer, ByVal nReserved As Integer, _
    ByVal hWnd As IntPtr, ByVal ignored As IntPtr) As Boolean
End Function

有一些提示你没有得到正确的菜单,很难想象你是如何想出 Long 作为参数类型的。请注意,此功能已经巧妙地包装在 .NET 中,必须调用它应该非常罕见。.NET ContextMenu 类已经调用了 TrackPopupMenu。ContextMenuStrip 类提供了更现代的版本,具有更好的呈现选项。

于 2013-07-01T09:52:47.720 回答