找到一点资料,关于win32 api调用的,Nodejs相关应用探讨(自己的笔记),记录在这里

找到一点资料,关于win32 api调用的,Nodejs相关应用探讨(自己的笔记),记录在这里

http://www.reddit.com/r/javascript/comments/103fkg/64bit_nodejs_winforms/

var ffi = require('ffi'),
  ref = require('ref'),
  Struct = require('ref-struct'),
  hWnd = new Buffer(8);

var ICCx = Struct({
  'dwSize': 'int32',
  'dwICC': 'int32'
});
var ICCxPtr = ref.refType(ICCx);
var comctl32 = ffi.Library('comctl32', {
  'InitCommonControlsEx': ['int32', [ICCxPtr]]
});

var WndClassEx = Struct({
  'cbSize': 'uint32',
  'style': 'uint32',
  'lpfnWndProc': 'pointer', // callback 'int32', ['pointer', 'uint32', 'int32', 'uint32']
  'cbClsExtra': 'int32',
  'cbWndExtra': 'int32',
  'hInstance': 'pointer', // can be 0?
  'hIcon': 'pointer',
  'hCursor': 'pointer',
  'hbrBackground': 'pointer',
  'lpszMenuName': 'pointer',
  'lpszClassName': 'pointer',
  'hIconSm': 'pointer'
});
var WndClassExPtr = ref.refType(WndClassEx);
var user32 = ffi.Library('user32', {
  'RegisterClassExW': ['int32', [WndClassExPtr]],
  'CreateWindowExW': ['pointer', [
    'int32', 'pointer', 'pointer', 'int32',    // style, name, name, style
    'int32', 'int32', 'int32', 'int32',        // x, y, w, h
    'pointer', 'pointer', 'pointer', 'pointer' // handles
  ]],
  'DefWindowProcW': ['uint32', ['pointer', 'uint32', 'int32', 'pointer']],
  'ShowWindow': ['bool', ['pointer', 'int32']],
  'UpdateWindow': ['bool', ['pointer']],
  'GetMessageW': ['bool', ['pointer', 'pointer', 'uint32', 'uint32']],
  'TranslateMessageEx': ['bool', ['pointer']],
  'DispatchMessageW': ['uint32', ['pointer']]
});

var kernel32 = ffi.Library('kernel32', {
  'GetModuleHandleExW': ['bool', [
    'int32', 'pointer', 'pointer' // flags, optional LPCTSTR name, ref hModule
  ]], // etc... / kernel32 is your friend!
});

var Msg = Struct({
  'hwnd': 'pointer',
  'message': 'uint32',
  'wParam': 'int32',
  'lParam': 'pointer',
  'time': 'int32',
  'pX': 'int32',
  'pY': 'int32'
});

// App-specific

// Names
var className = new Buffer('Node.js WinForms Class\0', 'ucs-2');
var windowName = new Buffer('Node.js WinForms App\0', 'ucs-2');

// hInstance
var hInstance = new Buffer(8);
kernel32.GetModuleHandleExW(0, null, hInstance);

// WndProc
var WndProc = ffi.Callback('uint32',
  ['pointer', 'uint32', 'int32', 'pointer'],
  function(hwnd, uMsg, wParam, lParam) {
    console.log('Got Message: ' + uMsg + ' /', hwnd.deref());
    var result = 0; // ref.alloc('int32');
    switch(uMsg) {
    default:
      result = user32.DefWindowProcW(hwnd, uMsg, wParam, lParam);
      console.log('DefWindowProc LRESULT: ' + result);
      return result;
    }
    console.log('Sending LRESULT: ' + result.deref())
    return result;
  }
);

// Common Controls
var icc = new ICCx;
icc.dwSize = 8;
icc.dwICC = 0x40ff;
comctl32.InitCommonControlsEx(icc.ref());

// Window Class
var wClass = new WndClassEx;
wClass.cbSize = 80; // x86 = 48
wClass.style = 0;
wClass.lpfnWndProc = WndProc;
wClass.cbClsExtra = 0;
wClass.cbWndExtra = 0;
wClass.hInstance = hInstance;
wClass.hIcon = null;
wClass.hCursor = null;
wClass.hbrBackground = null;
wClass.lpszMenuName = null;
wClass.lpszClassName = className;
wClass.hIconSm = null;

if (!user32.RegisterClassExW(wClass.ref()))
  throw 'Error registering class';

hWnd = user32.CreateWindowExW(
  0,
  className,
  windowName,
  0xcf0000, // overlapped window
  1 << 31, // use default
  1 << 31,
  320,
  200,
  null, null, hInstance, null
);

console.log(hWnd);

user32.ShowWindow(hWnd, 1);
user32.UpdateWindow(hWnd);

// message loop
var msg = new Msg;
var getMsgRes = 0;
while (user32.GetMessageW(msg.ref(), null, 0, 0)) {
  user32.TranslateMessageEx(msg.ref());
  user32.DispatchMessageW(msg.ref());
}

return msg.wParam;

3 回复

以下是一个关于如何在 Node.js 中使用 ffiref 库来调用 Windows API 的示例。该示例展示了如何创建一个基本的窗口应用程序。

示例代码

const ffi = require('ffi');
const ref = require('ref');
const Struct = require('ref-struct');
const path = require('path');

// 定义结构体
const POINT = Struct({
  x: 'int32',
  y: 'int32'
});

const MSG = Struct({
  hwnd: 'pointer',
  message: 'uint32',
  wParam: 'int32',
  lParam: 'pointer',
  time: 'int32',
  pt: POINT
});

const WNDCLASSEX = Struct({
  cbSize: 'uint32',
  style: 'uint32',
  lpfnWndProc: 'pointer',
  cbClsExtra: 'int32',
  cbWndExtra: 'int32',
  hInstance: 'pointer',
  hIcon: 'pointer',
  hCursor: 'pointer',
  hbrBackground: 'pointer',
  lpszMenuName: 'pointer',
  lpszClassName: 'pointer',
  hIconSm: 'pointer'
});

// 加载库
const user32 = ffi.Library('user32', {
  'RegisterClassExW': ['uint32', ['pointer']],
  'CreateWindowExW': ['pointer', ['uint32', 'string', 'string', 'uint32', 'int32', 'int32', 'int32', 'int32', 'pointer', 'pointer', 'pointer', 'pointer']],
  'DefWindowProcW': ['uint32', ['pointer', 'uint32', 'int32', 'pointer']],
  'ShowWindow': ['bool', ['pointer', 'int32']],
  'UpdateWindow': ['bool', ['pointer']],
  'GetMessageW': ['bool', ['pointer', 'pointer', 'uint32', 'uint32']],
  'TranslateMessage': ['bool', ['pointer']],
  'DispatchMessageW': ['uint32', ['pointer']]
});

const kernel32 = ffi.Library('kernel32', {
  'GetModuleHandleW': ['pointer', ['pointer']]
});

// 窗口过程函数
const WndProc = ffi.Callback('uint32', ['pointer', 'uint32', 'int32', 'pointer'], (hwnd, msg, wParam, lParam) => {
  if (msg === 0x0010 /* WM_DESTROY */) { // WM_DESTROY 消息
    user32.PostQuitMessage(0);
  } else {
    return user32.DefWindowProcW(hwnd, msg, wParam, lParam);
  }
  return 0;
});

// 注册窗口类
const wc = new WNDCLASSEX();
wc.cbSize = wc.size;
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = kernel32.GetModuleHandleW(null);
wc.hIcon = null;
wc.hCursor = null;
wc.hbrBackground = null;
wc.lpszMenuName = null;
wc.lpszClassName = 'NodeJSWindow';
wc.hIconSm = null;

if (user32.RegisterClassExW(wc.ref()) === 0) {
  throw new Error('Failed to register window class');
}

// 创建窗口
const hWnd = user32.CreateWindowExW(
  0, // dwExStyle
  wc.lpszClassName, // lpClassName
  'Node.js Window', // lpWindowName
  0x80000000 | 0x40000000, // dwStyle
  100, // X
  100, // Y
  800, // nWidth
  600, // nHeight
  null, // hWndParent
  null, // hMenu
  wc.hInstance, // hInstance
  null // lpParam
);

if (!hWnd) {
  throw new Error('Failed to create window');
}

// 显示并更新窗口
user32.ShowWindow(hWnd, 5); // SW_SHOW
user32.UpdateWindow(hWnd);

// 消息循环
const msg = new MSG();
while (user32.GetMessageW(msg.ref(), null, 0, 0) !== 0) {
  user32.TranslateMessage(msg.ref());
  user32.DispatchMessageW(msg.ref());
}

解释

  1. 结构体定义

    • POINT 结构体用于表示点。
    • MSG 结构体用于表示消息。
    • WNDCLASSEX 结构体用于表示窗口类。
  2. 加载库

    • 使用 ffi.Library 加载 user32.dllkernel32.dll,以便调用相应的 Windows API 函数。
  3. 窗口过程函数

    • WndProc 是窗口过程函数,用于处理窗口消息。这里处理了 WM_DESTROY 消息,并调用 PostQuitMessage 退出消息循环。
  4. 注册窗口类

    • 创建一个 WNDCLASSEX 实例并填充其字段,然后使用 RegisterClassExW 注册窗口类。
  5. 创建窗口

    • 使用 CreateWindowExW 创建窗口。
  6. 显示和更新窗口

    • 使用 ShowWindowUpdateWindow 显示并更新窗口。
  7. 消息循环

    • 使用 GetMessageWTranslateMessageDispatchMessageW 进行消息循环。

以上代码展示了如何使用 Node.js 调用 Windows API 创建一个简单的窗口应用程序。


这段代码展示了如何使用Node.js调用Windows API来创建一个简单的窗口应用程序。以下是一些关键点的解释:

  1. 引入必要的库

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

    这里引入了ffirefref-struct库,分别用于加载动态链接库、处理C风格的数据类型以及定义结构体。

  2. 定义数据结构

    var ICCx = Struct({
      'dwSize': 'int32',
      'dwICC': 'int32'
    });
    

    定义了一个名为ICCx的结构体,它包含两个整型成员。

  3. 加载Windows API库

    var comctl32 = ffi.Library('comctl32', {
      'InitCommonControlsEx': ['int32', [ICCxPtr]]
    });
    

    加载comctl32.dll库,并导出其中的InitCommonControlsEx函数。

  4. 定义窗口类

    var WndClassEx = Struct({
      'cbSize': 'uint32',
      'style': 'uint32',
      'lpfnWndProc': 'pointer',
      'cbClsExtra': 'int32',
      'cbWndExtra': 'int32',
      'hInstance': 'pointer',
      'hIcon': 'pointer',
      'hCursor': 'pointer',
      'hbrBackground': 'pointer',
      'lpszMenuName': 'pointer',
      'lpszClassName': 'pointer',
      'hIconSm': 'pointer'
    });
    

    定义了一个窗口类结构体WndClassEx,包含了窗口类的所有属性。

  5. 注册窗口类

    if (!user32.RegisterClassExW(wClass.ref()))
      throw 'Error registering class';
    

    使用RegisterClassExW函数注册窗口类。

  6. 创建窗口

    hWnd = user32.CreateWindowExW(
      0,
      className,
      windowName,
      0xcf0000,
      1 << 31,
      1 << 31,
      320,
      200,
      null, null, hInstance, null
    );
    

    使用CreateWindowExW函数创建窗口。

  7. 消息循环

    while (user32.GetMessageW(msg.ref(), null, 0, 0)) {
      user32.TranslateMessageEx(msg.ref());
      user32.DispatchMessageW(msg.ref());
    }
    

    创建一个消息循环来处理用户输入和其他事件。

这段代码演示了如何通过Node.js调用Windows API来创建一个简单的窗口应用程序。

回到顶部