第三章下 键盘输入
键盘相关数据结构
- sdlkey 枚举类型,每一个符号代表一个键,如sdlk_a、sdlk_space,在sdl_keysym.h中定义。
- sdlmod 枚举类型,类似sdlkey,但用于修饰键,如control、alt、shift,可以组合。
- sdl_keysym
typedef struct{ uint8 scancode; sdlkey sym; sdlmod mod; uint16 unicode; } sdl_keysym;用于按键和放开消息。scancode是硬件相关键码。除非你有特殊用途,否则忽略。sym指示键,mod为修饰键集合,例如kmod_num | kmod_caps | kmod_lshift 为numlock、capslock和左shift组合。最后unicode为对应字符。注意,仅当是按键消息时unicode才有效,放开消息时无效。unicode变换必须用sdl_enableunicode()打开。 - sdl_keyboardevent
typedef struct{ uint8 type; uint8 state; sdl_keysym keysym; } sdl_keyboardevent;描述一个键盘消息。type指示按键(sdl_keydown)或放开(sdl_keyup)。state是冗余的,和含义type相同只是符号不同(sdl_pressed,sdl_released)。
读取键盘消息
使用消息循环用sdl_pollevent()从消息队列里读取,并用switch-case检测sdl_keyup和sdl_keydown。下面是个基本的例子。
例3-10 读键盘消息
sdl_event event;
.
.
/* poll for events. sdl_pollevent() returns 0 when there are no */
/* more events on the event queue, our while loop will exit when */
/* that occurs. */
while( sdl_pollevent( &event ) ){
/* we are only worried about sdl_keydown and sdl_keyup events */
switch( event.type ){
case sdl_keydown:
printf( "key press detected\n" );
break;
case sdl_keyup:
printf( "key release detected\n" );
break;
default:
break;
}
}
更详细的内容
我们已经知道要用sdl_init和sdl_setvideomode初始化,但我们还得用另外两个函数取得必要信息。要调用sdl_enableunicode(1)以允许unicode变换,还要用sdl_getkeyname将sdlkey转换成可打印字符。注意:小于0x80的unicode字符直接映射到ascii码。下例用到这一点。
例3-11 解释按键消息
#include "sdl.h"
/* function prototypes */
void printkeyinfo( sdl_keyboardevent *key );
void printmodifiers( sdlmod mod );
/* main */
int main( int argc, char *argv[] ){
sdl_event event;
int quit = 0;
/* initialise sdl */
if( sdl_init( sdl_init_video ) ){
fprintf( stderr, "could not initialise sdl: %s\n", sdl_geterror() );
exit( -1 );
}
/* set a video mode */
if( !sdl_setvideomode( 320, 200, 0, 0 ) ){
fprintf( stderr, "could not set video mode: %s\n", sdl_geterror() );
sdl_quit();
exit( -1 );
}
/* enable unicode translation */
sdl_enableunicode( 1 );
/* loop until an sdl_quit event is found */
while( !quit ){
/* poll for events */
while( sdl_pollevent( &event ) ){
switch( event.type ){
/* keyboard event */
/* pass the event data onto printkeyinfo() */
case sdl_keydown:
case sdl_keyup:
printkeyinfo( &event.key );
break;
/* sdl_quit event (window close) */
case sdl_quit:
quit = 1;
break;
default:
break;
}
}
}
/* clean up */
sdl_quit();
exit( 0 );
}
/* print all information about a key event */
void printkeyinfo( sdl_keyboardevent *key ){
/* is it a release or a press? */
if( key->type == sdl_keyup )
printf( "release:- " );
else
printf( "press:- " );
/* print the hardware scancode first */
printf( "scancode: 0x%02x", key->keysym.scancode );
/* print the name of the key */
printf( ", name: %s", sdl_getkeyname( key->keysym.sym ) );
/* we want to print the unicode info, but we need to make */
/* sure its a press event first (remember, release events */
/* don't have unicode info */
if( key->type == sdl_keydown ){
/* if the unicode value is less than 0x80 then the */
/* unicode value can be used to get a printable */
/* representation of the key, using (char)unicode. */
printf(", unicode: " );
if( key->keysym.unicode < 0x80 && key->keysym.unicode > 0 ){
printf( "%c (0x%04x)", (char)key->keysym.unicode,
key->keysym.unicode );
}
else{
printf( "? (0x%04x)", key->keysym.unicode );
}
}
printf( "\n" );
/* print modifier info */
printmodifiers( key->keysym.mod );
}
/* print modifier info */
void printmodifiers( sdlmod mod ){
printf( "modifers: " );
/* if there are none then say so and return */
if( mod == kmod_none ){