Я пытаюсь реализовать простую программу для Windows, которая перехватывает события мыши низкого уровня в Node.js (TypeScript), используя ffi-napi
и WinAPI.
Вот мой код:
import * as ffi from 'ffi-napi';
import * as ref from 'ref-napi';
import { types } from 'ref-napi';
const StructType = require('ref-struct-di')(ref);
/* Types */
const LONG = types.long;
const ULONG = types.ulong;
const INT = types.int;
const UINT = types.uint;
const DWORD = ULONG;
const BOOL = INT;
const HANDLE = types.uint64;
const HHOOK = HANDLE;
const HWND = HANDLE;
const HINSTANCE = HANDLE;
const WPARAM = types.uint64;
const LPARAM = types.int64;
const LRESULT = types.int64;
const HOOKPROC = 'pointer';
/* Necessary structs */
const POINT = StructType({
x: LONG,
y: LONG
});
const MSG = StructType({
hwnd: HWND,
message: UINT,
wParam: WPARAM,
lParam: LPARAM,
time: DWORD,
pt: POINT,
lPrivate: DWORD
});
type WindowsHookCallback = (nCode: number, wParam: number, lParam: number) => number;
/* User32 bindings */
const u32 = ffi.Library('user32', {
'SetWindowsHookExW': [HHOOK, [INT, HOOKPROC, HINSTANCE, DWORD]],
'UnhookWindowsHookEx': [BOOL, [HHOOK]],
'CallNextHookEx': [LRESULT, [HHOOK, INT, WPARAM, LPARAM]],
'GetMessageW': [BOOL, [MSG, HWND, UINT, UINT]],
'TranslateMessage': [BOOL, [MSG]],
'DispatchMessageW': [LRESULT, [MSG]]
});
/* Some wrappers for them next */
function SetWindowsHookEx(idHook: number, lpfn: WindowsHookCallback, hmod: number, dwThreadId: number): number {
const callback = ffi.Callback(LRESULT, [INT, WPARAM, LPARAM], lpfn);
return u32.SetWindowsHookExW(idHook, callback, hmod, dwThreadId);
}
function UnhookWindowsHookEx(hhk: number): number {
return u32.UnhookWindowsHookEx(hhk);
}
function CallNextHookEx(hhk: number, nCode: number, wParam: number, lParam: number): number {
return u32.CallNextHookEx(hhk, nCode, wParam, lParam);
}
function GetMessageW(lpMsg: any, hWnd: number, wMsgFilterMin: number, wMsgFilterMax: number): number {
return u32.GetMessageW(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
}
function TranslateMessage(lpMsg: any): number {
return u32.TranslateMessage(lpMsg);
}
function DispatchMessageW(lpMsg: any): number {
return u32.DispatchMessageW(lpMsg);
}
/* Necessary consts */
const
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202;
WH_MOUSE_LL = 14;
let hHook= 0;
/* Callback for our low level hook */
function MouseHookCallback(nCode: number, wParam: number, lParam: number): number {
if (nCode >= 0) {
if (wParam === WM_LBUTTONDOWN) {
console.log('Left Button Down');
} else if (wParam === WM_LBUTTONUP) {
console.log('Left Button Up');
}
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
/* Set the hook */
hHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookCallback, 0, 0);
/* Message loop */
let msg = new MSG();
while (GetMessageW(msg.ref(), 0, 0, 0)) {
TranslateMessage(msg.ref());
DispatchMessageW(msg.ref());
}
Хорошо распознает щелчки мышью, но прерывается, когда мышь перемещается более чем на несколько пикселей. Я не могу выяснить, где проблема. Может ли кто-нибудь, кто работал с узлом ffi-napi
, объяснить, пожалуйста?
Я написал ту же программу на C:
#include <stdio.h>
#include <Windows.h>
HHOOK hHook;
LRESULT CALLBACK MouseHookCallback(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode >= 0) {
if (wParam == WM_LBUTTONDOWN) {
printf("Left Button Down\n");
}
else if (wParam == WM_LBUTTONUP) {
printf("Left Button Up\n");
}
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
int main()
{
hHook = SetWindowsHookExW(WH_MOUSE_LL, MouseHookCallback, 0, 0);
MSG msg;
while (GetMessageW(&msg, 0, 0, 0)) {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
, но она отлично работает и не создает sh, если Я перемещаю мышь на любое расстояние.