0

我要做的是使用以下代码在我的主窗体上跟踪 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属性在语法上存在问题。我该如何解决这个问题?

谢谢

4

1 回答 1

1

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

除了你设置PreserveSigFalse,我不太确定为什么。正如该字段的文档所示,它设计用于返回错误代码(例如,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具体来说,关于返回值的部分:

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

对于以下情况,返回值为零:

  • 当前桌面不是活动桌面
  • 前台线程属于另一个进程,桌面不允许挂钩或日志记录。
于 2011-12-21T10:30:48.093 回答