Here's a version I wrote in inline assembly:
Code:
void SetKey( BOOL bState,int keyID )
{
BYTE keyState[256];
/*
GetKeyboardState((LPBYTE)&keyState);
if( (bState && !(keyState[keyID] & 1)) || (!bState && (keyState[keyID] & 1)) )
{
keybd_event( keyID,0x45,KEYEVENTF_EXTENDEDKEY | 0,0 );
// Simulate a key release
keybd_event( keyID,0x45,KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP,0);
}
*/
__asm {
lea eax, keyState
push eax // Note: This pushes a pointer to keyState
call dword ptr [GetKeyboardState]
cmp bState, 0
je cont001
mov ebx, keyID
test keyState[ebx], 1
je cont002
jmp skip001
cont001: // bState can safely be assumed to be false at this point
mov ebx, keyID
test keyState[ebx], 1
je skip001
cont002:
push 0
push KEYEVENTF_EXTENDEDKEY // | 0
push 45H
push keyID
call dword ptr [keybd_event]
push 0
push KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP
push 45H
push keyID
call dword ptr [keybd_event]
skip001:
}
}
I hope you can adapt it to your requirements. In case of difficulties I'm willing to assist of course. :)
There is, BTW, some room for optimization in the translation of the
if condition: If you assume that the C++ implementation you use always represents the
bool value
true as a number that has the least significant bit set, the whole condition boils down to a mere bit-wise XOR. This is far beyond the demands of the C++ standard but I think it's common in concrete implementations.
Of course the XOR approach can even be used while perfectly respecting the C++ standard, but then there needs to be some conversion applied to the
bool operand which may outweigh the gain of that approach.
In general, I don't see a point in trying to remove the compiler/runtime overhead from C++ compiled code. This usually is much more effort than writing it in assembly language in the first place (maybe taking C++ compiled code as a model or inspiration).
:eek: You don't mean that seriously, do you? Please not that creepy busy-waiting! :thumbd: Windows has such a beautiful
Sleep() function for that... Looks like you compiled the code without optimization only, otherwise I would've assumed that the compiler optimized that away anyway.
BTW, this is redundant. The sole purpose of the
TEST instruction is to perform an
AND operation and set the flags accordingly, but to discard the result. OTOH the
AND instruction sets the flags as well (while keeping the result). So in this case you can either omit the
TEST instruction or omit the
AND and change the
TEST to
TEST AL, 1. Besides, you even can apply the
TEST directly to a memory location so the whole thing would boil down to:
Code:
test BYTE[ State + VK_CONTROL ], 1
je PASSED
Ok, I admit: I'm counting nanoseconds again... :rolleyes: