SDL 键盘事件
1. 事件处理
一个完整的 GUI 程序,需要处理各种事件,如按键,鼠标,窗口操作等。一般这种程序会设计成一个与底层交互的事件驱动模型。即底层不断发送事件,而在程序用一个循环不断处理各种事件。 各个 GUI 都是采用这样模型来实现,SDL 抽象这个模型,采用 SDL_event 来抽象表示具体的事件。 在 agar 中,事件处理函数最终还是使用 SDL 库。
在 AG_SetEvent()中设定事件,通过定义一个 AG_Event 型的结构体来描述事件信息。
在 AG_Eventloop()函数内,首先定义一个 SDL_Event 类型的数据,通过 SDL_PollEvent 函数来监听消息,即从底层来提取事件。事件处理允许程序响应来自用户的输入,而等待相应的时候,程序就会阻塞,从而将图形窗口定格在屏幕当中。如果有用户输入,则从阻塞状态中返回,同时 SDL_Event 也被赋予了代表某个事件的特定值。 SDL_PollEvents()函数的功能是事件轮询。首先通过 SDL_PumpEvents 函数来处理硬件独立的事件后,再通过 SDL_PeepEvents 从队列中提取事件。
另外还有两个事件处理函数:
SDL_WaitEvent()必须等到有一个事件才返回,而 SDL_PollEvent 没有事件也立即返回,这样提高系统反应速度。
SDL_PeepEvents()是提出查看事件,但事件本身仍然在事件队列中。
2. 键盘事件
在操作中,我们按下按键时,键盘芯片会检测到这个动作,将这个信号发送给计算机。对于每个按键,都会有一个与之对应的键盘扫描码,按下按键时,传递给计算机消息队列的就是键盘扫描码,将按键的键盘扫描码传递给电脑,就达到模拟按键的功能。 键盘扫描码是跟具体的硬件相关的,同一个键在不同键盘上的扫描码有可能不同。操作系统需要得到的信息的并不是键盘扫描码。键盘控制器将这个扫描码传给计算机,然后交给键盘驱动程序。键盘驱动程序会完成相关的工作,并把这个扫描码转换为键盘虚拟码。键盘虚拟码是针对键盘扫描码的非通用性所提出。尽管出于硬件原因,同一个按键可能有不同的扫描码,但是无论什么键盘,同一个按键的虚拟码总是相同的,这样程序就可以识别了。当键盘驱动程序把扫描码转换为虚拟码后,会把这个键盘操作的扫描码和虚拟码还有其它信息一起传递给操作系统。
操作系统在得到这个信息后,会对消息进行封装,封装之后,就成了一个包含完整信息的事件,然后把这个键盘事件消息插入到事件消息队列。最后,这个键盘消息最终会被送到当前的活动窗口那里,活动窗口会使用事件监听函数从事件队列中提取事件,所在的应用程序接收到这个事件消息后,就知道键盘上哪个键被按下,也就可以根据按键决定该作出什么响应返回给用户。
3. 单按键
在 SDL 中,当事件等待函数监听到事件后,判断事件类型,如果 event.type == SDL_KEYDOWN,表明用户按下键盘,保存在 event.key.keysym.sym 是相应的键值。而根据键值,调用函数 SDL_GetKeyName(event.key.keysym.sym)),即可得到按下的按键键名。
4. 组合按键
有时候我们需要按下组合按键,key.keysym.mod 保存组合键状态,如检测是否按下 ALT:if(event.key.keysym.mod & KMOD_ALT) 使用按键控制可执行程序运行,这里,举一个按键的使用加以说明。
上述 DEV3210 按键处理流程为: 首先打开 DEV3210 设备,当按下按键后,使用 read 函数读取按键键值。如果得到的键值是我们所需要按键的键值 0x80,说明对应的按键被按下。这里我们封装一个事件消息,事件消息包括事件类型,键值为 SDLK_8,组合按键。 SDL_PushEvent(&event)将该事件消息插入事件队列中,这样就相当于按下键值为 SDLK_8 的按键,当前窗口接收到该事件消息后,会根据按键作出相应响应返回给用户。
实际上,这里相当于按了两次键,一次为 DEV3210 开发板上按键,一次为键盘上数字 8 按键。
版权声明: 本文为 InfoQ 作者【柒号华仔】的原创文章。
原文链接:【http://xie.infoq.cn/article/3acf0dcf4d4037ed03addd6a8】。文章转载请联系作者。
评论