I'm trying to create an Electron node.js application that can perform certain functions using global keybindings. The global keybindings API in Electron doesn't work in games unfortunately so I need to create a native node module that listens to these low level key events.
So i'm using node-gyp to compile the project with visual studio 2015 and nan to provide the communication between node and c++. I've managed to get both aspects of the project working seperately(the low level key bindings and the node.js<-->nan communication) but I'm having trouble combining them. I also admit I have very little experience with c++(I haven't written a single c++ program).
#include "node_modules/nan/nan.h"
using namespace std;
using namespace Nan;
HHOOK _hook;
KBDLLHOOKSTRUCT kbdStruct;
class KeyboardEventWorker : public AsyncProgressWorker {
public:
KeyboardEventWorker(Callback *callback, Callback *progress)
: AsyncProgressWorker(callback), progress(progress) {}
~KeyboardEventWorker() {}
LRESULT CALLBACK HookCallback(int nCode,WPARAM wParam,LPARAM lParam) {
executionProgress->Send(reinterpret_cast<const char*>(nCode), sizeof(nCode));
return CallNextHookEx(_hook, nCode, wParam, lParam);
}
void Execute (const AsyncProgressWorker::ExecutionProgress& progress) {
executionProgress = &progress; //PROBLEM #1
_hook = SetWindowsHookEx(13, HookCallback, NULL, 0); //PROBLEM #2
SleepEx(INFINITE, true);
}
void HandleProgressCallback(const char *data, size_t size) {
HandleScope scope;
v8::Local<v8::Value> argv[] = {
New<v8::Integer>(*reinterpret_cast<int*>(const_cast<char*>(data)))
};
progress->Call(1, argv);
}
private:
Callback *progress;
AsyncProgressWorker::ExecutionProgress *executionProgress;
};
NAN_METHOD(DoProgress) {
Callback *progress = new Callback(info[0].As<v8::Function>());
Callback *callback = new Callback(info[1].As<v8::Function>());
AsyncQueueWorker(new KeyboardEventWorker(callback, progress));
}
NAN_MODULE_INIT(Init) {
Set(target
, New<v8::String>("init").ToLocalChecked()
, New<v8::FunctionTemplate>(DoProgress)->GetFunction());
}
NODE_MODULE(asyncprogressworker, Init)
Problem #1: To be able to send back messages to node.js, I'l need to copy the pointer of AsyncProgressWorker::ExecutionProgress and make it available to the entire class so when HookCallback triggers it can send a message to node.js.
The compiler doesn't like this
..\binding.cc(21): error C2440: '=': cannot convert from 'const Nan::AsyncProgressWorker::ExecutionProgress *' to 'Nan: :AsyncProgressWorker::ExecutionProgress *' [C:\Users\eksrow\gdrive\projects\vscode\node-native-hello-world\build\bindin g.vcxproj].
..\binding.cc(21): note: Conversion loses qualifiers
Formatted:
'const Nan::AsyncProgressWorker::ExecutionProgress *'
'Nan::AsyncProgressWorker::ExecutionProgress *'
This one I managed to solve by adding the keyword const to private member *executionProgress;. But I don't understand why that would fix it, const variables aren't supposed to be changed once they are set. Why does this compile?
Problem #2: This one is very peculiar:
..\binding.cc(22): error C3867: 'KeyboardEventWorker::HookCallback': non-standard syntax; use '&' to create a pointer t o member [C:\Users\eksrow\gdrive\projects\vscode\node-native-hello-world\build\binding.vcxproj]
I've looked up many examples online and they all have the same syntax regarding this:
I can't see the difference between my code and theirs regarding that line.
If I do what the compiler says and add an ampersand to that line, it gives a completely different error:
..\binding.cc(22): error C2276: '&': illegal operation on bound member function expression [C:\Users\eksrow\gdrive\proj ects\vscode\node-native-hello-world\build\binding.vcxproj] ..\binding.cc(22): error C2660: 'SetWindowsHookExA': function does not take 3 arguments [C:\Users\eksrow\gdrive\project s\vscode\node-native-hello-world\build\binding.vcxproj]