Windows(mouse_event)鼠标控制移动和点击

注意

当前函数后续也可以用(SendInput)函数来替换

C#

[System.Runtime.InteropServices.DllImport("user32")]
private static extern int mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);

C++

void mouse_event(
  [in] DWORD     dwFlags,
  [in] DWORD     dx,
  [in] DWORD     dy,
  [in] DWORD     dwData,
  [in] ULONG_PTR dwExtraInfo
);

实例

在按钮的当前位置基础上向右(X轴)并且向下(Y轴)移动50,按下右键按下或者释放XBUTTON1

mouse_event(MOUSEEVENTF_MOVE, 50, 50, XBUTTON1, 0);

使用场景

可用控制鼠标点击某一个位置,也可以通过当前函数影响到Windows休眠动作;

参数

[in] dwFlags

类型:DWORD

控制鼠标运动和按钮单击的各个方面。 此参数可以是以下值的某些组合。

含义

MOUSEEVENTF_ABSOLUTE

0x8000

dx 和 dy 参数包含规范化的绝对坐标。 如果未设置,则这些参数包含相对数据:自上次报告的位置以来的位置变化。 无论哪种类型的鼠标或类似鼠标的设备(如果有)连接到系统,都可以设置或不设置此标志。 有关相对鼠标运动的详细信息,请参阅以下“备注”部分。

MOUSEEVENTF_LEFTDOWN

0x0002

左按钮按下。

MOUSEEVENTF_LEFTUP

0x0004

左按钮已向上。

MOUSEEVENTF_MIDDLEDOWN

0x0020

中间按钮已关闭。

MOUSEEVENTF_MIDDLEUP

0x0040

中间按钮已向上。

MOUSEEVENTF_MOVE

0x0001

发生了移动。

MOUSEEVENTF_RIGHTDOWN

0x0008

右按钮已关闭。

MOUSEEVENTF_RIGHTUP

0x0010

右侧按钮已向上。

MOUSEEVENTF_WHEEL

0x0800

如果鼠标有滚轮,则滚轮已移动。 移动量在 dwData 中指定

MOUSEEVENTF_XDOWN

0x0080

按下了 X 按钮。

MOUSEEVENTF_XUP

0x0100

已释放 X 按钮。

MOUSEEVENTF_WHEEL

0x0800

滚轮按钮已旋转。

MOUSEEVENTF_HWHEEL

0x01000

滚轮按钮倾斜。

 

指定鼠标按钮状态的值设置为指示状态的更改,而不是正在进行的条件。 例如,如果按下并按住鼠标左键, 则MOUSEEVENTF_LEFTDOWN 是在首次按下左按钮时设置的,但不是在后续动作时设置的。 同样,仅在首次释放按钮时设置 MOUSEEVENTF_LEFTUP 。

不能在 dwFlags 参数中同时指定MOUSEEVENTF_WHEELMOUSEEVENTF_XDOWNMOUSEEVENTF_XUP,因为它们都需要使用 dwData 字段。

[in] dx

类型:DWORD

鼠标沿 x 轴的绝对位置或其自上次生成鼠标事件以来的运动量,具体取决于 MOUSEEVENTF_ABSOLUTE的设置。 绝对数据指定为鼠标的实际 x 坐标;相对数据指定为移动的米奇数。 麦克风是鼠标必须移动才能报告其移动量。

[in] dy

类型:DWORD

鼠标沿 y 轴的绝对位置或其自上次生成鼠标事件以来的运动量,具体取决于 MOUSEEVENTF_ABSOLUTE的设置。 绝对数据指定为鼠标的实际 y 坐标;相对数据指定为移动的米奇数。

[in] dwData

类型:DWORD

如果 dwFlags 包含 MOUSEEVENTF_WHEEL,则 dwData 指定滚轮移动量。 正值表示滚轮向前旋转(远离用户);负值表示滚轮向后旋转(朝向用户)。 一键式单击定义为 WHEEL_DELTA,即 120。

如果 dwFlags 包含 MOUSEEVENTF_HWHEEL,则 dwData 指定滚轮移动量。 正值表示方向盘向右倾斜;负值表示方向盘向左倾斜。

如果 dwFlags 包含 MOUSEEVENTF_XDOWN 或 MOUSEEVENTF_XUP,则 dwData 指定按下或释放了哪些 X 按钮。 此值可以是以下标志的任意组合。

如果 dwFlags 未 MOUSEEVENTF_WHEEL、 MOUSEEVENTF_XDOWN或 MOUSEEVENTF_XUP,则 dwData 应为零。

含义

XBUTTON1

0x0001

设置是否按下或释放第一个 X 按钮。

XBUTTON2

0x0002

设置是否按下或释放第二个 X 按钮。

[in] dwExtraInfo

类型: ULONG_PTR

与鼠标事件关联的附加值。 应用程序调用 GetMessageExtraInfo 以获取此额外信息。

备注

如果鼠标已移动(由 设置MOUSEEVENTF_MOVE 指示), dx 和 dy 将保留有关该动作的信息。 信息指定为绝对或相对整数值。

如果指定 了MOUSEEVENTF_ABSOLUTE 值, 则 dx 和 dy 包含介于 0 和 65,535 之间的规范化绝对坐标。 事件过程将这些坐标映射到显示图面。 坐标 (显示图面左上角的 0,0) 地图, (65535,65535) 贴图到右下角。

如果未指定 MOUSEEVENTF_ABSOLUTE 值, 则 dx 和 dy 指定从上次生成鼠标事件时起的相对运动 (上次报告的位置) 。 正值表示鼠标向右移动 (或向下移动) ;负值表示鼠标向左移动 (或向上移动) 。

相对鼠标运动取决于鼠标速度和加速级别的设置。 最终用户在 控制面板 中使用鼠标应用程序设置这些值。 应用程序使用 SystemParametersInfo 函数获取并设置这些值。

应用加速时,系统会对指定的相对鼠标运动应用两个测试。 如果沿 x 或 y 轴的指定距离大于第一个鼠标阈值,并且鼠标加速级别不为零,则操作系统会将距离加倍。 如果沿 x 轴或 y 轴的指定距离大于第二个鼠标阈值,并且鼠标加速级别等于 2,则操作系统会将应用第一个阈值测试产生的距离加倍。 因此,操作系统可以沿 x 轴或 y 轴将相对指定的鼠标运动乘以最多四倍。

应用加速后,系统会按所需的鼠标速度缩放结果值。 鼠标速度的范围从 1 (最慢) 到 20 (最快) ,表示指针根据鼠标移动的距离移动多少。 默认值为 10,这不会导致对鼠标运动进行其他修改。

mouse_event函数用于由需要执行此操作的应用程序合成鼠标事件。 应用程序也使用它,这些应用程序需要从鼠标获取比其位置和按钮状态更多的信息。 例如,如果平板电脑制造商想要将基于笔的信息传递给自己的应用程序,它可以编写一个 DLL,该 DLL 直接与平板电脑硬件通信,获取额外信息,并将其保存在队列中。 然后,DLL 使用标准按钮和 x/y 位置数据调用 mouse_event ,并在 dwExtraInfo 参数中调用一些指向排队的额外信息的指针或索引。 当应用程序需要额外信息时,它会使用存储在 dwExtraInfo 中的指针或索引调用 DLL,DLL 将返回额外的信息。

以下是一个简单的Java程序,利用Robot类实现捕获桌面屏幕图像,并将图像发送给服务器端。同时,程序可以接受客户端传来的鼠标或键盘操作指令,并模拟执行这些操作。 服务器端代码: ```java import java.awt.*; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import javax.imageio.ImageIO; public class Server { private static final int PORT = 8888; public static void main(String[] args) { try { ServerSocket serverSocket = new ServerSocket(PORT); System.out.println("Server started, waiting for client..."); Robot robot = new Robot(); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); while (true) { Socket socket = serverSocket.accept(); System.out.println("Client connected: " + socket.getInetAddress()); // Send screen image to client BufferedImage image = robot.createScreenCapture(new Rectangle(screenSize)); ImageIO.write(image, "png", socket.getOutputStream()); // Receive control command from client int cmd = socket.getInputStream().read(); if (cmd == 1) { // Move mouse int x = socket.getInputStream().read(); int y = socket.getInputStream().read(); robot.mouseMove(x, y); } else if (cmd == 2) { // Click mouse int button = socket.getInputStream().read(); if (button == 1) { robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); } else if (button == 2) { robot.mousePress(InputEvent.BUTTON2_DOWN_MASK); robot.mouseRelease(InputEvent.BUTTON2_DOWN_MASK); } else if (button == 3) { robot.mousePress(InputEvent.BUTTON3_DOWN_MASK); robot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK); } } else if (cmd == 3) { // Type key int key = socket.getInputStream().read(); robot.keyPress(key); robot.keyRelease(key); } socket.close(); } } catch (AWTException | IOException e) { e.printStackTrace(); } } } ``` 客户端代码: ```java import java.awt.*; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.io.IOException; import java.net.Socket; import javax.imageio.ImageIO; import javax.swing.*; public class Client extends JFrame { private static final int PORT = 8888; private static final String SERVER_IP = "127.0.0.1"; private static final int SCREEN_WIDTH = 800; private static final int SCREEN_HEIGHT = 600; private JLabel screenLabel; private Robot robot; public Client() { setTitle("Remote Control Client"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); screenLabel = new JLabel(); add(screenLabel); setResizable(false); pack(); setLocationRelativeTo(null); try { robot = new Robot(); } catch (AWTException e) { e.printStackTrace(); } } public void start() { while (true) { try { Socket socket = new Socket(SERVER_IP, PORT); // Receive screen image from server BufferedImage image = ImageIO.read(socket.getInputStream()); screenLabel.setIcon(new ImageIcon(image)); // Read user input int cmd = -1; int x = -1, y = -1; int button = -1; int key = -1; if (MouseInfo.getPointerInfo().getLocation().x >= 0 && MouseInfo.getPointerInfo().getLocation().y >= 0 && MouseInfo.getPointerInfo().getLocation().x < SCREEN_WIDTH && MouseInfo.getPointerInfo().getLocation().y < SCREEN_HEIGHT) { cmd = 1; x = MouseInfo.getPointerInfo().getLocation().x; y = MouseInfo.getPointerInfo().getLocation().y; if (SwingUtilities.isLeftMouseButtonPressed()) button = 1; else if (SwingUtilities.isMiddleMouseButtonPressed()) button = 2; else if (SwingUtilities.isRightMouseButtonPressed()) button = 3; } else { for (int i = KeyEvent.VK_0; i <= KeyEvent.VK_Z; i++) { if (robot.isKeyDown(i)) { cmd = 3; key = i; break; } } } // Send control command to server socket.getOutputStream().write(cmd); if (cmd == 1) { socket.getOutputStream().write(x); socket.getOutputStream().write(y); } else if (cmd == 2) { socket.getOutputStream().write(button); } else if (cmd == 3) { socket.getOutputStream().write(key); } socket.close(); } catch (IOException e) { e.printStackTrace(); } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { Client client = new Client(); client.setVisible(true); client.start(); } } ``` 在启动程序前,需要先确保客户端和服务器端在同一局域网内,并且服务器端先启动。启动程序后,客户端的界面会显示服务器端的屏幕画面,并且可以在客户端进行鼠标或键盘操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值