Implementing winapi(SendInput) with dart:ffi

Implementing winapi(SendInput) with dart:ffi

本文关键字:dart ffi with winapi SendInput Implementing      更新时间:2023-10-16

我正在尝试使用 ffi 在 dart 中实现 SendInput 函数。 它需要一个无符号整数、一个输入数组和一个整数。 我发现很难实现 INPUT 数组结构,这就是我到目前为止所做的:

import 'dart:ffi';
import 'package:ffi/ffi.dart';
import 'user32.dart'; //import dylib
typedef SendInputC = Uint32 Function(
Uint32 cInputs, Pointer pInputs, Int32 cbSize);
typedef SendInputDart = int Function(int inputCount, Pointer inputs, int size);
int SendInput(int type, {MouseInput mi, KeyboardInput ki, HardwareInput hi}) {
final SendInputP =
dylib.lookupFunction<SendInputC, SendInputDart>('SendInput');
var input = Input.allocate(
type: type,
mi: mi?.addressOf ?? nullptr,
ki: ki?.addressOf ?? nullptr,
hi: hi?.addressOf ?? nullptr);
var result = SendInputP(1, input.addressOf, sizeOf<Input>());
return result;
}
class Input extends Struct {
@Uint32()
int type;
Pointer<MouseInput> mi;
Pointer<KeyboardInput> ki;
Pointer<HardwareInput> hi;
factory Input.allocate(
{int type,
Pointer<MouseInput> mi,
Pointer<KeyboardInput> ki,
Pointer<HardwareInput> hi}) =>
allocate<Input>().ref
..type = type
..mi = mi
..ki = ki
..hi = hi;
}
/// MouseInput struct
class MouseInput extends Struct {
@Int32()
int dx;
@Int32()
int dy;
@Uint32()
int mouseData;
@Uint32()
int dwFlags;
@Uint32()
int time;
@Uint32()
int dwExtraInfo;
factory MouseInput.allocate(
{int dx = 0,
int dy = 0,
int mouseData = 0,
int dwFlags = 0,
int time = 0,
int dwExtraInfo = 0}) =>
allocate<MouseInput>().ref
..dx = dx
..dy = dy
..mouseData = mouseData
..dwFlags = dwFlags
..time = time
..dwExtraInfo = dwExtraInfo;
}
class KeyboardInput extends Struct {
@Uint16()
int wVk;
@Uint16()
int wScan;
@Uint32()
int dwFlags;
@Uint32()
int time;
@Uint32()
int dwExtraInfo;
factory KeyboardInput.allocate(
{int wVk = 0,
int wScan = 0,
int dwFlags = 0,
int time = 0,
int dwExtraInfo = 0}) =>
allocate<KeyboardInput>().ref
..wVk = wVk
..wScan = wScan
..dwFlags = dwFlags
..time = time
..dwExtraInfo = dwExtraInfo;
}
class HardwareInput extends Struct {
@Uint32()
int uMsg;
@Uint16()
int wParamL;
@Uint16()
int wParamH;
factory HardwareInput.allocate(
{int uMsg = 0, int wParamL = 0, int wParamH = 0}) =>
allocate<HardwareInput>().ref
..uMsg = uMsg
..wParamL = wParamL
..wParamH = wParamH;
}

但是调用SendInput函数不会产生任何效果并返回 0,例如,此代码不发送鼠标输入。

var mi = MouseInput.allocate(dx: 505, dy: 175, dwFlags: 0x0002);
var r = SendInput(0, mi: mi);

这就是函数在C++中的样子

INPUT input;
input.type = INPUT_MOUSE;
input.mi.dx = 505;
input.mi.dy = 175;
input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
input.mi.dwExtraInfo = 0;
input.mi.time = 0;

SendInput(1, &input, sizeof(input));
tagInput

结构包含联合,似乎它们尚未得到支持(https://github.com/dart-lang/sdk/issues/38491(,但我想知道在支持联合之前是否有解决方法。

你的方法行不通,因为你的结构太大了。您真正想要的是分配的内存具有与常规 C 版本相同的大小(即 28 字节(,因此如下所示:

class KeyboardInput extends Struct {
@Uint32() int type;
@Uint16() int virtualCode;
@Uint16() int scanCode;
@Uint32() int flags;
@Uint32() int time;
Pointer dwExtraInfo;
@Uint32() int _padding;
}

话虽如此 - 它仍然不起作用,我真的不知道为什么。我什至尝试只传递原始字节数组指针,这在 dart 中仍然不起作用(在 C 中它工作正常(。这可能是飞镖FFI本身的一个错误,但可能是很多其他的东西。我正在尝试破解它,因为我也需要它才能工作。

现在,您可以使用已弃用的函数:

import 'dart:ffi';
DynamicLibrary _user32 = DynamicLibrary.open("user32.dll");
typedef _keybd_event_C = Void Function(Uint8 bVk, Uint8 bScan, Uint32 dwFlags, Pointer dwExtraInfo);
typedef _keybd_event_Dart = void Function(int bVk, int bScan, int dwFlags, Pointer dwExtraInfo);
var keybd_event = _user32.lookupFunction<_keybd_event_C, _keybd_event_Dart>("keybd_event");
const MAPVK_VK_TO_VSC = 0;
typedef _MapVirtualKeyW_C = Uint32 Function(Uint32 uCode, Uint32 uMapType);
typedef _MapVirtualKeyW_Dart = int Function(int uCode, int uMapType);
var MapVirtualKeyW = _user32.lookupFunction<_MapVirtualKeyW_C, _MapVirtualKeyW_Dart>("MapVirtualKeyW");

void main() {
keybd_event(
0x5a, 
MapVirtualKeyW(0x5a, MAPVK_VK_TO_VSC), 
0, 
nullptr);
}

附注: 此外,如果您需要WinAPI的更多函数,则可以使用我快速拼接在一起的飞镖绑定生成器来获取WinAPI函数。您只需运行它并将 WinAPI 函数粘贴到上方的文本区域中,底部区域应显示飞镖绑定。有时它缺少一些类型定义(只需添加另一个类型Mapping(,但在大多数情况下,它:)工作得很好(不适用于结构坚韧(