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)),即可得到按下的按键键名。

SDL_Event event;
while(SDL_PollEvent(&event)){
    switch (event.type) {
        case SDL_KEYDOWN:
            printf("key %s down!\n", SDL_GetKeyName(event.key.keysym.sym));
        break;
        case SDL_QUIT:
            exit(0);
        break;
    }
}

4. 组合按键

        有时候我们需要按下组合按键,key.keysym.mod 保存组合键状态,如检测是否按下 ALT:
if(event.key.keysym.mod & KMOD_ALT) 使用按键控制可执行程序运行,这里,举一个按键的使用加以说明。

#define KBD_DEV "/dev/SOC3210_74HC165_button"
static int kbd_fd = -1;
unsigned char data1 = 0;
void key3210()
{
      int key = 0;
      int mod = 0;
      SDL_Event event;
      if((kbd_fd = open(KBD_DEV,O_RDONLY)) < 0){ //打开按键设备
            printf("Error opening %s deivce\n",KBD_DEV);
      }
      while(1)
      {
            usleep(200000);
            read(kbd_fd,&data1,sizeof(data1)); //读取按键键值
            if(data1)
            {
                  usleep(1000);
                  printf("button is 0x%x\n",data1);
            }
            switch(data1)
            {
                  case 0x80: //判断是否为欲按键
                       key = SDLK_8;
                       mod = 0;
                       break;
                  default:
                       break;
             }
            if(data1)
            {
                  if(key == SDLK_8 )
                  {
                       event.type = SDL_KEYDOWN; //定义事件类型
                       event.key.keysym.sym = key; //定义键值为SDLK_8
                       event.key.keysym.mod = mod; //组合按键
                       SDL_PushEvent(&event); //将事件消息插入事件队列
                  }
            }
            data1 = 0;
            key = 0;
      }
}

        上述DEV3210按键处理流程为:
        首先打开DEV3210设备,当按下按键后,使用read函数读取按键键值。如果得到的键值是我们所需要按键的键值0x80,说明对应的按键被按下。这里我们封装一个事件消息,事件消息包括事件类型,键值为SDLK_8,组合按键。 SDL_PushEvent(&event)将该事件消息插入事件队列中,这样就相当于按下键值为SDLK_8的按键,当前窗口接收到该事件消息后,会根据按键作出相应响应返回给用户。

        实际上,这里相当于按了两次键,一次为DEV3210开发板上按键,一次为键盘上数字8按键。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
要在SDL2中发送键盘事件,您可以按照以下步骤进行操作: 1. 首先,您需要初始化SDL2并创建一个窗口和渲染器。这可以通过调用`SDL_Init()`、`SDL_CreateWindow()`和`SDL_CreateRenderer()`函数来完成。 2. 为了接收键盘事件,您需要创建一个事件循环。您可以使用`SDL_PollEvent()`函数在循环中获取事件。 3. 在事件循环中,您可以检查每个事件的类型,以确定它是一个键盘事件键盘事件的类型是`SDL_KEYDOWN`和`SDL_KEYUP`。 4. 如果事件是键盘按下事件(`SDL_KEYDOWN`),您可以检查事件的`key.keysym.sym`属性来获取按下的键的代码。这将是一个SDL_Keycode类型的值。 5. 然后,您可以根据按下的键执行相应的操作。例如,您可以在控制台上打印出按下的键: ```c if (event.type == SDL_KEYDOWN) { SDL_Keycode keycode = event.key.keysym.sym; printf("Key pressed: %s\n", SDL_GetKeyName(keycode)); } ``` 6. 如果事件是键盘释放事件(`SDL_KEYUP`),您可以采取相应的操作,例如停止移动角色或停止播放声音等。 7. 最后,在您完成使用SDL2后,记得调用`SDL_Quit()`函数来清理并退出程序。 这是一个简单的示例代码片段,演示了如何在SDL2中发送键盘事件: ```c #include <SDL2/SDL.h> #include <stdio.h> int main() { SDL_Init(SDL_INIT_VIDEO); SDL_Window* window = SDL_CreateWindow("SDL2 Keyboard Event", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0); SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); SDL_Event event; int quit = 0; while (!quit) { while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) { quit = 1; } else if (event.type == SDL_KEYDOWN) { SDL_Keycode keycode = event.key.keysym.sym; printf("Key pressed: %s\n", SDL_GetKeyName(keycode)); } else if (event.type == SDL_KEYUP) { SDL_Keycode keycode = event.key.keysym.sym; printf("Key released: %s\n", SDL_GetKeyName(keycode)); } } // 渲染器的其他绘制逻辑... SDL_RenderPresent(renderer); } SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return 0; } ``` 希望这可以帮助到您!
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柒号华仔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值