Node.js 可调用的 C++ 模块:接收鼠标中间按钮按下事件
以下是一个示例代码,实现了在 Electron 下注册鼠标中间按钮按下事件的 C++ 模块,兼容 Linux,Windows 和 Mac 系统:
#include <node.h>
#include <nan.h>
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
// 依据不同的操作系统,引入不同的头文件和库
#if defined(_WIN32)
#include <windows.h>
#include <winuser.h>
#elif defined(__linux__)
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
#elif defined(__APPLE__)
#include <Carbon/Carbon.h>
#endif
using namespace v8;
using namespace std;
// 定义一个中间鼠标按钮按下的回调函数类型
typedef std::function<void()> MiddleMouseClickCallback;
// 定义一个全局的回调函数指针,用于存储注册的回调函数
MiddleMouseClickCallback gMiddleMouseClickCallback = nullptr;
// 定义一个函数,用于处理中间鼠标按钮按下的事件
void MiddleMouseClickHandler() {
// 调用回调函数
if (gMiddleMouseClickCallback) {
gMiddleMouseClickCallback();
}
}
// 定义一个函数,用于注册中间鼠标按钮按下的事件
NAN_METHOD(AddMiddleMouseClickListener) {
// 获取回调函数参数
if (info.Length() < 1 || !info[0]->IsFunction()) {
Nan::ThrowTypeError('Callback function required');
return;
}
// 将回调函数保存到全局变量中
gMiddleMouseClickCallback = MiddleMouseClickCallback(Local<Function>::Cast(info[0]));
// 根据不同的操作系统注册鼠标中间按钮按下的事件
#if defined(_WIN32)
// 使用windows API注册事件
if (!RegisterRawInputDevices) {
Nan::ThrowError('RegisterRawInputDevices is not available');
return;
}
RAWINPUTDEVICE rid;
rid.usUsagePage = 0x01;
rid.usUsage = 0x04;
rid.dwFlags = RIDEV_INPUTSINK;
rid.hwndTarget = NULL;
if (!RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE))) {
Nan::ThrowError('Failed to register raw input device');
return;
}
#elif defined(__linux__)
// 使用X11 API注册事件
Display* display = XOpenDisplay(NULL);
if (!display) {
Nan::ThrowError('Failed to open X11 display');
return;
}
int xi_opcode, event, error;
if (!XQueryExtension(display, 'XInputExtension', &xi_opcode, &event, &error)) {
Nan::ThrowError('XInput extension not available');
XCloseDisplay(display);
return;
}
XIEventMask event_mask;
unsigned char mask[XIMaskLen(XI_LASTEVENT)];
memset(mask, 0, sizeof(mask));
XISetMask(mask, XI_RawButtonPress);
event_mask.deviceid = XIAllMasterDevices;
event_mask.mask_len = sizeof(mask);
event_mask.mask = mask;
XISelectEvents(display, DefaultRootWindow(display), &event_mask, 1);
XEvent xevent;
while (1) {
XNextEvent(display, &xevent);
if (xevent.type == GenericEvent && xevent.xcookie.extension == xi_opcode && XGetEventData(display, &xevent.xcookie)) {
switch(xevent.xcookie.evtype) {
case XI_RawButtonPress:
if (xevent.xcookie.data_len == 24) {
int button = xevent.xcookie.data.l[1];
if (button == Button2) {
MiddleMouseClickHandler();
}
}
break;
default:
break;
}
XFreeEventData(display, &xevent.xcookie);
}
}
XCloseDisplay(display);
#elif defined(__APPLE__)
// 使用Carbon API注册事件
EventTypeSpec eventType;
eventType.eventClass = kEventClassMouse;
eventType.eventKind = kEventMouseDown;
if (!InstallApplicationEventHandler(NewEventHandlerUPP([](EventHandlerCallRef, EventRef event, void*)->OSStatus{
EventMouseButton button;
GetEventParameter(event, kEventParamMouseButton, typeMouseButton, nullptr, sizeof(button), nullptr, &button);
if (button == kEventMouseButtonMiddle) {
MiddleMouseClickHandler();
}
return noErr;
}), 1, &eventType, nullptr, nullptr)) {
Nan::ThrowError('Failed to install event handler');
return;
}
RunApplicationEventLoop();
#endif
// 通知js注册成功
info.GetReturnValue().Set(Nan::True());
}
// 模块初始化函数
NAN_MODULE_INIT(Init) {
Nan::Set(target, Nan::New('addMiddleMouseClickListener').ToLocalChecked(),
Nan::GetFunction(Nan::New<FunctionTemplate>(AddMiddleMouseClickListener)).ToLocalChecked());
}
// 声明模块
NODE_MODULE(middle_mouse_click, Init);
在 Electron 中,可以使用 require 来加载这个模块,并通过 addMiddleMouseClickListener 函数来注册鼠标中间按钮按下的事件,如下所示:
const middleMouseClick = require('middle_mouse_click');
middleMouseClick.addMiddleMouseClickListener(() => {
console.log('Middle mouse button clicked');
});
原文地址: https://www.cveoy.top/t/topic/okk7 著作权归作者所有。请勿转载和采集!