2013-02-10 3 views
10

Je développe une application node-webkit simple pour Windows (Vista, 7, ...) et j'ai besoin d'utiliser certaines fonctions WinAPI, notamment RegisterHotKey et SendInput, pour lier des raccourcis système et faire des frappes sur ça. Il n'y a pas d'API fournie par node-webkit, donc j'ai pensé utiliser node-ffi pour appeler ces fonctions. Je suis novice dans le développement de WinAPI, j'ai donc lu quelques manuels MSDN, mais j'ai trouvé que la plupart des exemples créent une fenêtre, une boucle de message, une procédure de gestion de message, etc. Donc, je ne comprends pas très bien, comment implémenter correctement l'appel à WinAPI à partir de node-webkit, sans créer de fenêtre séparée?Node-webkit WinAPI

Node-ffi tutorial ne couvre pas ce cas, donc j'ai trouvé la bibliothèque node Windows, mais il semble que cela implémente simplement l'application Windows au moyen de nœud.

Existe-t-il un moyen d'implémenter des appels natifs sans créer d'application Windows? Quelle est la bonne façon de faire cela?

+1

Avez-vous regardé ici: http://stackoverflow.com/questions/9624536/create-a-node-js-native-extension-on-windows. La réponse de josh3736 est pertinente pour vous. – user568109

+1

Je pense que la façon de modifier node-webkit pour ajouter votre API est plus facile et meilleure. Je peux chercher à fusionner votre code si vous contribuez. –

Répondre

17

J'ai écrit un script de noeud qui capture des raccourcis clavier sous Windows en utilisant les modules ffi, ref et ref-struct. J'ai eu quelques problèmes pour les faire travailler dans un .exe empaqueté puisque ffi et ref sont des adjonctions indigènes. Pour plus d'informations, voir ce github issue J'ai ouvert il y a un certain temps.

Quoi qu'il en soit, voici le 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)); 
    } 
} 

Si vous voulez que cela fonctionne avec nœud-webkit, assurez-vous que vous construisez tous les add-ons natifs avec nw-gyp avec le --target ensemble à votre version de node- WebKit (0.5.1 dans mon cas):

# 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 

revue la documentation MSDN pour comprendre les signatures de méthode et struct utilisés. J'espère que cela t'aides!