在VB.NET 2010中使用GetAsyncKeyState时的PInvokeStackImbalance

时间:2011-12-21 10:08:18

标签: vb.net dllimport keypress user32

我要做的是使用以下代码在我的主窗体上跟踪Ctrl + Tab按键

<DllImport("user32.dll", PreserveSig:=False)>
Private Shared Function GetAsyncKeyState(ByVal vKey As System.Windows.Forms.Keys) As Short
End Function

Private ReadOnly Property CtrlPressed As Boolean
    Get
        Dim keyval As Integer
        keyval = GetAsyncKeyState(Keys.ControlKey)
        If keyval = 0 Then
            CtrlPressed = False
        Else
            CtrlPressed = True
        End If
    End Get
End Property

但是在调用属性CtrlPressed时,我收到PInvokeStackImbalance错误。我确定声明了GetAsyncKeyState并且还导入了InteropServices,但CtrlPressed属性在语法上有错误。我该如何解决这个问题?

由于

1 个答案:

答案 0 :(得分:1)

堆栈不平衡错误几乎总是意味着您的P / Invoke定义签名错误。要做的第一件事就是仔细检查所有类型,并确保它们与本机函数的文档签名相匹配。在这种情况下,它看起来不错。

除非您将PreserveSig设置为False,否则我不确定原因。正如该字段的documentation所示,它设计用于返回错误代码的非托管方法(例如,HRESULT代码)。它指示运行时自动将这些错误代码转换为异常。但GetAsyncKeyState方法不会返回错误代码,因此启用此选项并没有多大意义。

以下代码适用于我:

<DllImport("user32.dll")> _
Private Shared Function GetAsyncKeyState(ByVal vKey As Keys) As Short
End Function

Private ReadOnly Property IsCtrlPressed As Boolean
    Get
        Dim isPressed As Short = GetAsyncKeyState(Keys.ControlKey)
        Return (isPressed & &H8000) != 0
    End Get
End Property

确保您已密切关注GetAsyncKeyState功能的documentation。具体来说,关于返回值的部分:

  

如果函数成功,则返回值指定自上次调用GetAsyncKeyState以来是否按下了键,以及该键当前是向上还是向下。如果设置了最高有效位,则键为关闭,如果设置了最低有效位,则在上一次调用GetAsyncKeyState后按下该键。但是,你不应该依赖这最后的行为;有关更多信息,请参阅备注。

     

以下情况的返回值为零:

     
      
  • 当前桌面不是活动桌面
  •   
  • 前台线程属于另一个进程,桌面不允许挂钩或日志记录。
  •