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

Posted

技术标签:

【中文标题】在 VB.NET 2010 中使用 GetAsyncKeyState 时的 PInvokeStackImbalance【英文标题】:PInvokeStackImbalance when using GetAsyncKeyState in VB.NET 2010 【发布时间】:2012-01-25 03:57:10 【问题描述】:

我正在尝试使用以下代码在我的主窗体上跟踪 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】:

堆栈不平衡错误几乎总是意味着您的 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

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

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

以下情况返回值为零:

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

【讨论】:

以上是关于在 VB.NET 2010 中使用 GetAsyncKeyState 时的 PInvokeStackImbalance的主要内容,如果未能解决你的问题,请参考以下文章

在 Visual Basic VB.Net 2010 中使用 System.DateTime 类型作为可选参数

VB.Net 2010中 ./和../的含义

如何在 vb.net 2010 的我的文档/屏幕截图中保存 jpg 文件

使用 vb.net 2010 锁定后端访问数据库中的表

从 Visual Studio 2010 (VB.NET) 读取访问查询

在 Visual Studio 2010 的 vb.net 中创建钻取 rdlc 报告