使用node-nan在node.js模块中设置WindowsHookEx
SetWindowsHookEx in a node.js module using node-nan
我正在尝试创建一个Electron node.js应用程序,该应用程序可以使用全局键绑定执行某些功能。不幸的是,Electron中的全局键绑定API在游戏中不起作用,所以我需要创建一个本地节点模块来侦听这些低级别的键事件。
因此,我使用node-gyp与visualstudio2015和nan一起编译该项目,以提供node与c++之间的通信。我已经设法使项目的两个方面分别工作(低级密钥绑定和node.js<-->nan通信),但我很难将它们结合起来。我也承认我对c++的经验很少(我还没有写过一个c++程序)。
#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)
问题#1:为了能够将消息发送回node.js,我需要复制AsyncProgressWorker::ExecutionProgress的指针,并使其对整个类可用,这样当HookCallback触发时,它就可以向node.js发送消息。
编译器不喜欢这个
\binding.cc(21):错误C2440:"=":无法从"const"转换Nan::AsyncProgressWorker::ExecutionProgress*'到'Nan::AsyncProgressWorker::ExecutionProgress*'[C:\Users\eksrow\gdrive\projects\vscode\node native hello world\build\binding.vcxproj].
\binding.cc(21):注意:转换丢失限定符
格式化:
"const Nan::AsyncProgressWorker::ExecutionProgress*"
'Nan::AsyncProgressWorker::ExecutionProgress*'
我通过在私有成员*executionProgress;中添加关键字const来解决这个问题;。但我不明白为什么这会解决问题,常量变量一旦设置就不应该被更改。为什么要编译?
问题2:这个很特别:
\binding.cc(22):错误C3867:"KeyboardEventWorker::HookCallback":非标准语法;使用"&"创建指向成员的指针[C:\Users\eksrow\gdrive\projects\vscode\node native hello world\build\binding.vcxproj]
我在网上查了很多例子,它们都有相同的语法:
- SetWindowsHookEx#1
- SetWindowsHookEx#2
关于这一行,我看不出我的代码和他们的代码有什么不同。
如果我按照编译器所说的去做,并在那一行中添加一个与号,它会给出一个完全不同的错误:
\binding.cc(22):错误C2276:"&":对绑定成员的非法操作函数表达式[C:\Users\eksrow\gdrive\projects\vscode\node native hello world\build\binding.vcxproj]..\binding.cc(22):错误C2660:"SetWindowsHookExA":函数不接受3个参数[C:\Users\eksrow\gdrive\projects\vscode\node本机hello world\build\binding.vcxproj]
对于问题#1,您正确地将const
限定符标识为问题。
之所以可以在声明const
成员变量后将其赋值,是因为const
位于const AsyncProgressWorker::ExecutionProgress *executionProgress
中。这是指向常量AsyncProgressWorker::ExecutionProgress的变量指针。这意味着你可以改变指针的值(例如,像上面的例子一样重新分配它),但你不能改变它指向的数据。这个问题的最高答案对这个概念有很好的解释。
对于问题#2,错误是由于试图将类的成员函数作为函数回调传递而引起的。这根本不可能(好吧,没有变通方法…见下文)-成员方法与函数不同,这正是SetWindowsHookEx
所期望的。您可以将回调函数设为static
,但之后将无法访问_hook
成员。
这里有一个外部页面,提供了一个(非常破解的)解决这个问题的方法。它应该允许您以当前尝试的方式使用SetWindowsHookEx
。但是,我建议您重新考虑应用程序的挂钩方式,看看是否有方法将单个全局函数或静态成员函数注册为应用程序的回调。
与您的问题无关:除非您在示例中省略了代码,否则您永远不会解开SetWindowsHookEx
中设置的钩子。查看MSDN中的UnhookWindowsHookEx
。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 在C++/Linux中设置单调时钟的一些技巧
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- 嵌套在类中时无法设置成员数据
- 需要帮助设置在C++中使用的Potrace
- 如何在自删除后将对象设置为nullptr
- 将指针设置为"nullptr"并不能防止双重删除?
- 如何在Ubuntu中使用cmake设置qt4
- ld:bind_at_load和-bitcode_bundle(Xcode设置ENABLE_bitcode=YES)不能
- 如何在boost beast http请求中设置http头
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 如何将这个C++哈希表转换为动态扩展和收缩,而不是使用硬设置的最大值
- 为什么文件名被设置为一个点,而不是在读取矢量中的文件名时
- 如何在24位SDL_Surface上设置像素的颜色
- std::设置自定义比较器
- 如何设置一个范围来提取我想要获得的信息
- 如何在C/C++中用FD_set Unix设置套接字文件描述符
- 通过选项卡的文本设置QTabWidget顺序
- 将特征矩阵的向量设置为0
- 使用node-nan在node.js模块中设置WindowsHookEx