Jump to content

GetAsyncKeyState, _IsPressed() vs. the Bluetooth headset. Now, fight !


Go to solution Solved by argumentum,

Recommended Posts

Posted (edited)

GetAsyncKeyState vs. Bluetooth headset
image.png.636c48baedfba069f245947079376358.png

Using the keyboard, the play/pause button behaves as expected but pressing the button in my Bluetooth headset does not.
My solution to this bad implementation in the driver is to add a "is held" vs "is pressed"/"is clicked" in an @extended return: ( 1 = that is held, vs 0 = keyboard repeat ) See edit below.

Func _IsPressed($sHexKey, $vDLL = "user32.dll")
    Local $aCall = DllCall($vDLL, "short", "GetAsyncKeyState", "int", "0x" & $sHexKey)
    If @error Then Return SetError(@error, @extended, False)
    Return SetError(0, BitAND($aCall[0], 0x1), BitAND($aCall[0], 0x8000) <> 0)
EndFunc   ;==>_IsPressed

So the question/help is: are you MVP/developers ok with this added feature ?, will any of you add this request to the trac system or should I add the request ?
Is this code above perfect or should be coded differently?

I'll use it for my case as:

If _IsPressed("B3", $hDLL) And @extended Then ConsoleWrite("Play/Pause" & @CRLF)

Thanks in advance for your participation.

PS: do the same to _WinAPI_GetAsyncKeyState(). Not needed.

Edit: Opened a trac ticket.

Edit: 2024.01.29: A better description of the code, given that I've change the logic:
The @extended holds the LSB ( least significant bit ). What is meant is that when the key is first pressed, the LSB is set to 1. On subsequent calls, the LSB is set to zero and the claim is to not trust the LSB ( BitAND($aCall[0], 0x1) @extended ) due to the nature of multitasking, hence the BitAND($aCall[0], 0x8000) return.

A good description would be:
@extended returns the LSB of the keypress. (See MSDN remarks)
 

Edited by argumentum
better code

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted

I am not sure if it's reliable. Please try this script:

$hUser32 = DllOpen('user32.dll')

While True
    If _IsPressed('1B', $hUser32) Then ExitLoop     ; Exit if ESC key is pressed
    While _IsPressed('41', $hUser32)
        ConsoleWrite('A is pressed.' & @TAB & @extended & @CRLF)
        Sleep(10)
    WEnd
    Sleep(10)
WEnd

DllClose($hUser32)

Func _IsPressed($sHexKey, $vDLL = "user32.dll")
    Local $aCall = DllCall($vDLL, "short", "GetAsyncKeyState", "int", "0x" & $sHexKey)
    If @error Then Return SetError(@error, @extended, False)
    Return SetError(0, $aCall[0] = 0xFFFF8000, BitAND($aCall[0], 0x8000) <> 0)
EndFunc

If I keep key A pressed down I would expect to get @extended = 1 until I release the key but I get mixed values of 0 and 1.

Posted (edited)
43 minutes ago, Andreik said:

but I get mixed values of 0 and 1.

the 1's is the key pressed but, every so often the keyboard will replay the key held down ( by a delay declared in the registry ).
Therefore between repeats, you'll get 1's and the 0's mean the key got pressed or repeated.

My problem is that the Bluetooth driver play/pause on fast click but turns the volume up/down if the key in the headset is held. Is a driver misbehaving that gives me the problem.

Using _WinAPI_SetWindowsHookEx(), it sees the single press (play/pause), but not the volume up/down.
Hence it is a problem with the OS ( by the way it integrates the Bluetooth and processes the user input device ).
The @extended info, is just extra info, that in my case is useful and does not brake prior code. Usually that extra info is meaningless. 

The post, is to make sure that I -not being a programmer-, came up with an implementation that is sound for production and not just a hack for my issue.
That is coded as it should be from the point of view of an experienced programmer.

Edited by argumentum
clarify

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted (edited)

For your specific case it's perfect, what I'm saying it's that probably it's not the best idea to change the actual _IsPressed() function since your proposed function it's working just in certain conditions. It might be better since it gives you additional info but not very consistent. Anyway I am happy that you posted because others might use this additional info so it's good to have another version of this function.

19 minutes ago, argumentum said:

I -not being a programmer

You have plenty of good code around. I'll ask mods to delete all your posts if you will keep saying this in 2024. :whistle: :lol:

 

PS: this is how you know you are getting old, when there are like 5 minutes until this year will pass but you are too lazy for anything else and prefer to test random code :yes:

Edited by Andreik
Posted
2 minutes ago, Andreik said:

since it gives you additional info but not very consistent.

It is consistent. The 0's mean that the key press got printed. The 1's mean that the key is still pressed but is not the first press. If the key is still held after a set time, well, repeat the keypress.

5 minutes ago, Andreik said:

if you will keep saying this in 2024. :whistle: :lol:

Thanks but, I have nowhere the experience or knowledge to say that what I present, is without a doubt the best there is. It may very well be, but I'm not that god like in regards to code.
I do present myself to my clients as god like, but is because I, in fact am, for them :lol: 

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted
1 minute ago, argumentum said:

It is consistent. The 0's mean that the key press got printed. The 1's mean that the key is still pressed but is not the first press. If the key is still held after a set time, well, repeat the keypress.

Ahhh I see now. I understand so hard and I'm not even drunk. In this case it's a nice addition. I'll have some more tests.

 

3 minutes ago, argumentum said:

I do present myself to my clients as god like, but is because I, in fact am, for them :lol: 

Just don't overprice them because you feel like a god. :lol:

Posted

The reason why we cannot rely on isHeld approach is well explained in MSDN :

Quote

Although the least significant bit of the return value indicates whether the key has been pressed since the last query, due to the preemptive multitasking nature of Windows, another application can call GetAsyncKeyState and receive the "recently pressed" bit instead of your application. The behavior of the least significant bit of the return value is retained strictly for compatibility with 16-bit Windows applications (which are non-preemptive) and should not be relied upon.

 

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...