本文将介绍如何编写一个 Node.js 可调用的 C++ 模块,该模块可以在 Electron 环境下运行,并监听 PC 端鼠标中键按下的事件。该模块将兼容 Linux、Windows 和 macOS 系统,并通过 Node.js 注册事件来回调 JavaScript 代码。

模块功能

该 C++ 模块将提供以下功能:

  • 监听鼠标中键按下事件: 兼容 Linux、Windows 和 macOS 系统。
  • 注册事件回调函数: 通过 Node.js 的 addMiddleMouseClickListener 函数注册。
  • 移除事件回调函数: 通过 Node.js 的 removeMiddleMouseClickListener 函数移除。
  • 允许多次注册: 当鼠标中键按下时,会一次调用所有注册的回调函数。
  • 未注册时不响应: 如果没有注册任何回调函数,则不会响应鼠标中键按下事件。

模块代码

#include <node.h>
#include <v8.h>
#include <stdio.h>
#include <stdlib.h>

#if defined(WIN32)
    #include <windows.h>
    #include <winuser.h>
#elif defined(__linux__)
    #include <X11/Xlib.h>
    #include <X11/Xutil.h>
#elif defined(__APPLE__)
    #include <ApplicationServices/ApplicationServices.h>
#endif

using namespace v8;

Persistent<Function> middleMouseClickListener;

#if defined(WIN32)
    LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) {
        if (nCode >= 0 && wParam == WM_MBUTTONDOWN) {
            Local<Function>::New(Isolate::GetCurrent(), middleMouseClickListener)->Call(Null(Isolate::GetCurrent()), 0, {});
        }
        return CallNextHookEx(NULL, nCode, wParam, lParam);
    }
    HHOOK mouseHook = NULL;
#elif defined(__linux__)
    Display *display;
    Window rootWindow;
    XEvent event;
#elif defined(__APPLE__)
    CGEventRef event;
#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, 'Invalid argument')));
        return;
    }
    Local<Function> callback = Local<Function>::Cast(args[0]);
    middleMouseClickListener.Reset(isolate, callback);

#if defined(WIN32)
    if (mouseHook == NULL) {
        mouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, NULL, 0);
        if (mouseHook == NULL) {
            isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, 'Failed to set Windows hook')));
        }
    }
#elif defined(__linux__)
    if (display == NULL) {
        display = XOpenDisplay(NULL);
        if (display == NULL) {
            isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, 'Failed to open X11 display')));
            return;
        }
        rootWindow = XDefaultRootWindow(display);
        XSelectInput(display, rootWindow, ButtonPressMask);
    }
#elif defined(__APPLE__)
    // no initialization needed
#endif
}

void RemoveMiddleMouseClickListener(const FunctionCallbackInfo<Value>& args) {
    middleMouseClickListener.Reset();
}

void Init(Handle<Object> exports) {
    NODE_SET_METHOD(exports, 'addMiddleMouseClickListener', AddMiddleMouseClickListener);
    NODE_SET_METHOD(exports, 'removeMiddleMouseClickListener', RemoveMiddleMouseClickListener);
}

#if defined(WIN32)
    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
        return TRUE;
    }
#endif

NODE_MODULE(middle_mouse_click, Init)

编译 C++ 模块

  1. 安装 node-gyp
npm install -g node-gyp
  1. 在命令行中进入 C++ 文件所在的目录,运行以下命令来编译 C++ 模块:
node-gyp configure
node-gyp build

编译成功后,会生成一个名为 build/Release/middle_mouse_click.node 的文件,这就是我们的 C++ 模块。

测试模块

创建一个 JavaScript 脚本来测试这个模块,命名为 test.js,代码如下:

const { addMiddleMouseClickListener, removeMiddleMouseClickListener } = require('./build/Release/middle_mouse_click.node');

function middleMouseClickHandler() {
    console.log('Middle mouse button clicked');
}

addMiddleMouseClickListener(middleMouseClickHandler);

setTimeout(() => {
    removeMiddleMouseClickListener(middleMouseClickHandler);
}, 10000);

最后,在命令行中运行以下命令来运行这个脚本:

node test.js

注意事项

  • 在 C++ 代码中监听事件时,不要使用阻塞的方式,以避免影响 Node.js 的运行。
  • 使用 node-gyp 编译 C++ 模块时,需要确保你的系统环境配置正确,并且安装了必要的依赖库。
  • 当你在 Electron 环境下使用这个模块时,你需要将 build/Release/middle_mouse_click.node 文件打包到你的 Electron 应用中。

示例代码

以上示例代码展示了如何使用这个 C++ 模块监听鼠标中键按下的事件。你可以根据自己的需求对代码进行修改和扩展。

Node.js 可调用的 C++ 模块:鼠标中键点击事件监听

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

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