2013-02-10 20 views
10

Windows用の単純なノードWebkitアプリケーション(Vista、7など)を開発しています.WyAPI関数、具体的にはRegisterHotKeySendInputを使用して、システム全体のホットキーをバインドしてキーストロークを作成する必要がありますその上に。そのようなAPIはnode-webkitによって提供されていないので、私はnode-ffiを使ってその関数を呼び出すと考えました。Node-webkit WinAPI

私はWinAPI開発の初心者ですので、いくつかのMSDNマニュアルを読んでいますが、ほとんどの例ではウィンドウ、メッセージループ、メッセージ処理手順などが作成されています。だから私は非常によく理解していない、別のウィンドウを作成せずにノードWebkitからWinAPIを正しく呼び出す方法を実装する方法は?

Node-ffi tutorialはこのケースをカバーしていないので、node Windowsライブラリを見つけましたが、ノードを使用してWindowsアプリケーションを実装しているようです。

Windowsアプリケーションを作成せずにネイティブコールを実装する方法はありますか?それを行う正しい方法は何ですか?

+1

こちらをご覧ください:http://stackoverflow.com/questions/9624536/create-a-node-js-native-extension-on-windows。 josh3736の答えはあなたにとって重要です。 – user568109

+1

あなたのAPIを追加するためにnode-webkitを変更する方が簡単で良いと思います。あなたが貢献するならあなたのコードをマージすることができます。 –

答えて

17

ffiref、およびref-structモジュールを使用して、Windowsでショートカットをキャプチャするノードスクリプトを作成しました。私はffirefがネイティブアドオンであるため、パッケージ化された.exeで動作するようにするいくつかの問題がありました。詳細はこちら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', '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)); 
    } 
} 

あなたは、これは、ノードのWebKitで動作するようにしたい場合は、リンパ節転移のバージョンに--targetセットでnw-gypですべてのネイティブのアドオンを構築してください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のドキュメントを参照してください。お役に立てれば!