我正在维护一个显示 Caps Lock , Num Lock 和 Insert 键的键状态的应用程序。我一直在使用user32.dll
方法GetKeyState()
来完成此操作:
Public Declare Function GetKeyState Lib "user32" Alias "GetKeyState" (ByVal nVirtKey As Long) As Integer
Public Sub CheckKeys()
lblCaps.ForeColor = CType(IIf(GetKeyState(Keys.CapsLock) <> 0, Color.Black, Color.Gray), System.Drawing.Color)
lblIns.ForeColor = CType(IIf(GetKeyState(Keys.Insert) <> 0, Color.Black, Color.Gray), System.Drawing.Color)
lblNum.ForeColor = CType(IIf(GetKeyState(Keys.NumLock) <> 0, Color.Black, Color.Gray), System.Drawing.Color)
End Sub
这很好,但是现在在将目标框架升级到.NET 4.0后,我从托管调试助手收到错误:
调用PInvoke函数&#39; [application] :: GetKeyState&#39;堆栈不平衡。这很可能是因为托管PInvoke签名与非托管目标签名不匹配。检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配。
我知道我可以分别使用My.Computer.Keyboard.CapsLock
和My.Computer.Keyboard.NumLock
布尔值来获取 Caps Lock 和 Num Lock 键的状态,但是是否有类似的方法来获取插入键的状态?
答案 0 :(得分:1)
您的P / Invoke签名错误:
Public Declare Function GetKeyState Lib "user32" Alias "GetKeyState" (ByVal nVirtKey As Long) As Short
MSDN states GetKeyState
&#39; nVirtKey
参数的类型为int
,返回类型为short
,即32位分别为带符号和16位整数值。在VB.NET中,Long
类型为Int64
,因此您将覆盖堆栈。
在VB6中,Long
为32位有符号且Integer
为16位有符号值且Short
不是关键字,因此VB.NET&#39; s变化正在破灭。
将参数更改为ByVal nVirtKey As Integer
,将返回类型更改为As Short
。
我注意到,与Caps-Lock和Num-Lock不同, Insert 键没有系统范围的状态,并且每个应用程序甚至每个控件都有所不同。我相信(尽管不确定)保持Insert键的状态是你的责任,并且GetKeyState
将无法正常工作,特别是你想要使用Insert键。