C# SendInput 模拟鼠标操作的实现方法
发布时间:2022-03-15 00:07:25
刚刚开始学习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 = https://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;


猜你喜欢
- DrawingContext比较类似WinForm中的Graphics 类,是基础的绘图对象,用于绘制各种图形,它主要API有如下
- 介绍Java命令模式(Command Pattern)是一种行为型设计模式,它将请求封装成一个对象,从而使不同的请求可以进行参数化,并支持请
- 不少朋友自己下载了一个Android SDK,怎样在Android studio中默认的Android SDK路径呢?打开Android s
- 前言由于不小心将and或者or写在了语句后面,导致mybatis无法自主判别,这种问题在新上手的同学中很是常见。下面我们探讨一下,在哪些情况
- Android Studio下载(下文统称AS)AS最新版下载请戳:AS下载Android SDK下载SDK安装器下载SDK安装器下载请戳:
- WPF 使用 DrawingContext 绘制刻度条框架使用大于等于.NET40;Visual Studio 2022;项目使用 
- Java枚举类型enum的详解及使用最近跟同事讨论问题的时候,突然同事提到我们为什么Java 中定义的常量值不采用enmu 枚举
- 背景今天学习Springboot,但是用的apache-maven 3.0 ,导入springboot1.5.19 ,Maven项目老是爆红
- 本文实例分析了Android开发之TimePicker控件用法。分享给大家供大家参考,具体如下:新建项目:New Android Proje
- 一、匹配字符串正则1//正则1 Regex r = new
- 本文实例讲述了C# linq查询之动态OrderBy用法。分享给大家供大家参考。具体分析如下:groupList是原始数据集合,List&l
- 本文为大家分享了C#基于Socket套接字的网络通信封装代码,供大家参考,具体内容如下摘要之所以要进行Socket套接字通信库封装,主要是直
- 最近接触到一个需求要求压缩导出文件,于是乎便要致力于研究一下工具类啦,故也诞生了此篇文章。下面代码中,溪源也将import导入的依赖也贴出来
- 不久前项目开始了一段时间了,刚开始怀疑是Android Studio中新加入的Instant Run功能引起的,于是重新打release包后
- 本文实例讲述了C#实现合并多个word文档的方法,是非常具有实用价值的技巧。分享给大家供大家参考。具体实现方法如下:using System
- Mybatis的缓存mybatis是一个查询数据库的封装框架,主要是封装提供灵活的增删改sql,开发中,service层能够通过mybati
- 概述:Flutter中常用的滑动布局 ScrollView 有 SingleChildScrollView、NestedScrollView
- Android 添加系统设置属性的实现及步骤Android源码开发中,常常要用到一些全局标志或者说变量,这时候我们可以给android系统添
- 目录RemoveSubstringReplaceSpiltJoinAppendRemoveRemove(int startIndex) 删除
- 一、定时任务1、cron表达式语法:秒 分 时 日 月 周 年(其中“年”Spring不支持,也就是说在spring定时任务中只能设置:秒