我正在为
Windows开发简单的node-webkit应用程序(Vista,7,…),我需要使用一些WinAPI功能,特别是RegisterHotKey和SendInput来绑定系统范围的热键,并根据这一点进行按键操作. node-webkit没有提供这样的API,所以我以为使用
node-ffi来调用这个函数.
我是WinAPI开发的新手,所以我已经阅读了一些MSDN手册,但是发现大多数示例创建窗口,消息循环,消息处理过程等等.所以我不太明白,如何从node-webkit正确地调用WinAPI,而不创建单独的窗口?
Node-ffi tutorial没有涵盖这种情况,所以我找到了node Windows库,但似乎它只是通过节点实现Windows应用程序.
解决方法
我写了一个节点脚本,使用
ffi
,ref
和
ref-struct
模块在Windows上捕获热键.我有一些问题让他们在一个打包的.exe工作,因为ffi和ref是本机附件.有关更多信息,请参阅此
github issue我稍后打开.
无论如何,这里是代码:
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'] ] /* 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,MEDIA_NEXT)); registrations.push(user32.RegisterHotKey(0,MEDIA_PREV)); registrations.push(user32.RegisterHotKey(0,MEDIA_STOP)); registrations.push(user32.RegisterHotKey(0,MEDIA_PLAY_PAUSE)); registrations.push(user32.RegisterHotKey(0,MEDIA_LAUNCH)); registrations.push(user32.RegisterHotKey(0,CTRL,PERIOD)); registrations.push(user32.RegisterHotKey(0,COMMA)); registrations.push(user32.RegisterHotKey(0,EQUAL)); registrations.push(user32.RegisterHotKey(0,DIVIDE)); registrations.push(user32.RegisterHotKey(0,CTRL | ALT,PAGEUP)); registrations.push(user32.RegisterHotKey(0,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)) { 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)); } }
如果您希望这可以使用node-webkit,请确保使用nt-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
查看MSDN文档以了解所使用的方法签名和结构体.希望这可以帮助!