View Full Version : checking for ctrl key input

10-06-2002, 09:09 AM
i'm trying to draw a polygon based on a user's clicks. the only way i can think of to end the polygon would be something like a ctrl+click. how can i check for that? and would it be in the mouseclick routine?

thanks again.

10-06-2002, 10:37 AM

why don't you put the end of the polygon on the right mouse button? or the middle button?
If you want to have a ctrl-click you will have to check for a keydown message, check whether it is the ctrl key, then set a flag. Change the flag on keyup.
Hm, while I'm writing this I wonder whether there is a message sent when you press the ctrl key. But there is a possibility to figure it out there is a modifier notify atleast in windows. something like this also exists in x-windows.



10-06-2002, 11:10 AM
the right-click and middle-click are being used for other functions ...
could you elaborate a bit on the use of the ctrl + left click ?


10-07-2002, 12:01 AM

glut specifies numeric value for those keys on the keyboard, whose ascii code cannot be specified.
i could not find the value for ctrl or shift key. Other values are specified in glut.h

10-07-2002, 12:20 AM
try the following:

add the message to get all mouse actions to your windows message loop.
In the code-block, where do you check after the pressed mouse button, you add the usage of a function called "GetAsyncKeyState()" (or something like this, i dont know exactly the name of this function)
This function enables you to catch all "non standard" key-presses, like CTRL, ALT and so on.

10-07-2002, 03:03 AM
this can be accomplished easily if you are using win32 calls. in your message handler for WM_LBUTTONDOWN, the variables wParam and lParam contain useful information. one contains the window coord of the mouse when the user clicked the left button, the other is a bit field for other keys (i.e. shift, alt and ctrl). i can't remember which is which, but check the VC++ help for more info.


10-08-2002, 09:44 AM

I've done quite some work with the win32 keyboard interface of GLFW lately (btw, with GLFW you get all keys to the keyboard function, including 'A', GLFW_KEY_LCTRL, GLFW_KEY_KP_ENTER etc), and it's not that difficult to do it under Win32, except when you want to check for things like LEFT SHIFT / RIGHT SHIFT etc. Then it gets really interesting (I have about 60 lines of code in there right now, just to tell if it's the left or the right shift key!).

Anyway, tip one: avoid GetAsyncKeyState(), because it's async (not synchronous with the rest of the messages). Normally this does not matter much, but when you have low FPS figures (should be expected in a modelling program), or if you wait for window messages before you do any actions (also typical in a modelling program), it gets critical.

Tip two: Within a win32 message loop you can catch SHIFT, CTRL and ALT keys in the WM_KEYDOWN/WM_SYSKEYDOWN messages (wParam can be VK_SHIFT, VK_CTRL or VK_MENU). You can keep your own status of these keys (WM_KEYDOWN => ctrl_pressed = TRUE, WM_KEYUP => ctrl_pressed = FALSE), and then when you get the mouse button event, you can check if CTRL was pressed simply by checking the value of ctrl_pressed.

Tip three (a bit uncertain): Instead of using your own flags, you can rely on the GetKeyState() function. Unlike GetAsyncKeyState(), this function IS synchronous to the event loop. So when you get your mouse button message, you can check GetKeyState( VK_CTRL ) & 0x8000 (bit 15 tells if the key was down or up when the mouse message happened). NOTE: I am a bit uncertain if this actually works in a mouse event. The MSDN docs says that it shall be used from key events.

And, if you're using something else than win32 (e.g. GLUT or X11), "tip two" should be possible to implement in one way or another. Under GLUT you may have to use a special key function (both key down and key up versions) - check the GLUT manual.

...finally: if you want to make a difference between left and right versions of the modifier keys, you're in for a ride if you're using win32. Of course, the next release of GLFW has a solution for this. http://www.opengl.org/discussion_boards/ubb/wink.gif

10-08-2002, 12:29 PM
marcus:how difficult can it be to distinguish between left/right shift in win32?Doesn't the OS provide calls to get something like the KeyCodes(not KeySyms) in X or at least the raw keyboard codes?These can't be the same for both keys.
Damn it,I must find someone stu.. errr, kind enough to port my app to win32.I doubt I'll have the patience to do it myself.
BTW did you fix tha numlock problem in X?

10-09-2002, 01:37 AM
Originally posted by zen:
marcus:how difficult can it be to distinguish between left/right shift in win32? Doesn't the OS provide calls to get something like the KeyCodes(not KeySyms) in X or at least the raw keyboard codes?

Well, the problem with the shift keys is really nasty. First of all, under win32 you only get VK_SHIFT messages (VK = virtual key, similar to keysyms under X), regardless if you're pressing LSHIFT or RSHIFT, so when you get your message, you have to figure out which one it was. Under Win NT/2K/XP you can use GetKeyState to check if the left and/or right shift key is currentle held down (and by remebering old key states it's possible to detect changes), or you can go for the scan code that is also included in the message (but that's not a very good solution - scan codes can differ between keyboards). Under Win 9x/ME you're stuck (as far as I can tell) - GetKeyState doesn't work with left/right versions of shift there. But it gets worse! It seems as if not all key up/down messages are sent for the shift keys. When you hold both keys down, and release one of them, you do not always get a key up message. I don't really know why this is or how it works, but it's really annoying. It's also a fact that this is only true for the shift keys. CTRL & ALT keys behave properly, and for them it's much simpler, because you can check a message flag that says "extended key", which is always true for the right versions of CTRL & ALT (not for SHIFT though!).

Anyway, I solved the "missing shift messages" by using GetAsyncKeyState to asynchronously check if the states of the shift keys are different than what I believed them to be (based on the key up/down messages), and if so update my internal key states. I do this after my event polling loop is done, so you may get out of sync shift messages, but at least you catch most shift events (if you poll events frequently, that is).

If anyone has a better solution - I'd like to see it.

Damn it,I must find someone stu.. errr, kind enough to port my app to win32.I doubt I'll have the patience to do it myself.
BTW did you fix tha numlock problem in X?

Perhaps try GLFW http://www.opengl.org/discussion_boards/ubb/wink.gif

About the numlock problem, I'm not sure (I can't boot Linux at the time so I can't test it). Since I really want a scan-code like interface (i.e. all keys should be treated as "buttons", not text input devices), I figured I could do a first check for keypad keys (e.g. GLFW_KEY_KP_1) by using keysym index = 1 (or is it 2?) instead of 0, and then (if I got no hit) go on with index 0 as usual. This way I force NumLock on, but I think it's better than forcing NumLock off.

10-09-2002, 02:55 AM
I really hate messing up my code just to make up for someone else's bug.Regarding numlock:I'm not sure what you mean by check.When a key(like a keypad key) is pressed a keycode is returned.You must then use this keycode to get the keysym.You can either use LookupString() or you can do it yourself by calculating index based on the modifier status and feedinf it to KeyCodeToKeySym().The second way should be a little more messy.Let me know if I'm missing something.

10-09-2002, 10:20 AM
Well Zen,

I was thinking of disregarding the NumLock key state all together and use one index value for XKeycodeToKeysym for checking for the keypad keys, and another index value for checking the rest of the keyboard. In other words I call XKeycodeToKeysym twice; the first time I do swicth(case...) for keypad keys, and the scond time i do swicth(case...) for "normal" keys, if that makes any sense to you. Do you think it would work?

By the way - thanks for the quoted docs in the Linux thread - I think I had read it before without really understanding the whole Keysym thing (i.e. that each key can have several Keysym's).

10-09-2002, 11:45 AM
Either I don't understand what you mean or you've got something wrong(which would surprise me since you've struggled with windowing systems more than me (due to GLFW)).Ok,this is how(I think) things work:
The first keyboard handling layer is handled by the kb driver in the kernel.This driver assigns a code to each key wich(as you said earlier) might vary among the various keyboards and kernels(but I don't think it does because I'm not sure how a cross-platform windowing system like X would work in this case).Anyway that's what the KeyCodes(I hate this mixed lower/uppercase stuff) seem to be.There's one KeyCode for every physical key on the board.And that's it.The driver doesn't care if a key on your board has NumLock painted on it,it's just a key and nothing more.This is all pretty good because it's low-level and you can do just about anything the keyboard does with it.So for some special applications it might make sense to use the raw keycodes but because they're not very functional(if you want numlocks and capslocks nad shifts that is to wich most users are used to) there are other keyboard handling layers on top of the kernel driver like the one used in the terminal or the one used by X.So if you don't want to use the X kb driver wich keeps track of numlocks,capslocks,shifts,etc and provides the functionality we're all used to,you'll have to implement it yourself.It since you need platform independence(which X provides) I think it would be wasted time since you'd end up reimplementing exactly what X implements in the first place(if you didn't care about portability you would not care about the keysyms on say sun or sgi keyboards so you might want to implement a simpler handler yourself allthough there wouldn't be any gain in this.
Having said all this(corrections are welcome) let's get to ypur approach:First of all,you're only taliking about numlock.The same goes for capslock and shift.Try it you won't get any capital letters or !@#$ for example.You're also talking about two checks.XKeyCodeToKeysym AFAIK doesn't do any checks,it just does a lookup on internal tables which hold up to four possible keysyms(that is server-dependent interpretations of a specific key).If you call XKeyCodeToKeysym twice for the key 8 of the numpad for example you'll get XK_KP_8,XK_KP_UP,or even nothing as a result independently of the numlock status.You'll have to calculate the index based on the numlock/capslock/ctrl/alt/shift status and feed that to XKeyCodeToKeysym to get the standard keyboard functionality.But that's what XLookupString does(+more) so it would only make sense not to use it if you want to implement a different functionality.In that case since you're coding a general purpose windowing system abstraction just get the keycode and the modifier bits,give them to the user and let him implement whatever behaviour he wants.Since most will want the standard one I doubt it will make GLFW very popoular(strangly people nowadays seem to favour ease-of-use over freedom-to-do-anything).Of course you can always provide both interfaces and let the user choose(as X does).
Well that's all.I hope I'm not mistaken but I'm fairly sure about this since I also wanted to use keycodes.See they ranged only from 8 to 255 while keysyms range from 0 to 655536.Since I wanted to support multiple keybinding tables so that each user/player could just load his own w/o having to change the keys one by one(which might sound rather stupid as I could just re-bind all keys by executing a simple script thus using a single map.I wanted to use the same mechanism for the console though and parsing a script every time the user pulled the console up/down might not be very good) I didn't especially like wasting a meg of memory just for the keymap.
The End

PS:hmmmm,looking at my post makes me wish the board had some kind of longest-post award.Anyway congrats if you managed to read up to this point.

[This message has been edited by zen (edited 10-09-2002).]

10-10-2002, 01:38 AM
Hi Zen - nice post http://www.opengl.org/discussion_boards/ubb/wink.gif

I understand your position - I just think you missed my point. What I am trying to do is a KeyCode like interface for GLFW. The keyboard interface, as it is today, is intended to be used for gaming input. For instance, there are no lower/upper case variations, GLFW only gives you the upper case versions (also no !"# etc).

I have realized that a "text" interface is also needed, which considers things like shift/caps, and it should probably also be some kind of Unicode interface to deal with international letters etc. This is in the TODO list, but it's not on the top priority list yet.

And as you said, I could use the KeyCodes directly, but it doesn't feel right, considering the vast amount of different systems running X11 (there must be at least one "incompatible" system).

10-10-2002, 02:39 AM
Well as I said the best and easiest IMHO thing to do is provide both raw keycodes and keysyms(which provide text input,unicode etc functionality) through XLookUpString.You might have a problem though because these return XK_* constant and not GLFW_*.And making a switch() or lookup table to convert 65536(for unicode) XK_*s to GLFW_*s doesn't sound like too much fun.Also bear in mind that you can change the X keyboard mapping(that is keycode to keysym mapping) directly in case you can somwhow exploit that.

[This message has been edited by zen (edited 10-10-2002).]