refactor: 把 koffi 的 Win32 加载抽到共用模块

粘贴和光标读取共用同一次 user32/kernel32 加载,避免重复定义结构体。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
hopechen067andClaude Opus 5.5 committed 2026-10-02 04:21:32 -04:00
1 parent 1ae69ab95e
commit 640a92edff
2 files changed
+83 -52

No files matched your search

+2 -52
View File
@@ -1,5 +1,7 @@
'use strict';
const { loadWin32 } = require('./win32');
const INPUT_KEYBOARD = 1;
const KEYEVENTF_KEYUP = 0x0002;
const VK_CONTROL = 0x11;
@@ -42,58 +44,6 @@ function writeSnapshot(clipboard, snap) {
clipboard.write(payload);
}
let win32 = null;
function loadWin32() {
if (win32) return win32;
if (process.platform !== 'win32') return null;
const koffi = require('koffi');
const user32 = koffi.load('user32.dll');
const kernel32 = koffi.load('kernel32.dll');
const KEYBDINPUT = koffi.struct('KEYBDINPUT', {
wVk: 'uint16_t',
wScan: 'uint16_t',
dwFlags: 'uint32_t',
time: 'uint32_t',
dwExtraInfo: 'uintptr_t',
});
const MOUSEINPUT = koffi.struct('MOUSEINPUT', {
dx: 'long',
dy: 'long',
mouseData: 'uint32_t',
dwFlags: 'uint32_t',
time: 'uint32_t',
dwExtraInfo: 'uintptr_t',
});
const HARDWAREINPUT = koffi.struct('HARDWAREINPUT', {
uMsg: 'uint32_t',
wParamL: 'uint16_t',
wParamH: 'uint16_t',
});
const INPUT = koffi.struct('INPUT', {
type: 'uint32_t',
u: koffi.union({
mi: MOUSEINPUT,
ki: KEYBDINPUT,
hi: HARDWAREINPUT,
}),
});
win32 = {
koffi,
INPUT,
GetForegroundWindow: user32.func('void * __stdcall GetForegroundWindow()'),
SetForegroundWindow: user32.func('bool __stdcall SetForegroundWindow(void *hWnd)'),
AllowSetForegroundWindow: user32.func('bool __stdcall AllowSetForegroundWindow(uint32_t dwProcessId)'),
GetWindowThreadProcessId: user32.func('uint32_t __stdcall GetWindowThreadProcessId(void *hWnd, _Out_ uint32_t *lpdwProcessId)'),
AttachThreadInput: user32.func('bool __stdcall AttachThreadInput(uint32_t idAttach, uint32_t idAttachTo, bool fAttach)'),
GetCurrentThreadId: kernel32.func('uint32_t __stdcall GetCurrentThreadId()'),
SendInput: user32.func('unsigned int __stdcall SendInput(unsigned int cInputs, INPUT *pInputs, int cbSize)'),
};
return win32;
}
function captureForeground() {
try {
const api = loadWin32();
+81
View File
@@ -0,0 +1,81 @@
'use strict';
let win32 = null;
function loadWin32() {
if (win32) return win32;
if (process.platform !== 'win32') return null;
const koffi = require('koffi');
const user32 = koffi.load('user32.dll');
const kernel32 = koffi.load('kernel32.dll');
const KEYBDINPUT = koffi.struct('KEYBDINPUT', {
wVk: 'uint16_t',
wScan: 'uint16_t',
dwFlags: 'uint32_t',
time: 'uint32_t',
dwExtraInfo: 'uintptr_t',
});
const MOUSEINPUT = koffi.struct('MOUSEINPUT', {
dx: 'long',
dy: 'long',
mouseData: 'uint32_t',
dwFlags: 'uint32_t',
time: 'uint32_t',
dwExtraInfo: 'uintptr_t',
});
const HARDWAREINPUT = koffi.struct('HARDWAREINPUT', {
uMsg: 'uint32_t',
wParamL: 'uint16_t',
wParamH: 'uint16_t',
});
const INPUT = koffi.struct('INPUT', {
type: 'uint32_t',
u: koffi.union({
mi: MOUSEINPUT,
ki: KEYBDINPUT,
hi: HARDWAREINPUT,
}),
});
// 64 位默认对齐:两个 DWORD 之后 HWND 从偏移 8 开始,末尾 RECT,共 72 字节。
const RECT = koffi.struct('RECT', {
left: 'long',
top: 'long',
right: 'long',
bottom: 'long',
});
const POINT = koffi.struct('POINT', {
x: 'long',
y: 'long',
});
const GUITHREADINFO = koffi.struct('GUITHREADINFO', {
cbSize: 'uint32_t',
flags: 'uint32_t',
hwndActive: 'void *',
hwndFocus: 'void *',
hwndCapture: 'void *',
hwndMenuOwner: 'void *',
hwndMoveSize: 'void *',
hwndCaret: 'void *',
rcCaret: RECT,
});
win32 = {
koffi,
INPUT,
GUITHREADINFO,
GetForegroundWindow: user32.func('void * __stdcall GetForegroundWindow()'),
SetForegroundWindow: user32.func('bool __stdcall SetForegroundWindow(void *hWnd)'),
AllowSetForegroundWindow: user32.func('bool __stdcall AllowSetForegroundWindow(uint32_t dwProcessId)'),
GetWindowThreadProcessId: user32.func('uint32_t __stdcall GetWindowThreadProcessId(void *hWnd, _Out_ uint32_t *lpdwProcessId)'),
AttachThreadInput: user32.func('bool __stdcall AttachThreadInput(uint32_t idAttach, uint32_t idAttachTo, bool fAttach)'),
GetCurrentThreadId: kernel32.func('uint32_t __stdcall GetCurrentThreadId()'),
SendInput: user32.func('unsigned int __stdcall SendInput(unsigned int cInputs, INPUT *pInputs, int cbSize)'),
GetGUIThreadInfo: user32.func('bool __stdcall GetGUIThreadInfo(uint32_t idThread, _Inout_ GUITHREADINFO *pgui)'),
ClientToScreen: user32.func('bool __stdcall ClientToScreen(void *hWnd, _Inout_ POINT *lpPoint)'),
};
return win32;
}
module.exports = { loadWin32 };