节点 ffi 矩形类型

问题描述 投票:0回答:3

我想使用node-ffi 和 user32 库获取节点中特定窗口的大小。根本无法使 Rect 指针工作,我要么得到 NULL 作为输出,要么出现致命错误。

https://msdn.microsoft.com/en-us/library/windows/desktop/ms633503(v=vs.85).aspx

Out LPRECT lpRect 应包含左上角和右下角的坐标。

var ffi = require('ffi');
var ref = require('ref');
var Struct = require('ref-struct');

var lpctstr = {
    name: 'lpctstr',
    indirection: 1,
    size: ref.sizeof.pointer,
    get: function(buffer, offset) {
        var _buf = buffer.readPointer(offset);
        if(_buf.isNull()) {
            return null;
        }
        return _buf.readCString(0);
    },
    set: function(buffer, offset, value) {
        var _buf = ref.allocCString(value, 'ucs2');

        return buffer.writePointer(_buf, offset);
    },
    ffi_type: ffi.types.CString.ffi_type
};


var lpdwordPtr = ref.refType(ref.types.ulong);

var pointStruct = new Struct({
  'x': 'long',
  'y': 'long'
});

var rectStruct = new Struct({
  left        : pointStruct,
  top         : pointStruct,
  right       : pointStruct,
  bottom      : pointStruct
});

var rectPtr = ref.refType(rectStruct);


var user32 = ffi.Library('user32', {
    FindWindowW: ['int', [lpctstr, lpctstr]],
    GetWindowThreadProcessId: ['int', ['int', lpdwordPtr]],
    SetForegroundWindow: ['bool', ['int']],
    GetWindowRect: [rectPtr, ['int']]
});

var hwnd = user32.FindWindowW(null, 'Calculator');
user32.SetForegroundWindow(hwnd);
var Rect = user32.GetWindowRect(hwnd);
console.log(JSON.stringify(Rect));
javascript node.js user32 node-ffi
3个回答
3
投票

我有点晚了,但我想我终于弄清楚了 GetWindowRect() 是如何工作的。

首先需要根据Documentation:

定义 Rect Struct
const rect = Struct({
  left : 'long',
  top : 'long',
  right : 'long',
  bottom : 'long',
});

然后你需要定义你的 user32 库:

//I think This is something like (struct rect *)
//because you need to path pointer of struct rect to this function
const rectPtr = ref.refType(rect);

var user32 = ffi.Library('user32.dll', {
                        GetForegroundWindow : ['long',[]],
                        GetWindowRect : ['bool',['long',rectPtr]]
});

在调用 GetWindowRect 之前,需要获取您想知道其大小的窗口的句柄。为了简单起见,我们只需调用 GetForegroundWindow 函数即可获取当前活动窗口:

const wind_handle = user32.GetForegroundWindow();

我们有一个窗口句柄,现在我们需要为 GetWindowRect() 创建实际的矩形结构来存储结果:

const rec_struct = new rect;

如果您在控制台中记录此对象,您将看到类似以下内容:

{ 左:0, 顶部:0, 右:0, 底部:0, '参考缓冲区': 缓冲区@0x000001C387A81E80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 }

正如我提到的,GetWindowRect 接受 buffer 作为它的第二个参数,并用实际 C 矩形结构的内容设置它的内容。因此,为了在我们的rec_struct对象中获取窗口信息,我们需要将rec_struct['ref.buffer']路径到GetWindowRect:

user32.GetWindowRect(fhwnd,rec['ref.buffer']);

现在如果你在控制台中记录rec_struct,你会得到它填充窗口的左上角和右下角的坐标:

{ 左:560, 顶部:220, 右:1360, 底部:820, '参考缓冲区': 缓冲区@0x0000012F3751F270 30 02 00 00 直流 00 00 00 50 05 00 00 34 03 00 00 }

现在窗口大小的计算将变得微不足道。


3
投票

我无法使用

ref-struct
方法让你的示例工作,但我找到了一种使用简单的“指针”类型来实现它的方法:

var user32 = new ffi.Library("user32", {
    GetWindowRect: ["bool", ["int32", "pointer"]],
});

export function GetWindowRect(handle: number) {
    var rectPointer = Buffer.alloc(4 * 4);
    var success = user32.GetWindowRect(handle, rectPointer);
    if (!success) return null;
    
    let rect = RectPointerToRect(rectPointer);
    console.log("Rect: " + JSON.stringify(rect));
    return rect;
}

function RectPointerToRect(rectPointer: Buffer) {
    let rect = {} as any;
    rect.left = rectPointer.readUInt32LE(0);
    rect.top = rectPointer.readUInt32LE(4);
    rect.right = rectPointer.readUInt32LE(8);
    rect.bottom = rectPointer.readUInt32LE(12);
    return rect;
}

1
投票

试试这个。我相信,您已经为 RECT 做出了四个 POINT,但它只需要 LONG。

var ffi = require('ffi');
var ref = require('ref');
var Struct = require('ref-struct');

var lpctstr = {
    name: 'lpctstr',
    indirection: 1,
    size: ref.sizeof.pointer,
    get: function(buffer, offset) {
        var _buf = buffer.readPointer(offset);
        if(_buf.isNull()) {
            return null;
        }
        return _buf.readCString(0);
    },
    set: function(buffer, offset, value) {
        var _buf = ref.allocCString(value, 'ucs2');

        return buffer.writePointer(_buf, offset);
    },
    ffi_type: ffi.types.CString.ffi_type
};


var lpdwordPtr = ref.refType(ref.types.ulong);

var pointStruct =  Struct({
  'x': ffi.types.ulong,
  'y': ffi.types.ulong
});

var rectStruct =  Struct({
  left        : ffi.types.ulong,
  top         : ffi.types.ulong,
  right       : ffi.types.ulong,
  bottom      : ffi.types.ulong
});

var rectPtr = ref.refType(rectStruct);


var user32 = ffi.Library('user32', {
    FindWindowW: ['int', [lpctstr, lpctstr]],
    GetWindowThreadProcessId: ['int', ['int', lpdwordPtr]],
    SetForegroundWindow: ['bool', ['int']],
    GetWindowRect: ['bool', ['int',rectStruct]]
});

var hwnd = user32.FindWindowW(null, 'E');
user32.SetForegroundWindow(hwnd);
var Rect = new rectStruct;
var bool = user32.GetWindowRect(hwnd, Rect);
console.log(JSON.stringify(Rect), Rect);
© www.soinside.com 2019 - 2024. All rights reserved.