Reputation: 131
When I try converting ASCII integers to keys that have more than one character I always get an incorrect result. A -> z / 0 -> 9 works correctly, but any key press that has more than one character always gives an incorrect result, e.g F1 -> F12 / Numlock 0 -> Numlock 9 / home key etc.
example, ASCII code for F3
is 114
but when I convert 114
to character it always outputs R
instead of F3
This is something similar to what I have tried:
(It seems useless in this example, but this isn't exactly how I will be using it)
Dim bind = "114" '(F3) depending on user input
Dim c As Char = bind 'Convert the ASCII integer(bind) to character(c)
TextBox1.text = c 'which in this case outputs as "r"
How do I fix this so that 114 / any other key that has more than one character
will output as F3 / their correct value
?
Edit, Updated example:
This code is for user defined shortcuts which needs to work outside the application, so I was using GetAsyncKeyState
to determine which ASCII integer was pressed, then using that ASCII integer for the bind, but I need to also then convert that integer into a character (F3 in this case) so the user knows which keybind is currently active.
Do
ExitLoop = False
For i = 0 To 255
result = 0
result = GetAsyncKeyState(i)
If result = -32767 Then
Dim c As Char = Chr(i) ' Convert ASCII integer to char.
Bind1.Text = c
Shortcut1 = i
ExitLoop = True
End If
Next i
Loop While ExitLoop = False
Upvotes: 1
Views: 1206
Reputation: 15774
The title is a bit misleading, as it's not the right way to solve your problem. You have GetAsyncKeyState which tells you about the state of the key passed by index according to its Virtual-Key Code. The value returned tells us if the key is currently pressed down. From the MSDN page,
If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState.
Since the return value is a UInt16
, and we want to see if the most significant bit is 1, we will And
the result with 0xFFFF (in VB, &HFFFF).
The program below will report all keys which are currently pressed, and put them together in a message, and put that message in the title bar of the form. Make a new WinForms project, and paste this code. You may need to delete Dispose
from the code behind the designer. The function GetVKeyPressed
has a limited number of supported keys, but you can make the required cases according to the Virtual-Key Code page.
Public Class Form1
Implements IDisposable
Declare Function GetAsyncKeyState Lib "User32" (ByVal vKey As Integer) As UInt16
Private timer As New System.Threading.Timer(AddressOf timerCallback, Nothing, -1, -1)
Private Function GetVKeyPressed(vKey As Integer) As String
' see https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
Select Case vKey
Case &H30 To &H39 ' 0 to 9
Return Chr(vKey).ToString()
Case &H41 To &H5A ' A to Z
Return Chr(vKey).ToString()
Case &H70 To &H87
Return "F" & (vKey - &H70 + 1)
Case &H1
Return "LMB"
Case &H2
Return "RMB"
Case Else
Return "Key not supported yet!"
End Select
End Function
Private Sub timerCallback(state As Object)
Dim results As New Dictionary(Of Integer, UInt16)()
For i = 0 To 255
results.Add(i, GetAsyncKeyState(i))
Next i
Dim pressedKeys = String.Join(", ", results.
Where(Function(kvp) kvp.Value And &HFFFF).
Select(Function(kvp) GetVKeyPressed(kvp.Key)))
Try
Me.Invoke(Sub() Me.Text = pressedKeys)
Catch ex As ObjectDisposedException
End Try
timer.Change(100, -1)
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
timer.Change(100, -1)
End Sub
Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
timer.Change(-1, -1)
End Sub
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
timer.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
End Class
Upvotes: 1