如何从托管的vb.net代码调用TrackPopupMenu函数

时间:2013-07-01 06:45:03

标签: vb.net marshalling unmanaged managed vb6-migration

我试图调用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)

以下是矩形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但仍然收到错误。

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

1 个答案:

答案 0 :(得分:1)

您的声明是错误的。第一个参数是菜单的句柄,因此必须是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中,不得不对它进行pinvoke它应该是非常罕见的。 TrackPopupMenu已由.NET ContextMenu类调用。 ContextMenuStrip类为其提供了更现代的版本,并提供了更好的渲染选项。