Keyboard and mouse events are handled by the structure Event
.
I. What is inside a structure Event?
Here is the structure defining Event:
struct Event {
int button;
int key;
int subWin;
};
1. Types
The type
variable indicates the nature of the event. There are 6 types of events:
EVT_NONE = 0,
EVT_BUT_ON = 2,
EVT_BUT_OFF = 3,
EVT_MOTION = 5,
EVT_KEY_ON,
EVT_KEY_OFF
};
- Button events indicate whether a mouse button was pressed or released (in which case the
pix
field indicates the mouse position and button
the button number, 1 for left, 2 for middle and 3 for right);
- the motion type indicates a mouse motion (the
pix
field indicates the new mouse position);
- key events indicate whether a keyboard key was pressed or released.
- The
EVT_NONE
type indicates a non-event, that is, nothing happened.
2. Mouse Tracking
By default, mouse motion events are only registered while a mouse button is kept pressed (mouse drag). If you want to be notified of mouse motion events even when no button is pressed, use
To deactivate, use
II. How to handle events
There is an event queue that registers all events. Each time a new event occurs, it is appended in the queue, independently of the user's code running.
New event registered in the event queue
1. GetEvent
To extract the first event of the queue (the least recent one), you call the getEvent
function, which fills its second argument.
When calling getEvent, the structure Event
contains the information "Key A pressed", which is extracted from the queue.
The parameters of getEvent are:
- ms: The time (int milliseconds) to wait to have a chance of registering a new event. A value of -1 implies that we wait indefinitely until the queue is not empty.
- ev: the filled-out structure.
When the queue is empty, ev
gets type EVT_NONE
to indicate that.
2. unGetEvent
It is possible to append manually a user created event with the function unGetEvent
.
3. flushEvents
You can decide to discard all waiting events and make the queue empty with this function.
III. Examples
1. Graphical buttons
To have a nice effect, it is good to have mouse tracking enabled to provide the user with some feedback. Use enableMouseTracking(true)
for that. The code studies the mouse cursor position and determines if it is inside a "button".
Event ev;
int w=300, h=50;
bool b = false;
do {
switch (ev.type) {
case EVT_NONE:
cout << "No event" << endl;
break;
case EVT_MOTION: {
int x = ev.pix.x();
int y = ev.pix.y();
if(P1.x()<=x && x<P1.x()+w && P1.y()<=y && y<P1.y()+h) {
} else if(P2.x()<=x && x<P2.x()+w && P2.y()<=y && y<P2.y()+h) {
} else {
}
break;
}
case EVT_KEY_ON:
cout << "Use your mouse!"<< endl;
break;
case EVT_BUT_ON: {
int x = ev.pix.x();
int y = ev.pix.y();
if(P1.x()<=x && x<P1.x()+w && P1.y()<=y && y<P1.y()+h) {
cout << "Starting a new Tetris game !!" << endl;
b = true;
}
break;
}
default: break;
}
} while ((ev.type!=EVT_KEY_ON || ev.key!='q' )&& !b);
A game's menu
2. Moving a ball with the keyboard
We examine the value of ev.key
to know the pressed key. Printable characters are identified by their ASCII code (for example 'A', '0', '?'). Non-printable keys are identified by a specific code in this list:
KEY_BACK=16777219,KEY_TAB=16777217,KEY_RETURN=16777220,
KEY_ESCAPE=16777216,KEY_SPACE=32,KEY_DELETE=16777223,KEY_START=16777250,
KEY_SHIFT=16777248,KEY_ALT=16777251,KEY_CONTROL=16777249,
KEY_MENU=16777301,KEY_PAUSE=16777224,KEY_CAPITAL=16777252,
KEY_END=16777233,KEY_HOME=16777232,
KEY_LEFT=16777234,KEY_UP=16777235,KEY_RIGHT=16777236,KEY_DOWN=16777237,
KEY_INSERT=16777222,
KEY_NUMPAD0=48, KEY_NUMPAD1, KEY_NUMPAD2, KEY_NUMPAD3, KEY_NUMPAD4,
KEY_NUMPAD5, KEY_NUMPAD6, KEY_NUMPAD7, KEY_NUMPAD8, KEY_NUMPAD9,
KEY_MULTIPLY=42,KEY_ADD,KEY_SEPARATOR,KEY_SUBTRACT,KEY_DECIMAL,
KEY_DIVIDE,
KEY_F1=16777264, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8,
KEY_F9, KEY_F10, KEY_F11, KEY_F12,
KEY_NUMLOCK=16777253, KEY_SCROLL=16777254, KEY_PAGEUP=16777238,
KEY_PAGEDOWN, KEY_NUMPAD_ENTER=16777221
};
To have a readable source code, you must never use the actual numeric values in this list, but only their code.
cout << "Use your arrow keys. Press 'q' to quit." << endl;
int x=50, y=200, r=5;
int xt=x, yt=y;
while(true) {
if(k == 'q')
break;
bool update = true;
switch(k){
case KEY_UP: y-=5; break;
case KEY_DOWN: y+=5; break;
case KEY_LEFT: x-=5; break;
case KEY_RIGHT:x+=5; break;
default: update=false; break;
}
if(update) {
xt = x; yt = y;
}
}
A keyboard controlled ball
3. Keyboard auto-repeat
When a key, other than Shift
, Ctrl
, or Alt
, is maintained pressed longer than some minimal time (tunable by the system), auto-repeatition occurs. In that case, the sequence of events is the following:
- EVT_KEY_ON
- EVT_KEY_ON
- ...
- EVT_KEY_OFF
That is, it behaves as if the key was pressed multiple times, but only the final key release event is registered.