[英]Node-webkit WinAPI
I'm developing simple node-webkit application for Windows (Vista, 7, …) and I need to use some WinAPI functions, specifically, RegisterHotKey
and SendInput
, to bind system-wide hotkeys and make keystrokes based on that. 我正在为Windows开发简单的node-webkit应用程序(Vista,7,...),我需要使用一些WinAPI函数,特别是
RegisterHotKey
和SendInput
来绑定系统范围的热键,并根据它进行击键。 There's no such API supplied by node-webkit, so I thought to use node-ffi to call that functions. node-webkit没有提供这样的API,所以我想使用node-ffi来调用这些函数。
I'm new to WinAPI development, so I've read some MSDN manuals, but found that most of examples create window, message loop, message handling procedure and so on. 我是WinAPI开发的新手,所以我读了一些MSDN手册,但发现大多数例子都创建了窗口,消息循环,消息处理程序等等。 So I don't understand quite well, how to implement correctly calling to WinAPI from node-webkit, without creating separate window?
所以我不太了解,如何从node-webkit正确调用WinAPI,而不创建单独的窗口?
Node-ffi tutorial doesn't cover that case, so I've found the node Windows library, but it seems that it just implements Windows application by means of node. Node-ffi教程没有涵盖这种情况,所以我找到了节点Windows库,但它似乎只是通过节点实现Windows应用程序。
Is there a way to implement native calls without creating windows application? 有没有办法在不创建Windows应用程序的情况下实现本机调用? What's the correct way to do that?
这样做的正确方法是什么?
I wrote a node script that captures hotkeys on windows using the ffi
, ref
, and ref-struct
modules. 我编写了一个节点脚本,使用
ffi
, ref
和ref-struct
模块在Windows上捕获热键。 I've had some issues getting them to work in a packaged .exe since ffi
and ref
are native add-ons. 我有一些问题让他们在打包的.exe中工作,因为
ffi
和ref
是本机附加组件。 For more information, see this github issue I opened awhile ago. 有关更多信息,请参阅我之前打开的这个github问题 。
Anyways, here's the code: 无论如何,这是代码:
var FFI = require('ffi'),
ref = require('ref'),
Struct = require('ref-struct');
/* First, create the necessary data structures that'll be used
by our windows api calls. */
var pointStruct = Struct({
'x': 'long',
'y': 'long'
});
var msgStruct = Struct({
'hwnd': 'int32',
'message': 'int32',
'wParam': 'int32',
'lParam': 'int32',
'time': 'int32',
'pt': pointStruct
});
var msgStructPtr = ref.refType(msgStruct);
/* Second, register the functions we'd like to use by providing
their method signatures. */
var user32 = new FFI.Library('user32', {
'RegisterHotKey': [
'bool', ['int32', 'int', 'int32', 'int32']
],
'GetMessageA': [
'bool', [msgStructPtr, 'int32', 'int32', 'int32']
]
/* You may prefer to use PeekMessageA which has the same
signature as GetMessageA, but is non-blocking. I haven't
tested it, though.
});
/* Third, register your hotkeys. I wanted to control a media player,
so these keys reflect that. */
var ALT = 0x0001,
CTRL = 0x0002,
SHIFT = 0x0004;
var MEDIA_NEXT = 0xB0,
MEDIA_PREV = 0xB1,
MEDIA_STOP = 0xB2,
MEDIA_PLAY_PAUSE = 0xB3,
MEDIA_LAUNCH = 0xB5;
var PERIOD = 0xBE,
COMMA = 0xBC,
EQUAL = 0xBB,
DIVIDE = 0xBF,
SQUOTE = 0xDE,
PAGEUP = 0x21,
PAGEDOWN = 0x22;
registrations = [];
registrations.push(user32.RegisterHotKey(0, 1, 0, MEDIA_NEXT));
registrations.push(user32.RegisterHotKey(0, 1, 0, MEDIA_PREV));
registrations.push(user32.RegisterHotKey(0, 1, 0, MEDIA_STOP));
registrations.push(user32.RegisterHotKey(0, 1, 0, MEDIA_PLAY_PAUSE));
registrations.push(user32.RegisterHotKey(0, 1, 0, MEDIA_LAUNCH));
registrations.push(user32.RegisterHotKey(0, 1, CTRL, PERIOD));
registrations.push(user32.RegisterHotKey(0, 1, CTRL, COMMA));
registrations.push(user32.RegisterHotKey(0, 1, CTRL, EQUAL));
registrations.push(user32.RegisterHotKey(0, 1, CTRL, DIVIDE));
registrations.push(user32.RegisterHotKey(0, 1, CTRL | ALT, PAGEUP));
registrations.push(user32.RegisterHotKey(0, 1, CTRL | ALT, PAGEDOWN));
// an array of booleans telling us which registrations failed/succeeded
console.log(registrations);
/* Fourth, wait for new hotkey events from the message queue. */
var myMsg = new msgStruct;
while (user32.GetMessageA(myMsg.ref(), 0, 0, 0)) {
var key = myMsg.lParam >> 16;
switch (key) {
case MEDIA_NEXT: console.log('media next'); break;
case MEDIA_PREV: console.log('media prev'); break;
case MEDIA_STOP: console.log('media stop'); break;
case MEDIA_PLAY_PAUSE: console.log('media play/pause'); break;
case MEDIA_LAUNCH: console.log('media launch'); break;
case PERIOD: console.log('next'); break;
case COMMA: console.log('previous'); break;
case EQUAL: console.log('play/pause'); break;
case DIVIDE: console.log('info'); break;
case PAGEUP: console.log('volume up'); break;
case PAGEDOWN: console.log('volume down'); break;
default: console.log('undefined hotkey', key, key.toString(16));
}
}
If you want this to work with node-webkit, make sure you build all the native add-ons with nw-gyp
with the --target
set to your version of node-webkit (0.5.1 in my case): 如果您希望这与node-webkit一起使用,请确保使用
nw-gyp
构建所有本机加载项,并将--target
设置为node-webkit的版本(在我的情况下为0.5.1):
# Make sure you run this command in the following directories (where the binding.gyp files are):
# node_modules/ffi/
# node_modules/ffi/node_modules/ref/
# node_modules/ref/
$ nw-gyp clean configure --target=v0.5.1 build
Review the MSDN docs to understand the method signatures and structs used. 查看MSDN文档以了解所使用的方法签名和结构。 Hope this helps!
希望这可以帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.