mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-12-15 15:19:59 +08:00
模拟操作添加屏幕找图(Mac)
This commit is contained in:
189
plugin/lib/quickcomposer/simulate/screenCapture.js
Normal file
189
plugin/lib/quickcomposer/simulate/screenCapture.js
Normal file
@@ -0,0 +1,189 @@
|
||||
const { execFile } = require("child_process");
|
||||
const { promisify } = require("util");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const os = require("os");
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
const readFileAsync = promisify(fs.readFile);
|
||||
const unlinkAsync = promisify(fs.unlink);
|
||||
|
||||
// Windows C# 截图代码
|
||||
const csharpScript = Buffer.from(
|
||||
`
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
public class ScreenCapture {
|
||||
[DllImport("user32.dll")]
|
||||
static extern IntPtr GetDC(IntPtr hwnd);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);
|
||||
|
||||
[DllImport("gdi32.dll")]
|
||||
static extern IntPtr CreateCompatibleDC(IntPtr hdc);
|
||||
|
||||
[DllImport("gdi32.dll")]
|
||||
static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int width, int height);
|
||||
|
||||
[DllImport("gdi32.dll")]
|
||||
static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
|
||||
|
||||
[DllImport("gdi32.dll")]
|
||||
static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int width, int height,
|
||||
IntPtr hdcSrc, int xSrc, int ySrc, int rop);
|
||||
|
||||
[DllImport("gdi32.dll")]
|
||||
static extern bool DeleteDC(IntPtr hdc);
|
||||
|
||||
[DllImport("gdi32.dll")]
|
||||
static extern bool DeleteObject(IntPtr hObject);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
static extern bool GetCursorPos(ref Point point);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
static extern bool GetWindowRect(IntPtr hwnd, ref Rectangle rect);
|
||||
|
||||
public static void CaptureScreen(string outputPath) {
|
||||
IntPtr desktopDC = GetDC(IntPtr.Zero);
|
||||
Rectangle bounds = System.Windows.Forms.Screen.PrimaryScreen.Bounds;
|
||||
|
||||
IntPtr memoryDC = CreateCompatibleDC(desktopDC);
|
||||
IntPtr bitmap = CreateCompatibleBitmap(desktopDC, bounds.Width, bounds.Height);
|
||||
IntPtr oldBitmap = SelectObject(memoryDC, bitmap);
|
||||
|
||||
try {
|
||||
BitBlt(memoryDC, 0, 0, bounds.Width, bounds.Height, desktopDC, 0, 0, 0x00CC0020);
|
||||
|
||||
using (var bmp = Image.FromHbitmap(bitmap)) {
|
||||
bmp.Save(outputPath, ImageFormat.Png);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
SelectObject(memoryDC, oldBitmap);
|
||||
DeleteObject(bitmap);
|
||||
DeleteDC(memoryDC);
|
||||
ReleaseDC(IntPtr.Zero, desktopDC);
|
||||
}
|
||||
}
|
||||
}`
|
||||
).toString("base64");
|
||||
|
||||
// Windows 截图实现
|
||||
async function captureWindowsScreen() {
|
||||
const tmpFile = path.join(os.tmpdir(), `screen-${Date.now()}.png`);
|
||||
|
||||
try {
|
||||
// 使用base64编码的C#代码执行
|
||||
const command = `
|
||||
$code = [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('${csharpScript}'));
|
||||
Add-Type -TypeDefinition $code;
|
||||
[ScreenCapture]::CaptureScreen('${tmpFile.replace(/\\/g, "\\\\")}');
|
||||
`;
|
||||
|
||||
await execFileAsync("powershell", [
|
||||
"-NoProfile",
|
||||
"-NonInteractive",
|
||||
"-ExecutionPolicy",
|
||||
"Bypass",
|
||||
"-Command",
|
||||
command,
|
||||
]);
|
||||
|
||||
// 读取截图
|
||||
const imageBuffer = await readFileAsync(tmpFile);
|
||||
return `data:image/png;base64,${imageBuffer.toString("base64")}`;
|
||||
} catch (error) {
|
||||
console.error("Windows截图失败:", error);
|
||||
return null;
|
||||
} finally {
|
||||
// 清理临时文件
|
||||
await unlinkAsync(tmpFile).catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
// macOS 截图实现
|
||||
async function captureMacScreen() {
|
||||
const tmpFile = path.join(os.tmpdir(), `screen-${Date.now()}.png`);
|
||||
|
||||
try {
|
||||
await execFileAsync("screencapture", ["-x", "-C", "-T", "0", tmpFile]);
|
||||
const imageBuffer = await readFileAsync(tmpFile);
|
||||
return `data:image/png;base64,${imageBuffer.toString("base64")}`;
|
||||
} catch (error) {
|
||||
console.error("macOS截图失败:", error);
|
||||
return null;
|
||||
} finally {
|
||||
await unlinkAsync(tmpFile).catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
// Linux 截图实现
|
||||
async function captureLinuxScreen() {
|
||||
const tmpFile = path.join(os.tmpdir(), `screen-${Date.now()}.png`);
|
||||
|
||||
try {
|
||||
// 检查可用的截图工具
|
||||
let tool = null;
|
||||
try {
|
||||
await execFileAsync("which", ["gnome-screenshot"]);
|
||||
tool = "gnome-screenshot";
|
||||
} catch {
|
||||
try {
|
||||
await execFileAsync("which", ["scrot"]);
|
||||
tool = "scrot";
|
||||
} catch {
|
||||
try {
|
||||
await execFileAsync("which", ["import"]);
|
||||
tool = "import";
|
||||
} catch {
|
||||
console.error("未找到可用的Linux截图工具");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 根据可用工具执行截图
|
||||
switch (tool) {
|
||||
case "gnome-screenshot":
|
||||
await execFileAsync("gnome-screenshot", ["-f", tmpFile]);
|
||||
break;
|
||||
case "scrot":
|
||||
await execFileAsync("scrot", [tmpFile]);
|
||||
break;
|
||||
case "import":
|
||||
await execFileAsync("import", ["-window", "root", tmpFile]);
|
||||
break;
|
||||
}
|
||||
|
||||
const imageBuffer = await readFileAsync(tmpFile);
|
||||
return `data:image/png;base64,${imageBuffer.toString("base64")}`;
|
||||
} catch (error) {
|
||||
console.error("Linux截图失败:", error);
|
||||
return null;
|
||||
} finally {
|
||||
await unlinkAsync(tmpFile).catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
// 统一的截图接口
|
||||
async function captureScreen() {
|
||||
try {
|
||||
if (process.platform === "darwin") {
|
||||
return await captureMacScreen();
|
||||
} else if (process.platform === "win32") {
|
||||
return await captureWindowsScreen();
|
||||
} else if (process.platform === "linux") {
|
||||
return await captureLinuxScreen();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("截图失败:", error);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
module.exports = { captureScreen };
|
||||
Reference in New Issue
Block a user