转载:
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。