【问题标题】:node ffi Rect type节点 ffi Rect 类型
【发布时间】:2016-10-28 13:36:23
【问题描述】:

我想使用 node-ffi 和 user32 库在 node 中获取特定窗口的大小。根本无法使 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


    【解决方案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);
    

    【讨论】:

      【解决方案2】:

      我无法使用ref-struct 方法让您的示例工作,但我想出了一种使用简单“指针”类型的方法:

      var user32 = new ffi.Library("user32", {
          GetWindowRect: ["bool", ["int32", "pointer"]],
      });
      
      export function GetWindowPosition(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;
      }
      

      【讨论】:

        【解决方案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() 创建实际的 rect 结构来存储结果:

        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 接受缓冲区作为它的第二个参数,并将其内容设置为实际 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 dc 00 00 00 50 05 00 00 34 03 00 00 }

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-07-23
          • 2018-09-20
          • 2019-03-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多