我正在尝试使用ffi在dart中实现SendInput函数。它需要一个无符号整数、一个输入数组和一个整数。我发现很难实现输入数组结构,这就是我到目前为止所做的:
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 ),但我想知道在联合得到支持之前是否有解决方法。
发布于 2020-01-01 16:54:34
你的方法不会起作用,因为你的结构太大了。您真正想要的是分配的内存与常规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;
}话虽如此,它仍然不能工作,我真的不知道为什么。我甚至在experimented中只传递了原始字节数组指针,这在dart中仍然不起作用(在C语言中它可以很好地工作)。这可能是dart FFI本身的一个bug,但也可以是很多其他东西。我正在尝试破解它,因为我也需要它来工作。
现在,您可以使用刚刚生效的弃用函数:
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的更多函数,你可以使用我的quickly stitched together dart binding generator来实现WinAPI函数。您只需运行它并将WinAPI函数粘贴到上面的文本区,底部区域应该会显示dart绑定。有时它缺少一些类型定义(只需添加另一个类型Mapping),但在大多数情况下,它工作得很好:) (不适用于structs tough)
https://stackoverflow.com/questions/59358895
复制相似问题