linux环境的c语言实现模拟人对鼠标和键盘的操作

2019-04-14 17:58发布

转载:https://blog.csdn.net/zouxy09/article/details/7920253 鉴于上文排版实在不敢苟同,而且里面部分内容不够详细,在这里稍做修改补充。 1,代码部分: 在Linux下写的简单的模拟鼠标和键盘事件的程序: #include #include #include #include #include   //按键模拟,按键包含按下和松开两个环节 void simulate_key(int fd, int kval) {          struct input_event event;         gettimeofday(&event.time, 0);          //按下kval键          event.type = EV_KEY;          event.value = 1;          event.code = kval;          write(fd, &event, sizeof(event));        //同步,也就是把它报告给系统          event.type = EV_SYN;          event.value = 0;          event.code = SYN_REPORT;          write(fd, &event, sizeof(event));            memset(&event, 0, sizeof(event));          gettimeofday(&event.time, 0);          //松开kval键         event.type = EV_KEY;          event.value = 0;          event.code = kval;          write(fd, &event, sizeof(event));        //同步,也就是把它报告给系统        event.type = EV_SYN;        event.value = 0;        event.code = SYN_REPORT;        write(fd, &event, sizeof(event)); }   //鼠标移动模拟 void simulate_mouse(int fd, int rel_x, int rel_y) {     struct input_event event;     gettimeofday(&event.time, 0);     //x轴坐标的相对位移     event.type = EV_REL;     event.value = rel_x;     event.code = REL_X;     write(fd, &event, sizeof(event));     //y轴坐标的相对位移     event.type = EV_REL;     event.value = rel_y;     event.code = REL_Y;     write(fd, &event, sizeof(event));     //同步     event.type = EV_SYN;     event.value = 0;     event.code = SYN_REPORT;     write(fd, &event, sizeof(event)); }   int main(int argc, char **argv) {          int fd_mouse = -1;          int fd_kbd = -1;          int i = 0;            fd_kbd = open("/dev/input/event3", O_RDWR);          if(fd_kbd <= 0)          {                    printf("Can not open keyboard input file ");                    return -1;          }            fd_mouse = open("/dev/input/event2", O_RDWR);         if(fd_mouse <= 0)         {                 printf("Can not open mouse input file ");                 return -1;         }                   for (i = 0; i < 50; i++)          {                    simulate_key(fd_mouse, BTN_LEFT);  //模拟按下鼠标左键                    //if (i % 3 == 0)                    //      simulate_key(fd_kbd, KEY_A);  //模拟按下键盘A键                   //模拟鼠标相对上次x和y轴相应移动10个像素                    //simulate_mouse(fd_mouse, 10, 10);                                      sleep(3);          }          close(fd_kbd);          close(fd_mouse); } 2,参数设定: 输入事件的结构体: struct input_event {     struct timeval time;  //按键时间     __u16 type;  //事件的类型     __u16 code;  //要模拟成什么按键     __s32 value;  //是按下1还是释放0 };   标准按键的编码:(只列举部分) type: 事件的类型: EV_KEY, 按键事件,如键盘的按键(按下哪个键),鼠标的左键右键(是非击下)等; EV_REL, 相对坐标,主要是指鼠标的移动事件(相对位移); EV_ABS, 绝对坐标,主要指触摸屏的移动事件,但好像这个不能用在鼠标上面,也就是说无法通过这个来获取鼠标的绝对坐标(鼠标是一个相对位移的设备)。   code: 事件的代码:        如果事件的类型代码是EV_KEY,该代码code为设备键盘代码。代码植0~127为键盘上的按键代码,0x110~0x116为鼠标上按键代码,其中0x110(BTN_ LEFT)为鼠标左键,0x111(BTN_RIGHT)为鼠标右键,0x112(BTN_ MIDDLE)为鼠标中键。其它代码含义请参看include/linux /input.h文件。该文件中会定义相应的宏来代表不同的按键。        如果事件的类型代码是EV_REL,code值表示轨迹的类型。如指示鼠标的X轴方向 REL_X(代码为0x00),指示鼠标的Y轴方向REL_Y,指示鼠标中轮子方向REL_WHEEL。   value: 事件的值:        如果事件的类型代码是EV_KEY,当按键按下时值为1,松开时值为0;        如果事件的类型代码是EV_ REL,value的正数值和负数值分别代表两个不同方向的值。例如:如果code是REL_X,value是10的话,就表示鼠标相对于上一次的坐标,往x轴向右移动10个像素点。 我测试过在我的电脑(系统ubuntun 18.04)上时,左上角是(0,0),即就是坐标原点,向下是y轴正方向,向右是x轴正方向。        那么如何模拟组合键呢?其实和大家平时按键盘的过程是一样的,我们用程序按照这个过程来模拟就可以了。以CTRL + SPACE为例: //先发送一个 CTRL按下去的事件 //再发送一个 SPACE按下去的事件 //然后发送一个释放 SPACE的事件 //再发送一个释放 CTRL的事件 得注意每步的发送都需要同步一次。        有关于本系统构建的文章结构都会由三个部分来组织,一是该功能模块的介绍和在Linux下简单应用程序的实现;二是将该功能模块整合到交互系统(先以TLD为地基)中去;三是分析目前存在的问题与未来的解决构思。 3,代码讲解:  #cat /proc/bus/input/devices可以查看到当前input子系统下面的所有event设备,我们找到鼠标和键盘的即可。 例如: I: Bus=0003 Vendor=046d Product=c018 Version=0111 N: Name=" USB Optical Mouse" P: Phys=usb-0000:00:1d.1-2/input0 S: Sysfs=/class/input/input24 U: Uniq= H: Handlers=mouse1 event2 B: EV=7 B: KEY=70000 0 0 0 0 0 0 0 0 B: REL=103 上面Name处可以看到这个鼠标设备,然后对应的句柄Handlers是event2;  /dev/input目录下的事件都是在驱动中调用input_register_device(struct input_dev *dev)产生的。 4,编译可能出现问题: 就是open函数打开报错,原因是对文件的权限问题,用chmod 777 给对应的事件文件增加权限就行,我比较懒,所以用777。 另外,愿意的可以在https://blog.csdn.net/hbtj_1216/article/details/50865440可以看看 gettimeofday()函数的使用。 5,补充: 因为上文,使用的是相对坐标,听同事说X11的库里面有直接获取绝对坐标的API。