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

转载:https://blog.csdn.net/zouxy09/article/details/7920253

鉴于上文排版实在不敢苟同,而且里面部分内容不够详细,在这里稍做修改补充。

1,代码部分:

在Linux下写的简单的模拟鼠标和键盘事件的程序:

#include <stdio.h>

#include <linux/input.h>

#include <fcntl.h>

#include <sys/time.h>

#include <unistd.h>

//按键模拟,按键包含按下和松开两个环节

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\n");

                   return -1;

         }

         fd_mouse = open("/dev/input/event2", O_RDWR);

        if(fd_mouse <= 0)

        {

                printf("Can not open mouse input file\n");

                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。

猜你喜欢

转载自blog.csdn.net/weixin_39465823/article/details/81704828