I apologise for not doing more research on my own. I have searched MSDN, but the simple (I think) information I want seems to be buried in masses of what is not immediately useful to me.
I think GetAsyncKeyState would do it if invoked once for each key (as well as once at the start of the routine I want to pause).
I am looking for a function that when called will return when and only when (although a forced return would also be nice) a key is pressed - any key.
Can anyone suggest an answer or a direction for further research?
Thank you - Robert Leeper
Quote from: raleep on March 12, 2015, 01:14:58 PM
I am looking for a function that when called will return when and only when (although a forced return would also be nice) a key is pressed - any key.
Never mind about the forced return - I see how to do [something like] that.
if you're talking about console-mode programs, i suggest crt__getch
it's part of the msvcrt library
but, the console is buggish, and the library often yields best results
for GUI-mode programs, you write a handler in WndProc
it activates when a key is pressed, but allows other processing when no key is in the buffer
Hello raleep,
Don't really think this is what you want but at least it's a starting point
include \masm32\include\masm32rt.inc
.data
thechar db 0, 0
format db 'You pressed %s',10,0
.code
start:
print "Press any key, ctrl-C to exit", 10, 0
@@:
call wait_key
mov thechar, al
invoke crt_printf, ADDR format, ADDR thechar
jmp @B
ret
end start
Assume you know how to run this with masm32
wait_key is using the function dedndave mentioned, crt__getch, and can be found in \masm32\m32lib\wait_key.asm
Assuming that your goal here is to detect key presses in your app, and not in other apps, crt__getch is easy, and while it cannot detect "any" key it can detect all but the shift and toggle keys.
Edit: modified code to display the return value as a number and a character.
;===============================================================================
include \masm32\include\masm32rt.inc
;===============================================================================
.data
.code
;===============================================================================
start:
;===============================================================================
@@:
invoke crt__getch
cmp eax, "X"
je @F
cmp eax, "x"
je @F
printf("%d\t%c\n",eax,eax)
jmp @B
@@:
inkey
exit
end start
;===============================================================================
hi Michael,
as i recall, _getch IS capable of detecting all keys except system keys (ALT-?) and CTRL-C (CTRL-Break)
if you want to detect CTRL-Break, install a handler for it
if it returns 0 or 0E0h on the first call, it must be called again (arrow keys, function keys, etc)
very similar to how the old 16-bit INT 16h worked
here is a function that returns immediately if no key has been pressed (non-blocking)
it's one i have used often
give me a few minutes, and i can adapt it to a blocking function
;*************************************************************************
InKyb PROC
;Polled Keyboard Input - DednDave 8, 2010
;
;This function returns a keystroke in EAX if there is one in the buffer.
;If the buffer is empty, the function returns immediately.
;
;If the keyboard buffer is empty, AH = 0, AL = 0, ZF = 1.
;If the stroke is a regular key, AH = 0, AL = key char, ZF = 0.
;If the stroke is an extended key, AH = extended key, AL = E0h, ZF = 0.
;If the stroke is a function key, AH = function key, AL = 0, ZF = 0.
;
;ECX, EDX are not preserved.
call crt__kbhit
or eax,eax
jz InKyb1
call crt__getch
and eax,0FFh
jz InKyb0
cmp al,0E0h
jnz InKyb1
InKyb0: push eax
call crt__getch
pop edx
shl eax,8
or eax,edx
InKyb1: retn
InKyb ENDP
;*************************************************************************
here - give this a try....
Dave, from a 32-bit app running under Windows 7-64 the _getch function does not return until you press a non-toggle or non-shift key. And, one that I forgot to test, it does not return when you press the Pause/Break key. The arrow and function keys work as you describe, returning 0E0h ahead of the arrow keys and 0 ahead of the function keys.
MSDN _getch _getwch (https://msdn.microsoft.com/en-us/library/078sfkak.aspx)
And your app behaves the same way, not responding to the shift, toggle, or Pause/Break keys.
that's strange
under XP (32-bit), shift , caps lock, and num lock work as expected
even many of the CTRL keys work
ALT keys are system keys, which msvcrt authors chose not to override - understandably
The key combinations involving the shift and toggle keys, or at least the ones that I tested, work as expected. _getch, like most or all high-level input functions, does not meet the "any key" requirement because it does not detect the shift or toggle keys when they are pressed as single keys. Perhaps I should have interpreted "any key" as "any normal key".
you can use one of the console API functions to "get any key"
really, i try not to spend too much time on it, because the console is buggish
no matter what you do, you get buggish behavior :P
to me, it works fine for simple test programs or tools in "teletype" fashion
i.e., print a line, get a line - no fancy cursor movement stuff
here's one that uses ReadConsoleInput...
;***********************************************************************************************
AnyKey PROC
;Wait for Any Console Key Press - DednDave
;version 1, 12-2011
;version 2, 2-2013
;
; This function returns when any console key is pressed (bKeyDown = 1).
;A possible drawback is that all input event records are removed from
;the console input queue until a key is pressed. In many cases, this is
;not an issue. The virtual key code, virtual scan code, TCHAR character,
;and control key state values are returned in registers.
;Call With: Nothing
;
; Returns: EAX = TCHAR character (high word of EAX = 0)
; ECX = control key state flags
; Bit Name Meaning
; 0 RIGHT_ALT_PRESSED Right ALT key is pressed
; 1 LEFT_ALT_PRESSED Left ALT key is pressed
; 2 RIGHT_CTRL_PRESSED Right CTRL key is pressed
; 3 LEFT_CTRL_PRESSED Left CTRL key is pressed
; 4 SHIFT_PRESSED SHIFT key is pressed
; 5 NUMLOCK_ON NUM LOCK light is on
; 6 SCROLLLOCK_ON SCROLL LOCK light is on
; 7 CAPSLOCK_ON CAPS LOCK light is on
; 8 ENHANCED_KEY Key is enhanced
; EDX:
; low word (DX) = virtual key code
; high word = virtual scan code
;
; all other registers are preserved
;-------------------------------------------------
LOCAL ir :INPUT_RECORD
LOCAL uRecCnt :UINT
LOCAL hStdInp :HANDLE
;-------------------------------------------------
INVOKE GetStdHandle,STD_INPUT_HANDLE
mov hStdInp,eax
.repeat
INVOKE ReadConsoleInput,hStdInp,addr ir,1,addr uRecCnt
movzx ecx,word ptr ir.EventType
mov edx,dword ptr ir.KeyEvent.wVirtualKeyCode
.until (ecx==KEY_EVENT) && (ecx==ir.KeyEvent.bKeyDown) && (dx!=VK_SHIFT) && (dx!=VK_CONTROL) && (dx!=VK_MENU)
movzx eax,word ptr ir.KeyEvent.UnicodeChar
mov ecx,ir.KeyEvent.dwControlKeyState
ret
AnyKey ENDP
;***********************************************************************************************
it doesn't mention it, but that one is UNICODE aware, i think
notice that you can modify this line to customize behaviour for different key sets
.until (ecx==KEY_EVENT) && (ecx==ir.KeyEvent.bKeyDown) && (dx!=VK_SHIFT) && (dx!=VK_CONTROL) && (dx!=VK_MENU)
Quote from: dedndave on March 12, 2015, 02:07:17 PM
if you're talking about console-mode programs, i suggest crt__getch
it's part of the msvcrt library
but, the console is buggish, and the library often yields best results
for GUI-mode programs, you write a handler in WndProc
it activates when a key is pressed, but allows other processing when no key is in the buffer
sbrtst_test:
call beep0
pushad
call wosw
invoke crt__getch
popad
jmp sbrtst_test
This doesn't work for me; it just goes on beeping until stopped.
Old-fashioned but seems to work:
include \masm32\include\masm32rt.inc
.data?
kb1 db 256 dup(?)
kb2 db 256 dup(?)
.code
start:
mov esi, offset kb1
mov edi, offset kb2
.Repeat
invoke GetKeyboardState, esi
.Repeat
invoke Sleep, 1
invoke GetKeyState, VK_SHIFT
invoke GetKeyboardState, edi
mov ecx, 255
push esi
push edi
repe cmpsb
pop edi
pop esi
.Until sdword ptr ecx>0
neg cl
sub cl, 2
.Break .if ecx==VK_ESCAPE
print str$(ecx), " was pressed", 13, 10
.Until 0
print "bye"
exit
end start
sbrtst_test:
call beep0
pushad
call wosw
invoke crt__getch
popad
jmp sbrtst_test
that code will continually loop and beep whenever a key is pressed
first of all, the PUSHAD/POPAD preserves and restores all the registers, including EAX
crt__getch returns a value in EAX that should be tested for key-presses (destroyed by POPAD)
and - you don't display that value
also, the loop ends with an unconditional branch back to the top
you may way to use a conditional branch, instead
I know this is a dumb question, but I don't know why it is ... why don't u use the extremely straightforward example I posted?
Quote from: rrr314159 on March 15, 2015, 02:31:42 PM
why don't u use the extremely straightforward example I posted?
OP wants
any key, including Shift etc; which, btw, works with the example that
I posted
(just to keep up the competitive spirit here :badgrin: )
Competition is a fine thing, keeps everyone on their toes, establishes camaraderie and a mutual sense of shared progress. It's great except that, sometimes, when carried too far, it can lead to a very undesirable consequence, which ruins the friendly spirit hutch works so assiduously to cultivate here - and that's no good. That undesirable consequence is: sometimes I lose!
In this case, you're right, OP asked for *all* keys; your routine does that. However - OP is working with dedndave to get a routine working with _getch, even as we speak. Deduction, *all* keys isn't so critical. My example (which I slaved over for, at the very least, a minute or two) also uses _getch; works; is as simple as dirt; so why not start there, and move up to GetKeyboardState after, if really desired?
Moving along, the way you do GetKeyboardState is vey clean compared to hack jobs I've seen. I guess the call to GetKeyState is necessary, or you wouldn't do it, but I don't really know why. OP mentioned GetAsyncKeyState; if that's really wanted your routine (I think) is easily modified to use that instead ... ?
So I reckon you win, still there's a decent chance that *all* keys really isn't necessary.
Quote from: rrr314159 on March 15, 2015, 05:13:16 PMMoving along, the way you do GetKeyboardState is vey clean compared to hack jobs I've seen. I guess the call to GetKeyState is necessary
It seems so. Without it, no success. Apparently GetKeyboardState needs some gentle reminder that it has been asked to do something. My best guess is that the console has a message loop, and therefore needs a message of some kind to be activated.
Now let's wait for Dave's best guess 8)
Quote from: dedndave on March 15, 2015, 06:10:05 AM
sbrtst_test:
call beep0
pushad
call wosw
invoke crt__getch
popad
jmp sbrtst_test
that code will continually loop and beep whenever a key is pressed
first of all, the PUSHAD/POPAD preserves and restores all the registers, including EAX
crt__getch returns a value in EAX that should be tested for key-presses (destroyed by POPAD)
and - you don't display that value
also, the loop ends with an unconditional branch back to the top
you may way to use a conditional branch, instead
I expected crt__getch not to return until a key was pressed. :redface:
I'll need to work on this some more.
Thank you.
we don't see the code for beep0 or wosw