02-25-2011 11:22 AM
My application uses a callback with EVENT_KEY_PRESS to detect when function keys are pressed on the keyboard. A routine is executed based on the function key. This all works fine.
Is there a way to tell when the pressed key has been released?
The goal is for the routine to execute only once and not repeat if the user is holding down the key for an extended period of tiime.
Any insights are appreciated,
Thanks,
Scott T.
Solved! Go to Solution.
02-25-2011 04:56 PM
Scott:
I don't know of the equivalent of a KEY_UP event. As you already know, EVENT_KEYPRESS is fired when the key is pressed down, not when it's released.
With some limitations, you can use a timer to help ignore a key held too long.
For EVENT_KEYPRESS, eventData1 is the code for the key you pressed. When the event is fired, check if the same key was pressed as last time. If it is the same, check how much time has passed since the last press. If it's less than some time period you choose, ignore it as a held key. If the time between events is longer than your chosen delay, consider it to be a new keypress.
The limitation with this approach is the keyboard typematic repeat delay. If you press and hold a key, there is a delay (typically 0.5 seconds) set in BIOS before the key starts repeating.
If the set delay in your program is less than the keyboard typematic repeat delay, you will get a double count when the key is held the length of the typematic repeat delay.
If the set delay is longer than the typematic repeat delay, you won't get the double count, but you may miss fast repeated taps at the key.
Look at the attached sample program to see what I mean.
02-28-2011 10:11 AM
Hi Scott,
You may also want to take a look at this forum:
It's an old forum but it suggests an alternate method of detecting Key Up events.
Let me know if this works for you!
02-28-2011 12:03 PM - edited 02-28-2011 12:06 PM
Thanks Tanya. I'm sorry I missed that. Using the Windows KeyUp message works better and is easier (and easier is better)!
Forget the timer, forget checking if the same key is pressed.
Just set a global variable for keydown.
Install a callback for the Windows WM_KEYUP message.
Start with the keydown global FALSE.
When EVENT_KEYPRESS is received, check if keydown is TRUE. If it is, ignore the event.
If keydown is not TRUE, that means it's a new keypress. Do whatever you want for the new keypress.
When the Windows message WM_KEYUP is received, set keydown FALSE.
I attached a simple example to this post which demonstrates this. The user interface has a checkbox to allow the user to test for keyup or not, to demonstrate the difference.
02-28-2011 12:20 PM - edited 02-28-2011 12:20 PM
Note: You can also use this method to avoid multiple keypress events for any key.
Scott used the example of function keys. If you also want to avoid entering repeated alpha-numeric keys, return 1 from your textbox callback to swallow the event if it's not a new keypress.
A new .c file (to replace the one in my previously posted project) is attached which demonstrates this.
03-02-2011 07:15 AM
Al & Tanya
Thanks for the input. Works great on the individual panels of my application.
Still trying to come up with a solution to work across panels.
For example: A key is pressed and a new full screen panel is displayed. If the key remains held down, then the function associated with the key on the new panel is executed rather than waiting for a key release and then another press.
Scott
03-02-2011 07:56 AM
Scott:
If you get an EVENT_KEYPRESS on a new panel, the callback from the new panel will be called, but in that callback you'll check the global g_keydown.
g_keydown needs to be global for the entire project and needs to be checked in any callback for which you're concerned about a held key.
I don't see a problem with a new panel if you check g_keydown. As a side note, you need to be careful any time you have a global that can be modified in multiple places, but in this case you don't really care which control or panel is waiting for it to be released: you just care if it was released.
03-02-2011 10:16 AM
Al
The key release check is now working across all panels. My application was set up as you had described.
I was using the F1 thorough F10 function keys for inputs. I reprogrammed to use the 1 through 0 number keys instead. Everything works fine now.
When I used F10, the new panel would be displayed, but the key release was never detected (even with repeated presses).
If the number 0 key is used instead, the release is always detected in the new panel.
When the application is loaded on another PC via the distribution kit, the same F10 anomaly is present.
Not sure what the F10 is about, but at least the app is operational.
Scott T
03-02-2011 10:54 AM
F10 is treated as if it were an an Alt key combination so WM_SYSKEYUP is sent instead of WM_KEYUP.
Michael
NI
03-02-2011 11:07 AM - edited 03-02-2011 11:10 AM
Michael:
Thanks for the info. I wonder why Windows treats F10 differently than the other function keys. Function keys F1 through F9, and F11 and F12 all generate WM_KEYUP, but F10 generates WM_SYSKEYUP. Here's a link from Microsoft that explains a little more: http://msdn.microsoft.com/en-us/library/gg153546(v=vs.85).aspx
Scott:
If you want to use the function keys, the solution could be as simple as installing callbacks (can even be the same function) for both messages.
InstallWinMsgCallback (panelHandle, WM_KEYUP, KeyupCallback,
VAL_MODE_IN_QUEUE, NULL, &postinghandle);
InstallWinMsgCallback (panelHandle, WM_SYSKEYUP, KeyupCallback,
VAL_MODE_IN_QUEUE, NULL, &postinghandle);