C# SendInput 模拟鼠标操作的实现方法
刚刚开始学习c#,想自己做一个网页游戏的挂。游戏里面有收钱的动作,一个建筑物一个建筑物的点,很累啊。于是想用c#模拟鼠标操作替我收钱,想着学习这个对以后的测试工作也有帮助,于是有了动力。学习过程也是曲折的,因为网上搜了半天资料很少。该游戏是flash的,用sendmessage不行,因为取不到里面的对象。查到有些介绍mouse_event的文章,但是msdn上说已经过时。于是查到了sendinput函数。
废话少说,上代码:
首先看下 win api 中sendinput函数描述:
uint winapi sendinput(
__in uint ninputs,
__in lpinput pinputs,
__in int cbsize
);
对应的c#代码:
[dllimport("user32.dll")]
public static extern uint32 sendinput(uint32 ninputs,input[] pinputs, int cbsize);
其中参数pinputs是的数组类型,数组元素input结构,所以我们下面还要在c#中定义对应的input结构或者对象。input结构中主要是定义你需要的鼠标或者键盘等操作。ninputs指明pinputs数组长度。cbsize指明input结构的大小。
定义input结构,下面是win api 中input结构描述:
typedef struct taginput {
dword type;
union {
mouseinput mi;
keybdinput ki;
hardwareinput hi;
} ;
} input, *pinput;
对应的c#代码
[structlayout(layoutkind.explicit)]
public struct input
{
[fieldoffset(0)]public int32 type;
[fieldoffset(4)]public mouseinput mi;
[fieldoffset(4)]public tagkeybdinput ki;
[fieldoffset(4)]public taghardwareinput hi;
}
上面看到,还有mouseinput,keybdinput,hardwareinput结构需要定义。下面直接贴出代码啦。
win api中描述:
typedef struct tagmouseinput { long dx; long dy; dword mousedata; dword dwflags; dword time; ulong_ptr dwextrainfo; } mouseinput, *pmouseinput;
typedef struct tagkeybdinput { word wvk; word wscan; dword dwflags; dword time; ulong_ptr dwextrainfo; } keybdinput, *pkeybdinput;
typedef struct taghardwareinput { dword umsg; word wparaml; word wparamh; } hardwareinput, *phardwareinput;
c#中对应代码:
[structlayout(layoutkind.sequential)]
public struct mouseinput
{
public int32 dx;
public int32 dy;
public int32 mousedata;
public int32 dwflag;
public int32 time;
public intptr dwextrainfo;
}
[structlayout(layoutkind.sequential)]
public struct tagkeybdinput
{
int16 wvk;
int16 wscan;
int32 dwflags;
int32 time;
intptr dwextrainfo;
}
[structlayout(layoutkind.sequential)]
public struct taghardwareinput
{
int32 umsg;
int16 wparaml;
int16 wparamh;
}
我主要是模拟鼠标,所以只需定义鼠标的flag值:
const int mouseevent_absolute = 0x8000;
const int mouserevent_hwheel = 0x01000;
const int mouseevent_move = 0x0001;
const int mouseevent_move_nocoalesce = 0x2000;
const int mouseevent_leftdown = 0x0002;
const int mouseevent_leftup = 0x0004;
const int mouseevent_middledown = 0x0020;
const int mouseevent_middleup = 0x0040;
const int mouseevent_rightdown = 0x0008;
const int mouseevent_rightup = 0x0010;
const int mouseevent_wheel = 0x0800;
const int mousseevent_xup = 0x0100;
const int mousseevent_xdown = 0x0080;
c#中模拟鼠标操作的代码:
for (i = x; i <= x+width; i += 450)
//x为flash窗口的左上角的x轴绝对坐标值。屏幕左上角坐标是(0,0)。width是flash窗口宽度。
{
for (j = y; j <= y +height; j+=150) //y为flash窗口的左上角的y轴绝对坐标值。height是flash窗口高度。
{
mouseinput myminput = new mouseinput();
myminput.dx = i;
myminput.dy = j;
myminput.mousedata = //www.jb51.net/cx361/archive/2011/12/11/0;
myminput.dwflag = mouseevent_absolute | mouseevent_move | mouseevent_leftdown | mouseevent_leftup;
myminput.time = 0;
input[] myinput = new input[1];
myinput[0] = new input();
myinput[0].type = 0;
myinput[0].mi = myminput;
uint32 result = sendinput((uint)myinput.length, myinput, marshal.sizeof(myinput[0].gettype()));
if (result == 0)
{
messagebox.show("fail");
}
}
}
知识点:将像素坐标转化为绝对坐标:
api中mouseinput结构中的dx,dy含义是绝对坐标,是相对屏幕的而言的,屏幕左上角的坐标为(0,0),右下角的坐标为(65535,65535)。而我们在c#中获得的对象(frame,button,flash等)的坐标都是像素坐标,是跟你当前屏幕的分辨率相关的。假如你的显示器分辨率是1024*768,那么屏幕左上角的像素坐标是(0,0),右下角坐标为(1024,768)。转换函数如下:
dx = x * (65335/screenwidth) //x,y为像素坐标。
dy = y * (65335/screenheight)//screenwidth和screenheight,其实是当前显示器的分辨率,获得方法是screenwidth=screen.primaryscreen.workingarea.width;
screenheight=screen.primaryscreen.workingarea.height;