以下是一个示例代码,实现了在 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');
});
Node.js 可调用的 C++ 模块:接收鼠标中间按钮按下事件

原文地址: https://www.cveoy.top/t/topic/okk7 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录