当前位置:   article > 正文

代码控制鼠标光标移动并点击和代码模拟键盘按下(C#)_c#实现鼠标键盘自动执行

c#实现鼠标键盘自动执行

前面介绍过通过代码的方式模拟键盘按下,博文如下:

C#通过代码的方式模拟键盘按下_c# 模拟键盘输入_zxy2847225301的博客-CSDN博客

这个博文是通过win32的keybd_event实现,可能会未来的window版本中被淘汰(不是我说的,看到老外一篇文章中说的)

本文的内容参考自:

How to Send Inputs using C# - CodeProject

本文的主要核心是利用了win32的函数SendInput,将会实现并演示如下的效果:

演示效果1:   点击按钮,然后模拟键盘输入,把输入的内容显示到文本框上

演示效果2:   点击按钮,然后控制鼠标光标移动(对角线移动)

演示效果3:   点击按钮,然后控制鼠标光标移动到演示效果1中的那个按钮的位置上,并实现点击,接着就会看到效果1中的效果(模拟键盘输入,把输入的内容显示到文本框上)

本文测试环境:

vistual studio 2017

.net framework 4.0

winform

步骤如下:

1   新建winform项目,.net framework选4.0,名为SendInputDemo,并新建类Win32SendInputApi并编辑如下:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.InteropServices;
  5. using System.Text;
  6. namespace SendInputDemo
  7. {
  8. public class Win32SendInputApi
  9. {
  10. /// <summary>
  11. /// 键盘输入参数
  12. /// </summary>
  13. [StructLayout(LayoutKind.Sequential)]
  14. public struct KeyboardInput
  15. {
  16. public ushort wVk;
  17. public ushort wScan;
  18. public uint dwFlags;
  19. public uint time;
  20. public IntPtr dwExtraInfo;
  21. }
  22. /// <summary>
  23. /// 鼠标输入参数
  24. /// </summary>
  25. [StructLayout(LayoutKind.Sequential)]
  26. public struct MouseInput
  27. {
  28. public int dx;
  29. public int dy;
  30. public uint mouseData;
  31. public uint dwFlags;
  32. public uint time;
  33. public IntPtr dwExtraInfo;
  34. }
  35. /// <summary>
  36. /// Hardware输入参数,Hardware不知道是什么设备,应该类似于传感器输入之类的设备(usb输入或者串口输入)
  37. /// </summary>
  38. [StructLayout(LayoutKind.Sequential)]
  39. public struct HardwareInput
  40. {
  41. public uint uMsg;
  42. public ushort wParamL;
  43. public ushort wParamH;
  44. }
  45. [StructLayout(LayoutKind.Explicit)]
  46. public struct InputUnion
  47. {
  48. [FieldOffset(0)] public MouseInput mi;
  49. [FieldOffset(0)] public KeyboardInput ki;
  50. [FieldOffset(0)] public HardwareInput hi;
  51. }
  52. public struct Input
  53. {
  54. public int type;
  55. public InputUnion u;
  56. }
  57. [Flags]
  58. public enum InputType
  59. {
  60. Mouse = 0, //鼠标
  61. Keyboard = 1,//键盘
  62. Hardware = 2
  63. }
  64. /// <summary>
  65. /// 键盘状态
  66. /// </summary>
  67. [Flags]
  68. public enum KeyEventF
  69. {
  70. KeyDown = 0x0000, //键盘按下
  71. ExtendedKey = 0x0001, //不懂,看名字像追加键
  72. KeyUp = 0x0002, //键盘抬起
  73. Unicode = 0x0004, //不懂
  74. Scancode = 0x0008 //不懂
  75. }
  76. /// <summary>
  77. /// 鼠标参数类型
  78. /// </summary>
  79. [Flags]
  80. public enum MouseEventF
  81. {
  82. Absolute = 0x8000,
  83. HWheel = 0x01000,
  84. Move = 0x0001, //鼠标移动
  85. MoveNoCoalesce = 0x2000,
  86. LeftDown = 0x0002, //鼠标左键按下
  87. LeftUp = 0x0004, //鼠标左键抬起
  88. RightDown = 0x0008, //鼠标右键按下
  89. RightUp = 0x0010, //鼠标右键抬起
  90. MiddleDown = 0x0020, //鼠标中键按下
  91. MiddleUp = 0x0040, //鼠标中键抬下
  92. VirtualDesk = 0x4000, //不懂,看名字像是虚拟桌面
  93. Wheel = 0x0800, //鼠标滚轮
  94. XDown = 0x0080,
  95. XUp = 0x0100
  96. }
  97. [DllImport("user32.dll", SetLastError = true)]
  98. public static extern uint SendInput(uint nInputs, Input[] pInputs, int cbSize);
  99. [DllImport("user32.dll")]
  100. public static extern IntPtr GetMessageExtraInfo();
  101. /// <summary>
  102. /// 获取鼠标的坐标
  103. /// </summary>
  104. /// <param name="lpPoint"></param>
  105. /// <returns></returns>
  106. [DllImport("user32.dll")]
  107. public static extern bool GetCursorPos(out POINT lpPoint);
  108. [StructLayout(LayoutKind.Sequential)]
  109. public struct POINT
  110. {
  111. public int X;
  112. public int Y;
  113. }
  114. /// <summary>
  115. /// 设置鼠标的位置
  116. /// </summary>
  117. /// <param name="x"></param>
  118. /// <param name="y"></param>
  119. /// <returns></returns>
  120. [DllImport("User32.dll")]
  121. public static extern bool SetCursorPos(int x, int y);
  122. }
  123. }

2  winform的UI布局如下:

 

3  实现演示效果1:   点击按钮,然后模拟键盘输入,把输入的内容显示到文本框上

'触发键盘按下'按钮的代码逻辑如下:

  1. public partial class Form1 : Form
  2. {
  3. public Form1()
  4. {
  5. InitializeComponent();
  6. this.btnPress.Click += new System.EventHandler(this.btnPress_Click);
  7. }
  8. /// <summary>
  9. /// 触发键盘按下按钮点击事件
  10. /// </summary>
  11. /// <param name="sender"></param>
  12. /// <param name="e"></param>
  13. private void btnPress_Click(object sender, EventArgs e)
  14. {
  15. this.txtKeyInput.Focus();
  16. Input[] inputs = new Input[]
  17. {
  18. new Input
  19. {
  20. type = (int)InputType.Keyboard,
  21. u = new InputUnion
  22. {
  23. ki = new KeyboardInput
  24. {
  25. wVk = 0,
  26. wScan = 0x02, // 数字1
  27. dwFlags = (uint)(KeyEventF.KeyDown | KeyEventF.Scancode),
  28. dwExtraInfo = Win32SendInputApi.GetMessageExtraInfo()
  29. }
  30. }
  31. }
  32. };
  33. Win32SendInputApi.SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(Input)));
  34. this.txtKeyInput.Focus();
  35. }
  36. }

运行效果如下:

每点一次按钮,就录入一个1

键盘的16进制编码可以参考这个网址:Keyboard scancodes: Keyboard scancodes

如上图中的01代表键盘上的ESC键,02 数字键1或者!键(在笔记本键盘上,这两个键是公用的),相信你能看懂后面编码对应的按钮含义了

 

 

4  实现演示效果2:   点击按钮,然后控制鼠标光标移动(对角线移动)

 '设置鼠标的位置'按钮的代码逻辑如下:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Runtime.InteropServices;
  8. using System.Text;
  9. using System.Threading;
  10. using System.Windows.Forms;
  11. using static SendInputDemo.Win32SendInputApi;
  12. namespace SendInputDemo
  13. {
  14. public partial class Form1 : Form
  15. {
  16. public Form1()
  17. {
  18. InitializeComponent();
  19. this.btnSetCurPosition.Click += new System.EventHandler(this.btnSetCurPosition_Click);
  20. }
  21. /// <summary>
  22. /// 设置鼠标的位置按钮点击事件
  23. /// </summary>
  24. /// <param name="sender"></param>
  25. /// <param name="e"></param>
  26. private void btnSetCurPosition_Click(object sender, EventArgs e)
  27. {
  28. for (int i = 0; i <150; i+=20)
  29. {
  30. POINT lpPoint;
  31. Win32SendInputApi.GetCursorPos(out lpPoint);
  32. Win32SendInputApi.SetCursorPos(lpPoint.X + i, lpPoint.Y +i);
  33. Thread.Sleep(100);
  34. }
  35. }
  36. }
  37. }

上面的逻辑是:获取到当前鼠标光标的位置,然后赋予鼠标光标新的位置,每次设置睡眠100毫秒才能看到效果

运行效果:

可以看到鼠标光标在按钮"设置鼠标的位置"上点击后,鼠标光标逐渐以对角线的方式往右下角移动

5  实现演示效果3:   点击按钮,然后控制鼠标光标移动到演示效果1中的那个按钮的位置上,并实现点击,接着就会看到效果1中的效果(模拟键盘输入,把输入的内容显示到文本框上)

'设置鼠标的位置并按模拟鼠标点击'的代码逻辑如下:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Runtime.InteropServices;
  8. using System.Text;
  9. using System.Threading;
  10. using System.Windows.Forms;
  11. using static SendInputDemo.Win32SendInputApi;
  12. namespace SendInputDemo
  13. {
  14. public partial class Form1 : Form
  15. {
  16. public Form1()
  17. {
  18. InitializeComponent();
  19. this.btnPress.Click += new System.EventHandler(this.btnPress_Click);
  20. this.btnSetCurPosition.Click += new System.EventHandler(this.btnSetCurPosition_Click);
  21. this.btnMouseClick.Click += new System.EventHandler(this.btnMouseClick_Click);
  22. }
  23. /// <summary>
  24. /// 设置鼠标的位置并按模拟鼠标点击按钮点击事件
  25. /// </summary>
  26. /// <param name="sender"></param>
  27. /// <param name="e"></param>
  28. private void btnMouseClick_Click(object sender, EventArgs e)
  29. {
  30. //PointToScreen为btnPress控件转屏幕坐标
  31. Point pointScreen =this.btnPress.PointToScreen(new Point(0,0));
  32. //Point pointScreen =this.btnPress.PointToScreen(new Point(0,0))可以换成
  33. //这样的写法Point pointScreen = this.PointToScreen(new Point(btnPress.Location.X, btnPress.Location.Y));
  34. Win32SendInputApi.SetCursorPos(pointScreen.X+10, pointScreen.Y+1);
  35. Input[] inputs = new Input[]
  36. {
  37. new Input
  38. {
  39. type = (int) InputType.Mouse,
  40. u = new InputUnion
  41. {
  42. mi = new MouseInput
  43. {
  44. dx =pointScreen.X+10,
  45. dy =pointScreen.Y+1,
  46. dwFlags = (uint)(MouseEventF.LeftDown), //鼠标左键按下
  47. dwExtraInfo = Win32SendInputApi.GetMessageExtraInfo()
  48. }
  49. }
  50. },
  51. new Input
  52. {
  53. type = (int) InputType.Mouse,
  54. u = new InputUnion
  55. {
  56. mi = new MouseInput
  57. {
  58. dx =pointScreen.X+10,
  59. dy =pointScreen.Y+1,
  60. dwFlags = (uint)(MouseEventF.LeftUp), //鼠标左键抬起
  61. dwExtraInfo = Win32SendInputApi.GetMessageExtraInfo()
  62. }
  63. }
  64. }
  65. };
  66. Win32SendInputApi.SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(Input)));
  67. }
  68. }
  69. }

想要在'触发键盘按下'按钮(名为btnPress)触发自动按钮逻辑,就得通过PointToScreen把控件的坐标转换为计算机桌面的坐标(以前做Unity 3D的时候经常看到这种骚操作),然后把转换后的坐标作为鼠标光标的位置,最后通过模拟鼠标左键按下和抬起,一定要鼠标按下和抬起一起使用才有效,因为鼠标按下和抬起同时完成才算实现鼠标按下的逻辑。

运行效果如下图:

 

好了,本文的内容到此结束(Tips:在线招个亲,最近家里逼得太急了,老铁有亲戚朋友啥的适龄未婚、活的女的都可以介绍哈,本人情况:男,1993出生,广州工作,广东人,硕士毕业,其它的可以私聊)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/272484
推荐阅读
相关标签
  

闽ICP备14008679号