diff --git a/src/main/paste.js b/src/main/paste.js index 82f19cb..c684d11 100644 --- a/src/main/paste.js +++ b/src/main/paste.js @@ -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(); diff --git a/src/main/win32.js b/src/main/win32.js new file mode 100644 index 0000000..d9e0347 --- /dev/null +++ b/src/main/win32.js @@ -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 };