创建一个 Node.js 可调用的 C++ 模块:监听鼠标中间按钮事件

本教程将带你创建一个 Node.js 可调用的 C++ 模块,用于监听鼠标中间按钮事件,并提供跨平台兼容性(Windows、Linux、Mac)。

功能概述:

  • 接收 PC 端鼠标中间按钮按下的事件。
  • 兼容 Linux、Windows 和 Mac 系统。
  • 通过 Node.js 注册事件并回调 JavaScript 代码。
  • 提供 addMiddleMouseClickListener 函数注册事件监听。
  • 提供 removeMiddleMouseClickListener 函数移除事件监听。
  • 允许多次注册事件,鼠标中间按钮按下时会一次性调用所有注册的回调函数。
  • 如果未注册事件,则不会响应鼠标中间按钮事件。

步骤:

  1. 安装 node-gyp

    npm install -g node-gyp
    
  2. 创建 addon.cc 文件:

    // addon.cc
    #include <node.h>
    #include <uv.h>
    
    #if defined(_WIN32)
    #include <windows.h>
    #include <winuser.h>
    #elif defined(__linux__)
    #include <X11/Xlib.h>
    #include <X11/Xutil.h>
    #include <X11/XKBlib.h>
    #endif
    
    using namespace v8;
    
    static Persistent<Function> callback;
    
    #if defined(_WIN32)
    HHOOK hook;
    LRESULT CALLBACK mouseProc(int nCode, WPARAM wParam, LPARAM lParam)
    {
        if (nCode >= 0 && wParam == WM_MBUTTONDOWN)
        {
            Local<Value> argv[] = {
                String::NewFromUtf8(Isolate::GetCurrent(), 'middle mouse button clicked')
            };
            callback.Get(Isolate::GetCurrent())->Call(Null(Isolate::GetCurrent()), 1, argv);
        }
    
        return CallNextHookEx(hook, nCode, wParam, lParam);
    }
    #elif defined(__linux__)
    Display* display;
    Window root, child;
    int root_x, root_y, win_x, win_y;
    unsigned int mask;
    
    void mouseProc(uv_poll_t *handle, int status, int events)
    {
        if (status < 0)
        {
            fprintf(stderr, "Error in poll: %s\n", uv_err_name(status));
            return;
        }
    
        if (events & UV_READABLE)
        {
            if (XQueryPointer(display, root, &root, &child, &root_x, &root_y, &win_x, &win_y, &mask))
            {
                if (mask & Button2Mask)
                {
                    Local<Value> argv[] = {
                        String::NewFromUtf8(Isolate::GetCurrent(), 'middle mouse button clicked')
                    };
                    callback.Get(Isolate::GetCurrent())->Call(Null(Isolate::GetCurrent()), 1, argv);
                }
            }
        }
    }
    #endif
    
    void addMiddleMouseClickListener(const FunctionCallbackInfo<Value>& args)
    {
        Isolate* isolate = args.GetIsolate();
    
        if (args.Length() != 1 || !args[0]->IsFunction())
        {
            isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, 'Wrong arguments')));
            return;
        }
    
        callback.Reset(isolate, Local<Function>::Cast(args[0]));
    
        #if defined(_WIN32)
        hook = SetWindowsHookEx(WH_MOUSE_LL, mouseProc, GetModuleHandle(NULL), 0);
        #elif defined(__linux__)
        display = XOpenDisplay(NULL);
        root = DefaultRootWindow(display);
    
        uv_poll_t poll_handle;
        uv_poll_init(uv_default_loop(), &poll_handle, ConnectionNumber(display));
        uv_poll_start(&poll_handle, UV_READABLE, mouseProc);
        #endif
    }
    
    void removeMiddleMouseClickListener(const FunctionCallbackInfo<Value>& args)
    {
        Isolate* isolate = args.GetIsolate();
        callback.Reset();
    
        #if defined(_WIN32)
        UnhookWindowsHookEx(hook);
        #elif defined(__linux__)
        XCloseDisplay(display);
        #endif
    }
    
    void init(Local<Object> exports)
    {
        NODE_SET_METHOD(exports, "addMiddleMouseClickListener", addMiddleMouseClickListener);
        NODE_SET_METHOD(exports, "removeMiddleMouseClickListener", removeMiddleMouseClickListener);
    }
    
    NODE_MODULE(addon, init)
    
  3. 更新 package.json 文件:

    "scripts": {
        "build": "node-gyp configure build"
    },
    "gypfile": true
    
  4. 编译 C++ 模块:

    npm run build
    
  5. 创建 demo.js 文件:

    // demo.js
    const addon = require('./build/Release/addon');
    
    addon.addMiddleMouseClickListener(() => {
        console.log('middle mouse button clicked');
    });
    
    setTimeout(() => {
        addon.removeMiddleMouseClickListener();
    }, 10000);
    
  6. 运行 demo.js 文件:

    node demo.js
    

注意:

  • addon.cc 文件中,根据不同的操作系统使用不同的 API 来监听鼠标事件。
  • demo.js 文件中,先注册事件监听,并在 10 秒后移除事件监听。
  • 确保你的代码中没有阻塞操作,否则可能会影响鼠标事件的监听。

现在,你就可以使用这个 C++ 模块来监听鼠标中间按钮事件,并在 Node.js 中执行相应的操作。

Node.js 可调用的 C++ 模块:鼠标中间按钮事件监听

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

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