diff --git a/bindings/go/dll_windows.go b/bindings/go/dll_windows.go index bec4fd2..f9b2d21 100644 --- a/bindings/go/dll_windows.go +++ b/bindings/go/dll_windows.go @@ -76,6 +76,7 @@ var ( procBindWindow *windows.LazyProc procBindWindowEx *windows.LazyProc procUnBindWindow *windows.LazyProc + procLockInput *windows.LazyProc procGetBindWindow *windows.LazyProc procIsBind *windows.LazyProc procGetCursorPos *windows.LazyProc @@ -83,6 +84,11 @@ var ( procMoveR *windows.LazyProc procMoveTo *windows.LazyProc procMoveToEx *windows.LazyProc + procMoveToSmooth *windows.LazyProc + procMoveToExSmooth *windows.LazyProc + procMovePath *windows.LazyProc + procDragPath *windows.LazyProc + procSetMouseTrajectory *windows.LazyProc procLeftClick *windows.LazyProc procLeftDoubleClick *windows.LazyProc procLeftDown *windows.LazyProc @@ -299,6 +305,7 @@ func bindProcs() { procBindWindow = dll.NewProc("OpBindWindow") procBindWindowEx = dll.NewProc("OpBindWindowEx") procUnBindWindow = dll.NewProc("OpUnBindWindow") + procLockInput = dll.NewProc("OpLockInput") procGetBindWindow = dll.NewProc("OpGetBindWindow") procIsBind = dll.NewProc("OpIsBind") procGetCursorPos = dll.NewProc("OpGetCursorPos") @@ -306,6 +313,11 @@ func bindProcs() { procMoveR = dll.NewProc("OpMoveR") procMoveTo = dll.NewProc("OpMoveTo") procMoveToEx = dll.NewProc("OpMoveToEx") + procMoveToSmooth = dll.NewProc("OpMoveToSmooth") + procMoveToExSmooth = dll.NewProc("OpMoveToExSmooth") + procMovePath = dll.NewProc("OpMovePath") + procDragPath = dll.NewProc("OpDragPath") + procSetMouseTrajectory = dll.NewProc("OpSetMouseTrajectory") procLeftClick = dll.NewProc("OpLeftClick") procLeftDoubleClick = dll.NewProc("OpLeftDoubleClick") procLeftDown = dll.NewProc("OpLeftDown") diff --git a/bindings/go/image_windows.go b/bindings/go/image_windows.go index edcbd8a..274e90d 100644 --- a/bindings/go/image_windows.go +++ b/bindings/go/image_windows.go @@ -60,7 +60,7 @@ func (o *Op) FindMultiColorEx(x1, y1, x2, y2 int, firstColor, offsetColor string func (o *Op) FindPic(x1, y1, x2, y2 int, files, deltaColor string, sim float64, dir int) (int, int, int) { if !o.valid() { - return 0, 0, 0 + return -1, -1, -1 } var x, y int32 @@ -88,7 +88,7 @@ func (o *Op) FindPicExS(x1, y1, x2, y2 int, files, deltaColor string, sim float6 func (o *Op) FindColorBlock(x1, y1, x2, y2 int, color string, sim float64, count, height, width int) (int, int, int) { if !o.valid() { - return 0, 0, 0 + return 0, -1, -1 } var x, y int32 diff --git a/bindings/go/input_windows.go b/bindings/go/input_windows.go index d4feaf5..f5a0481 100644 --- a/bindings/go/input_windows.go +++ b/bindings/go/input_windows.go @@ -48,6 +48,59 @@ func (o *Op) MoveToEx(x, y, w, h int) string { return wcharString(ret) } +func (o *Op) MoveToSmooth(x, y, duration int) int { + if !o.valid() { + return 0 + } + + ret, _, _ := procMoveToSmooth.Call(o.handle, uintptr(x), uintptr(y), uintptr(duration)) + return int(ret) +} + +func (o *Op) MoveToExSmooth(x, y, w, h, duration int) string { + if !o.valid() { + return "" + } + + ret, _, _ := procMoveToExSmooth.Call(o.handle, uintptr(x), uintptr(y), uintptr(w), uintptr(h), uintptr(duration)) + return wcharString(ret) +} + +func (o *Op) MovePath(path string, duration int) int { + if !o.valid() { + return 0 + } + + ret, _, _ := procMovePath.Call(o.handle, strArg(path), uintptr(duration)) + return int(ret) +} + +func (o *Op) DragPath(path string, duration int) int { + if !o.valid() { + return 0 + } + + ret, _, _ := procDragPath.Call(o.handle, strArg(path), uintptr(duration)) + return int(ret) +} + +func (o *Op) SetMouseTrajectory(mode, minDuration, maxDuration, jitter, startDelay, endDelay int) int { + if !o.valid() { + return 0 + } + + ret, _, _ := procSetMouseTrajectory.Call( + o.handle, + uintptr(mode), + uintptr(minDuration), + uintptr(maxDuration), + uintptr(jitter), + uintptr(startDelay), + uintptr(endDelay), + ) + return int(ret) +} + func (o *Op) LeftClick() int { return o.callNoArgs(procLeftClick) } @@ -163,6 +216,15 @@ func (o *Op) SetMouseDelay(typ string, delay int) int { return int(ret) } +func (o *Op) LockInput(lock int) int { + if !o.valid() { + return 0 + } + + ret, _, _ := procLockInput.Call(o.handle, uintptr(lock)) + return int(ret) +} + func (o *Op) GetKeyState(vkCode int) int { if !o.valid() { return 0 diff --git a/bindings/go/ocr_windows.go b/bindings/go/ocr_windows.go index 1c6831d..2e1f229 100644 --- a/bindings/go/ocr_windows.go +++ b/bindings/go/ocr_windows.go @@ -56,12 +56,12 @@ func (o *Op) GetDict(idx, fontIndex int) string { return wcharString(ret) } -func (o *Op) SetMemDict(idx int, data string, size int) int { +func (o *Op) SetMemDict(idx int, data []byte) int { if !o.valid() { return 0 } - ret, _, _ := procSetMemDict.Call(o.handle, uintptr(idx), strArg(data), uintptr(size)) + ret, _, _ := procSetMemDict.Call(o.handle, uintptr(idx), bytesPtr(data), uintptr(len(data))) return int(ret) } diff --git a/bindings/python/op/_ffi.py b/bindings/python/op/_ffi.py index fe14b6b..c648d24 100644 --- a/bindings/python/op/_ffi.py +++ b/bindings/python/op/_ffi.py @@ -176,6 +176,7 @@ def _bind(dll: ctypes.WinDLL) -> ctypes.WinDLL: ("OpBindWindow", c_int, [op_handle, intptr_t, c_wchar_p, c_wchar_p, c_wchar_p, c_int]), ("OpBindWindowEx", c_int, [op_handle, intptr_t, intptr_t, c_wchar_p, c_wchar_p, c_wchar_p, c_int]), ("OpUnBindWindow", c_int, [op_handle]), + ("OpLockInput", c_int, [op_handle, c_int]), ("OpGetBindWindow", intptr_t, [op_handle]), ("OpIsBind", c_int, [op_handle]), ("OpGetCursorPos", c_int, [op_handle, c_int_p, c_int_p]), @@ -183,6 +184,11 @@ def _bind(dll: ctypes.WinDLL) -> ctypes.WinDLL: ("OpMoveR", c_int, [op_handle, c_int, c_int]), ("OpMoveTo", c_int, [op_handle, c_int, c_int]), ("OpMoveToEx", c_wchar_p, [op_handle, c_int, c_int, c_int, c_int]), + ("OpMoveToSmooth", c_int, [op_handle, c_int, c_int, c_int]), + ("OpMoveToExSmooth", c_wchar_p, [op_handle, c_int, c_int, c_int, c_int, c_int]), + ("OpMovePath", c_int, [op_handle, c_wchar_p, c_int]), + ("OpDragPath", c_int, [op_handle, c_wchar_p, c_int]), + ("OpSetMouseTrajectory", c_int, [op_handle, c_int, c_int, c_int, c_int, c_int, c_int]), ("OpLeftClick", c_int, [op_handle]), ("OpLeftDoubleClick", c_int, [op_handle]), ("OpLeftDown", c_int, [op_handle]), @@ -281,7 +287,7 @@ def _bind(dll: ctypes.WinDLL) -> ctypes.WinDLL: ("OpYoloDetectFromFile", c_wchar_p, [op_handle, c_wchar_p, c_double, c_double]), ("OpSetDict", c_int, [op_handle, c_int, c_wchar_p]), ("OpGetDict", c_wchar_p, [op_handle, c_int, c_int]), - ("OpSetMemDict", c_int, [op_handle, c_int, c_wchar_p, c_int]), + ("OpSetMemDict", c_int, [op_handle, c_int, c_void_p, c_int]), ("OpUseDict", c_int, [op_handle, c_int]), ("OpAddDict", c_int, [op_handle, c_int, c_wchar_p]), ("OpSaveDict", c_int, [op_handle, c_int, c_wchar_p]), diff --git a/bindings/python/op/api.py b/bindings/python/op/api.py index f35ed7d..9978705 100644 --- a/bindings/python/op/api.py +++ b/bindings/python/op/api.py @@ -1,6 +1,7 @@ from __future__ import annotations import ctypes +import locale from enum import Enum from pathlib import Path from typing import Any @@ -402,6 +403,9 @@ def bind_window_ex( def unbind_window(self) -> bool: return self._call_ok("OpUnBindWindow") + def lock_input(self, lock: int) -> bool: + return self._call_ok("OpLockInput", int(lock)) + def get_bind_window(self) -> int: return self._call_intptr("OpGetBindWindow") @@ -424,6 +428,37 @@ def move_to(self, x: int, y: int) -> bool: def move_to_ex(self, x: int, y: int, width: int, height: int) -> str: return self._call_string("OpMoveToEx", int(x), int(y), int(width), int(height)) + def move_to_smooth(self, x: int, y: int, duration: int) -> bool: + return self._call_ok("OpMoveToSmooth", int(x), int(y), int(duration)) + + def move_to_ex_smooth(self, x: int, y: int, width: int, height: int, duration: int) -> str: + return self._call_string("OpMoveToExSmooth", int(x), int(y), int(width), int(height), int(duration)) + + def move_path(self, path: str, duration: int) -> bool: + return self._call_ok("OpMovePath", str(path), int(duration)) + + def drag_path(self, path: str, duration: int) -> bool: + return self._call_ok("OpDragPath", str(path), int(duration)) + + def set_mouse_trajectory( + self, + mode: int, + min_duration: int, + max_duration: int, + jitter: int, + start_delay: int, + end_delay: int, + ) -> bool: + return self._call_ok( + "OpSetMouseTrajectory", + int(mode), + int(min_duration), + int(max_duration), + int(jitter), + int(start_delay), + int(end_delay), + ) + def left_click(self) -> bool: return self._call_ok("OpLeftClick") @@ -1090,9 +1125,20 @@ def set_dict(self, idx: int, file_name: str | Path) -> bool: def get_dict(self, idx: int, font_index: int) -> str: return self._call_string("OpGetDict", int(idx), int(font_index)) - def set_mem_dict(self, idx: int, data: str, size: int | None = None) -> bool: - data_size = len(data) if size is None else int(size) - return self._call_ok("OpSetMemDict", int(idx), data, data_size) + def set_mem_dict(self, idx: int, data: str | bytes | bytearray | memoryview | int, size: int | None = None) -> bool: + self._check_open() + if isinstance(data, int): + if size is None: + raise ValueError("size is required when data is a pointer") + ptr = ctypes.c_void_p(data) + data_size = int(size) + else: + raw = data.encode(locale.getpreferredencoding(False)) if isinstance(data, str) else bytes(data) + buffer = ctypes.create_string_buffer(raw) + ptr = ctypes.cast(buffer, ctypes.c_void_p) + data_size = len(raw) if size is None else int(size) + ok = self._dll.OpSetMemDict(self._handle, int(idx), ptr, data_size) + return self._ok(ok, "OpSetMemDict") def use_dict(self, idx: int) -> bool: return self._call_ok("OpUseDict", int(idx)) diff --git a/doc/open_issues_scan.md b/doc/open_issues_scan.md deleted file mode 100644 index 49cee7c..0000000 --- a/doc/open_issues_scan.md +++ /dev/null @@ -1,93 +0,0 @@ -# Open Issues Scan - -这份说明用于归纳当前公开 GitHub issue 的主要问题簇,并给出和代码实现相对应的 triage 结论,方便后续维护与分诊。 - -## 高优先级结论 - -### 1. `MoveToEx` 返回值不一致已修复 - -- 对应 issue:`#181` -- 旧实现返回的是数值状态,不是字符串。 -- 当前实现随机移动后返回实际落点字符串 `"x,y"`,并支持负 `w`/`h` 分别表示向左/向上随机。 -- 代码依据: - - `libop/libop.h`:`void MoveToEx(long x, long y, long w, long h, std::wstring &ret);` - - `libop/com/op.idl`:`HRESULT MoveToEx(..., [out, retval] BSTR* ret);` - - `libop/libop.cpp`:将鼠标后端实际落点格式化为字符串。 - -结论:实现已对齐外部 wiki 的字符串返回语义。 - -### 2. `OcrFromFile` 之前确实忽略了 `color_format` - -- 关联问题:`#145` 相关 OCR 参数困惑 -- 在本次扫描前,`ImageSearchService::OcrFromFile()` 虽然接收了颜色参数,但内部固定调用 `OCR(L"", ...)`,导致颜色过滤被静默忽略。 -- 现已修正为调用 `OCR(color, ...)`。 - -结论:这不是 `#145` 中完全相同的报错路径,但它确实是一个真实的 OCR 接口契约问题,已经值得修复。 - -### 3. 跨语言崩溃问题仍需要最小复现 - -- 对应 issue:`#149`、`#138` -- 表现:`C#` 中调用 `CmpColor` 或 `FindPic` 时出现 `AccessViolationException` / 受保护内存访问错误。 -- 本次扫描没有在这两个方法里发现单行可定位的明显内存破坏点。 -- 更可能的风险点: - - 宿主进程与 COM DLL 的 x86/x64 位数不匹配 - - 未绑定窗口、绑定状态异常、截图源无效 - - 宿主应用自身的 COM 生命周期或线程模型问题 - -结论:这类问题目前更适合标记为 `needs-repro`,先收集最小 C# 复现样例。 - -### 4. 强制终止线程不是受支持的生命周期 - -- 对应 issue:`#140` -- 报告中使用了 `QThread.terminate()` 强制终止并重启线程。 -- issue 作者自己也确认了改用 `deleteLater()` 后可以规避问题。 - -结论:这类问题应先作为线程生命周期约束写入文档,再决定是否继续追查更深层的线程安全问题。 - -## 后台输入问题簇 - -当前最集中的 issue 是后台输入/游戏兼容性:`#176`、`#136`、`#124`、`#114`、`#103`。 - -### 当前代码明确支持的能力 - -- 鼠标后端: - - `normal` - - `windows` - - `dx` -- 键盘后端: - - `normal` - - `normal.hd` - - `windows` -- 当前没有公开提供 `keypad=dx`。 - -### 为什么仍然会有大量相关 issue - -- `windows` 键盘路径依赖 `WM_KEYDOWN` / `WM_KEYUP`,不少游戏并不把它当作真实设备输入。 -- `dx` 鼠标路径依赖注入 Hook 与自定义消息,在目标进程重启、渲染链路变化、输入过滤更严格时仍可能失效。 -- 组合键和滚轮在后台模式下尤其脆弱,因为很多程序读取的是实时键盘状态、低层 Hook,或更贴近真实设备的输入链路,而不是单纯窗口消息。 - -结论:这类 issue 中有相当一部分更像“能力边界”或“目标程序兼容性限制”,不一定是简单 bug。 - -## 文档缺口 - -当前 README 已经覆盖了 OCR 服务模式与 `SetDisplayInput`,但从 issue 看仍有几个明显缺口: - -- Python 用户依然不清楚如何用内存图像走 `SetDisplayInput` -- C# 用户频繁遇到位数/宿主集成问题 -- 后台键鼠限制虽然有写,但对游戏场景还不够直白 -- 外部 wiki 可能比仓库源码老,容易出现签名漂移 - -## 建议使用的 triage 标签 - -- `bug`:已确认的实现缺陷 -- `docs`:文档错误或缺失 -- `feature`:能力诉求 -- `question`:使用问题,无需改代码 -- `needs-repro`:缺少稳定复现 -- `known-limitation`:受 Windows / 游戏 / 输入模型限制 - -## 建议的后续动作 - -1. 为 `#149`、`#138` 收集最小复现:宿主位数、DLL 位数、是否免注册、是否先 `BindWindow`、失败是否可稳定重现。 -2. 审核外部 wiki 中容易漂移的接口,优先检查鼠标类方法。 -3. 继续在 README 中补充 Python / C# 的最小可运行示例,尤其是 OCR、内存图像输入、免注册或位数相关说明。 diff --git a/doc/todo.md b/doc/todo.md deleted file mode 100644 index f0251d7..0000000 --- a/doc/todo.md +++ /dev/null @@ -1,108 +0,0 @@ -# OP 项目任务清单(含 Issue 链接) - -## P0(本周必须完成) - -- [ ] **T1 稳定 SetDisplayInput 内存模式** - - 目标:修复 `mem:` 输入路径,确保 Win10/11 + Python/C# 均可用 - - 关联 Issue: - - https://github.com/WallBreaker2/op/issues/175 - - https://github.com/WallBreaker2/op/issues/173 - - 验收标准:最小复现通过;新增回归用例;文档更新 - -- [ ] **T2 修复绑定后闪退与卡死** - - 目标:解决绑定窗口闪退、`GetCmdStr` 卡死、线程重启异常 - - 关联 Issue: - - https://github.com/WallBreaker2/op/issues/133 - - https://github.com/WallBreaker2/op/issues/139 - - https://github.com/WallBreaker2/op/issues/140 - - 验收标准:3 次绑定/解绑无崩溃;超时可控;线程可重复初始化 - -- [ ] **T3 修复 SendString 失效** - - 目标:修复发送文字在部分场景不生效问题 - - 关联 Issue: - - https://github.com/WallBreaker2/op/issues/73 - - 验收标准:前后台发送均通过;补齐输入法/布局说明;新增回归脚本 - -- [ ] **T4 统一后台键鼠事件链路** - - 目标:统一 DX9/DX11/normal 模式下键鼠行为一致性 - - 关联 Issue: - - https://github.com/WallBreaker2/op/issues/103 - - https://github.com/WallBreaker2/op/issues/114 - - https://github.com/WallBreaker2/op/issues/124 - - https://github.com/WallBreaker2/op/issues/136 - - https://github.com/WallBreaker2/op/issues/163 - - https://github.com/WallBreaker2/op/issues/176 - - 验收标准:点击/滚轮/组合键/按键状态回归全通过;模式差异文档明确 - ---- - -## P1(下周完成) - -- [ ] **T5 修复 OCR 32/64 位可用性** - - 目标:修复 `OcrEx/OcrAuto` 在 x86/x64 + tess_model 下异常 - - 关联 Issue: - - https://github.com/WallBreaker2/op/issues/145 - - https://github.com/WallBreaker2/op/issues/153 - - 验收标准:标准样本集返回非空;准确率达到基线;新增回归用例 - -- [ ] **T6 整理 OCR 引擎优化提案** - - 目标:形成 OCR 改造路线(性能/精度) - - 关联 Issue: - - https://github.com/WallBreaker2/op/issues/118 - - 验收标准:输出方案文档;明确阶段目标与指标 - -- [ ] **T7 补齐 D3D12 / 3D 绑定说明与兼容** - - 目标:完善 D3D12 绑定、错误码、3D 窗口截图说明 - - 关联 Issue: - - https://github.com/WallBreaker2/op/issues/96 - - https://github.com/WallBreaker2/op/issues/132 - - 验收标准:示例可运行;错误码说明完整;FAQ 补充 - -- [ ] **T8 发布雷电后台完整例程** - - 目标:提供“绑定 -> 截图 -> 找色 -> 键鼠”全流程示例 - - 关联 Issue: - - https://github.com/WallBreaker2/op/issues/131 - - https://github.com/WallBreaker2/op/issues/171 - - 验收标准:示例可跑通;README 完整;可复现 - -- [ ] **T9 修复 C# 调用兼容问题** - - 目标:修复 C#4.7 / .NET6 调用异常,补齐免注册流程 - - 关联 Issue: - - https://github.com/WallBreaker2/op/issues/106 - - https://github.com/WallBreaker2/op/issues/138 - - https://github.com/WallBreaker2/op/issues/149 - - 验收标准:两套框架示例通过;文档可执行 - -- [ ] **T10 补 Node.js 接入示例** - - 目标:提供 Node.js 最小可运行示例(安装/加载/调用/错误处理) - - 关联 Issue: - - https://github.com/WallBreaker2/op/issues/146 - - 验收标准:示例可运行;步骤清晰 - ---- - -## P2(增强与生态) - -- [ ] **T11 新增 lockinput 能力** - - 目标:提供锁定/解锁外部输入 API - - 关联 Issue: - - https://github.com/WallBreaker2/op/issues/77 - - 验收标准:API 可用;异常恢复机制;风险提示文档 - -- [ ] **T12 新增 WaitKey(0,0) 当前按键值** - - 目标:支持直接返回当前按键值 - - 关联 Issue: - - https://github.com/WallBreaker2/op/issues/122 - - 验收标准:返回值规范;键码映射表发布;示例通过 - -- [ ] **T13 评估 Java 生态方案** - - 目标:明确官方支持边界并给出可维护 Java 路径 - - 关联 Issue: - - https://github.com/WallBreaker2/op/issues/174 - - 验收标准:方案结论清晰;示例链接可用;维护策略明确 - -- [ ] **T14 社区类 Issue 归档策略** - - 目标:非缺陷类 issue 统一转 Discussion / 关闭模板 - - 关联 Issue: - - https://github.com/WallBreaker2/op/issues/164 - - 验收标准:模板生效;历史案例归档;贡献指南更新 diff --git a/include/libop.h b/include/libop.h index 6c414de..86931f0 100644 --- a/include/libop.h +++ b/include/libop.h @@ -226,6 +226,8 @@ class OP_API Op { _In_ const wchar_t *mouse, _In_ const wchar_t *keypad, _In_ long mode, _Out_ long *ret); // 解绑窗口 void UnBindWindow(_Out_ long *ret); + // 临时锁定目标窗口的外部输入。只对 dx 鼠标、dx 键盘有效。 + void LockInput(_In_ long lock, _Out_ long *ret); // 获取当前对象已经绑定的显示窗口句柄. 无绑定返回0 void GetBindWindow(_Out_ LONG_PTR *ret); // 判定当前对象是否已绑定窗口. @@ -241,6 +243,18 @@ class OP_API Op { void MoveTo(_In_ long x, _In_ long y, _Out_ long *ret); // 把鼠标移动到目的范围内的任意一点 void MoveToEx(_In_ long x, _In_ long y, _In_ long w, _In_ long h, _Out_ std::wstring &ret); + // 按模拟轨迹移动到指定点 + void MoveToSmooth(_In_ long x, _In_ long y, _In_ long duration, _Out_ long *ret); + // 在目标范围内随机取点,并按模拟轨迹移动过去 + void MoveToExSmooth(_In_ long x, _In_ long y, _In_ long w, _In_ long h, _In_ long duration, + _Out_ std::wstring &ret); + // 按 x,y|x,y 格式提供的路径移动 + void MovePath(_In_ const wchar_t *path, _In_ long duration, _Out_ long *ret); + // 按 x,y|x,y 格式提供的路径拖拽 + void DragPath(_In_ const wchar_t *path, _In_ long duration, _Out_ long *ret); + // 设置模拟轨迹参数,只影响 Smooth 和 Path 系列鼠标移动 + void SetMouseTrajectory(_In_ long mode, _In_ long min_duration, _In_ long max_duration, _In_ long jitter, + _In_ long start_delay, _In_ long end_delay, _Out_ long *ret); // 按下鼠标左键 void LeftClick(_Out_ long *ret); // 双击鼠标左键 @@ -442,7 +456,7 @@ class OP_API Op { // 获取指定字库中指定条目的字库信息 void GetDict(_In_ long idx, _In_ long font_index, _Out_ std::wstring &retstr); // 设置内存字库文件 - void SetMemDict(_In_ long idx, _In_ const wchar_t *data, _In_ long size, _Out_ long *ret); + void SetMemDict(_In_ long idx, _In_reads_bytes_(size) const void *data, _In_ long size, _Out_ long *ret); // 使用哪个字库文件进行识别 void UseDict(_In_ long idx, _Out_ long *ret); // 给指定的字库中添加一条字库信息 diff --git a/include/op_c_api.h b/include/op_c_api.h index 2f6534f..5118b58 100644 --- a/include/op_c_api.h +++ b/include/op_c_api.h @@ -110,6 +110,7 @@ OP_C_API int OP_CALL OpBindWindow(op_handle handle, intptr_t hwnd, const wchar_t OP_C_API int OP_CALL OpBindWindowEx(op_handle handle, intptr_t display_hwnd, intptr_t input_hwnd, const wchar_t *display, const wchar_t *mouse, const wchar_t *keypad, int mode); OP_C_API int OP_CALL OpUnBindWindow(op_handle handle); +OP_C_API int OP_CALL OpLockInput(op_handle handle, int lock); OP_C_API intptr_t OP_CALL OpGetBindWindow(op_handle handle); OP_C_API int OP_CALL OpIsBind(op_handle handle); @@ -119,6 +120,12 @@ OP_C_API const wchar_t *OP_CALL OpGetCursorShape(op_handle handle); OP_C_API int OP_CALL OpMoveR(op_handle handle, int x, int y); OP_C_API int OP_CALL OpMoveTo(op_handle handle, int x, int y); OP_C_API const wchar_t *OP_CALL OpMoveToEx(op_handle handle, int x, int y, int w, int h); +OP_C_API int OP_CALL OpMoveToSmooth(op_handle handle, int x, int y, int duration); +OP_C_API const wchar_t *OP_CALL OpMoveToExSmooth(op_handle handle, int x, int y, int w, int h, int duration); +OP_C_API int OP_CALL OpMovePath(op_handle handle, const wchar_t *path, int duration); +OP_C_API int OP_CALL OpDragPath(op_handle handle, const wchar_t *path, int duration); +OP_C_API int OP_CALL OpSetMouseTrajectory(op_handle handle, int mode, int min_duration, int max_duration, int jitter, + int start_delay, int end_delay); OP_C_API int OP_CALL OpLeftClick(op_handle handle); OP_C_API int OP_CALL OpLeftDoubleClick(op_handle handle); OP_C_API int OP_CALL OpLeftDown(op_handle handle); @@ -265,7 +272,7 @@ OP_C_API const wchar_t *OP_CALL OpYoloDetectFromFile(op_handle handle, const wch double iou); OP_C_API int OP_CALL OpSetDict(op_handle handle, int idx, const wchar_t *file_name); OP_C_API const wchar_t *OP_CALL OpGetDict(op_handle handle, int idx, int font_index); -OP_C_API int OP_CALL OpSetMemDict(op_handle handle, int idx, const wchar_t *data, int size); +OP_C_API int OP_CALL OpSetMemDict(op_handle handle, int idx, const void *data, int size); OP_C_API int OP_CALL OpUseDict(op_handle handle, int idx); OP_C_API int OP_CALL OpAddDict(op_handle handle, int idx, const wchar_t *dict_info); OP_C_API int OP_CALL OpSaveDict(op_handle handle, int idx, const wchar_t *file_name); diff --git a/libop/CMakeLists.txt b/libop/CMakeLists.txt index 49b3667..5cd40bc 100644 --- a/libop/CMakeLists.txt +++ b/libop/CMakeLists.txt @@ -150,11 +150,11 @@ if(enable_wgc) list(APPEND OP_LOCAL_CXX20_SOURCES "capture/backends/WgcCapture.cpp") endif() -set(OP_RUNTIME_SOURCES - "runtime/AutomationModes.cpp" - "runtime/RuntimeUtils.cpp" - "runtime/RuntimeEnvironment.cpp" - "runtime/WindowsVersion.cpp" +set(OP_BASE_SOURCES + "base/AutomationModes.cpp" + "base/Utils.cpp" + "base/Environment.cpp" + "base/WindowsVersion.cpp" ) set(OP_WINDOW_SOURCES @@ -221,7 +221,7 @@ set(OP_LIBOP_SOURCES ${OP_CAPTURE_SOURCES} ${OP_INPUT_SOURCES} ${OP_HOOK_SOURCES} - ${OP_RUNTIME_SOURCES} + ${OP_BASE_SOURCES} ${OP_WINDOW_SOURCES} ${OP_IMAGE_SOURCES} ${OP_NETWORK_SOURCES} diff --git a/libop/runtime/AutomationModes.cpp b/libop/base/AutomationModes.cpp similarity index 100% rename from libop/runtime/AutomationModes.cpp rename to libop/base/AutomationModes.cpp diff --git a/libop/runtime/AutomationModes.h b/libop/base/AutomationModes.h similarity index 96% rename from libop/runtime/AutomationModes.h rename to libop/base/AutomationModes.h index 86c0a21..79e35b2 100644 --- a/libop/runtime/AutomationModes.h +++ b/libop/base/AutomationModes.h @@ -1,6 +1,6 @@ #pragma once -#ifndef OP_RUNTIME_AUTOMATION_MODES_H_ -#define OP_RUNTIME_AUTOMATION_MODES_H_ +#ifndef OP_BASE_AUTOMATION_MODES_H_ +#define OP_BASE_AUTOMATION_MODES_H_ #include "Types.h" #include #define SAFE_CLOSE(h) \ @@ -103,7 +103,7 @@ extern long MOUSE_DX_DELAY; #ifndef OP_VERSION #define OP_VERSION MAKE_OP_VERSION(0, 4, 8, 1) -#endif // OP_RUNTIME_AUTOMATION_MODES_H_ +#endif // OP_VERSION // 模块句柄 // extern HINSTANCE gInstance; // 是否显示错误信息 @@ -113,4 +113,4 @@ extern long MOUSE_DX_DELAY; // extern wstring g_op_name; -#endif +#endif // OP_BASE_AUTOMATION_MODES_H_ diff --git a/libop/runtime/RuntimeEnvironment.cpp b/libop/base/Environment.cpp similarity index 97% rename from libop/runtime/RuntimeEnvironment.cpp rename to libop/base/Environment.cpp index 6fdeacc..2a4c5d5 100644 --- a/libop/runtime/RuntimeEnvironment.cpp +++ b/libop/base/Environment.cpp @@ -1,4 +1,4 @@ -#include "RuntimeEnvironment.h" +#include "Environment.h" #include #include diff --git a/libop/runtime/RuntimeEnvironment.h b/libop/base/Environment.h similarity index 73% rename from libop/runtime/RuntimeEnvironment.h rename to libop/base/Environment.h index d07e592..f15448d 100644 --- a/libop/runtime/RuntimeEnvironment.h +++ b/libop/base/Environment.h @@ -1,5 +1,5 @@ -#ifndef OP_RUNTIME_RUNTIME_ENVIRONMENT_H_ -#define OP_RUNTIME_RUNTIME_ENVIRONMENT_H_ +#ifndef OP_BASE_ENVIRONMENT_H_ +#define OP_BASE_ENVIRONMENT_H_ #include class RuntimeEnvironment { public: @@ -14,4 +14,4 @@ class RuntimeEnvironment { static std::wstring m_basePath; static std::wstring m_opName; }; -#endif // OP_RUNTIME_RUNTIME_ENVIRONMENT_H_ +#endif // OP_BASE_ENVIRONMENT_H_ diff --git a/libop/base/JsonUtils.h b/libop/base/JsonUtils.h new file mode 100644 index 0000000..ca514e1 --- /dev/null +++ b/libop/base/JsonUtils.h @@ -0,0 +1,94 @@ +#pragma once + +#include +#include +#include + +namespace op::internal::json { + +inline std::wstring EscapeString(const std::wstring &value) { + std::wstring escaped; + escaped.reserve(value.size() + 8); + for (wchar_t ch : value) { + switch (ch) { + case L'\\': + escaped += L"\\\\"; + break; + case L'"': + escaped += L"\\\""; + break; + case L'\b': + escaped += L"\\b"; + break; + case L'\f': + escaped += L"\\f"; + break; + case L'\n': + escaped += L"\\n"; + break; + case L'\r': + escaped += L"\\r"; + break; + case L'\t': + escaped += L"\\t"; + break; + default: + escaped.push_back(ch); + break; + } + } + return escaped; +} + +// 这里只反转服务响应里用到的字符串转义,不做完整 JSON 语法解析。 +inline std::string UnescapeString(const std::string &value) { + std::string out; + out.reserve(value.size()); + for (size_t i = 0; i < value.size(); ++i) { + if (value[i] != '\\') { + out.push_back(value[i]); + continue; + } + if (i + 1 >= value.size()) + break; + char c = value[++i]; + switch (c) { + case '"': + out.push_back('"'); + break; + case '\\': + out.push_back('\\'); + break; + case '/': + out.push_back('/'); + break; + case 'b': + out.push_back('\b'); + break; + case 'f': + out.push_back('\f'); + break; + case 'n': + out.push_back('\n'); + break; + case 'r': + out.push_back('\r'); + break; + case 't': + out.push_back('\t'); + break; + default: + out.push_back(c); + break; + } + } + return out; +} + +inline std::wstring FormatDouble(double value, int precision = 6) { + std::wostringstream oss; + oss << std::fixed << std::setprecision(precision) << value; + return oss.str(); +} + +} // namespace op::internal::json diff --git a/libop/runtime/ThreadPool.h b/libop/base/ThreadPool.h similarity index 95% rename from libop/runtime/ThreadPool.h rename to libop/base/ThreadPool.h index ad71b80..e2fde14 100644 --- a/libop/runtime/ThreadPool.h +++ b/libop/base/ThreadPool.h @@ -1,5 +1,5 @@ -#ifndef OP_RUNTIME_THREAD_POOL_H_ -#define OP_RUNTIME_THREAD_POOL_H_ +#ifndef OP_BASE_THREAD_POOL_H_ +#define OP_BASE_THREAD_POOL_H_ #include #include @@ -87,4 +87,4 @@ inline ThreadPool::~ThreadPool() { for (std::thread &worker : workers) worker.join(); } -#endif // OP_RUNTIME_THREAD_POOL_H_ +#endif // OP_BASE_THREAD_POOL_H_ diff --git a/libop/runtime/Types.h b/libop/base/Types.h similarity index 97% rename from libop/runtime/Types.h rename to libop/base/Types.h index 8ac2f4f..0b42066 100644 --- a/libop/runtime/Types.h +++ b/libop/base/Types.h @@ -1,6 +1,6 @@ #pragma once -#ifndef OP_RUNTIME_TYPES_H_ -#define OP_RUNTIME_TYPES_H_ +#ifndef OP_BASE_TYPES_H_ +#define OP_BASE_TYPES_H_ #include #include @@ -138,4 +138,4 @@ using vyolo_rec_t = std::vector; } // namespace op -#endif // OP_RUNTIME_TYPES_H_ +#endif // OP_BASE_TYPES_H_ diff --git a/libop/runtime/RuntimeUtils.cpp b/libop/base/Utils.cpp similarity index 99% rename from libop/runtime/RuntimeUtils.cpp rename to libop/base/Utils.cpp index c7e7129..979b97b 100644 --- a/libop/runtime/RuntimeUtils.cpp +++ b/libop/base/Utils.cpp @@ -1,7 +1,7 @@ // #include "stdafx.h" -#include "RuntimeUtils.h" +#include "Utils.h" #include "AutomationModes.h" -#include "RuntimeEnvironment.h" +#include "Environment.h" #include #include #include diff --git a/libop/runtime/RuntimeUtils.h b/libop/base/Utils.h similarity index 95% rename from libop/runtime/RuntimeUtils.h rename to libop/base/Utils.h index 63982d9..fc3bbff 100644 --- a/libop/runtime/RuntimeUtils.h +++ b/libop/base/Utils.h @@ -1,6 +1,6 @@ #pragma once -#ifndef OP_RUNTIME_RUNTIME_UTILS_H_ -#define OP_RUNTIME_RUNTIME_UTILS_H_ +#ifndef OP_BASE_UTILS_H_ +#define OP_BASE_UTILS_H_ #include "Types.h" std::wstring _s2wstring(const std::string &s); std::string _ws2string(const std::wstring &s); @@ -86,4 +86,4 @@ std::wostream &operator<<(std::wostream &o, point_t const &rhs); bool Delay(long mis); bool Delays(long mis_min, long mis_max); -#endif // OP_RUNTIME_RUNTIME_UTILS_H_ +#endif // OP_BASE_UTILS_H_ diff --git a/libop/runtime/WindowsHandle.h b/libop/base/WindowsHandle.h similarity index 91% rename from libop/runtime/WindowsHandle.h rename to libop/base/WindowsHandle.h index 6f1f17c..03ccf80 100644 --- a/libop/runtime/WindowsHandle.h +++ b/libop/base/WindowsHandle.h @@ -1,6 +1,6 @@ #pragma once -#ifndef OP_RUNTIME_WINDOWS_HANDLE_H_ -#define OP_RUNTIME_WINDOWS_HANDLE_H_ +#ifndef OP_BASE_WINDOWS_HANDLE_H_ +#define OP_BASE_WINDOWS_HANDLE_H_ #include @@ -61,4 +61,4 @@ class unique_handle { } // namespace op::win32 -#endif // OP_RUNTIME_WINDOWS_HANDLE_H_ +#endif // OP_BASE_WINDOWS_HANDLE_H_ diff --git a/libop/runtime/WindowsVersion.cpp b/libop/base/WindowsVersion.cpp similarity index 100% rename from libop/runtime/WindowsVersion.cpp rename to libop/base/WindowsVersion.cpp diff --git a/libop/runtime/WindowsVersion.h b/libop/base/WindowsVersion.h similarity index 100% rename from libop/runtime/WindowsVersion.h rename to libop/base/WindowsVersion.h diff --git a/libop/binding/BindingSession.cpp b/libop/binding/BindingSession.cpp index bd4eef0..6d898dd 100644 --- a/libop/binding/BindingSession.cpp +++ b/libop/binding/BindingSession.cpp @@ -1,8 +1,8 @@ // #include "stdafx.h" #include "BindingSession.h" -#include "../runtime/AutomationModes.h" -#include "../runtime/RuntimeUtils.h" -#include "../runtime/WindowsVersion.h" +#include "../base/AutomationModes.h" +#include "../base/Utils.h" +#include "../base/WindowsVersion.h" #include #include #include @@ -16,6 +16,7 @@ #endif #include "../capture/sources/MemoryImageSource.h" +#include "../hook/InputHookClient.h" #include "../input/keyboard/DxKeyboard.h" #include "../input/keyboard/WinKeyboard.h" #include "../input/mouse/DxMouse.h" @@ -135,7 +136,8 @@ const wchar_t *display_mode_name(int display) { } // namespace BindingSession::BindingSession() - : _display_hwnd(0), _input_hwnd(0), _is_bind(0), _capture(nullptr), _mouse(std::make_unique()), + : _display_hwnd(0), _input_hwnd(0), _is_bind(0), _display(0), _mode(0), _mouse_mode(INPUT_TYPE::IN_NORMAL), + _keypad_mode(INPUT_TYPE::IN_NORMAL), _capture(nullptr), _mouse(std::make_unique()), _keyboard(std::make_unique()) { _display_method = std::make_pair(L"screen", L""); } @@ -248,6 +250,8 @@ long BindingSession::BindWindowEx(LONG_PTR display_hwnd, LONG_PTR input_hwnd, co _display = display; _display_hwnd = displayWnd; _input_hwnd = inputWnd; + _mouse_mode = mouse; + _keypad_mode = keypad; set_display_method(L"screen"); _capture = createDisplay(display); @@ -309,12 +313,35 @@ long BindingSession::UnBindWindow() { return reset_bind_state(true); } +long BindingSession::LockInput(long lock) { + if (lock < 0 || lock > 3) + return 0; + if (lock == 0) + return op::hook::input_hook_client::LockInput(_input_hwnd, 0); + if (!_is_bind || !_input_hwnd) + return 0; + + const bool need_mouse = lock == 1 || lock == 2; + const bool need_keyboard = lock == 1 || lock == 3; + if ((need_mouse && _mouse_mode != INPUT_TYPE::IN_DX) || (need_keyboard && _keypad_mode != INPUT_TYPE::IN_DX)) + return 0; + + return op::hook::input_hook_client::LockInput(_input_hwnd, static_cast(lock)); +} + long BindingSession::reset_bind_state(bool restore_default_input) { + if (_input_hwnd && (_mouse_mode == INPUT_TYPE::IN_DX || _keypad_mode == INPUT_TYPE::IN_DX)) { + // 解绑时主动解锁,避免脚本异常退出后目标窗口还留在锁定状态。 + op::hook::input_hook_client::LockInput(_input_hwnd, 0); + } + _display_hwnd = NULL; _input_hwnd = NULL; _display = 0; _is_bind = 0; _mode = 0; + _mouse_mode = INPUT_TYPE::IN_NORMAL; + _keypad_mode = INPUT_TYPE::IN_NORMAL; if (_capture) { _capture->UnBind(); diff --git a/libop/binding/BindingSession.h b/libop/binding/BindingSession.h index efaa444..ae94e7d 100644 --- a/libop/binding/BindingSession.h +++ b/libop/binding/BindingSession.h @@ -26,6 +26,7 @@ class BindingSession { virtual long BindWindow(LONG_PTR hwnd, const wstring &sdisplay, const wstring &smouse, const wstring &skeypad, long mode); virtual long UnBindWindow(); + virtual long LockInput(long lock); // 返回当前绑定的显示窗口句柄。使用 BindWindowEx 时,输入句柄可能不同于这个句柄。 virtual LONG_PTR GetBindWindow(); virtual long IsBind(); @@ -53,6 +54,8 @@ class BindingSession { int _is_bind; int _display; int _mode; + int _mouse_mode; + int _keypad_mode; std::pair _display_method; Image _pic; diff --git a/libop/c_api/op_c_api.cpp b/libop/c_api/op_c_api.cpp index 29b210e..b9220a1 100644 --- a/libop/c_api/op_c_api.cpp +++ b/libop/c_api/op_c_api.cpp @@ -2,7 +2,7 @@ #include "../../include/libop.h" #include "../memory/ProcessMemory.h" -#include "../runtime/RuntimeEnvironment.h" +#include "../base/Environment.h" #include #include @@ -88,10 +88,30 @@ const wchar_t *call_string(op_handle handle, Func &&func) { } } +template +const wchar_t *call_json_string(op_handle handle, const wchar_t *fallback, Func &&func) { + if (!handle) + return fallback; + + try { + handle->string_result.clear(); + std::forward(func)(handle->op, handle->string_result); + if (handle->string_result.empty()) + handle->string_result = fallback; + return handle->string_result.c_str(); + } catch (...) { + return fallback; + } +} + const wchar_t *safe_text(const wchar_t *text) { return text ? text : L""; } +constexpr const wchar_t *kJsonFailure = L"{\"ok\":0}"; +constexpr const wchar_t *kJsonResultsFailure = L"{\"ok\":0,\"results\":[]}"; +constexpr const wchar_t *kYoloJsonFailure = L"{\"ok\":0,\"code\":-1,\"results\":[]}"; + long in_int(const int *value) { return value ? *value : 0; } @@ -480,6 +500,10 @@ int OP_CALL OpUnbindWindow(op_handle handle) { return OpUnBindWindow(handle); } +int OP_CALL OpLockInput(op_handle handle, int lock) { + return call_ret(handle, [&](op::Op &op, long *ret) { op.LockInput(lock, ret); }); +} + intptr_t OP_CALL OpGetBindWindow(op_handle handle) { return call_intptr(handle, [](op::Op &op, LONG_PTR *ret) { op.GetBindWindow(ret); }); } @@ -515,6 +539,29 @@ const wchar_t *OP_CALL OpMoveToEx(op_handle handle, int x, int y, int w, int h) return call_string(handle, [&](op::Op &op, std::wstring &ret) { op.MoveToEx(x, y, w, h, ret); }); } +int OP_CALL OpMoveToSmooth(op_handle handle, int x, int y, int duration) { + return call_ret(handle, [&](op::Op &op, long *ret) { op.MoveToSmooth(x, y, duration, ret); }); +} + +const wchar_t *OP_CALL OpMoveToExSmooth(op_handle handle, int x, int y, int w, int h, int duration) { + return call_string(handle, [&](op::Op &op, std::wstring &ret) { op.MoveToExSmooth(x, y, w, h, duration, ret); }); +} + +int OP_CALL OpMovePath(op_handle handle, const wchar_t *path, int duration) { + return call_ret(handle, [&](op::Op &op, long *ret) { op.MovePath(safe_text(path), duration, ret); }); +} + +int OP_CALL OpDragPath(op_handle handle, const wchar_t *path, int duration) { + return call_ret(handle, [&](op::Op &op, long *ret) { op.DragPath(safe_text(path), duration, ret); }); +} + +int OP_CALL OpSetMouseTrajectory(op_handle handle, int mode, int min_duration, int max_duration, int jitter, + int start_delay, int end_delay) { + return call_ret(handle, [&](op::Op &op, long *ret) { + op.SetMouseTrajectory(mode, min_duration, max_duration, jitter, start_delay, end_delay, ret); + }); +} + #define OP_MOUSE_RET(name, method) \ int OP_CALL name(op_handle handle) { return call_ret(handle, [](op::Op &op, long *ret) { op.method(ret); }); } @@ -644,12 +691,24 @@ const wchar_t *OP_CALL OpFindMultiColorEx(op_handle handle, int x1, int y1, int int OP_CALL OpFindPic(op_handle handle, int x1, int y1, int x2, int y2, const wchar_t *files, const wchar_t *delta_color, double sim, int dir, int *x, int *y) { - return call_ret(handle, [&](op::Op &op, long *ret) { - long lx = 0, ly = 0; - op.FindPic(x1, y1, x2, y2, safe_text(files), safe_text(delta_color), sim, dir, &lx, &ly, ret); + out_int(x, -1); + out_int(y, -1); + if (!handle) + return -1; + + try { + long lx = -1; + long ly = -1; + long ret = -1; + handle->op.FindPic(x1, y1, x2, y2, safe_text(files), safe_text(delta_color), sim, dir, &lx, &ly, &ret); out_int(x, lx); out_int(y, ly); - }); + return static_cast(ret); + } catch (...) { + out_int(x, -1); + out_int(y, -1); + return -1; + } } const wchar_t *OP_CALL OpFindPicEx(op_handle handle, int x1, int y1, int x2, int y2, const wchar_t *files, @@ -668,8 +727,10 @@ const wchar_t *OP_CALL OpFindPicExS(op_handle handle, int x1, int y1, int x2, in int OP_CALL OpFindColorBlock(op_handle handle, int x1, int y1, int x2, int y2, const wchar_t *color, double sim, int count, int height, int width, int *x, int *y) { + out_int(x, -1); + out_int(y, -1); return call_ret(handle, [&](op::Op &op, long *ret) { - long lx = 0, ly = 0; + long lx = -1, ly = -1; op.FindColorBlock(x1, y1, x2, y2, safe_text(color), sim, count, height, width, &lx, &ly, ret); out_int(x, lx); out_int(y, ly); @@ -708,6 +769,8 @@ int OP_CALL OpLoadMemPic(op_handle handle, const wchar_t *file_name, void *data, } int OP_CALL OpGetPicSize(op_handle handle, const wchar_t *pic_name, int *width, int *height) { + out_int(width, 0); + out_int(height, 0); return call_ret(handle, [&](op::Op &op, long *ret) { long w = 0, h = 0; op.GetPicSize(safe_text(pic_name), &w, &h, ret); @@ -852,14 +915,14 @@ int OP_CALL OpCvSharpen(op_handle handle, const wchar_t *src_file, const wchar_t } const wchar_t *OP_CALL OpCvConnectedComponents(op_handle handle, const wchar_t *src_file, double min_area) { - return call_string(handle, [&](op::Op &op, std::wstring &json) { + return call_json_string(handle, kJsonResultsFailure, [&](op::Op &op, std::wstring &json) { long ret = 0; op.CvConnectedComponents(safe_text(src_file), min_area, json, &ret); }); } const wchar_t *OP_CALL OpCvFindContours(op_handle handle, const wchar_t *src_file, double min_area) { - return call_string(handle, [&](op::Op &op, std::wstring &json) { + return call_json_string(handle, kJsonResultsFailure, [&](op::Op &op, std::wstring &json) { long ret = 0; op.CvFindContours(safe_text(src_file), min_area, json, &ret); }); @@ -916,7 +979,7 @@ int OP_CALL OpCvThin(op_handle handle, const wchar_t *src_file, const wchar_t *d const wchar_t *OP_CALL OpCvMatchTemplate(op_handle handle, int x, int y, int width, int height, const wchar_t *template_name, double threshold, int dir, int strip_mode, int method, int color_mode) { - return call_string(handle, [&](op::Op &op, std::wstring &json) { + return call_json_string(handle, kJsonFailure, [&](op::Op &op, std::wstring &json) { long ret = 0; op.CvMatchTemplate(x, y, width, height, safe_text(template_name), threshold, dir, strip_mode, method, color_mode, json, &ret); @@ -926,7 +989,7 @@ const wchar_t *OP_CALL OpCvMatchTemplate(op_handle handle, int x, int y, int wid const wchar_t *OP_CALL OpCvMatchTemplateScale(op_handle handle, int x, int y, int width, int height, const wchar_t *template_name, const wchar_t *scales, double threshold, int method, int color_mode) { - return call_string(handle, [&](op::Op &op, std::wstring &json) { + return call_json_string(handle, kJsonFailure, [&](op::Op &op, std::wstring &json) { long ret = 0; op.CvMatchTemplateScale(x, y, width, height, safe_text(template_name), safe_text(scales), threshold, method, color_mode, json, &ret); @@ -936,7 +999,7 @@ const wchar_t *OP_CALL OpCvMatchTemplateScale(op_handle handle, int x, int y, in const wchar_t *OP_CALL OpCvMatchAnyTemplate(op_handle handle, int x, int y, int width, int height, const wchar_t *template_names, double threshold, int dir, int strip_mode, int method, int color_mode) { - return call_string(handle, [&](op::Op &op, std::wstring &json) { + return call_json_string(handle, kJsonFailure, [&](op::Op &op, std::wstring &json) { long ret = 0; op.CvMatchAnyTemplate(x, y, width, height, safe_text(template_names), threshold, dir, strip_mode, method, color_mode, json, &ret); @@ -946,7 +1009,7 @@ const wchar_t *OP_CALL OpCvMatchAnyTemplate(op_handle handle, int x, int y, int const wchar_t *OP_CALL OpCvMatchAllTemplates(op_handle handle, int x, int y, int width, int height, const wchar_t *template_names, double threshold, int dir, int strip_mode, int method, int color_mode) { - return call_string(handle, [&](op::Op &op, std::wstring &json) { + return call_json_string(handle, kJsonResultsFailure, [&](op::Op &op, std::wstring &json) { long ret = 0; op.CvMatchAllTemplates(x, y, width, height, safe_text(template_names), threshold, dir, strip_mode, method, color_mode, json, &ret); @@ -955,7 +1018,7 @@ const wchar_t *OP_CALL OpCvMatchAllTemplates(op_handle handle, int x, int y, int const wchar_t *OP_CALL OpCvFeatureMatchTemplate(op_handle handle, int x, int y, int width, int height, const wchar_t *template_name, double threshold) { - return call_string(handle, [&](op::Op &op, std::wstring &json) { + return call_json_string(handle, kJsonFailure, [&](op::Op &op, std::wstring &json) { long ret = 0; op.CvFeatureMatchTemplate(x, y, width, height, safe_text(template_name), threshold, json, &ret); }); @@ -963,7 +1026,7 @@ const wchar_t *OP_CALL OpCvFeatureMatchTemplate(op_handle handle, int x, int y, const wchar_t *OP_CALL OpCvEdgeMatchTemplate(op_handle handle, int x, int y, int width, int height, const wchar_t *template_name, double threshold) { - return call_string(handle, [&](op::Op &op, std::wstring &json) { + return call_json_string(handle, kJsonFailure, [&](op::Op &op, std::wstring &json) { long ret = 0; op.CvEdgeMatchTemplate(x, y, width, height, safe_text(template_name), threshold, json, &ret); }); @@ -971,7 +1034,7 @@ const wchar_t *OP_CALL OpCvEdgeMatchTemplate(op_handle handle, int x, int y, int const wchar_t *OP_CALL OpCvShapeMatchTemplate(op_handle handle, int x, int y, int width, int height, const wchar_t *template_name, double threshold) { - return call_string(handle, [&](op::Op &op, std::wstring &json) { + return call_json_string(handle, kJsonFailure, [&](op::Op &op, std::wstring &json) { long ret = 0; op.CvShapeMatchTemplate(x, y, width, height, safe_text(template_name), threshold, json, &ret); }); @@ -994,14 +1057,14 @@ int OP_CALL OpSetYoloEngine(op_handle handle, const wchar_t *path_of_engine, con } const wchar_t *OP_CALL OpYoloDetect(op_handle handle, int x1, int y1, int x2, int y2, double conf, double iou) { - return call_string(handle, [&](op::Op &op, std::wstring &ret) { + return call_json_string(handle, kYoloJsonFailure, [&](op::Op &op, std::wstring &ret) { long status = 0; op.YoloDetect(x1, y1, x2, y2, conf, iou, ret, &status); }); } const wchar_t *OP_CALL OpYoloDetectFromFile(op_handle handle, const wchar_t *file_name, double conf, double iou) { - return call_string(handle, [&](op::Op &op, std::wstring &ret) { + return call_json_string(handle, kYoloJsonFailure, [&](op::Op &op, std::wstring &ret) { long status = 0; op.YoloDetectFromFile(safe_text(file_name), conf, iou, ret, &status); }); @@ -1015,8 +1078,8 @@ const wchar_t *OP_CALL OpGetDict(op_handle handle, int idx, int font_index) { return call_string(handle, [&](op::Op &op, std::wstring &ret) { op.GetDict(idx, font_index, ret); }); } -int OP_CALL OpSetMemDict(op_handle handle, int idx, const wchar_t *data, int size) { - return call_ret(handle, [&](op::Op &op, long *ret) { op.SetMemDict(idx, safe_text(data), size, ret); }); +int OP_CALL OpSetMemDict(op_handle handle, int idx, const void *data, int size) { + return call_ret(handle, [&](op::Op &op, long *ret) { op.SetMemDict(idx, data, size, ret); }); } int OP_CALL OpUseDict(op_handle handle, int idx) { diff --git a/libop/capture/ICaptureBackend.cpp b/libop/capture/ICaptureBackend.cpp index 1922aa1..c5824e3 100644 --- a/libop/capture/ICaptureBackend.cpp +++ b/libop/capture/ICaptureBackend.cpp @@ -1,7 +1,7 @@ // #include "stdafx.h" #include "ICaptureBackend.h" -#include "../runtime/AutomationModes.h" -#include "../runtime/RuntimeUtils.h" +#include "../base/AutomationModes.h" +#include "../base/Utils.h" #include namespace op::capture { diff --git a/libop/capture/backends/DxgiCapture.cpp b/libop/capture/backends/DxgiCapture.cpp index 8018157..b4b1ab7 100644 --- a/libop/capture/backends/DxgiCapture.cpp +++ b/libop/capture/backends/DxgiCapture.cpp @@ -1,9 +1,10 @@ // DXGIDuplicator.cpp #include "DxgiCapture.h" +#include "../../hook/DxCaptureCommon.h" #include "../../image/Image.h" -#include "../../runtime/AutomationModes.h" -#include "../../runtime/RuntimeUtils.h" +#include "../../base/AutomationModes.h" +#include "../../base/Utils.h" #include #include #include @@ -13,6 +14,7 @@ namespace op::capture { namespace { using ATL::CComPtr; +using op::hook::D3D11TextureMap; template bool set_out(Target *target, Value value) { if (!target) @@ -59,37 +61,6 @@ class DxgiFrameLease { bool acquired_ = false; }; -class D3D11TextureMap { - public: - D3D11TextureMap(ID3D11DeviceContext *context, ID3D11Resource *resource) : context_(context), resource_(resource) { - } - - ~D3D11TextureMap() { - if (mapped_) { - context_->Unmap(resource_, 0); - } - } - - D3D11TextureMap(const D3D11TextureMap &) = delete; - D3D11TextureMap &operator=(const D3D11TextureMap &) = delete; - - HRESULT map(D3D11_MAPPED_SUBRESOURCE *mapped) { - if (!context_ || !resource_ || !mapped) { - return E_POINTER; - } - HRESULT hr = context_->Map(resource_, 0, D3D11_MAP_READ, 0, mapped); - if (SUCCEEDED(hr)) { - mapped_ = true; - } - return hr; - } - - private: - ID3D11DeviceContext *context_; - ID3D11Resource *resource_; - bool mapped_ = false; -}; - } // namespace DxgiCapture::DxgiCapture() = default; diff --git a/libop/capture/backends/GdiCapture.cpp b/libop/capture/backends/GdiCapture.cpp index 0f67fe1..3e9acf0 100644 --- a/libop/capture/backends/GdiCapture.cpp +++ b/libop/capture/backends/GdiCapture.cpp @@ -9,8 +9,8 @@ #include "../../window/WindowService.h" #include "../../image/Image.h" -#include "../../runtime/AutomationModes.h" -#include "../../runtime/RuntimeUtils.h" +#include "../../base/AutomationModes.h" +#include "../../base/Utils.h" namespace { diff --git a/libop/capture/backends/GdiCapture.h b/libop/capture/backends/GdiCapture.h index e173843..8c580d9 100644 --- a/libop/capture/backends/GdiCapture.h +++ b/libop/capture/backends/GdiCapture.h @@ -2,7 +2,7 @@ #ifndef OP_CAPTURE_BACKENDS_GDI_CAPTURE_H_ #define OP_CAPTURE_BACKENDS_GDI_CAPTURE_H_ #include "../ICaptureBackend.h" -#include "../../runtime/Types.h" +#include "../../base/Types.h" #include namespace op { struct Image; diff --git a/libop/capture/backends/HookCapture.cpp b/libop/capture/backends/HookCapture.cpp index 2c71ff4..7f8041d 100644 --- a/libop/capture/backends/HookCapture.cpp +++ b/libop/capture/backends/HookCapture.cpp @@ -2,9 +2,9 @@ // #include "stdafx.h" #include "HookCapture.h" -#include "../../runtime/AutomationModes.h" -#include "../../runtime/RuntimeEnvironment.h" -#include "../../runtime/RuntimeUtils.h" +#include "../../base/AutomationModes.h" +#include "../../base/Environment.h" +#include "../../base/Utils.h" #include "../../hook/HookModule.h" #include "BlackBone/Process/Process.h" #include "BlackBone/Process/RPC/RemoteFunction.hpp" diff --git a/libop/capture/backends/WgcCapture.cpp b/libop/capture/backends/WgcCapture.cpp index 221a13a..67a5734 100644 --- a/libop/capture/backends/WgcCapture.cpp +++ b/libop/capture/backends/WgcCapture.cpp @@ -1,9 +1,10 @@ #include "WgcCapture.h" +#include "../../hook/DxCaptureCommon.h" #include "../../image/Image.h" -#include "../../runtime/AutomationModes.h" -#include "../../runtime/RuntimeUtils.h" -#include "../../runtime/WindowsVersion.h" +#include "../../base/AutomationModes.h" +#include "../../base/Utils.h" +#include "../../base/WindowsVersion.h" #include #include #include @@ -20,6 +21,8 @@ namespace op::capture { namespace { +using op::hook::D3D11TextureMap; + template void set_out(Target *target, Value value) { if (target) *target = static_cast(value); @@ -34,37 +37,6 @@ struct ClientBoxCandidate { bool valid = false; }; -class D3D11TextureMap { - public: - D3D11TextureMap(ID3D11DeviceContext *context, ID3D11Resource *resource) : context_(context), resource_(resource) { - } - - ~D3D11TextureMap() { - if (mapped_) { - context_->Unmap(resource_, 0); - } - } - - D3D11TextureMap(const D3D11TextureMap &) = delete; - D3D11TextureMap &operator=(const D3D11TextureMap &) = delete; - - HRESULT map(D3D11_MAPPED_SUBRESOURCE *mapped) { - if (!context_ || !resource_ || !mapped) { - return E_POINTER; - } - HRESULT hr = context_->Map(resource_, 0, D3D11_MAP_READ, 0, mapped); - if (SUCCEEDED(hr)) { - mapped_ = true; - } - return hr; - } - - private: - ID3D11DeviceContext *context_; - ID3D11Resource *resource_; - bool mapped_ = false; -}; - bool wgcSessionPropertyPresent(const wchar_t *property_name) { try { return winrt::Windows::Foundation::Metadata::ApiInformation::IsPropertyPresent( diff --git a/libop/com/OpAutomation.cpp b/libop/com/OpAutomation.cpp index b1a4a94..17abd79 100644 --- a/libop/com/OpAutomation.cpp +++ b/libop/com/OpAutomation.cpp @@ -3,7 +3,7 @@ #include "OpAutomation.h" #include "stdafx.h" -#include "../runtime/AutomationModes.h" +#include "../base/AutomationModes.h" #include #include #include @@ -473,6 +473,11 @@ STDMETHODIMP OpAutomation::UnBindWindow(LONG *ret) { return S_OK; } +STDMETHODIMP OpAutomation::LockInput(LONG lock, LONG *ret) { + obj.LockInput(lock, ret); + return S_OK; +} + STDMETHODIMP OpAutomation::GetBindWindow(LONGLONG *ret) { LONG_PTR hwnd = 0; obj.GetBindWindow(&hwnd); @@ -521,6 +526,40 @@ STDMETHODIMP OpAutomation::MoveToEx(LONG x, LONG y, LONG w, LONG h, BSTR *ret) { return CopyOutBstr(ret, s); } +STDMETHODIMP OpAutomation::MoveToSmooth(LONG x, LONG y, LONG duration, LONG *ret) { + obj.MoveToSmooth(x, y, duration, ret); + + return S_OK; +} + +STDMETHODIMP OpAutomation::MoveToExSmooth(LONG x, LONG y, LONG w, LONG h, LONG duration, BSTR *ret) { + if (!ret) + return E_POINTER; + + std::wstring s; + obj.MoveToExSmooth(x, y, w, h, duration, s); + return CopyOutBstr(ret, s); +} + +STDMETHODIMP OpAutomation::MovePath(BSTR path, LONG duration, LONG *ret) { + obj.MovePath(path, duration, ret); + + return S_OK; +} + +STDMETHODIMP OpAutomation::DragPath(BSTR path, LONG duration, LONG *ret) { + obj.DragPath(path, duration, ret); + + return S_OK; +} + +STDMETHODIMP OpAutomation::SetMouseTrajectory(LONG mode, LONG min_duration, LONG max_duration, LONG jitter, + LONG start_delay, LONG end_delay, LONG *ret) { + obj.SetMouseTrajectory(mode, min_duration, max_duration, jitter, start_delay, end_delay, ret); + + return S_OK; +} + STDMETHODIMP OpAutomation::LeftClick(LONG *ret) { obj.LeftClick(ret); @@ -884,32 +923,17 @@ STDMETHODIMP OpAutomation::GetPicSize(BSTR pic_name, VARIANT *width, VARIANT *he return S_OK; } -// 获取指定区域的图像,用二进制数据的方式返回 -STDMETHODIMP OpAutomation::GetScreenData(LONG x1, LONG y1, LONG x2, LONG y2, LONG *ret) { - // #if OP64 - // data->vt = VT_I8; - // data->llVal = 0; - // #else - // data->vt = VT_I4; - // data->lVal = 0; - // #endif - // * ret = 0; - // void* data_ = nullptr; - // obj.GetScreenData(x1, y1, x2, y2, &data_, ret); - // - // #if OP64 - // data->llVal = (long long)data_; - // #else - // data->lVal = (long)data_; - // #endif - // * ret = 1; +// 返回截图内存地址,x64 下不能用 LONG,否则高位会被截断。 +STDMETHODIMP OpAutomation::GetScreenData(LONG x1, LONG y1, LONG x2, LONG y2, LONGLONG *ret) { if (!ret) return E_POINTER; - SetOutValue(ret, 0L); + SetOutValue(ret, 0LL); size_t data_ = 0; long capture_ret = 0; obj.GetScreenData(x1, y1, x2, y2, &data_, &capture_ret); - return SetOutValue(ret, static_cast(data_)); + if (!capture_ret) + return S_OK; + return SetOutValue(ret, static_cast(data_)); } STDMETHODIMP OpAutomation::GetScreenDataBmp(LONG x1, LONG y1, LONG x2, LONG y2, VARIANT *data, VARIANT *size, @@ -972,9 +996,35 @@ STDMETHODIMP OpAutomation::GetDict(LONG idx, LONG font_index, BSTR *retstr) { return S_OK; } -// 设置字库文件 -STDMETHODIMP OpAutomation::SetMemDict(LONG idx, BSTR data, LONG size, LONG *ret) { - obj.SetMemDict(idx, data, size, ret); +// 从内存字节设置全局字库槽,支持 OP 二进制 .dict 和文本字库内容。 +STDMETHODIMP OpAutomation::SetMemDict(LONG idx, SAFEARRAY *data, LONG *ret) { + if (!ret) + return E_POINTER; + + *ret = 0; + if (!data) + return S_OK; + + if (SafeArrayGetDim(data) != 1) + return S_OK; + + VARTYPE vt = VT_EMPTY; + if (FAILED(SafeArrayGetVartype(data, &vt)) || vt != VT_UI1) + return S_OK; + + LONG lower = 0; + LONG upper = -1; + if (FAILED(SafeArrayGetLBound(data, 1, &lower)) || FAILED(SafeArrayGetUBound(data, 1, &upper)) || upper < lower) + return S_OK; + + void *bytes = nullptr; + const HRESULT hr = SafeArrayAccessData(data, &bytes); + if (FAILED(hr)) + return hr; + + const LONG byte_count = upper - lower + 1; + obj.SetMemDict(idx, bytes, byte_count, ret); + SafeArrayUnaccessData(data); return S_OK; } diff --git a/libop/com/OpAutomation.h b/libop/com/OpAutomation.h index 6fc62b6..34ba841 100644 --- a/libop/com/OpAutomation.h +++ b/libop/com/OpAutomation.h @@ -180,6 +180,8 @@ class ATL_NO_VTABLE OpAutomation (LONGLONG display_hwnd, LONGLONG input_hwnd, BSTR display, BSTR mouse, BSTR keypad, LONG mode, LONG *ret); // STDMETHOD(UnBindWindow)(LONG *ret); + // 临时锁定目标窗口的外部输入。只对 dx 鼠标、dx 键盘有效。 + STDMETHOD(LockInput)(LONG lock, LONG *ret); // 获取当前对象已经绑定的窗口句柄. 无绑定返回0 STDMETHOD(GetBindWindow)(LONGLONG *ret); // 判定当前对象是否已绑定窗口. @@ -195,6 +197,17 @@ class ATL_NO_VTABLE OpAutomation STDMETHOD(MoveTo)(LONG x, LONG y, LONG *ret); // 把鼠标移动到目的范围内的任意一点 STDMETHOD(MoveToEx)(LONG x, LONG y, LONG w, LONG h, BSTR *ret); + // 按模拟轨迹移动到指定点 + STDMETHOD(MoveToSmooth)(LONG x, LONG y, LONG duration, LONG *ret); + // 在目标范围内随机取点,并按模拟轨迹移动过去 + STDMETHOD(MoveToExSmooth)(LONG x, LONG y, LONG w, LONG h, LONG duration, BSTR *ret); + // 按 x,y|x,y 格式提供的路径移动 + STDMETHOD(MovePath)(BSTR path, LONG duration, LONG *ret); + // 按 x,y|x,y 格式提供的路径拖拽 + STDMETHOD(DragPath)(BSTR path, LONG duration, LONG *ret); + // 设置模拟轨迹参数,只影响 Smooth 和 Path 系列鼠标移动 + STDMETHOD(SetMouseTrajectory)(LONG mode, LONG min_duration, LONG max_duration, LONG jitter, LONG start_delay, + LONG end_delay, LONG *ret); // 按下鼠标左键 STDMETHOD(LeftClick)(LONG *ret); // 双击鼠标左键 @@ -300,7 +313,7 @@ class ATL_NO_VTABLE OpAutomation STDMETHOD(LoadMemPic)(BSTR pic_name, long long data, LONG size, LONG *ret); STDMETHOD(GetPicSize)(BSTR pic_name, VARIANT *width, VARIANT *height, LONG *ret); // 获取指定区域的图像,用二进制数据的方式返回 - STDMETHOD(GetScreenData)(LONG x1, LONG y1, LONG x2, LONG y2, LONG *ret); + STDMETHOD(GetScreenData)(LONG x1, LONG y1, LONG x2, LONG y2, LONGLONG *ret); // Get a 24-bit bitmap payload for the specified region. STDMETHOD(GetScreenDataBmp)(LONG x1, LONG y1, LONG x2, LONG y2, VARIANT *data, VARIANT *size, LONG *ret); // Get current screen frame info. @@ -312,7 +325,7 @@ class ATL_NO_VTABLE OpAutomation STDMETHOD(SetDict)(LONG idx, BSTR file_name, LONG *ret); STDMETHOD(GetDict)(LONG idx, LONG font_index, BSTR *ret_str); // 设置内存字库文件 - STDMETHOD(SetMemDict)(LONG idx, BSTR data, LONG size, LONG *ret); + STDMETHOD(SetMemDict)(LONG idx, SAFEARRAY *data, LONG *ret); // 使用哪个字库文件进行识别 STDMETHOD(UseDict)(LONG idx, LONG *ret); // 给指定的字库中添加一条字库信息 diff --git a/libop/com/dllmain.cpp b/libop/com/dllmain.cpp index a7c4cae..d38b02c 100644 --- a/libop/com/dllmain.cpp +++ b/libop/com/dllmain.cpp @@ -1,7 +1,7 @@ // dllmain.cpp: DllMain 的实现。 #include "dllmain.h" -#include "../runtime/RuntimeEnvironment.h" +#include "../base/Environment.h" #include "compreg.h" #include "op_i.h" #include "resource.h" diff --git a/libop/com/op.def b/libop/com/op.def index 7d089ad..224a56b 100644 --- a/libop/com/op.def +++ b/libop/com/op.def @@ -12,6 +12,7 @@ EXPORTS ReleaseDisplayHook PRIVATE SetInputHook PRIVATE ReleaseInputHook PRIVATE + SetInputLock PRIVATE GetInputCursorShapeHash PRIVATE GetInputCursorShapeMeta PRIVATE GetInputCursorShapeHashLow PRIVATE diff --git a/libop/com/op.idl b/libop/com/op.idl index 69f1619..cf81bae 100644 --- a/libop/com/op.idl +++ b/libop/com/op.idl @@ -92,6 +92,7 @@ interface IOpAutomation : IDispatch [id(102)] HRESULT GetBindWindow([out, retval] hyper* ret); [id(103)] HRESULT IsBind([out, retval] LONG* ret); [id(104)] HRESULT BindWindowEx([in] hyper display_hwnd, [in] hyper input_hwnd, [in] BSTR display, [in] BSTR mouse, [in] BSTR keypad, [in] LONG mode, [out, retval] LONG* ret); + [id(105)] HRESULT LockInput([in] LONG lock, [out, retval] LONG* ret); //mouse & ketboard 120-149 [id(120)] HRESULT GetCursorPos([out] VARIANT* x, [out] VARIANT* y, [out, retval] LONG* ret); [id(121)] HRESULT MoveR([in] LONG x, [in] LONG y, [out, retval] LONG* ret); @@ -137,6 +138,11 @@ interface IOpAutomation : IDispatch [id(142)] HRESULT KeyPress([in] LONG vk_code, [out, retval] LONG* ret); [id(143)] HRESULT KeyPressChar([in] BSTR vk_code, [out, retval] LONG* ret); [id(144)] HRESULT GetCursorShape([out, retval] BSTR* ret); + [id(145)] HRESULT MoveToSmooth([in] LONG x, [in] LONG y, [in] LONG duration, [out, retval] LONG* ret); + [id(146)] HRESULT MoveToExSmooth([in] LONG x, [in] LONG y, [in] LONG w, [in] LONG h, [in] LONG duration, [out, retval] BSTR* ret); + [id(147)] HRESULT MovePath([in] BSTR path, [in] LONG duration, [out, retval] LONG* ret); + [id(148)] HRESULT DragPath([in] BSTR path, [in] LONG duration, [out, retval] LONG* ret); + [id(149)] HRESULT SetMouseTrajectory([in] LONG mode, [in] LONG min_duration, [in] LONG max_duration, [in] LONG jitter, [in] LONG start_delay, [in] LONG end_delay, [out, retval] LONG* ret); //image & color 150-199 [id(150)] HRESULT Capture([in] LONG x1, [in] LONG y1, [in] LONG x2, [in] LONG y2, [in] BSTR file_name, [out, retval] LONG* ret); [id(151)] HRESULT CmpColor([in] LONG x, [in] LONG y, [in] BSTR color, [in] DOUBLE sim, [out, retval] LONG* ret); @@ -155,7 +161,7 @@ interface IOpAutomation : IDispatch [id(164)] HRESULT SetDisplayInput([in] BSTR method, [out, retval] LONG* ret); [id(165)] HRESULT LoadPic([in] BSTR pic_name, [out, retval] LONG* ret); [id(166)] HRESULT FreePic([in] BSTR Pic_name, [out, retval] LONG* ret); - [id(167)] HRESULT GetScreenData([in] LONG x1, [in] LONG y1, [in] LONG x2, [in] LONG y2, [out, retval]LONG* ret); + [id(167)] HRESULT GetScreenData([in] LONG x1, [in] LONG y1, [in] LONG x2, [in] LONG y2, [out, retval] hyper* ret); [id(168)] HRESULT GetScreenDataBmp([in] LONG x1, [in] LONG y1, [in] LONG x2, [in] LONG y2, [out] VARIANT* data, [out] VARIANT* size, [out, retval]LONG* ret); [id(169)] HRESULT MatchPicName([in] BSTR pic_name, [out, retval] BSTR* retstr); [id(170)] HRESULT LoadMemPic([in] BSTR pic_name, [in]long long data, [in]LONG size,[out, retval] LONG* ret); @@ -185,7 +191,7 @@ interface IOpAutomation : IDispatch [id(211)] HRESULT SetYoloEngine([in] BSTR path_of_engine, [in] BSTR dll_name, [in] BSTR argv, [out, retval] LONG* ret); [id(212)] HRESULT YoloDetect([in] LONG x1, [in] LONG y1, [in] LONG x2, [in] LONG y2, [in] DOUBLE conf, [in] DOUBLE iou, [out] BSTR* retjson, [out, retval] LONG* ret); [id(213)] HRESULT YoloDetectFromFile([in] BSTR file_name, [in] DOUBLE conf, [in] DOUBLE iou, [out] BSTR* retjson, [out, retval] LONG* ret); - [id(220)] HRESULT SetMemDict([in] LONG idx, [in]BSTR data, [in]LONG size, [out, retval] LONG* ret); + [id(220)] HRESULT SetMemDict([in] LONG idx, [in] SAFEARRAY(BYTE) data, [out, retval] LONG* ret); [id(221)] HRESULT GetDict([in] LONG idx, [in] LONG font_index, [out, retval] BSTR* retstr); [id(222)] HRESULT AddDict([in] LONG idx, [in] BSTR dict_info, [out, retval] LONG* ret); [id(223)] HRESULT SaveDict([in] LONG idx, [in] BSTR file_name, [out, retval] LONG* ret); diff --git a/libop/hook/ApiResolver.cpp b/libop/hook/ApiResolver.cpp index fa27183..5073bbf 100644 --- a/libop/hook/ApiResolver.cpp +++ b/libop/hook/ApiResolver.cpp @@ -1,6 +1,6 @@ // #include "stdafx.h" #include "ApiResolver.h" -#include "../runtime/Types.h" +#include "../base/Types.h" void *ResolveApi(const char *mod_name, const char *func_name) { auto hdll = ::GetModuleHandleA(mod_name); diff --git a/libop/hook/D3D10Capture.cpp b/libop/hook/D3D10Capture.cpp index 574e19d..bfe7556 100644 --- a/libop/hook/D3D10Capture.cpp +++ b/libop/hook/D3D10Capture.cpp @@ -5,8 +5,8 @@ #include "../capture/FrameInfo.h" #include "../ipc/ProcessMutex.h" #include "../ipc/SharedMemory.h" -#include "../runtime/AutomationModes.h" -#include "../runtime/RuntimeUtils.h" +#include "../base/AutomationModes.h" +#include "../base/Utils.h" #include #include #include diff --git a/libop/hook/D3D11Capture.cpp b/libop/hook/D3D11Capture.cpp index b2f5a70..1dbc664 100644 --- a/libop/hook/D3D11Capture.cpp +++ b/libop/hook/D3D11Capture.cpp @@ -5,8 +5,8 @@ #include "../capture/FrameInfo.h" #include "../ipc/ProcessMutex.h" #include "../ipc/SharedMemory.h" -#include "../runtime/AutomationModes.h" -#include "../runtime/RuntimeUtils.h" +#include "../base/AutomationModes.h" +#include "../base/Utils.h" #include #include #include @@ -39,37 +39,6 @@ void write_shared_frame(std::span sharedFrame, HWND hwnd, UINT width, } // namespace -class D3D11TextureMap { - public: - D3D11TextureMap(ID3D11DeviceContext *context, ID3D11Resource *resource) : context_(context), resource_(resource) { - } - - ~D3D11TextureMap() { - if (mapped_) { - context_->Unmap(resource_, 0); - } - } - - D3D11TextureMap(const D3D11TextureMap &) = delete; - D3D11TextureMap &operator=(const D3D11TextureMap &) = delete; - - HRESULT map(D3D11_MAPPED_SUBRESOURCE *mapped) { - if (!context_ || !resource_ || !mapped) { - return E_POINTER; - } - HRESULT hr = context_->Map(resource_, 0, D3D11_MAP_READ, 0, mapped); - if (hr >= 0) { - mapped_ = true; - } - return hr; - } - - private: - ID3D11DeviceContext *context_; - ID3D11Resource *resource_; - bool mapped_ = false; -}; - void dx11_capture(IDXGISwapChain *swapchain) { HRESULT hr = 0; CComPtr backbufferptr; diff --git a/libop/hook/D3D12Capture.cpp b/libop/hook/D3D12Capture.cpp index f52e45d..d166e11 100644 --- a/libop/hook/D3D12Capture.cpp +++ b/libop/hook/D3D12Capture.cpp @@ -8,8 +8,8 @@ #include "../capture/FrameInfo.h" #include "../ipc/ProcessMutex.h" #include "../ipc/SharedMemory.h" -#include "../runtime/AutomationModes.h" -#include "../runtime/RuntimeUtils.h" +#include "../base/AutomationModes.h" +#include "../base/Utils.h" #define DEBUG_HOOK 0 diff --git a/libop/hook/D3D9Capture.cpp b/libop/hook/D3D9Capture.cpp index 7bc64ea..4697a5a 100644 --- a/libop/hook/D3D9Capture.cpp +++ b/libop/hook/D3D9Capture.cpp @@ -4,7 +4,7 @@ #include "../capture/FrameInfo.h" #include "../ipc/ProcessMutex.h" #include "../ipc/SharedMemory.h" -#include "../runtime/AutomationModes.h" +#include "../base/AutomationModes.h" #include namespace op::hook { diff --git a/libop/hook/DisplayHook.cpp b/libop/hook/DisplayHook.cpp index 8ef86a6..8f18f01 100644 --- a/libop/hook/DisplayHook.cpp +++ b/libop/hook/DisplayHook.cpp @@ -14,7 +14,7 @@ #include "kiero_d3d9.hpp" #include "kiero_opengl.hpp" #include "../hook/ApiResolver.h" -#include "../runtime/AutomationModes.h" +#include "../base/AutomationModes.h" #include #include diff --git a/libop/hook/DisplayHook.h b/libop/hook/DisplayHook.h index 58b719e..361d3af 100644 --- a/libop/hook/DisplayHook.h +++ b/libop/hook/DisplayHook.h @@ -1,7 +1,7 @@ // #pragma once #ifndef OP_HOOK_DISPLAY_HOOK_H_ #define OP_HOOK_DISPLAY_HOOK_H_ -#include "../runtime/AutomationModes.h" +#include "../base/AutomationModes.h" #include namespace op::hook { diff --git a/libop/hook/DxCaptureCommon.cpp b/libop/hook/DxCaptureCommon.cpp index 19158c7..6340649 100644 --- a/libop/hook/DxCaptureCommon.cpp +++ b/libop/hook/DxCaptureCommon.cpp @@ -1,7 +1,7 @@ #include "DxCaptureCommon.h" #include "DisplayHook.h" -#include "../runtime/AutomationModes.h" +#include "../base/AutomationModes.h" namespace op::hook { diff --git a/libop/hook/DxCaptureCommon.h b/libop/hook/DxCaptureCommon.h index 4e544b1..b1c3f3a 100644 --- a/libop/hook/DxCaptureCommon.h +++ b/libop/hook/DxCaptureCommon.h @@ -1,9 +1,43 @@ #pragma once +#include #include namespace op::hook { +// Map/Unmap 必须成对出现,封成小对象能避免失败路径漏掉 Unmap。 +class D3D11TextureMap { + public: + D3D11TextureMap(ID3D11DeviceContext *context, ID3D11Resource *resource) + : context_(context), resource_(resource) { + } + + ~D3D11TextureMap() { + if (mapped_) { + context_->Unmap(resource_, 0); + } + } + + D3D11TextureMap(const D3D11TextureMap &) = delete; + D3D11TextureMap &operator=(const D3D11TextureMap &) = delete; + + HRESULT map(D3D11_MAPPED_SUBRESOURCE *mapped) { + if (!context_ || !resource_ || !mapped) { + return E_POINTER; + } + const HRESULT hr = context_->Map(resource_, 0, D3D11_MAP_READ, 0, mapped); + if (SUCCEEDED(hr)) { + mapped_ = true; + } + return hr; + } + + private: + ID3D11DeviceContext *context_; + ID3D11Resource *resource_; + bool mapped_ = false; +}; + DXGI_FORMAT NormalizeDxgiFormat(DXGI_FORMAT format); int GetImageBufferFormat(DXGI_FORMAT format); diff --git a/libop/hook/HookExport.cpp b/libop/hook/HookExport.cpp index 3521d34..df216c4 100644 --- a/libop/hook/HookExport.cpp +++ b/libop/hook/HookExport.cpp @@ -1,5 +1,5 @@ #include "HookExport.h" -#include "../runtime/RuntimeEnvironment.h" +#include "../base/Environment.h" #include "DisplayHook.h" #include "InputHook.h" @@ -82,6 +82,12 @@ long __stdcall ReleaseInputHook() { return 1; } +long __stdcall SetInputLock(int lock) { + if (!InputHook::is_hooked) + return lock == 0 ? 1 : 0; + return InputHook::lockInput(lock); +} + unsigned long long __stdcall GetInputCursorShapeHash() { return InputHook::cursorShapeHash(); } diff --git a/libop/hook/HookExport.h b/libop/hook/HookExport.h index 00aeb22..c084288 100644 --- a/libop/hook/HookExport.h +++ b/libop/hook/HookExport.h @@ -1,4 +1,4 @@ -#include "../runtime/AutomationModes.h" +#include "../base/AutomationModes.h" // 描述: 设置显示Hook // 返回值:1 成功,0失败 @@ -16,6 +16,10 @@ DLL_API long __stdcall SetInputHook(HWND hwnd_, int input_type_); // 返回值:1 成功,0失败 DLL_API long __stdcall ReleaseInputHook(); +// 描述: 锁定目标窗口的外部输入,仅作用于输入 Hook。 +// 返回值:1 成功,0失败 +DLL_API long __stdcall SetInputLock(int lock); + // 描述: 获取目标进程内最近一次 SetCursor 的光标 hash。 DLL_API unsigned long long __stdcall GetInputCursorShapeHash(); diff --git a/libop/hook/HookModule.h b/libop/hook/HookModule.h index 2607748..e2f9a2d 100644 --- a/libop/hook/HookModule.h +++ b/libop/hook/HookModule.h @@ -1,7 +1,7 @@ #pragma once -#include "../runtime/AutomationModes.h" -#include "../runtime/RuntimeEnvironment.h" +#include "../base/AutomationModes.h" +#include "../base/Environment.h" #include diff --git a/libop/hook/InputHook.cpp b/libop/hook/InputHook.cpp index 3c3a076..1aceb30 100644 --- a/libop/hook/InputHook.cpp +++ b/libop/hook/InputHook.cpp @@ -1,6 +1,7 @@ #include "InputHook.h" -#include "../runtime/RuntimeUtils.h" -#include "../runtime/RuntimeEnvironment.h" +#include "../base/Utils.h" +#include "../base/Environment.h" +#include "../input/keyboard/KeyMessageUtils.h" #include "../input/mouse/CursorShape.h" #include "../hook/ApiResolver.h" #include "MinHookRuntime.h" @@ -36,10 +37,13 @@ HCURSOR InputHook::m_cursor = nullptr; bool InputHook::m_cursorVisible = false; unsigned long long InputHook::m_cursorHash = 0; unsigned long long InputHook::m_cursorMeta = 0; +LONG InputHook::m_inputLock = 0; bool InputHook::is_hooked = false; namespace { +namespace key_message = op::input::key_message; + WNDPROC g_rawWindowProc = nullptr; void *g_mouseGetDeviceStateRaw = nullptr; void *g_keyboardGetDeviceStateRaw = nullptr; @@ -119,7 +123,6 @@ UINT WINAPI hkGetRawInputDeviceList(PRAWINPUTDEVICELIST devices, PUINT count, UI UINT WINAPI hkGetRegisteredRawInputDevices(PRAWINPUTDEVICE devices, PUINT count, UINT size); HCURSOR WINAPI hkSetCursor(HCURSOR cursor); LRESULT CALLBACK opWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); -bool is_extended_vk(WPARAM vk); bool create_hook(void *target, void *detour, void **original = nullptr) { if (!target || !detour) @@ -146,8 +149,6 @@ void remove_input_hooks() { } g_hookTargets.clear(); } -WORD scan_code(WPARAM vk); - template void set_out(Target *target, Value value) { if (target) *target = static_cast(value); @@ -187,6 +188,101 @@ bool fake_raw_device(HANDLE device) { return fake_mouse_device(device) || fake_keyboard_device(device); } +bool raw_type_locked(DWORD type) { + if (type == RIM_TYPEMOUSE) + return InputHook::mouseLocked(); + if (type == RIM_TYPEKEYBOARD) + return InputHook::keyboardLocked(); + return InputHook::mouseLocked() && InputHook::keyboardLocked(); +} + +bool has_input_lock() { + return InputHook::mouseLocked() || InputHook::keyboardLocked(); +} + +bool mouse_window_message(UINT message) { + switch (message) { + case WM_MOUSEMOVE: + case WM_NCMOUSEMOVE: + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_LBUTTONDBLCLK: + case WM_NCLBUTTONDOWN: + case WM_NCLBUTTONUP: + case WM_NCLBUTTONDBLCLK: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_MBUTTONDBLCLK: + case WM_NCMBUTTONDOWN: + case WM_NCMBUTTONUP: + case WM_NCMBUTTONDBLCLK: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_RBUTTONDBLCLK: + case WM_NCRBUTTONDOWN: + case WM_NCRBUTTONUP: + case WM_NCRBUTTONDBLCLK: + case WM_XBUTTONDOWN: + case WM_XBUTTONUP: + case WM_XBUTTONDBLCLK: + case WM_NCXBUTTONDOWN: + case WM_NCXBUTTONUP: + case WM_NCXBUTTONDBLCLK: + case WM_MOUSEWHEEL: + case WM_MOUSEHWHEEL: + return true; + default: + return false; + } +} + +bool keyboard_window_message(UINT message) { + switch (message) { + case WM_KEYDOWN: + case WM_KEYUP: + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + case WM_CHAR: + case WM_SYSCHAR: + case WM_DEADCHAR: + case WM_SYSDEADCHAR: + case WM_UNICHAR: + case WM_HOTKEY: + return true; + default: + return false; + } +} + +bool mouse_button_vk(int vk) { + return vk == VK_LBUTTON || vk == VK_RBUTTON || vk == VK_MBUTTON || vk == VK_XBUTTON1 || vk == VK_XBUTTON2; +} + +bool virtual_key_locked(int vk) { + return mouse_button_vk(vk) ? InputHook::mouseLocked() : InputHook::keyboardLocked(); +} + +UINT raw_input_aligned_size(UINT size) { + const UINT_PTR align = sizeof(void *); + return static_cast((static_cast(size) + align - 1) & ~(align - 1)); +} + +UINT empty_raw_input(PUINT size) { + if (size) + *size = 0; + return 0; +} + +UINT blocked_raw_input_data(LPVOID data, PUINT size) { + if (size) + *size = 0; + if (!data) + return 0; + + ::SetLastError(ERROR_INVALID_HANDLE); + return static_cast(-1); +} + void push_dinput_event(std::deque &events, DWORD offset, DWORD data) { if (events.size() >= kDinputEventLimit) events.pop_front(); @@ -209,12 +305,10 @@ void push_raw_event(const RAWINPUT &raw) { ::PostMessage(InputHook::input_hwnd, WM_INPUT, RIM_INPUT, reinterpret_cast(handle)); } -RAWINPUT *find_raw_event(HRAWINPUT handle) { - for (auto &event : g_rawEvents) { - if (event.first == handle) - return &event.second; - } - return nullptr; +std::deque>::iterator find_raw_event(HRAWINPUT handle) { + return std::find_if(g_rawEvents.begin(), g_rawEvents.end(), [&](const auto &event) { + return event.first == handle; + }); } DWORD mouse_button_offset(int key) { @@ -392,14 +486,10 @@ void hook_raw_input() { } void fill_mouse_state(DWORD size, LPVOID ptr) { - if (size == sizeof(MouseState)) { - memcpy(ptr, &InputHook::m_mouseState, sizeof(MouseState)); - return; - } - // DirectInput 鼠标轴是相对移动量,读取后需要消费,避免同一次移动被重复返回。 const LONG dx = InputHook::m_mouseState.lAxisX; const LONG dy = InputHook::m_mouseState.lAxisY; + const LONG wheel = InputHook::consumeWheelDelta(); InputHook::m_mouseState.lAxisX = 0; InputHook::m_mouseState.lAxisY = 0; @@ -407,16 +497,17 @@ void fill_mouse_state(DWORD size, LPVOID ptr) { DIMOUSESTATE state = {}; state.lX = dx; state.lY = dy; - state.lZ = InputHook::consumeWheelDelta(); + state.lZ = wheel; state.rgbButtons[0] = InputHook::m_mouseState.abButtons[0]; state.rgbButtons[1] = InputHook::m_mouseState.abButtons[1]; state.rgbButtons[2] = InputHook::m_mouseState.abButtons[2]; + state.rgbButtons[3] = InputHook::m_mouseState.abButtons[3]; memcpy(ptr, &state, sizeof(state)); } else { DIMOUSESTATE2 state = {}; state.lX = dx; state.lY = dy; - state.lZ = InputHook::consumeWheelDelta(); + state.lZ = wheel; state.rgbButtons[0] = InputHook::m_mouseState.abButtons[0]; state.rgbButtons[1] = InputHook::m_mouseState.abButtons[1]; state.rgbButtons[2] = InputHook::m_mouseState.abButtons[2]; @@ -480,8 +571,10 @@ RAWINPUT make_raw_keyboard(WPARAM vk, bool down) { raw.header.dwSize = sizeof(RAWINPUT); raw.header.hDevice = reinterpret_cast(kFakeRawKeyboardDevice); raw.header.wParam = RIM_INPUT; - raw.data.keyboard.MakeCode = scan_code(vk); - raw.data.keyboard.Flags = static_cast((down ? RI_KEY_MAKE : RI_KEY_BREAK) | (is_extended_vk(vk) ? RI_KEY_E0 : 0)); + raw.data.keyboard.MakeCode = key_message::ScanCode(static_cast(vk)); + raw.data.keyboard.Flags = static_cast( + (down ? RI_KEY_MAKE : RI_KEY_BREAK) | + (key_message::IsExtendedVirtualKey(static_cast(vk)) ? RI_KEY_E0 : 0)); raw.data.keyboard.VKey = static_cast(vk); raw.data.keyboard.Message = down ? WM_KEYDOWN : WM_KEYUP; return raw; @@ -508,6 +601,69 @@ UINT write_raw_input(const RAWINPUT &raw, UINT command, LPVOID data, PUINT size) return bytes; } +bool real_raw_input_locked(HRAWINPUT raw_input) { + if (!has_input_lock()) + return false; + if (!g_getRawInputDataRaw) + return true; + + RAWINPUTHEADER header = {}; + UINT header_size = sizeof(header); + const UINT ret = reinterpret_cast(g_getRawInputDataRaw)( + raw_input, RID_HEADER, &header, &header_size, sizeof(RAWINPUTHEADER)); + if (ret == sizeof(RAWINPUTHEADER)) + return raw_type_locked(header.dwType); + + return InputHook::mouseLocked() && InputHook::keyboardLocked(); +} + +UINT read_filtered_raw_input_buffer(PRAWINPUT data, PUINT size, UINT header_size) { + if (!g_getRawInputBufferRaw) + return empty_raw_input(size); + if (!data) + return reinterpret_cast(g_getRawInputBufferRaw)(data, size, header_size); + + const UINT capacity_bytes = *size; + if (capacity_bytes == 0) + return empty_raw_input(size); + + std::vector buffer(capacity_bytes); + UINT read_bytes = capacity_bytes; + const UINT count = reinterpret_cast(g_getRawInputBufferRaw)( + reinterpret_cast(buffer.data()), &read_bytes, header_size); + if (count == static_cast(-1)) + return count; + + BYTE *src = buffer.data(); + BYTE *end = buffer.data() + read_bytes; + BYTE *dst = reinterpret_cast(data); + UINT written_count = 0; + UINT written_bytes = 0; + for (UINT i = 0; i < count && src + sizeof(RAWINPUTHEADER) <= end; ++i) { + auto *raw = reinterpret_cast(src); + const UINT raw_size = raw->header.dwSize; + if (raw_size < sizeof(RAWINPUTHEADER) || src + raw_size > end) + break; + + const UINT aligned_size = raw_input_aligned_size(raw_size); + if (!raw_type_locked(raw->header.dwType) && written_bytes + aligned_size <= capacity_bytes) { + std::memmove(dst + written_bytes, src, raw_size); + if (aligned_size > raw_size) + std::memset(dst + written_bytes + raw_size, 0, aligned_size - raw_size); + written_bytes += aligned_size; + ++written_count; + } + + BYTE *next_src = src + aligned_size; + if (next_src <= src || next_src > end) + break; + src = next_src; + } + + set_out(size, written_bytes); + return written_count; +} + RID_DEVICE_INFO make_raw_device_info(HANDLE device) { RID_DEVICE_INFO info = {}; info.cbSize = sizeof(info); @@ -671,62 +827,12 @@ UINT append_fake_raw_device_list(PRAWINPUTDEVICELIST devices, PUINT count, UINT return written_total; } -bool is_extended_vk(WPARAM vk) { - switch (vk) { - case VK_RMENU: - case VK_RCONTROL: - case VK_INSERT: - case VK_DELETE: - case VK_HOME: - case VK_END: - case VK_PRIOR: - case VK_NEXT: - case VK_LEFT: - case VK_RIGHT: - case VK_UP: - case VK_DOWN: - case VK_NUMLOCK: - case VK_SNAPSHOT: - case VK_DIVIDE: - case VK_APPS: - case VK_LWIN: - case VK_RWIN: - return true; - default: - return false; - } -} - BYTE dik_code(WPARAM vk) { - switch (vk) { - case VK_NUMLOCK: - return 0x45; - case VK_PAUSE: - return 0xC5; - case VK_SNAPSHOT: - return 0xB7; - default: - break; - } - - BYTE scan = static_cast(::MapVirtualKey(static_cast(vk), MAPVK_VK_TO_VSC) & 0xff); - if (scan == 0) - return 0; - return is_extended_vk(vk) ? static_cast(scan | 0x80) : scan; -} - -WORD scan_code(WPARAM vk) { - return static_cast((::MapVirtualKey(static_cast(vk), MAPVK_VK_TO_VSC)) & 0xff); + return key_message::DirectInputScanCode(static_cast(vk)); } LPARAM make_key_lparam(WPARAM vk, bool up) { - DWORD value = 1; - value |= static_cast(scan_code(vk)) << 16; - if (is_extended_vk(vk)) - value |= 1u << 24; - if (up) - value |= 3u << 30; - return static_cast(value); + return key_message::BuildKeyLParam(static_cast(vk), up); } LPARAM client_to_screen_lparam(HWND hwnd, LPARAM lparam) { @@ -755,6 +861,7 @@ int InputHook::setup(HWND hwnd) { m_lastMouseX = 0; m_lastMouseY = 0; m_wheelDelta = 0; + m_inputLock = 0; if (!AcquireMinHook()) return 0; @@ -828,9 +935,25 @@ int InputHook::release() { m_cursorVisible = false; m_cursorHash = 0; m_cursorMeta = 0; + m_inputLock = 0; return restored ? 1 : 0; } +int InputHook::lockInput(int lock) { + if (lock < 0 || lock > 3) + return 0; + m_inputLock = lock; + return 1; +} + +bool InputHook::mouseLocked() { + return m_inputLock == 1 || m_inputLock == 2; +} + +bool InputHook::keyboardLocked() { + return m_inputLock == 1 || m_inputLock == 3; +} + void InputHook::moveTo(LPARAM lp) { const SHORT x = static_cast(LOWORD(lp)); const SHORT y = static_cast(HIWORD(lp)); @@ -952,7 +1075,7 @@ HRESULT __stdcall hkGetDeviceState(IDirectInputDevice8W *device, DWORD size, LPV return DI_OK; } if (ptr && (is_mouse || (!known_device && same_vtable(device, g_mouseVtablePtr))) && - (size == sizeof(MouseState) || size == sizeof(DIMOUSESTATE) || size == sizeof(DIMOUSESTATE2))) { + (size == sizeof(DIMOUSESTATE) || size == sizeof(DIMOUSESTATE2))) { fill_mouse_state(size, ptr); return DI_OK; } @@ -989,7 +1112,7 @@ HRESULT __stdcall hkGetDeviceData(IDirectInputDevice8W *device, DWORD object_siz SHORT WINAPI hkGetKeyState(int vk) { SHORT original = 0; - if (g_getKeyStateRaw) + if (!virtual_key_locked(vk) && g_getKeyStateRaw) original = reinterpret_cast(g_getKeyStateRaw)(vk); if (InputHook::isKeyDown(vk)) return static_cast(original | 0x8000); @@ -998,7 +1121,7 @@ SHORT WINAPI hkGetKeyState(int vk) { SHORT WINAPI hkGetAsyncKeyState(int vk) { SHORT original = 0; - if (g_getAsyncKeyStateRaw) + if (!virtual_key_locked(vk) && g_getAsyncKeyStateRaw) original = reinterpret_cast(g_getAsyncKeyStateRaw)(vk); if (InputHook::isKeyDown(vk)) return static_cast(original | 0x8000); @@ -1016,6 +1139,8 @@ BOOL WINAPI hkGetKeyboardState(PBYTE key_state) { memset(key_state, 0, 256); for (int i = 0; i < 256; ++i) { + if (virtual_key_locked(i)) + key_state[i] &= 0x7F; if (InputHook::m_vkState[i] & 0x80) key_state[i] |= 0x80; } @@ -1037,10 +1162,20 @@ UINT WINAPI hkGetRawInputData(HRAWINPUT raw_input, UINT command, LPVOID data, PU return static_cast(-1); std::lock_guard lock(g_eventMutex); - RAWINPUT *raw = find_raw_event(raw_input); - return raw ? write_raw_input(*raw, command, data, size) : static_cast(-1); + // 这是脚本自己压进来的 Raw Input,锁定外部输入时也要放行。 + auto it = find_raw_event(raw_input); + if (it == g_rawEvents.end()) + return static_cast(-1); + + const UINT ret = write_raw_input(it->second, command, data, size); + if (ret != static_cast(-1) && command == RID_INPUT && data) + g_rawEvents.erase(it); + return ret; } + if (real_raw_input_locked(raw_input)) + return blocked_raw_input_data(data, size); + if (g_getRawInputDataRaw) return reinterpret_cast(g_getRawInputDataRaw)(raw_input, command, data, size, header_size); return static_cast(-1); @@ -1057,6 +1192,8 @@ UINT WINAPI hkGetRawInputBuffer(PRAWINPUT data, PUINT size, UINT header_size) { set_out(size, sizeof(RAWINPUT)); return 0; } + if (InputHook::mouseLocked() && InputHook::keyboardLocked()) + return empty_raw_input(size); if (g_getRawInputBufferRaw) return reinterpret_cast(g_getRawInputBufferRaw)(data, size, header_size); set_out(size, 0); @@ -1075,6 +1212,8 @@ UINT WINAPI hkGetRawInputBuffer(PRAWINPUT data, PUINT size, UINT header_size) { if (copied > 0 || !g_getRawInputBufferRaw) return copied; + if (has_input_lock()) + return read_filtered_raw_input_buffer(data, size, header_size); return reinterpret_cast(g_getRawInputBufferRaw)(data, size, header_size); } @@ -1227,6 +1366,12 @@ LRESULT CALLBACK opWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam return 1; } + // 只拦外部输入。OP_WM_* 是脚本自己发来的消息,上面的分支已经放行。 + if ((InputHook::mouseLocked() && mouse_window_message(message)) || + (InputHook::keyboardLocked() && keyboard_window_message(message))) { + return 1; + } + return ::CallWindowProc(g_rawWindowProc, hwnd, message, wparam, lparam); } diff --git a/libop/hook/InputHook.h b/libop/hook/InputHook.h index 5673f75..6c8c321 100644 --- a/libop/hook/InputHook.h +++ b/libop/hook/InputHook.h @@ -1,13 +1,14 @@ #ifndef OP_HOOK_INPUT_HOOK_H_ #define OP_HOOK_INPUT_HOOK_H_ -#include "../runtime/AutomationModes.h" +#include "../base/AutomationModes.h" namespace op::hook { struct MouseState { LONG lAxisX; LONG lAxisY; + // 内部累计状态,不对应 DirectInput 的 DIMOUSESTATE 内存布局。 BYTE abButtons[5]; BYTE bPadding[3]; // 保持结构体 4 字节对齐。 }; @@ -20,6 +21,9 @@ class InputHook { static int setup(HWND hwnd_); static int release(); + static int lockInput(int lock); + static bool mouseLocked(); + static bool keyboardLocked(); static void moveTo(LPARAM lp); static void button(LPARAM lp, int key, bool down); static void updateWheel(WPARAM, LPARAM, bool horizontal); @@ -39,6 +43,7 @@ class InputHook { static bool m_cursorVisible; static unsigned long long m_cursorHash; static unsigned long long m_cursorMeta; + static LONG m_inputLock; }; } // namespace op::hook diff --git a/libop/hook/InputHookClient.cpp b/libop/hook/InputHookClient.cpp index 1e272f1..bb21233 100644 --- a/libop/hook/InputHookClient.cpp +++ b/libop/hook/InputHookClient.cpp @@ -1,7 +1,7 @@ #include "InputHookClient.h" -#include "../runtime/AutomationModes.h" -#include "../runtime/RuntimeUtils.h" -#include "../runtime/RuntimeEnvironment.h" +#include "../base/AutomationModes.h" +#include "../base/Utils.h" +#include "../base/Environment.h" #include "HookModule.h" #include "BlackBone/Process/Process.h" #include "BlackBone/Process/RPC/RemoteFunction.hpp" @@ -91,6 +91,34 @@ long call_release_input_hook(HWND hwnd) { return ret; } +long call_set_input_lock(HWND hwnd, int lock) { + DWORD pid = 0; + ::GetWindowThreadProcessId(hwnd, &pid); + if (pid == 0) + return 0; + + blackbone::Process proc; + const NTSTATUS status = proc.Attach(pid); + if (!NT_SUCCESS(status)) { + setlog(L"input hook lock attach failed. pid=%d hwnd=%p status=0x%X", pid, hwnd, status); + return 0; + } + + long ret = 0; + const std::wstring dll_name = resolve_hook_dll(proc); + using set_input_lock_t = long(__stdcall *)(int); + auto remote = blackbone::MakeRemoteFunction(proc, dll_name, "SetInputLock"); + if (remote) { + auto call_ret = remote(lock); + ret = call_ret.result(); + } else { + setlog(L"remote function 'SetInputLock' not found in %s.", dll_name.c_str()); + } + + proc.Detach(); + return ret; +} + bool call_cursor_shape(HWND hwnd, unsigned long long &hash, unsigned long long &meta) { DWORD pid = 0; ::GetWindowThreadProcessId(hwnd, &pid); @@ -164,6 +192,19 @@ long UnBind(HWND hwnd) { return call_release_input_hook(hwnd); } +long LockInput(HWND hwnd, int lock) { + if (lock < 0 || lock > 3) + return 0; + if (!hwnd) + return lock == 0 ? 1 : 0; + + std::lock_guard guard(g_mutex); + if (g_bind_refs.find(hwnd) == g_bind_refs.end()) + return lock == 0 ? 1 : 0; + + return call_set_input_lock(hwnd, lock); +} + bool GetCursorShape(HWND hwnd, unsigned long long &hash, unsigned long long &meta) { if (!hwnd) return false; diff --git a/libop/hook/InputHookClient.h b/libop/hook/InputHookClient.h index e99a9d1..449fd18 100644 --- a/libop/hook/InputHookClient.h +++ b/libop/hook/InputHookClient.h @@ -6,6 +6,7 @@ namespace op::hook::input_hook_client { long Bind(HWND hwnd, int mode); long UnBind(HWND hwnd); +long LockInput(HWND hwnd, int lock); bool GetCursorShape(HWND hwnd, unsigned long long &hash, unsigned long long &meta); } // namespace op::hook::input_hook_client diff --git a/libop/hook/OpenGLCapture.cpp b/libop/hook/OpenGLCapture.cpp index 8f61cef..a33ed78 100644 --- a/libop/hook/OpenGLCapture.cpp +++ b/libop/hook/OpenGLCapture.cpp @@ -5,8 +5,8 @@ #include "../hook/ApiResolver.h" #include "../ipc/ProcessMutex.h" #include "../ipc/SharedMemory.h" -#include "../runtime/AutomationModes.h" -#include "../runtime/RuntimeUtils.h" +#include "../base/AutomationModes.h" +#include "../base/Utils.h" #include #define DEBUG_HOOK 0 diff --git a/libop/image/Color.h b/libop/image/Color.h index 2b77e3b..a499140 100644 --- a/libop/image/Color.h +++ b/libop/image/Color.h @@ -1,7 +1,7 @@ #pragma once #ifndef OP_IMAGE_COLOR_H_ #define OP_IMAGE_COLOR_H_ -#include "../runtime/Types.h" +#include "../base/Types.h" #include #define WORD_BKCOLOR 0 #define WORD_COLOR 1 diff --git a/libop/image/Image.h b/libop/image/Image.h index 8e12ae9..b6a58d7 100644 --- a/libop/image/Image.h +++ b/libop/image/Image.h @@ -1,7 +1,7 @@ #pragma once #ifndef OP_IMAGE_IMAGE_H_ #define OP_IMAGE_IMAGE_H_ -#include "../runtime/Types.h" +#include "../base/Types.h" #include #include #include diff --git a/libop/image/ImageSearchAlgorithms.cpp b/libop/image/ImageSearchAlgorithms.cpp index f707877..27e073e 100644 --- a/libop/image/ImageSearchAlgorithms.cpp +++ b/libop/image/ImageSearchAlgorithms.cpp @@ -10,7 +10,7 @@ #include #include -#include "../runtime/RuntimeUtils.h" +#include "../base/Utils.h" using std::to_wstring; @@ -165,6 +165,20 @@ void build_pic_match_template(Image &img, PicMatchTemplate &match) { match.gray_norm = sum(match.gray.begin(), match.gray.end()); } +void prepare_pic_views(const std::vector &pics, std::vector &prepared, + std::vector &views) { + prepared.resize(pics.size()); + views.clear(); + views.reserve(pics.size()); + // 这里保留旧行为:空图片直接跳过,算法层看到的是压缩后的模板视图列表。 + for (size_t i = 0; i < pics.size(); ++i) { + if (!pics[i]) + continue; + build_pic_match_template(*pics[i], prepared[i]); + views.push_back(&prepared[i]); + } +} + void gen_next(const Image &img, vector &next) { next.resize(img.width * img.height); @@ -679,15 +693,9 @@ long ImageSearchAlgorithms::FindMultiColorEx(std::vector &first_colo } long ImageSearchAlgorithms::FindPic(std::vector &pics, color_t dfcolor, double sim, long dir, long &x, long &y) { - std::vector prepared(pics.size()); + std::vector prepared; std::vector views; - views.reserve(pics.size()); - for (size_t i = 0; i < pics.size(); ++i) { - if (!pics[i]) - continue; - build_pic_match_template(*pics[i], prepared[i]); - views.push_back(&prepared[i]); - } + prepare_pic_views(pics, prepared, views); return FindPic(views, dfcolor, sim, dir, x, y); } @@ -726,15 +734,9 @@ long ImageSearchAlgorithms::FindPic(std::vector &pics, color } long ImageSearchAlgorithms::FindPicTh(std::vector &pics, color_t dfcolor, double sim, long dir, long &x, long &y) { - std::vector prepared(pics.size()); + std::vector prepared; std::vector views; - views.reserve(pics.size()); - for (size_t i = 0; i < pics.size(); ++i) { - if (!pics[i]) - continue; - build_pic_match_template(*pics[i], prepared[i]); - views.push_back(&prepared[i]); - } + prepare_pic_views(pics, prepared, views); return FindPicTh(views, dfcolor, sim, dir, x, y); } @@ -804,15 +806,9 @@ long ImageSearchAlgorithms::FindPicTh(std::vector &pics, col } long ImageSearchAlgorithms::FindPicEx(std::vector &pics, color_t dfcolor, double sim, long dir, vpoint_desc_t &vpd) { - std::vector prepared(pics.size()); + std::vector prepared; std::vector views; - views.reserve(pics.size()); - for (size_t i = 0; i < pics.size(); ++i) { - if (!pics[i]) - continue; - build_pic_match_template(*pics[i], prepared[i]); - views.push_back(&prepared[i]); - } + prepare_pic_views(pics, prepared, views); return FindPicEx(views, dfcolor, sim, dir, vpd); } @@ -853,15 +849,9 @@ long ImageSearchAlgorithms::FindPicEx(std::vector &pics, col } long ImageSearchAlgorithms::FindPicExTh(std::vector &pics, color_t dfcolor, double sim, long dir, vpoint_desc_t &vpd) { - std::vector prepared(pics.size()); + std::vector prepared; std::vector views; - views.reserve(pics.size()); - for (size_t i = 0; i < pics.size(); ++i) { - if (!pics[i]) - continue; - build_pic_match_template(*pics[i], prepared[i]); - views.push_back(&prepared[i]); - } + prepare_pic_views(pics, prepared, views); return FindPicExTh(views, dfcolor, sim, dir, vpd); } diff --git a/libop/image/ImageSearchAlgorithms.h b/libop/image/ImageSearchAlgorithms.h index c41aa7e..a2a9eb1 100644 --- a/libop/image/ImageSearchAlgorithms.h +++ b/libop/image/ImageSearchAlgorithms.h @@ -5,11 +5,11 @@ 常见的图像算法,例如图像查找,颜色序列匹配(多点着色) 由于ocr与图像查找类似,故也在类ImageLoc中实现 */ -#include "../runtime/Types.h" +#include "../base/Types.h" #include "../ocr/Dictionary.h" #include "../image/BitFunctions.h" #include "../image/Color.h" -#include "../runtime/ThreadPool.h" +#include "../base/ThreadPool.h" #include #include diff --git a/libop/image/ImageSearchService.cpp b/libop/image/ImageSearchService.cpp index d46671f..6dccf4e 100644 --- a/libop/image/ImageSearchService.cpp +++ b/libop/image/ImageSearchService.cpp @@ -1,6 +1,6 @@ // #include "stdafx.h" #include "ImageSearchService.h" -#include "../runtime/RuntimeUtils.h" +#include "../base/Utils.h" #include "../ocr/OcrService.h" #include #include @@ -218,13 +218,15 @@ long ImageSearchService::FindColorEx(const wstring &color, double sim, long dir, return ImageSearchAlgorithms::FindColorEx(colors, sim, dir, retstr); } -long ImageSearchService::FindMultiColor(const wstring &first_color, const wstring &offset_color, double sim, long dir, long &x, - long &y) { - std::vector vfirst_color; +void ImageSearchService::parse_multi_color_args(const wstring &first_color, const wstring &offset_color, + std::vector &vfirst_color, + std::vector &voffset_cr) { str2colordfs(first_color, vfirst_color); + + // offset_color 兼容旧格式: x|y|颜色描述,多段之间用英文逗号分隔。 std::vector vseconds; split(offset_color, vseconds, L","); - std::vector voffset_cr; + voffset_cr.clear(); for (auto &it : vseconds) { size_t id1, id2; id1 = it.find(L'|'); @@ -239,30 +241,21 @@ long ImageSearchService::FindMultiColor(const wstring &first_color, const wstrin voffset_cr.push_back(tp); } } +} + +long ImageSearchService::FindMultiColor(const wstring &first_color, const wstring &offset_color, double sim, long dir, + long &x, long &y) { + std::vector vfirst_color; + std::vector voffset_cr; + parse_multi_color_args(first_color, offset_color, vfirst_color, voffset_cr); return ImageSearchAlgorithms::FindMultiColor(vfirst_color, voffset_cr, sim, dir, x, y); } long ImageSearchService::FindMultiColorEx(const wstring &first_color, const wstring &offset_color, double sim, long dir, - wstring &retstr) { + wstring &retstr) { std::vector vfirst_color; - str2colordfs(first_color, vfirst_color); - std::vector vseconds; - split(offset_color, vseconds, L","); std::vector voffset_cr; - for (auto &it : vseconds) { - size_t id1, id2; - id1 = it.find(L'|'); - id2 = (id1 == wstring::npos ? wstring::npos : it.find(L'|', id1 + 1)); - if (id2 != wstring::npos) { - pt_cr_df_t tp; - swscanf(it.c_str(), L"%d|%d", &tp.x, &tp.y); - if (id2 + 1 != it.length()) - str2colordfs(it.substr(id2 + 1), tp.crdfs); - else - break; - voffset_cr.push_back(tp); - } - } + parse_multi_color_args(first_color, offset_color, vfirst_color, voffset_cr); return ImageSearchAlgorithms::FindMultiColorEx(vfirst_color, voffset_cr, sim, dir, retstr); } // 图形定位 @@ -360,14 +353,20 @@ std::wstring ImageSearchService::GetDict(long idx, long font_index) { return dict->words[font_index].to_string(); } -long ImageSearchService::SetMemDict(int idx, void *data, long size) { - if (idx < 0 || idx >= _max_dict) +long ImageSearchService::SetMemDict(int idx, const void *data, long size) { + if (idx < 0 || idx >= _max_dict || !data || size <= 0) return 0; - auto &dict = _private_dicts[idx]; - dict.clear(); - dict.read_memory_dict_dm((const char *)data, size); - _private_dict_overrides[idx] = true; - return dict.empty() ? 0 : 1; + + auto dict = std::make_shared(); + if (!dict->read_memory_dict(data, static_cast(size)) || dict->empty()) + return 0; + + if (!store_global_file_dict(idx, dict)) + return 0; + + _private_dicts[idx].clear(); + _private_dict_overrides[idx] = false; + return 1; } long ImageSearchService::UseDict(int idx) { @@ -839,6 +838,9 @@ long ImageSearchService::LoadMemPic(const wstring &file_name, void *data, long s } long ImageSearchService::GetPicSize(const wstring &file_name, long *width, long *height) { + set_out(width, 0L); + set_out(height, 0L); + std::shared_ptr image; std::shared_ptr match; find_cached_pic(file_name, image, match); diff --git a/libop/image/ImageSearchService.h b/libop/image/ImageSearchService.h index 7f080f2..8c83a51 100644 --- a/libop/image/ImageSearchService.h +++ b/libop/image/ImageSearchService.h @@ -19,7 +19,8 @@ namespace op::image { */ class ImageSearchService : public ImageSearchAlgorithms { public: - const static int _max_dict = 10; + // 字库槽位对外范围为 0-99。 + const static int _max_dict = 100; ImageSearchService(); ~ImageSearchService(); @@ -51,7 +52,7 @@ class ImageSearchService : public ImageSearchAlgorithms { long GetColorNum(const wstring &color, double sim); - long SetMemDict(int idx, void *data, long size); + long SetMemDict(int idx, const void *data, long size); long SetDict(int idx, const wstring &file); @@ -127,7 +128,7 @@ class ImageSearchService : public ImageSearchAlgorithms { void str2binaryfbk(const wstring &color); private: - // SetMemDict/AddDict 写入对象私有槽;SetDict 写入全局文件字库槽。 + // SetDict/SetMemDict 写入全局字库槽;AddDict/ClearDict 写入对象私有槽。 Dictionary _private_dicts[_max_dict]; bool _private_dict_overrides[_max_dict]; // 当前字库索引 @@ -147,6 +148,8 @@ class ImageSearchService : public ImageSearchAlgorithms { // RETURN TYPE 0:word colors info; 1:bk color info int str2colordfs(const wstring &color_str, std::vector &colors); int str2colordfs(const wstring &color_str, std::vector &colors, std::vector *explicit_dfs); + void parse_multi_color_args(const wstring &first_color, const wstring &offset_color, + std::vector &vfirst_color, std::vector &voffset_cr); void str2binaryfbk(const wstring &color, double sim); void str2pointbinaryfbk(const wstring &color); void str2pointbinaryfbk(const wstring &color, double sim); diff --git a/libop/image/ImageView.h b/libop/image/ImageView.h index 5c17fac..ee6e529 100644 --- a/libop/image/ImageView.h +++ b/libop/image/ImageView.h @@ -1,6 +1,6 @@ #ifndef OP_IMAGE_IMAGE_VIEW_H_ #define OP_IMAGE_IMAGE_VIEW_H_ -#include "../runtime/Types.h" +#include "../base/Types.h" #include "../image/Image.h" namespace op { diff --git a/libop/input/InputMessageUtils.h b/libop/input/InputMessageUtils.h new file mode 100644 index 0000000..290a1ee --- /dev/null +++ b/libop/input/InputMessageUtils.h @@ -0,0 +1,12 @@ +#pragma once + +#include "../base/Types.h" + +namespace op::input::message { + +// 键鼠的窗口消息都用同一套超时发送,避免目标窗口卡住时脚本一起挂住。 +inline long SendTimeout(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { + return ::SendMessageTimeout(hwnd, message, wparam, lparam, SMTO_BLOCK, 2000, nullptr) ? 1L : 0L; +} + +} // namespace op::input::message diff --git a/libop/input/keyboard/DxKeyboard.cpp b/libop/input/keyboard/DxKeyboard.cpp index 575fddf..e273001 100644 --- a/libop/input/keyboard/DxKeyboard.cpp +++ b/libop/input/keyboard/DxKeyboard.cpp @@ -1,54 +1,14 @@ #include "DxKeyboard.h" +#include "KeyMessageUtils.h" #include "../../hook/HookProtocol.h" #include "../../hook/InputHookClient.h" -#include "../../runtime/AutomationModes.h" -#include "../../runtime/RuntimeUtils.h" +#include "../../base/AutomationModes.h" +#include "../../base/Utils.h" namespace input_hook_client = op::hook::input_hook_client; namespace { -long send_input_message(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { - return ::SendMessageTimeout(hwnd, message, wparam, lparam, SMTO_BLOCK, 2000, nullptr) ? 1L : 0L; -} - -bool is_extended_vk(long vk_code) { - switch (vk_code) { - case VK_RMENU: - case VK_RCONTROL: - case VK_INSERT: - case VK_DELETE: - case VK_HOME: - case VK_END: - case VK_PRIOR: - case VK_NEXT: - case VK_LEFT: - case VK_RIGHT: - case VK_UP: - case VK_DOWN: - case VK_NUMLOCK: - case VK_SNAPSHOT: - case VK_DIVIDE: - case VK_APPS: - case VK_LWIN: - case VK_RWIN: - return true; - default: - return false; - } -} - -LPARAM key_lparam(long vk_code, bool key_up) { - DWORD value = 1; - const WORD scan_code = static_cast(::MapVirtualKey(vk_code, MAPVK_VK_TO_VSC)); - value |= static_cast(scan_code) << 16; - if (is_extended_vk(vk_code)) - value |= 1u << 24; - if (key_up) - value |= 3u << 30; - return static_cast(value); -} - bool valid_vk(long vk_code) { return 0 <= vk_code && vk_code < 256; } @@ -90,7 +50,8 @@ long DxKeyboard::KeyDown(long vk_code) { if (!valid_vk(vk_code)) return 0; - const long ret = send_input_message(_hwnd, OP_WM_KEYDOWN, static_cast(vk_code), key_lparam(vk_code, false)); + const long ret = message::SendTimeout(_hwnd, OP_WM_KEYDOWN, static_cast(vk_code), + key_message::BuildKeyLParam(static_cast(vk_code), false)); if (ret == 1) _keys[static_cast(vk_code)] = 0x80; return ret; @@ -100,7 +61,8 @@ long DxKeyboard::KeyUp(long vk_code) { if (!valid_vk(vk_code)) return 0; - const long ret = send_input_message(_hwnd, OP_WM_KEYUP, static_cast(vk_code), key_lparam(vk_code, true)); + const long ret = message::SendTimeout(_hwnd, OP_WM_KEYUP, static_cast(vk_code), + key_message::BuildKeyLParam(static_cast(vk_code), true)); if (ret == 1) _keys[static_cast(vk_code)] = 0; return ret; @@ -133,7 +95,7 @@ long DxKeyboard::KeyPress(long vk_code) { } long DxKeyboard::InputChar(wchar_t ch) { - return send_input_message(_hwnd, OP_WM_CHAR, static_cast(ch), 1); + return message::SendTimeout(_hwnd, OP_WM_CHAR, static_cast(ch), 1); } } // namespace op::input diff --git a/libop/input/keyboard/KeyMessageUtils.h b/libop/input/keyboard/KeyMessageUtils.h new file mode 100644 index 0000000..80553fe --- /dev/null +++ b/libop/input/keyboard/KeyMessageUtils.h @@ -0,0 +1,70 @@ +#pragma once + +#include "../InputMessageUtils.h" +#include "../../base/Types.h" + +namespace op::input::key_message { + +inline bool IsExtendedVirtualKey(UINT vk_code) { + switch (vk_code) { + case VK_RMENU: + case VK_RCONTROL: + case VK_INSERT: + case VK_DELETE: + case VK_HOME: + case VK_END: + case VK_PRIOR: + case VK_NEXT: + case VK_LEFT: + case VK_RIGHT: + case VK_UP: + case VK_DOWN: + case VK_NUMLOCK: + case VK_SNAPSHOT: + case VK_DIVIDE: + case VK_APPS: + case VK_LWIN: + case VK_RWIN: + return true; + default: + return false; + } +} + +inline WORD ScanCode(UINT vk_code) { + return static_cast((::MapVirtualKey(vk_code, MAPVK_VK_TO_VSC)) & 0xff); +} + +// Windows 键盘消息的 lParam 需要同时带扫描码、扩展键和按下/抬起状态。 +inline LPARAM BuildKeyLParam(UINT vk_code, bool key_up, bool alt_context = false) { + DWORD data = 1; + data |= static_cast(ScanCode(vk_code)) << 16; + if (IsExtendedVirtualKey(vk_code)) + data |= 1u << 24; + if (alt_context) + data |= 1u << 29; + if (key_up) + data |= 3u << 30; + return static_cast(data); +} + +// DirectInput 的扫描码和普通窗口消息略有差异,少数特殊键统一在这里处理。 +inline BYTE DirectInputScanCode(UINT vk_code) { + switch (vk_code) { + case VK_NUMLOCK: + return 0x45; + case VK_PAUSE: + return 0xC5; + case VK_SNAPSHOT: + return 0xB7; + default: + break; + } + + BYTE scan = static_cast(::MapVirtualKey(vk_code, MAPVK_VK_TO_VSC) & 0xff); + if (scan == 0) + return 0; + return IsExtendedVirtualKey(vk_code) ? static_cast(scan | 0x80) : scan; +} + +} // namespace op::input::key_message diff --git a/libop/input/keyboard/KeyboardBackend.cpp b/libop/input/keyboard/KeyboardBackend.cpp index f979928..9bc2cf1 100644 --- a/libop/input/keyboard/KeyboardBackend.cpp +++ b/libop/input/keyboard/KeyboardBackend.cpp @@ -1,7 +1,7 @@ // #include "stdafx.h" #include "KeyboardBackend.h" // #include "AutomationModes.h" -// #include "RuntimeUtils.h" +// #include "Utils.h" // // static uint oem_code(uint key){ // short code[256] = { 0 }; diff --git a/libop/input/keyboard/KeyboardBackend.h b/libop/input/keyboard/KeyboardBackend.h index 67bde7e..56a8b92 100644 --- a/libop/input/keyboard/KeyboardBackend.h +++ b/libop/input/keyboard/KeyboardBackend.h @@ -1,5 +1,5 @@ #pragma once -#include "../../runtime/Types.h" +#include "../../base/Types.h" namespace op::input { diff --git a/libop/input/keyboard/WinKeyboard.cpp b/libop/input/keyboard/WinKeyboard.cpp index 8c92cde..032b235 100644 --- a/libop/input/keyboard/WinKeyboard.cpp +++ b/libop/input/keyboard/WinKeyboard.cpp @@ -1,15 +1,10 @@ // #include "stdafx.h" #include "WinKeyboard.h" -#include "../../runtime/AutomationModes.h" -#include "../../runtime/RuntimeUtils.h" +#include "KeyMessageUtils.h" +#include "../../base/AutomationModes.h" +#include "../../base/Utils.h" #include -namespace { -long send_message_result(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { - return ::SendMessageTimeout(hwnd, message, wparam, lparam, SMTO_BLOCK, 2000, nullptr) ? 1L : 0L; -} -} - static unsigned int oem_code(unsigned int key) { short code[256] = {0}; code['q'] = 0x10; @@ -56,46 +51,6 @@ static bool is_shift_vk(long vk_code) { return vk_code == VK_SHIFT || vk_code == VK_LSHIFT || vk_code == VK_RSHIFT; } -static bool is_extended_vk(long vk_code) { - switch (vk_code) { - case VK_RMENU: - case VK_RCONTROL: - case VK_INSERT: - case VK_DELETE: - case VK_HOME: - case VK_END: - case VK_PRIOR: - case VK_NEXT: - case VK_LEFT: - case VK_RIGHT: - case VK_UP: - case VK_DOWN: - case VK_NUMLOCK: - case VK_SNAPSHOT: - case VK_DIVIDE: - case VK_APPS: - case VK_LWIN: - case VK_RWIN: - return true; - default: - return false; - } -} - -// 按键消息的 lParam 需要带扫描码、扩展键标志和按下/抬起状态。 -static LPARAM build_windows_key_lparam(long vk_code, bool key_up, bool extended, bool alt_context) { - DWORD data = 1; - const WORD scan_code = static_cast(::MapVirtualKey(vk_code, MAPVK_VK_TO_VSC)); - data |= static_cast(scan_code) << 16; - if (extended) - data |= 1u << 24; - if (alt_context) - data |= 1u << 29; - if (key_up) - data |= 3u << 30; - return static_cast(data); -} - // 按当前修饰键状态把虚拟键翻译成字符,供 WM_CHAR / WM_SYSCHAR 使用。 static bool translate_vk_to_text(long vk_code, bool shift_down, bool ctrl_down, bool alt_down, std::wstring &text) { BYTE key_state[256] = {0}; @@ -174,7 +129,7 @@ long WinKeyboard::KeyDown(long vk_code) { Input.ki.wScan = MapVirtualKey(vk_code, MAPVK_VK_TO_VSC); Input.ki.dwFlags = KEYEVENTF_SCANCODE; // 扫描码模式下,扩展键还需要补扩展键标志。 - if (is_extended_vk(vk_code)) + if (key_message::IsExtendedVirtualKey(static_cast(vk_code))) Input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; ret = ::SendInput(1, &Input, sizeof(INPUT)); if (ret == 0) @@ -183,13 +138,12 @@ long WinKeyboard::KeyDown(long vk_code) { } case INPUT_TYPE::IN_WINDOWS: { // windows 模式下补扩展键标志,并在 Alt 参与时切到系统键消息。 - const bool extended = is_extended_vk(vk_code); const bool use_system_message = is_alt_vk(vk_code) || _alt_down; const bool alt_context = _alt_down && !is_alt_vk(vk_code); const UINT message = use_system_message ? WM_SYSKEYDOWN : WM_KEYDOWN; - const LPARAM lparam = build_windows_key_lparam(vk_code, false, extended, alt_context); + const LPARAM lparam = key_message::BuildKeyLParam(static_cast(vk_code), false, alt_context); - ret = send_message_result(_hwnd, message, vk_code, lparam); + ret = message::SendTimeout(_hwnd, message, vk_code, lparam); if (ret == 0) setlog("error code=%d", GetLastError()); else { @@ -234,7 +188,7 @@ long WinKeyboard::KeyUp(long vk_code) { Input.ki.wScan = MapVirtualKey(vk_code, MAPVK_VK_TO_VSC); Input.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP; // 抬键时保持和按下阶段一致的扩展键标志。 - if (is_extended_vk(vk_code)) + if (key_message::IsExtendedVirtualKey(static_cast(vk_code))) Input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; ret = ::SendInput(1, &Input, sizeof(INPUT)); if (ret == 0) @@ -244,13 +198,12 @@ long WinKeyboard::KeyUp(long vk_code) { case INPUT_TYPE::IN_WINDOWS: { // 抬键时保持和按下阶段一致的消息类型与 lParam 位语义。 - const bool extended = is_extended_vk(vk_code); const bool use_system_message = is_alt_vk(vk_code) || _alt_down; const bool alt_context = _alt_down && !is_alt_vk(vk_code); const UINT message = use_system_message ? WM_SYSKEYUP : WM_KEYUP; - const LPARAM lparam = build_windows_key_lparam(vk_code, true, extended, alt_context); + const LPARAM lparam = key_message::BuildKeyLParam(static_cast(vk_code), true, alt_context); - ret = send_message_result(_hwnd, message, vk_code, lparam); + ret = message::SendTimeout(_hwnd, message, vk_code, lparam); if (ret == 0) setlog("error code=%d", GetLastError()); else { @@ -304,7 +257,7 @@ long WinKeyboard::KeyPress(long vk_code) { if (translate_vk_to_text(vk_code, _shift_down, _ctrl_down, _alt_down, text)) { const UINT char_message = _alt_down ? WM_SYSCHAR : WM_CHAR; for (wchar_t ch : text) - ::SendMessageTimeout(_hwnd, char_message, ch, 1, SMTO_BLOCK, 2000, nullptr); + message::SendTimeout(_hwnd, char_message, ch, 1); } ::Delay(KEYPAD_WINDOWS_DELAY); break; @@ -327,7 +280,7 @@ long WinKeyboard::InputChar(wchar_t ch) { return ::SendInput(2, inputs, sizeof(INPUT)) == 2 ? 1 : 0; } case INPUT_TYPE::IN_WINDOWS: - return send_message_result(_hwnd, WM_CHAR, static_cast(ch), 1); + return message::SendTimeout(_hwnd, WM_CHAR, static_cast(ch), 1); } return 0; } diff --git a/libop/input/mouse/DxMouse.cpp b/libop/input/mouse/DxMouse.cpp index 3f23983..db5babe 100644 --- a/libop/input/mouse/DxMouse.cpp +++ b/libop/input/mouse/DxMouse.cpp @@ -1,18 +1,13 @@ #include "DxMouse.h" #include "CursorShape.h" +#include "../InputMessageUtils.h" #include "../../hook/HookProtocol.h" #include "../../hook/InputHookClient.h" -#include "../../runtime/AutomationModes.h" -#include "../../runtime/RuntimeUtils.h" +#include "../../base/AutomationModes.h" +#include "../../base/Utils.h" namespace input_hook_client = op::hook::input_hook_client; -namespace { -long send_op_message(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { - return ::SendMessageTimeout(hwnd, message, wparam, lparam, SMTO_BLOCK, 2000, nullptr) ? 1L : 0L; -} -} - namespace op::input { DxMouse::DxMouse() { @@ -79,7 +74,7 @@ long DxMouse::MoveR(int rx, int ry) { long DxMouse::MoveTo(int x, int y) { const POINT pt{x, y}; - long ret = send_op_message(_hwnd, OP_WM_MOUSEMOVE, button_state(), MAKELPARAM(pt.x, pt.y)); + long ret = message::SendTimeout(_hwnd, OP_WM_MOUSEMOVE, button_state(), MAKELPARAM(pt.x, pt.y)); _x = pt.x, _y = pt.y; return ret; @@ -88,7 +83,7 @@ long DxMouse::MoveTo(int x, int y) { long DxMouse::send_button(UINT message, WPARAM button, bool down) { const POINT pt = current_client_point(); const WPARAM state = button_state_with(button, down); - const long ret = send_op_message(_hwnd, message, state, MAKELPARAM(pt.x, pt.y)); + const long ret = message::SendTimeout(_hwnd, message, state, MAKELPARAM(pt.x, pt.y)); if (ret) set_button_state(button, down); return ret; @@ -97,8 +92,8 @@ long DxMouse::send_button(UINT message, WPARAM button, bool down) { long DxMouse::send_xbutton(UINT message, WORD xbutton, WPARAM button, bool down) { const POINT pt = current_client_point(); const WPARAM state = button_state_with(button, down); - const long ret = send_op_message(_hwnd, message, MAKEWPARAM(static_cast(state), xbutton), - MAKELPARAM(pt.x, pt.y)); + const long ret = + message::SendTimeout(_hwnd, message, MAKEWPARAM(static_cast(state), xbutton), MAKELPARAM(pt.x, pt.y)); if (ret) set_button_state(button, down); return ret; @@ -114,7 +109,7 @@ long DxMouse::click(long (DxMouse::*down)(), long (DxMouse::*up)()) { long DxMouse::send_double_click(UINT message, UINT up_message, WPARAM button) { const POINT pt = current_client_point(); const WPARAM state = button_state_with(button, true); - const long r1 = send_op_message(_hwnd, message, state, MAKELPARAM(pt.x, pt.y)); + const long r1 = message::SendTimeout(_hwnd, message, state, MAKELPARAM(pt.x, pt.y)); if (r1) set_button_state(button, true); ::Delay(MOUSE_DX_DELAY); @@ -144,8 +139,9 @@ long DxMouse::xbutton_double_click(long (DxMouse::*click_func)(), WORD xbutton_i long DxMouse::wheel(UINT message, int delta) { const POINT pt = current_client_point(); - return send_op_message(_hwnd, message, MAKEWPARAM(static_cast(button_state()), static_cast(delta)), - MAKELPARAM(pt.x, pt.y)); + return message::SendTimeout(_hwnd, message, + MAKEWPARAM(static_cast(button_state()), static_cast(delta)), + MAKELPARAM(pt.x, pt.y)); } long DxMouse::LeftClick() { diff --git a/libop/input/mouse/DxMouse.h b/libop/input/mouse/DxMouse.h index 4236c1c..97cd068 100644 --- a/libop/input/mouse/DxMouse.h +++ b/libop/input/mouse/DxMouse.h @@ -1,5 +1,5 @@ #pragma once -#include "../../runtime/Types.h" +#include "../../base/Types.h" #include "WinMouse.h" namespace op::input { diff --git a/libop/input/mouse/WinMouse.cpp b/libop/input/mouse/WinMouse.cpp index b245a18..a99aed5 100644 --- a/libop/input/mouse/WinMouse.cpp +++ b/libop/input/mouse/WinMouse.cpp @@ -1,18 +1,208 @@ // #include "stdafx.h" #include "WinMouse.h" #include "CursorShape.h" -#include "../../runtime/AutomationModes.h" -#include "../../runtime/RuntimeUtils.h" +#include "../InputMessageUtils.h" +#include "../../base/AutomationModes.h" +#include "../../base/Utils.h" +#include +#include +#include +#include +#include +#include +#include +#include namespace { -long send_message_result(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { - return ::SendMessageTimeout(hwnd, message, wparam, lparam, SMTO_BLOCK, 2000, nullptr) ? 1L : 0L; +double point_distance(POINT a, POINT b) { + const double dx = static_cast(b.x - a.x); + const double dy = static_cast(b.y - a.y); + return std::sqrt(dx * dx + dy * dy); +} + +int movement_steps(POINT from, POINT to, int duration) { + const double distance = point_distance(from, to); + const int by_distance = static_cast(std::ceil(distance / 10.0)); + const int by_duration = duration > 0 ? static_cast(std::ceil(duration / 8.0)) : 0; + int steps = by_distance; + steps = (std::max)(steps, by_duration); + steps = (std::max)(steps, 3); + return std::clamp(steps, 3, 120); +} + +double smoothstep(double t) { + return t * t * (3.0 - 2.0 * t); +} + +double random_signed_unit() { + return (static_cast(rand()) / static_cast(RAND_MAX)) * 2.0 - 1.0; +} + +int random_offset(int value) { + if (value == 0) + return 0; + const int span = value == INT_MIN ? INT_MAX : std::abs(value); + const int offset = rand() % span; + return value > 0 ? offset : -offset; +} + +POINT bezier_point(POINT p0, POINT p1, POINT p2, POINT p3, double t) { + const double u = 1.0 - t; + const double uu = u * u; + const double tt = t * t; + const double x = uu * u * p0.x + 3.0 * uu * t * p1.x + 3.0 * u * tt * p2.x + tt * t * p3.x; + const double y = uu * u * p0.y + 3.0 * uu * t * p1.y + 3.0 * u * tt * p2.y + tt * t * p3.y; + return POINT{static_cast(std::lround(x)), static_cast(std::lround(y))}; +} + +std::vector build_linear_path(POINT from, POINT to, int duration) { + if (point_distance(from, to) < 1.0) + return {to}; + + std::vector path; + const int steps = movement_steps(from, to, duration); + path.reserve(static_cast(steps)); + POINT last{LONG_MIN, LONG_MIN}; + for (int i = 1; i <= steps; ++i) { + const double t = smoothstep(static_cast(i) / static_cast(steps)); + POINT pt{static_cast(std::lround(from.x + (to.x - from.x) * t)), + static_cast(std::lround(from.y + (to.y - from.y) * t))}; + if (pt.x != last.x || pt.y != last.y) { + path.push_back(pt); + last = pt; + } + } + if (path.empty() || path.back().x != to.x || path.back().y != to.y) + path.push_back(to); + return path; +} + +std::vector build_smooth_path(POINT from, POINT to, int duration, int jitter) { + const double distance = point_distance(from, to); + if (distance < 1.0) + return {to}; + + const double dx = static_cast(to.x - from.x); + const double dy = static_cast(to.y - from.y); + const double nx = -dy / distance; + const double ny = dx / distance; + const double raw_bend = distance * static_cast(jitter) / 100.0; + const double bend = raw_bend > 0.0 ? std::clamp(raw_bend, 3.0, 80.0) : 0.0; + const double bend1 = bend * random_signed_unit(); + const double bend2 = bend * random_signed_unit(); + + // 控制点只做轻微偏移,保留方向感,同时避免完全笔直的机械轨迹。 + POINT c1{static_cast(std::lround(from.x + dx * 0.35 + nx * bend1)), + static_cast(std::lround(from.y + dy * 0.35 + ny * bend1))}; + POINT c2{static_cast(std::lround(from.x + dx * 0.70 + nx * bend2)), + static_cast(std::lround(from.y + dy * 0.70 + ny * bend2))}; + + std::vector path; + const int steps = movement_steps(from, to, duration); + path.reserve(static_cast(steps)); + POINT last{LONG_MIN, LONG_MIN}; + for (int i = 1; i <= steps; ++i) { + const double t = smoothstep(static_cast(i) / static_cast(steps)); + POINT pt = bezier_point(from, c1, c2, to, t); + if (pt.x != last.x || pt.y != last.y) { + path.push_back(pt); + last = pt; + } + } + if (path.empty() || path.back().x != to.x || path.back().y != to.y) + path.push_back(to); + return path; +} + +std::vector build_mouse_path(POINT from, POINT to, int duration, int mode, int jitter) { + if (mode == 1) + return build_linear_path(from, to, duration); + return build_smooth_path(from, to, duration, jitter); +} + +bool parse_path_point(const std::wstring &text, POINT &pt) { + std::wistringstream stream(text); + long x = 0; + long y = 0; + wchar_t comma = 0; + if (!(stream >> x >> comma >> y) || comma != L',') + return false; + while (stream && std::iswspace(stream.peek())) + stream.get(); + if (!stream.eof()) + return false; + pt = POINT{static_cast(x), static_cast(y)}; + return true; +} + +bool parse_mouse_path(const std::wstring &path_text, std::vector &path) { + path.clear(); + size_t start = 0; + while (start <= path_text.size()) { + const size_t end = path_text.find(L'|', start); + const std::wstring item = path_text.substr(start, end == std::wstring::npos ? std::wstring::npos : end - start); + POINT pt{}; + if (!parse_path_point(item, pt)) + return false; + path.push_back(pt); + if (end == std::wstring::npos) + break; + start = end + 1; + } + return path.size() >= 2; +} + +std::vector expand_mouse_path(const std::vector &key_points) { + if (key_points.empty()) + return {}; + + std::vector path; + path.push_back(key_points.front()); + for (size_t i = 1; i < key_points.size(); ++i) { + const POINT from = key_points[i - 1]; + const POINT to = key_points[i]; + const int steps = std::clamp(static_cast(std::ceil(point_distance(from, to) / 10.0)), 1, 60); + POINT last = path.back(); + for (int step = 1; step <= steps; ++step) { + const double t = static_cast(step) / static_cast(steps); + POINT pt{static_cast(std::lround(from.x + (to.x - from.x) * t)), + static_cast(std::lround(from.y + (to.y - from.y) * t))}; + if (pt.x != last.x || pt.y != last.y) { + path.push_back(pt); + last = pt; + } + } + } + return path; +} + +long run_mouse_path(const std::vector &path, int duration, + const std::function &move_to_point) { + if (path.empty() || duration < 0) + return 0; + + const int delay = duration > 0 && path.size() > 1 ? duration / static_cast(path.size() - 1) : 0; + for (size_t i = 0; i < path.size(); ++i) { + if (!move_to_point(path[i])) + return 0; + if (delay > 0 && i + 1 < path.size()) + ::Delay(delay); + } + return 1; +} + +void delay_if_needed(int delay) { + if (delay > 0) + ::Delay(delay); } } namespace op::input { -WinMouse::WinMouse() : _hwnd(NULL), _mode(0), _x(0), _y(0), _button_state(0) { +WinMouse::WinMouse() + : _hwnd(NULL), _mode(0), _x(0), _y(0), _button_state(0), _trajectory_mode(0), + _trajectory_min_duration(0), _trajectory_max_duration(0), _trajectory_jitter(18), + _trajectory_start_delay(0), _trajectory_end_delay(0) { } WinMouse::~WinMouse() { @@ -103,7 +293,7 @@ long WinMouse::MoveTo(int x, int y) { break; } case INPUT_TYPE::IN_WINDOWS: { - ret = send_message_result(_hwnd, WM_MOUSEMOVE, button_state(), MAKELPARAM(client_pt.x, client_pt.y)); + ret = message::SendTimeout(_hwnd, WM_MOUSEMOVE, button_state(), MAKELPARAM(client_pt.x, client_pt.y)); break; } } @@ -158,7 +348,7 @@ long WinMouse::send_input_click(DWORD down_flags, DWORD up_flags, DWORD mouse_da long WinMouse::send_windows_button(UINT message, WPARAM button, bool down) { const POINT pt = current_client_point(); const WPARAM state = button_state_with(button, down); - const long ret = send_message_result(_hwnd, message, state, MAKELPARAM(pt.x, pt.y)); + const long ret = message::SendTimeout(_hwnd, message, state, MAKELPARAM(pt.x, pt.y)); if (ret) set_button_state(button, down); return ret; @@ -167,8 +357,8 @@ long WinMouse::send_windows_button(UINT message, WPARAM button, bool down) { long WinMouse::send_windows_xbutton(UINT message, WORD xbutton, WPARAM button, bool down) { const POINT pt = current_client_point(); const WPARAM state = button_state_with(button, down); - const long ret = send_message_result(_hwnd, message, MAKEWPARAM(static_cast(state), xbutton), - MAKELPARAM(pt.x, pt.y)); + const long ret = + message::SendTimeout(_hwnd, message, MAKEWPARAM(static_cast(state), xbutton), MAKELPARAM(pt.x, pt.y)); if (ret) set_button_state(button, down); return ret; @@ -194,7 +384,7 @@ long WinMouse::button_double_click(long (WinMouse::*click)(), UINT message, UINT ::Delay(delay); const POINT pt = current_client_point(); const WPARAM state = button_state_with(button, true); - const long r2 = send_message_result(_hwnd, message, state, MAKELPARAM(pt.x, pt.y)); + const long r2 = message::SendTimeout(_hwnd, message, state, MAKELPARAM(pt.x, pt.y)); if (r2) set_button_state(button, true); ::Delay(delay); @@ -228,28 +418,123 @@ long WinMouse::send_wheel(DWORD input_flag, UINT window_message, int delta) { case INPUT_TYPE::IN_WINDOWS: { POINT pt = current_client_point(); ::ClientToScreen(_hwnd, &pt); - return send_message_result(_hwnd, window_message, - MAKEWPARAM(static_cast(button_state()), static_cast(delta)), - MAKELPARAM(pt.x, pt.y)); + return message::SendTimeout(_hwnd, window_message, + MAKEWPARAM(static_cast(button_state()), static_cast(delta)), + MAKELPARAM(pt.x, pt.y)); } } return 0; } long WinMouse::MoveToEx(int x, int y, int w, int h, int &dst_x, int &dst_y) { - auto random_offset = [](int value) { - if (value == 0) - return 0; - const int span = std::abs(value); - const int offset = rand() % span; - return value > 0 ? offset : -offset; - }; - dst_x = x + random_offset(w); dst_y = y + random_offset(h); return MoveTo(dst_x, dst_y); } +int WinMouse::resolve_trajectory_duration(int duration) const { + if (duration < 0) + return -1; + + int resolved = duration > 0 ? duration : _trajectory_min_duration; + resolved = (std::max)(resolved, _trajectory_min_duration); + if (_trajectory_max_duration > 0) + resolved = (std::min)(resolved, _trajectory_max_duration); + return resolved; +} + +long WinMouse::MoveToSmooth(int x, int y, int duration) { + const int resolved_duration = resolve_trajectory_duration(duration); + if (resolved_duration < 0) + return 0; + + POINT from = current_client_point(); + if (_mode == INPUT_TYPE::IN_NORMAL) { + long current_x = 0; + long current_y = 0; + if (GetCursorPos(current_x, current_y)) { + from.x = static_cast(current_x); + from.y = static_cast(current_y); + } + } + + const POINT to{x, y}; + const std::vector path = + build_mouse_path(from, to, resolved_duration, _trajectory_mode, _trajectory_jitter); + delay_if_needed(_trajectory_start_delay); + const long ret = run_mouse_path(path, resolved_duration, [this](POINT pt) { return MoveTo(pt.x, pt.y); }); + if (ret) + delay_if_needed(_trajectory_end_delay); + return ret; +} + +long WinMouse::MoveToExSmooth(int x, int y, int w, int h, int duration, int &dst_x, int &dst_y) { + dst_x = x + random_offset(w); + dst_y = y + random_offset(h); + return MoveToSmooth(dst_x, dst_y, duration); +} + +long WinMouse::MovePath(const std::wstring &path_text, int duration) { + std::vector key_points; + const int resolved_duration = resolve_trajectory_duration(duration); + if (resolved_duration < 0 || !parse_mouse_path(path_text, key_points)) + return 0; + + // MovePath 接收的是关键点,段内补点后再发送,避免长距离两点之间直接跳过去。 + const std::vector path = expand_mouse_path(key_points); + if (path.size() < 2) + return 0; + delay_if_needed(_trajectory_start_delay); + const long ret = run_mouse_path(path, resolved_duration, [this](POINT pt) { return MoveTo(pt.x, pt.y); }); + if (ret) + delay_if_needed(_trajectory_end_delay); + return ret; +} + +long WinMouse::DragPath(const std::wstring &path_text, int duration) { + std::vector key_points; + const int resolved_duration = resolve_trajectory_duration(duration); + if (resolved_duration < 0 || !parse_mouse_path(path_text, key_points)) + return 0; + + const std::vector path = expand_mouse_path(key_points); + if (path.size() < 2) + return 0; + if (!MoveTo(path.front().x, path.front().y)) + return 0; + + const long down_ret = LeftDown(); + if (!down_ret) + return 0; + + delay_if_needed(_trajectory_start_delay); + std::vector moving_path(path.begin() + 1, path.end()); + const long move_ret = + run_mouse_path(moving_path, resolved_duration, [this](POINT pt) { return MoveTo(pt.x, pt.y); }); + // 拖拽到终点后先停一下再松手,更接近按住后确认落点的操作习惯。 + delay_if_needed(_trajectory_end_delay); + const long up_ret = LeftUp(); + return move_ret && up_ret ? 1 : 0; +} + +long WinMouse::SetMouseTrajectory(int mode, int min_duration, int max_duration, int jitter, int start_delay, + int end_delay) { + if (mode < 0 || mode > 2 || min_duration < 0 || max_duration < 0 || jitter < 0 || jitter > 100 || + start_delay < 0 || end_delay < 0) + return 0; + if (max_duration > 0 && min_duration > max_duration) + return 0; + + // max_duration 为 0 表示不封顶,旧脚本传入的 duration 会按原样生效。 + _trajectory_mode = mode; + _trajectory_min_duration = min_duration; + _trajectory_max_duration = max_duration; + _trajectory_jitter = jitter; + _trajectory_start_delay = start_delay; + _trajectory_end_delay = end_delay; + return 1; +} + long WinMouse::LeftClick() { switch (_mode) { case INPUT_TYPE::IN_NORMAL: { diff --git a/libop/input/mouse/WinMouse.h b/libop/input/mouse/WinMouse.h index 8d101ff..ed22d3f 100644 --- a/libop/input/mouse/WinMouse.h +++ b/libop/input/mouse/WinMouse.h @@ -1,5 +1,5 @@ #pragma once -#include "../../runtime/Types.h" +#include "../../base/Types.h" #include namespace op::input { @@ -23,6 +23,17 @@ class WinMouse { virtual long MoveToEx(int x, int y, int w, int h, int &dst_x, int &dst_y); + virtual long MoveToSmooth(int x, int y, int duration); + + virtual long MoveToExSmooth(int x, int y, int w, int h, int duration, int &dst_x, int &dst_y); + + virtual long MovePath(const std::wstring &path, int duration); + + virtual long DragPath(const std::wstring &path, int duration); + + virtual long SetMouseTrajectory(int mode, int min_duration, int max_duration, int jitter, int start_delay, + int end_delay); + virtual long LeftClick(); virtual long LeftDoubleClick(); @@ -87,11 +98,18 @@ class WinMouse { long xbutton(WORD xbutton, WPARAM button, bool down); long xbutton_double_click(long (WinMouse::*click)(), WORD xbutton, WPARAM button, long delay); long send_wheel(DWORD input_flag, UINT window_message, int delta); + int resolve_trajectory_duration(int duration) const; HWND _hwnd; int _mode; int _x, _y; WPARAM _button_state; + int _trajectory_mode; + int _trajectory_min_duration; + int _trajectory_max_duration; + int _trajectory_jitter; + int _trajectory_start_delay; + int _trajectory_end_delay; }; } // namespace op::input diff --git a/libop/ipc/Pipe.cpp b/libop/ipc/Pipe.cpp index 90d9e4b..e0c618d 100644 --- a/libop/ipc/Pipe.cpp +++ b/libop/ipc/Pipe.cpp @@ -1,8 +1,8 @@ // #include "stdafx.h" #include "Pipe.h" -#include "../runtime/AutomationModes.h" -#include "../runtime/RuntimeUtils.h" -#include "../runtime/WindowsHandle.h" +#include "../base/AutomationModes.h" +#include "../base/Utils.h" +#include "../base/WindowsHandle.h" #include #include #include diff --git a/libop/ipc/ProcessMutex.h b/libop/ipc/ProcessMutex.h index dcb83d2..aa68f17 100644 --- a/libop/ipc/ProcessMutex.h +++ b/libop/ipc/ProcessMutex.h @@ -1,5 +1,5 @@ #pragma once -#include "../runtime/WindowsHandle.h" +#include "../base/WindowsHandle.h" #include #include #include diff --git a/libop/ipc/SharedMemory.h b/libop/ipc/SharedMemory.h index ff09b4e..a81dcd1 100644 --- a/libop/ipc/SharedMemory.h +++ b/libop/ipc/SharedMemory.h @@ -1,5 +1,5 @@ #pragma once -#include "../runtime/WindowsHandle.h" +#include "../base/WindowsHandle.h" #include #include #include diff --git a/libop/memory/ProcessMemory.h b/libop/memory/ProcessMemory.h index f6c0db7..8b2059b 100644 --- a/libop/memory/ProcessMemory.h +++ b/libop/memory/ProcessMemory.h @@ -1,7 +1,7 @@ #pragma once #ifndef OP_MEMORY_PROCESS_MEMORY_H_ #define OP_MEMORY_PROCESS_MEMORY_H_ -#include "../runtime/RuntimeUtils.h" +#include "../base/Utils.h" #include "BlackBone/Process/Process.h" #include #include diff --git a/libop/network/HttpClient.cpp b/libop/network/HttpClient.cpp index 247f3a8..1b73c28 100644 --- a/libop/network/HttpClient.cpp +++ b/libop/network/HttpClient.cpp @@ -1,5 +1,6 @@ #include "HttpClient.h" -#include "../runtime/RuntimeUtils.h" +#include "../base/JsonUtils.h" +#include "../base/Utils.h" #include #include #include @@ -229,47 +230,7 @@ bool http_post_json(const ParsedUrl &url, const std::string &body, int timeout_m } std::string json_unescape(const std::string &s) { - std::string out; - out.reserve(s.size()); - for (size_t i = 0; i < s.size(); ++i) { - if (s[i] != '\\') { - out.push_back(s[i]); - continue; - } - if (i + 1 >= s.size()) - break; - char c = s[++i]; - switch (c) { - case '"': - out.push_back('"'); - break; - case '\\': - out.push_back('\\'); - break; - case '/': - out.push_back('/'); - break; - case 'b': - out.push_back('\b'); - break; - case 'f': - out.push_back('\f'); - break; - case 'n': - out.push_back('\n'); - break; - case 'r': - out.push_back('\r'); - break; - case 't': - out.push_back('\t'); - break; - default: - out.push_back(c); - break; - } - } - return out; + return internal::json::UnescapeString(s); } // --- shared endpoint configuration --- diff --git a/libop/network/HttpClient.h b/libop/network/HttpClient.h index 1225830..f7b18e5 100644 --- a/libop/network/HttpClient.h +++ b/libop/network/HttpClient.h @@ -1,5 +1,5 @@ #pragma once -#include "../runtime/Types.h" +#include "../base/Types.h" #include #include #include diff --git a/libop/ocr/Dictionary.h b/libop/ocr/Dictionary.h index 9358a9f..4b3cc6d 100644 --- a/libop/ocr/Dictionary.h +++ b/libop/ocr/Dictionary.h @@ -1,10 +1,11 @@ #pragma once #ifndef OP_OCR_DICTIONARY_H_ #define OP_OCR_DICTIONARY_H_ -#include "../runtime/RuntimeUtils.h" +#include "../base/Utils.h" #include "Image.h" #include "BitFunctions.h" #include +#include #include #include #include @@ -319,6 +320,13 @@ inline bool parse_text_dict_entry(const std::wstring &s, word1_t &word) { } // namespace dict_entry_importer struct Dictionary { + // SetMemDict 没有文件名,不能靠后缀判断;这里按内存内容识别字库格式。 + enum class memory_format { + invalid, + op_binary, + text, + }; + // v0 v1 struct dict_info_t { __int16 _this_ver; // 0 1 @@ -333,11 +341,82 @@ struct Dictionary { Dictionary() { } std::vector words; + static bool read_bytes(const unsigned char *buf, size_t size, size_t &offset, void *out, size_t out_size) { + if (!buf || !out || offset > size || out_size > size - offset) + return false; + std::memcpy(out, buf + offset, out_size); + offset += out_size; + return true; + } + static bool valid_word_info(const word1_info &head) { + if (head.w == 0 || head.h == 0) + return false; + const size_t bit_count = static_cast(head.w) * static_cast(head.h); + return head.bit_cnt > 0 && static_cast(head.bit_cnt) <= bit_count; + } + // OP 二进制字库没有 magic,这里用头部校验和完整长度校验来避免文本误判。 + static bool is_binary_dict_memory(const void *data, size_t size) { + const auto *buf = static_cast(data); + size_t offset = 0; + dict_info_t file_info; + if (!read_bytes(buf, size, offset, &file_info, sizeof(file_info))) + return false; + if (file_info._word_count <= 0) + return false; + if (file_info._check_code != (file_info._this_ver ^ file_info._word_count)) + return false; + + const size_t word_count = static_cast(file_info._word_count); + if (file_info._this_ver == 0) { + if (word_count > (size - offset) / sizeof(word_t)) + return false; + for (size_t i = 0; i < word_count; ++i) { + word_t old_word; + if (!read_bytes(buf, size, offset, &old_word, sizeof(old_word))) + return false; + if (old_word.info.width <= 0 || old_word.info.height <= 0 || old_word.info.width > 255 || + old_word.info.height > 255 || old_word.info.bit_count <= 0 || + old_word.info.bit_count > old_word.info.width * old_word.info.height) + return false; + } + return offset == size; + } + + if (file_info._this_ver != 1) + return false; + + for (size_t i = 0; i < word_count; ++i) { + word1_info head; + if (!read_bytes(buf, size, offset, &head, sizeof(head))) + return false; + if (!valid_word_info(head)) + return false; + const size_t data_size = (static_cast(head.w) * static_cast(head.h) + 7u) / 8u; + if (offset > size || data_size > size - offset) + return false; + offset += data_size; + } + return offset == size; + } + // 先识别合法 OP 二进制字库;不符合时,再按文本字库内容处理。 + static memory_format detect_memory_format(const void *data, size_t size) { + if (!data || size == 0) + return memory_format::invalid; + if (is_binary_dict_memory(data, size)) + return memory_format::op_binary; + + const auto *buf = static_cast(data); + for (size_t i = 0; i < size; ++i) { + if (buf[i] == '$') + return memory_format::text; + } + return memory_format::invalid; + } void read_dict(const std::wstring &s) { if (s.empty()) return; - // SetDict 的入口:优先识别 OP 二进制 .dict,失败后尝试大漠文本字库。 + // SetDict 的入口:优先识别 OP 二进制 .dict;不符合时再按大漠文本字库读取。 if (read_binary_dict(s)) return; read_dict_dm(s); @@ -406,6 +485,57 @@ struct Dictionary { sort_dict(); return true; } + bool read_binary_dict_memory(const void *data, size_t size) { + clear(); + if (!is_binary_dict_memory(data, size)) + return false; + + const auto *buf = static_cast(data); + size_t offset = 0; + dict_info_t file_info; + if (!read_bytes(buf, size, offset, &file_info, sizeof(file_info))) + return false; + + info = file_info; + words.resize(static_cast(file_info._word_count)); + if (file_info._this_ver == 0) { + info._this_ver = 1; + word_t tmp; + for (size_t i = 0; i < words.size(); ++i) { + if (!read_bytes(buf, size, offset, &tmp, sizeof(tmp))) { + clear(); + return false; + } + words[i].from_word(tmp); + } + info._check_code = info._this_ver ^ info._word_count; + } else if (file_info._this_ver == 1) { + word1_info head; + for (size_t i = 0; i < words.size(); ++i) { + if (!read_bytes(buf, size, offset, &head, sizeof(head))) { + clear(); + return false; + } + words[i].info = head; + const size_t data_size = (static_cast(head.w) * static_cast(head.h) + 7u) / 8u; + words[i].data.resize(data_size); + if (!read_bytes(buf, size, offset, words[i].data.data(), data_size)) { + clear(); + return false; + } + } + } else { + clear(); + return false; + } + + if (offset != size) { + clear(); + return false; + } + sort_dict(); + return true; + } void read_dict_dm(const std::wstring &s) { clear(); std::fstream file; @@ -429,7 +559,7 @@ struct Dictionary { size_t idx1 = ss.find(L'$'); auto idx2 = ss.find(L'$', idx1 + 1); word1_t wd1; - // 文件导入只接受大漠文本格式;OP 三段文本只用于 AddDict/SetMemDict 单条导入。 + // 文件导入只接受大漠文本格式;OP 三段文本用于 AddDict 和内存文本字库。 if (idx1 != -1 && idx2 != -1 && dm_dict_compat::parse_dm_text_word(ss, wd1)) add_word(wd1); } @@ -463,6 +593,19 @@ struct Dictionary { } sort_dict(); } + bool read_memory_dict(const void *data, size_t size) { + // 内存入口支持完整 .dict 字节,也支持按行保存的文本字库。 + switch (detect_memory_format(data, size)) { + case memory_format::op_binary: + return read_binary_dict_memory(data, size); + case memory_format::text: + read_memory_dict_dm(static_cast(data), size); + return !empty(); + default: + clear(); + return false; + } + } bool write_dict(const std::wstring &s) { std::fstream file; diff --git a/libop/ocr/OcrService.cpp b/libop/ocr/OcrService.cpp index 59d180b..8cdefbf 100644 --- a/libop/ocr/OcrService.cpp +++ b/libop/ocr/OcrService.cpp @@ -1,6 +1,6 @@ #include "OcrService.h" #include "../network/HttpClient.h" -#include "../runtime/RuntimeUtils.h" +#include "../base/Utils.h" #include #include diff --git a/libop/ocr/OcrService.h b/libop/ocr/OcrService.h index a14a94d..d6b5ed5 100644 --- a/libop/ocr/OcrService.h +++ b/libop/ocr/OcrService.h @@ -1,5 +1,5 @@ #pragma once -#include "../runtime/Types.h" +#include "../base/Types.h" #include namespace op::ocr { diff --git a/libop/ocr/TesseractOcr.cpp b/libop/ocr/TesseractOcr.cpp index c36e3d9..bee8294 100644 --- a/libop/ocr/TesseractOcr.cpp +++ b/libop/ocr/TesseractOcr.cpp @@ -1,8 +1,8 @@ #include "TesseractOcr.h" -#include "../runtime/RuntimeUtils.h" +#include "../base/Utils.h" -#include "../runtime/RuntimeEnvironment.h" +#include "../base/Environment.h" #include diff --git a/libop/ocr/TesseractOcr.h b/libop/ocr/TesseractOcr.h index d6f9779..6d7261b 100644 --- a/libop/ocr/TesseractOcr.h +++ b/libop/ocr/TesseractOcr.h @@ -1,5 +1,5 @@ #pragma once -#include "../runtime/Types.h" +#include "../base/Types.h" namespace tesseract { class TessBaseAPI; }; diff --git a/libop/op/OpAlgorithm.cpp b/libop/op/OpAlgorithm.cpp index e66e5d8..81568bf 100644 --- a/libop/op/OpAlgorithm.cpp +++ b/libop/op/OpAlgorithm.cpp @@ -1,7 +1,7 @@ #include "OpContext.h" #include "algorithm/AStar.h" -#include "runtime/RuntimeUtils.h" +#include "base/Utils.h" #include diff --git a/libop/op/OpCaptureHelpers.h b/libop/op/OpCaptureHelpers.h new file mode 100644 index 0000000..c566158 --- /dev/null +++ b/libop/op/OpCaptureHelpers.h @@ -0,0 +1,51 @@ +#pragma once + +#include "OpContext.h" +#include "base/Utils.h" + +#include + +namespace op::internal { + +template +void capture_region(OpContext *context, long x, long y, long width, long height, Fn &&fn) { + if (!context) + return; + + if (!context->bkproc.requestCapture(x, y, width, height, context->image_proc._src)) { + setlog("error requestCapture"); + return; + } + + // 截图偏移必须和成功捕获后的坐标保持一致,后续找图、找色会用它还原窗口坐标。 + context->image_proc.set_offset(x, y); + std::forward(fn)(); +} + +template +void capture_converted_region(OpContext *context, long x1, long y1, long x2, long y2, Fn &&fn) { + // 这里的坐标已经过 RectConvert,直接作为截图偏移使用。 + capture_region(context, x1, y1, x2 - x1, y2 - y1, std::forward(fn)); +} + +template +void with_captured_region(OpContext *context, long &x1, long &y1, long &x2, long &y2, long width, long height, + Fn &&fn) { + if (!context || !context->bkproc.check_bind() || !context->bkproc.RectConvert(x1, y1, x2, y2)) + return; + + capture_region(context, x1, y1, width, height, std::forward(fn)); +} + +template +void with_captured_region(OpContext *context, long &x1, long &y1, long &x2, long &y2, Fn &&fn) { + if (!context || !context->bkproc.check_bind() || !context->bkproc.RectConvert(x1, y1, x2, y2)) + return; + + const long width = x2 - x1; + const long height = y2 - y1; + // 区域被裁剪后再设置偏移,调用方看到的仍是实际截图范围。 + capture_region(context, x1, y1, width, height, std::forward(fn)); +} + +} // namespace op::internal diff --git a/libop/op/OpContext.cpp b/libop/op/OpContext.cpp index 6f951a3..8f93b5e 100644 --- a/libop/op/OpContext.cpp +++ b/libop/op/OpContext.cpp @@ -1,6 +1,6 @@ #include "OpContext.h" -#include "runtime/RuntimeEnvironment.h" +#include "base/Environment.h" #include #include diff --git a/libop/op/OpImage.cpp b/libop/op/OpImage.cpp index 06b2605..e82f809 100644 --- a/libop/op/OpImage.cpp +++ b/libop/op/OpImage.cpp @@ -1,8 +1,9 @@ #include "OpContext.h" +#include "OpCaptureHelpers.h" #include "OpResult.h" #include "capture/FrameInfo.h" -#include "runtime/RuntimeUtils.h" +#include "base/Utils.h" #include @@ -40,29 +41,18 @@ void op::Op::Capture(long x1, long y1, long x2, long y2, const wchar_t *file_nam internal::set_result(ret, 0L); - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x1, y1, x2, y2)) { - if (!m_context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, m_context->image_proc._src)) { - setlog("error requestCapture"); - } else { - m_context->image_proc.set_offset(x1, y1); - - internal::set_result(ret, m_context->image_proc.Capture(file_name)); - } - } + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + internal::set_result(ret, m_context->image_proc.Capture(file_name)); + }); } // 比较指定坐标点(x,y)的颜色 void op::Op::CmpColor(long x, long y, const wchar_t *color, double sim, long *ret) { // LONG rx = -1, ry = -1; long tx = x + small_block_size, ty = y + small_block_size; internal::set_result(ret, 0L); - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x, y, tx, ty)) { - if (!m_context->bkproc.requestCapture(x, y, small_block_size, small_block_size, m_context->image_proc._src)) { - setlog("error requestCapture"); - } else { - m_context->image_proc.set_offset(x, y); - internal::set_result(ret, m_context->image_proc.CmpColor(x, y, color, sim)); - } - } + internal::with_captured_region(m_context.get(), x, y, tx, ty, small_block_size, small_block_size, [&]() { + internal::set_result(ret, m_context->image_proc.CmpColor(x, y, color, sim)); + }); } // 查找指定区域内的颜色 void op::Op::FindColor(long x1, long y1, long x2, long y2, const wchar_t *color, double sim, long dir, long *x, long *y, @@ -74,30 +64,20 @@ void op::Op::FindColor(long x1, long y1, long x2, long y2, const wchar_t *color, internal::set_result(x, found_x); internal::set_result(y, found_y); - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x1, y1, x2, y2)) { - if (!m_context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, m_context->image_proc._src)) { - setlog("error requestCapture"); - } else { - m_context->image_proc.set_offset(x1, y1); - internal::set_result(ret, m_context->image_proc.FindColor(color, sim, dir, found_x, found_y)); - internal::set_result(x, found_x); - internal::set_result(y, found_y); - } - } + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + internal::set_result(ret, m_context->image_proc.FindColor(color, sim, dir, found_x, found_y)); + internal::set_result(x, found_x); + internal::set_result(y, found_y); + }); } // 查找指定区域内的所有颜色 void op::Op::FindColorEx(long x1, long y1, long x2, long y2, const wchar_t *color, double sim, long dir, std::wstring &retstr) { // wstring str; retstr.clear(); - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x1, y1, x2, y2)) { - if (!m_context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, m_context->image_proc._src)) { - setlog("error requestCapture"); - } else { - m_context->image_proc.set_offset(x1, y1); - m_context->image_proc.FindColorEx(color, sim, dir, retstr); - } - } + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + m_context->image_proc.FindColorEx(color, sim, dir, retstr); + }); } // 根据指定的多点查找颜色坐标 void op::Op::FindMultiColor(long x1, long y1, long x2, long y2, const wchar_t *first_color, const wchar_t *offset_color, @@ -109,37 +89,27 @@ void op::Op::FindMultiColor(long x1, long y1, long x2, long y2, const wchar_t *f internal::set_result(x, found_x); internal::set_result(y, found_y); - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x1, y1, x2, y2)) { - if (!m_context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, m_context->image_proc._src)) { - setlog("error requestCapture"); - } else { - m_context->image_proc.set_offset(x1, y1); - internal::set_result(ret, - m_context->image_proc.FindMultiColor(first_color, offset_color, sim, dir, found_x, - found_y)); - internal::set_result(x, found_x); - internal::set_result(y, found_y); - } + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + internal::set_result(ret, + m_context->image_proc.FindMultiColor(first_color, offset_color, sim, dir, found_x, + found_y)); + internal::set_result(x, found_x); + internal::set_result(y, found_y); + }); - /*if (*ret) { + /*if (*ret) { rx += x1; ry += y1; rx -= m_context->bkproc._capture->get_client_x(); ry -= m_context->bkproc._capture->get_client_y(); }*/ - } } // 根据指定的多点查找所有颜色坐标 void op::Op::FindMultiColorEx(long x1, long y1, long x2, long y2, const wchar_t *first_color, const wchar_t *offset_color, double sim, long dir, std::wstring &retstr) { retstr.clear(); - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x1, y1, x2, y2)) { - if (!m_context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, m_context->image_proc._src)) { - setlog("error requestCapture"); - } else { - m_context->image_proc.set_offset(x1, y1); - m_context->image_proc.FindMultiColorEx(first_color, offset_color, sim, dir, retstr); - } - } + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + m_context->image_proc.FindMultiColorEx(first_color, offset_color, sim, dir, retstr); + }); // retstr = str; } // 查找指定区域内的图片 @@ -148,114 +118,80 @@ void op::Op::FindPic(long x1, long y1, long x2, long y2, const wchar_t *files, c long found_x = -1; long found_y = -1; - internal::set_result(ret, 0L); + internal::set_result(ret, -1L); internal::set_result(x, found_x); internal::set_result(y, found_y); - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x1, y1, x2, y2)) { - if (!m_context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, m_context->image_proc._src)) { - setlog("error requestCapture"); - } else { - m_context->image_proc.set_offset(x1, y1); - internal::set_result(ret, m_context->image_proc.FindPic(files, delta_color, sim, dir, found_x, found_y)); - internal::set_result(x, found_x); - internal::set_result(y, found_y); - } + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + internal::set_result(ret, m_context->image_proc.FindPic(files, delta_color, sim, dir, found_x, found_y)); + internal::set_result(x, found_x); + internal::set_result(y, found_y); + }); - /*if (*ret) { + /*if (*ret) { rx += x1; ry += y1; rx -= m_context->bkproc._capture->get_client_x(); ry -= m_context->bkproc._capture->get_client_y(); }*/ - } } // 查找多个图片 void op::Op::FindPicEx(long x1, long y1, long x2, long y2, const wchar_t *files, const wchar_t *delta_color, double sim, long dir, std::wstring &retstr) { retstr.clear(); - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x1, y1, x2, y2)) { - if (!m_context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, m_context->image_proc._src)) { - setlog("error requestCapture"); - } else { - m_context->image_proc.set_offset(x1, y1); - m_context->image_proc.FindPicEx(files, delta_color, sim, dir, retstr); - } - } + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + m_context->image_proc.FindPicEx(files, delta_color, sim, dir, retstr); + }); } void op::Op::FindPicExS(long x1, long y1, long x2, long y2, const wchar_t *files, const wchar_t *delta_color, double sim, long dir, std::wstring &retstr) { retstr.clear(); - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x1, y1, x2, y2)) { - if (!m_context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, m_context->image_proc._src)) { - setlog("error requestCapture"); - } else { - m_context->image_proc.set_offset(x1, y1); - m_context->image_proc.FindPicEx(files, delta_color, sim, dir, retstr, false); - } - } + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + m_context->image_proc.FindPicEx(files, delta_color, sim, dir, retstr, false); + }); } void op::Op::FindColorBlock(long x1, long y1, long x2, long y2, const wchar_t *color, double sim, long count, long height, long width, long *x, long *y, long *ret) { - long found_x = 0; - long found_y = 0; + long found_x = -1; + long found_y = -1; internal::set_result(ret, 0L); - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x1, y1, x2, y2)) { - if (!m_context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, m_context->image_proc._src)) { - setlog("error requestCapture"); - } else { - m_context->image_proc.set_offset(x1, y1); - internal::set_result(ret, - m_context->image_proc.FindColorBlock(color, sim, count, height, width, found_x, found_y)); - internal::set_result(x, found_x); - internal::set_result(y, found_y); - } - } + internal::set_result(x, found_x); + internal::set_result(y, found_y); + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + internal::set_result(ret, + m_context->image_proc.FindColorBlock(color, sim, count, height, width, found_x, found_y)); + internal::set_result(x, found_x); + internal::set_result(y, found_y); + }); } void op::Op::FindColorBlockEx(long x1, long y1, long x2, long y2, const wchar_t *color, double sim, long count, long height, long width, std::wstring &retstr) { retstr.clear(); - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x1, y1, x2, y2)) { - if (!m_context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, m_context->image_proc._src)) { - setlog("error requestCapture"); - } else { - m_context->image_proc.set_offset(x1, y1); - m_context->image_proc.FindColorBlockEx(color, sim, count, height, width, retstr); - } - } + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + m_context->image_proc.FindColorBlockEx(color, sim, count, height, width, retstr); + }); } // 获取(x,y)的颜色 void op::Op::GetColor(long x, long y, std::wstring &ret) { color_t cr; auto tx = x + small_block_size, ty = y + small_block_size; - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x, y, tx, ty)) { - if (m_context->bkproc.requestCapture(x, y, small_block_size, small_block_size, m_context->image_proc._src)) { - m_context->image_proc.set_offset(x, y); - cr = m_context->image_proc._src.at(0, 0); - } else { - setlog("error requestCapture"); - } - } else { - // setlog("") - } + internal::with_captured_region(m_context.get(), x, y, tx, ty, small_block_size, small_block_size, [&]() { + cr = m_context->image_proc._src.at(0, 0); + }); ret = cr.towstr(); } void op::Op::GetColorNum(long x1, long y1, long x2, long y2, const wchar_t *color, double sim, long *ret) { - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x1, y1, x2, y2)) { - if (!m_context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, m_context->image_proc._src)) { - setlog("error requestCapture"); - } else { - m_context->image_proc.set_offset(x1, y1); - internal::set_result(ret, m_context->image_proc.GetColorNum(color, sim)); - } - } + internal::set_result(ret, 0L); + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + internal::set_result(ret, m_context->image_proc.GetColorNum(color, sim)); + }); } void op::Op::SetDisplayInput(const wchar_t *mode, long *ret) { @@ -275,6 +211,8 @@ void op::Op::LoadMemPic(const wchar_t *file_name, void *data, long size, long *r } void op::Op::GetPicSize(const wchar_t *pic_name, long *width, long *height, long *ret) { + internal::set_result(width, 0L); + internal::set_result(height, 0L); internal::set_result(ret, m_context->image_proc.GetPicSize(pic_name, width, height)); } @@ -282,57 +220,48 @@ void op::Op::GetScreenData(long x1, long y1, long x2, long y2, size_t *data, lon internal::set_result(data, 0); internal::set_result(ret, 0L); auto &img = m_context->image_proc._src; - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x1, y1, x2, y2)) { - if (!m_context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, m_context->image_proc._src)) { - setlog("error requestCapture"); - } else { - m_context->image_proc.set_offset(x1, y1); - m_context->screenData.resize(img.size() * 4); + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + m_context->screenData.resize(img.size() * 4); - if (m_context->screen_data_mode == SC_DATA_BOTTOM) { - for (int i = 0; i < img.height; i++) { - memcpy(m_context->screenData.data() + i * img.width * 4, img.ptr(img.height - 1 - i), - img.width * 4); - } - } else { - memcpy(m_context->screenData.data(), img.pdata, img.size() * 4); + if (m_context->screen_data_mode == SC_DATA_BOTTOM) { + for (int i = 0; i < img.height; i++) { + memcpy(m_context->screenData.data() + i * img.width * 4, img.ptr(img.height - 1 - i), + img.width * 4); } - internal::set_result(data, reinterpret_cast(m_context->screenData.data())); - internal::set_result(ret, 1L); + } else { + memcpy(m_context->screenData.data(), img.pdata, img.size() * 4); } - } + internal::set_result(data, reinterpret_cast(m_context->screenData.data())); + internal::set_result(ret, 1L); + }); } void op::Op::GetScreenDataBmp(long x1, long y1, long x2, long y2, size_t *data, long *size, long *ret) { internal::set_result(data, 0); internal::set_result(size, 0L); internal::set_result(ret, 0L); - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x1, y1, x2, y2)) { - if (!m_context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, m_context->image_proc._src)) { - setlog("rerror requestCapture"); - } else { - m_context->image_proc.set_offset(x1, y1); - auto &img = m_context->image_proc._src; - - BITMAPFILEHEADER bfh = {0}; // bmp file header - BITMAPINFOHEADER bih = {0}; // bmp info header - const int szBfh = sizeof(BITMAPFILEHEADER); - const int szBih = sizeof(BITMAPINFOHEADER); - bfh.bfOffBits = szBfh + szBih; - bfh.bfSize = bfh.bfOffBits + img.width * img.height * 4; - bfh.bfType = static_cast(0x4d42); - - bih.biBitCount = 32; // 每个像素字节大小 - bih.biCompression = BI_RGB; - // bih.biHeight = -img.height;//高度 反 - bih.biHeight = m_context->screen_data_mode == SC_DATA_BOTTOM ? img.height : -img.height; // 高度 - bih.biPlanes = 1; - bih.biSize = sizeof(BITMAPINFOHEADER); - bih.biSizeImage = img.width * 4 * img.height; // 图像数据大小 - bih.biWidth = img.width; // 宽度 - - m_context->screenDataBmp.resize(bfh.bfSize); - /* std::ofstream f; + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + auto &img = m_context->image_proc._src; + + BITMAPFILEHEADER bfh = {0}; // bmp file header + BITMAPINFOHEADER bih = {0}; // bmp info header + const int szBfh = sizeof(BITMAPFILEHEADER); + const int szBih = sizeof(BITMAPINFOHEADER); + bfh.bfOffBits = szBfh + szBih; + bfh.bfSize = bfh.bfOffBits + img.width * img.height * 4; + bfh.bfType = static_cast(0x4d42); + + bih.biBitCount = 32; // 每个像素字节大小 + bih.biCompression = BI_RGB; + // bih.biHeight = -img.height;//高度 反 + bih.biHeight = m_context->screen_data_mode == SC_DATA_BOTTOM ? img.height : -img.height; // 高度 + bih.biPlanes = 1; + bih.biSize = sizeof(BITMAPINFOHEADER); + bih.biSizeImage = img.width * 4 * img.height; // 图像数据大小 + bih.biWidth = img.width; // 宽度 + + m_context->screenDataBmp.resize(bfh.bfSize); + /* std::ofstream f; f.open("xx.bmp",std::ios::binary); if (f) { f.write((char*)&bfh, sizeof(bfh)); @@ -341,25 +270,24 @@ void op::Op::GetScreenDataBmp(long x1, long y1, long x2, long y2, size_t *data, } f.close();*/ - auto dst = m_context->screenDataBmp.data(); - - memcpy(dst, &bfh, sizeof(bfh)); - memcpy(dst + sizeof(bfh), &bih, sizeof(bih)); - dst += sizeof(bfh) + sizeof(bih); - if (m_context->screen_data_mode == SC_DATA_BOTTOM) { - for (int i = 0; i < img.height; i++) { - memcpy(dst + i * img.width * 4, img.ptr(img.height - 1 - i), img.width * 4); - } - } else { - memcpy(dst, img.pdata, img.size() * 4); + auto dst = m_context->screenDataBmp.data(); + + memcpy(dst, &bfh, sizeof(bfh)); + memcpy(dst + sizeof(bfh), &bih, sizeof(bih)); + dst += sizeof(bfh) + sizeof(bih); + if (m_context->screen_data_mode == SC_DATA_BOTTOM) { + for (int i = 0; i < img.height; i++) { + memcpy(dst + i * img.width * 4, img.ptr(img.height - 1 - i), img.width * 4); } - - // memcpy(dst + sizeof(bfh)+sizeof(bih), img.pdata, img.size()*4); - internal::set_result(data, reinterpret_cast(m_context->screenDataBmp.data())); - internal::set_result(size, bfh.bfSize); - internal::set_result(ret, 1L); + } else { + memcpy(dst, img.pdata, img.size() * 4); } - } + + // memcpy(dst + sizeof(bfh)+sizeof(bih), img.pdata, img.size()*4); + internal::set_result(data, reinterpret_cast(m_context->screenDataBmp.data())); + internal::set_result(size, bfh.bfSize); + internal::set_result(ret, 1L); + }); } void op::Op::GetScreenFrameInfo(long *frame_id, long *time) { diff --git a/libop/op/OpInput.cpp b/libop/op/OpInput.cpp index 5b40316..f600fc6 100644 --- a/libop/op/OpInput.cpp +++ b/libop/op/OpInput.cpp @@ -1,8 +1,8 @@ #include "OpContext.h" #include "OpResult.h" -#include "runtime/AutomationModes.h" -#include "runtime/RuntimeUtils.h" +#include "base/AutomationModes.h" +#include "base/Utils.h" #include @@ -115,6 +115,10 @@ void op::Op::UnBindWindow(long *ret) { internal::set_result(ret, m_context->bkproc.UnBindWindow()); } +void op::Op::LockInput(long lock, long *ret) { + internal::set_result(ret, m_context->bkproc.LockInput(lock)); +} + void op::Op::GetBindWindow(LONG_PTR *ret) { internal::set_result(ret, m_context->bkproc.GetBindWindow()); } @@ -153,6 +157,36 @@ void op::Op::MoveToEx(long x, long y, long w, long h, std::wstring &ret) { } } +void op::Op::MoveToSmooth(long x, long y, long duration, long *ret) { + internal::set_result(ret, m_context->bkproc._mouse->MoveToSmooth(x, y, duration)); +} + +void op::Op::MoveToExSmooth(long x, long y, long w, long h, long duration, std::wstring &ret) { + int dst_x = x; + int dst_y = y; + if (m_context->bkproc._mouse->MoveToExSmooth(x, y, w, h, duration, dst_x, dst_y)) { + ret = std::to_wstring(dst_x) + L"," + std::to_wstring(dst_y); + } else { + ret.clear(); + } +} + +void op::Op::MovePath(const wchar_t *path, long duration, long *ret) { + internal::set_result(ret, m_context->bkproc._mouse->MovePath(path ? path : L"", duration)); +} + +void op::Op::DragPath(const wchar_t *path, long duration, long *ret) { + internal::set_result(ret, m_context->bkproc._mouse->DragPath(path ? path : L"", duration)); +} + +void op::Op::SetMouseTrajectory(long mode, long min_duration, long max_duration, long jitter, long start_delay, + long end_delay, long *ret) { + const long result = m_context->bkproc._mouse->SetMouseTrajectory( + static_cast(mode), static_cast(min_duration), static_cast(max_duration), + static_cast(jitter), static_cast(start_delay), static_cast(end_delay)); + internal::set_result(ret, result); +} + void op::Op::LeftClick(long *ret) { internal::set_result(ret, m_context->bkproc._mouse->LeftClick()); } diff --git a/libop/op/OpOcr.cpp b/libop/op/OpOcr.cpp index baa3659..74397c5 100644 --- a/libop/op/OpOcr.cpp +++ b/libop/op/OpOcr.cpp @@ -1,8 +1,9 @@ #include "OpContext.h" +#include "OpCaptureHelpers.h" #include "OpResult.h" #include "ocr/OcrService.h" -#include "runtime/RuntimeUtils.h" +#include "base/Utils.h" #include @@ -117,25 +118,6 @@ double normalize_similarity(double sim) { return sim < 0. || sim > 1. ? 1. : sim; } -template -void capture_converted_region(op::internal::OpContext *context, long x1, long y1, long x2, long y2, Fn fn) { - if (!context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, context->image_proc._src)) { - setlog("error requestCapture"); - return; - } - - context->image_proc.set_offset(x1, y1); - fn(); -} - -template -void with_captured_region(op::internal::OpContext *context, long &x1, long &y1, long &x2, long &y2, Fn fn) { - if (!context->bkproc.check_bind() || !context->bkproc.RectConvert(x1, y1, x2, y2)) - return; - - capture_converted_region(context, x1, y1, x2, y2, fn); -} - } // namespace long op::Op::SetOcrEngine(const wchar_t *path_of_engine, const wchar_t *dll_name, const wchar_t *argv) { @@ -155,8 +137,8 @@ void op::Op::GetDict(long idx, long font_index, std::wstring &retstr) { } // 设置内存字库文件 -void op::Op::SetMemDict(long idx, const wchar_t *data, long size, long *ret) { - internal::set_result(ret, m_context->image_proc.SetMemDict(idx, (void *)data, size)); +void op::Op::SetMemDict(long idx, const void *data, long size, long *ret) { + internal::set_result(ret, m_context->image_proc.SetMemDict(idx, data, size)); } // 使用哪个字库文件进行识别 @@ -218,7 +200,7 @@ void op::Op::FetchWordEx(long x1, long y1, long x2, long y2, const wchar_t *colo const std::wstring word_text = word ? word : L""; sim = normalize_similarity(sim); - with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { rect_t rc; rc.x1 = rc.y1 = 0; rc.x2 = x2 - x1; @@ -233,7 +215,7 @@ void op::Op::ExtractWordRects(long x1, long y1, long x2, long y2, const wchar_t const std::wstring color_text = color ? color : L""; sim = normalize_similarity(sim); - with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { std::vector rects; m_context->image_proc.ExtractWordRects(color_text, sim, min_word_h, rects); append_word_rects(rects, x1, y1, retstr); @@ -246,7 +228,7 @@ void op::Op::ExtractWordRectsEx(long x1, long y1, long x2, long y2, const wchar_ const std::wstring color_text = color ? color : L""; sim = normalize_similarity(sim); - with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { std::vector rects; m_context->image_proc.ExtractWordRectsEx(color_text, sim, min_word_w, min_word_h, padding, rects); append_word_rects(rects, x1, y1, retstr); @@ -260,7 +242,7 @@ void op::Op::FetchWords(long x1, long y1, long x2, long y2, const wchar_t *color const std::wstring word_text = words ? words : L""; sim = normalize_similarity(sim); - with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { m_context->image_proc.FetchWords(color_text, sim, word_text, min_word_h, retstr); }); } @@ -272,7 +254,7 @@ void op::Op::FetchWordsEx(long x1, long y1, long x2, long y2, const wchar_t *col const std::wstring word_text = words ? words : L""; sim = normalize_similarity(sim); - with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { m_context->image_proc.FetchWordsEx(color_text, sim, word_text, min_word_w, min_word_h, padding, retstr); }); } @@ -291,7 +273,7 @@ void op::Op::FetchWordsByRects(long x1, long y1, long x2, long y2, const wchar_t if (local_rects.size() != word_text.size()) return; - capture_converted_region(m_context.get(), x1, y1, x2, y2, [&]() { + internal::capture_converted_region(m_context.get(), x1, y1, x2, y2, [&]() { m_context->image_proc.FetchWordsByRects(color_text, sim, word_text, local_rects, retstr); }); } @@ -304,7 +286,7 @@ void op::Op::GetBinaryPreview(long x1, long y1, long x2, long y2, const wchar_t const std::wstring color_text = color ? color : L""; sim = normalize_similarity(sim); - with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { internal::set_result(ret, m_context->image_proc.GetBinaryPreview(color_text, sim, retstr)); }); } @@ -334,25 +316,20 @@ void op::Op::RenameWordDict(const wchar_t *dict_info, const wchar_t *words, std: void op::Op::GetWordsNoDict(long x1, long y1, long x2, long y2, const wchar_t *color, std::wstring &retstr) { wstring str; const std::wstring color_text = color ? color : L""; - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x1, y1, x2, y2)) { - if (!m_context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, m_context->image_proc._src)) { - setlog("error requestCapture"); - } else { - m_context->image_proc.set_offset(x1, y1); - m_context->image_proc.str2binaryfbk(color_text); - std::vector vroi; - m_context->image_proc.get_rois(5, vroi); - for (auto &it : vroi) { - const wstring tempWord = m_context->image_proc.FetchWord(it, color_text, L""); - str += std::to_wstring(it.x1); - str += L","; - str += std::to_wstring(it.y1); - str += L"-"; - str += tempWord; - str += L"/"; - } + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + m_context->image_proc.str2binaryfbk(color_text); + std::vector vroi; + m_context->image_proc.get_rois(5, vroi); + for (auto &it : vroi) { + const wstring tempWord = m_context->image_proc.FetchWord(it, color_text, L""); + str += std::to_wstring(it.x1); + str += L","; + str += std::to_wstring(it.y1); + str += L"-"; + str += tempWord; + str += L"/"; } - } + }); retstr = str; } // 在使用GetWords进行词组识别以后,可以用此接口进行识别词组数量的计算 @@ -435,27 +412,17 @@ void op::Op::GetWordResultStr(const wchar_t *result, long index, std::wstring &r // 识别屏幕范围(x1,y1,x2,y2)内符合color_format的字符串,并且相似度为sim,sim取值范围(0.1-1.0), void op::Op::Ocr(long x1, long y1, long x2, long y2, const wchar_t *color, double sim, std::wstring &retstr) { wstring str; - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x1, y1, x2, y2)) { - if (!m_context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, m_context->image_proc._src)) { - setlog("error requestCapture"); - } else { - m_context->image_proc.set_offset(x1, y1); - m_context->image_proc.OCR(color, sim, str); - } - } + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + m_context->image_proc.OCR(color, sim, str); + }); retstr = str; } // 回识别到的字符串,以及每个字符的坐标. void op::Op::OcrEx(long x1, long y1, long x2, long y2, const wchar_t *color, double sim, std::wstring &retstr) { wstring str; - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x1, y1, x2, y2)) { - if (!m_context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, m_context->image_proc._src)) { - setlog("error requestCapture"); - } else { - m_context->image_proc.set_offset(x1, y1); - m_context->image_proc.OcrEx(color, sim, str); - } - } + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + m_context->image_proc.OcrEx(color, sim, str); + }); retstr = str; } // 在屏幕范围(x1,y1,x2,y2)内,查找string(可以是任意个字符串的组合),并返回符合color_format的坐标位置 @@ -467,42 +434,26 @@ void op::Op::FindStr(long x1, long y1, long x2, long y2, const wchar_t *strs, co internal::set_result(retx, x); internal::set_result(rety, y); internal::set_result(ret, 0L); - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x1, y1, x2, y2)) { - if (!m_context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, m_context->image_proc._src)) { - setlog("error requestCapture"); - } else { - m_context->image_proc.set_offset(x1, y1); - internal::set_result(ret, m_context->image_proc.FindStr(strs, color, sim, x, y)); - internal::set_result(retx, x); - internal::set_result(rety, y); - } - } + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + internal::set_result(ret, m_context->image_proc.FindStr(strs, color, sim, x, y)); + internal::set_result(retx, x); + internal::set_result(rety, y); + }); } // 返回符合color_format的所有坐标位置 void op::Op::FindStrEx(long x1, long y1, long x2, long y2, const wchar_t *strs, const wchar_t *color, double sim, std::wstring &retstr) { wstring str; - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x1, y1, x2, y2)) { - if (!m_context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, m_context->image_proc._src)) { - setlog("error requestCapture"); - } else { - m_context->image_proc.set_offset(x1, y1); - m_context->image_proc.FindStrEx(strs, color, sim, str); - } - } + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, + [&]() { m_context->image_proc.FindStrEx(strs, color, sim, str); }); retstr = str; } void op::Op::OcrAuto(long x1, long y1, long x2, long y2, double sim, std::wstring &retstr) { wstring str; - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x1, y1, x2, y2)) { - if (!m_context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, m_context->image_proc._src)) { - setlog("error requestCapture"); - } else { - m_context->image_proc.set_offset(x1, y1); - m_context->image_proc.OcrAuto(sim, str); - } - } + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { + m_context->image_proc.OcrAuto(sim, str); + }); retstr = str; } @@ -520,12 +471,6 @@ void op::Op::OcrAutoFromFile(const wchar_t *file_name, double sim, std::wstring } void op::Op::FindLine(long x1, long y1, long x2, long y2, const wchar_t *color, double sim, wstring &retstr) { - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x1, y1, x2, y2)) { - if (!m_context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, m_context->image_proc._src)) { - setlog("error requestCapture"); - } else { - m_context->image_proc.set_offset(x1, y1); - m_context->image_proc.FindLine(color, sim, retstr); - } - } + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, + [&]() { m_context->image_proc.FindLine(color, sim, retstr); }); } diff --git a/libop/op/OpOpenCv.cpp b/libop/op/OpOpenCv.cpp index c751e9b..e8d499b 100644 --- a/libop/op/OpOpenCv.cpp +++ b/libop/op/OpOpenCv.cpp @@ -3,7 +3,7 @@ #include "opencv/OpenCvBridge.h" #include "opencv/TemplateMatcher.h" -#include "runtime/RuntimeUtils.h" +#include "base/Utils.h" #include diff --git a/libop/op/OpProcess.cpp b/libop/op/OpProcess.cpp index c32ef2c..fb5b6d5 100644 --- a/libop/op/OpProcess.cpp +++ b/libop/op/OpProcess.cpp @@ -2,7 +2,7 @@ #include "OpResult.h" #include "ipc/CommandRunner.h" -#include "runtime/RuntimeUtils.h" +#include "base/Utils.h" #include "window/DllInjector.h" #include diff --git a/libop/op/OpRuntime.cpp b/libop/op/OpRuntime.cpp index a4d4fb1..b5c8be4 100644 --- a/libop/op/OpRuntime.cpp +++ b/libop/op/OpRuntime.cpp @@ -1,8 +1,8 @@ #include "OpContext.h" #include "OpResult.h" -#include "runtime/RuntimeEnvironment.h" -#include "runtime/RuntimeUtils.h" +#include "base/Environment.h" +#include "base/Utils.h" #include #include diff --git a/libop/op/OpWindow.cpp b/libop/op/OpWindow.cpp index 2d6253c..0316578 100644 --- a/libop/op/OpWindow.cpp +++ b/libop/op/OpWindow.cpp @@ -1,7 +1,7 @@ #include "OpContext.h" #include "OpResult.h" -#include "runtime/RuntimeUtils.h" +#include "base/Utils.h" #include "window/WindowLayout.h" #include diff --git a/libop/op/OpYolo.cpp b/libop/op/OpYolo.cpp index dd1b99f..1bb81cd 100644 --- a/libop/op/OpYolo.cpp +++ b/libop/op/OpYolo.cpp @@ -1,8 +1,10 @@ #include "OpContext.h" +#include "OpCaptureHelpers.h" #include "OpResult.h" #include "image/Image.h" -#include "runtime/RuntimeUtils.h" +#include "base/JsonUtils.h" +#include "base/Utils.h" #include "yolo/YoloDetector.h" #include @@ -12,35 +14,10 @@ namespace { -static std::wstring json_escape(const std::wstring &text) { - std::wstring out; - for (const auto ch : text) { - switch (ch) { - case L'\\': - out += L"\\\\"; - break; - case L'"': - out += L"\\\""; - break; - case L'\n': - out += L"\\n"; - break; - case L'\r': - out += L"\\r"; - break; - case L'\t': - out += L"\\t"; - break; - default: - out += ch; - break; - } - } - return out; -} +constexpr const wchar_t *kYoloFailureJson = L"{\"ok\":0,\"code\":-1,\"results\":[]}"; static void build_yolo_json(const op::vyolo_rec_t &items, std::wstring &retjson) { - retjson = L"{\"code\":0,\"results\":["; + retjson = L"{\"ok\":1,\"code\":0,\"results\":["; bool first = true; for (const auto &it : items) { if (!first) @@ -49,7 +26,7 @@ static void build_yolo_json(const op::vyolo_rec_t &items, std::wstring &retjson) retjson += L"{\"class_id\":"; retjson += std::to_wstring(it.class_id); retjson += L",\"label\":\""; - retjson += json_escape(it.label); + retjson += op::internal::json::EscapeString(it.label); retjson += L"\",\"bbox\":["; retjson += std::to_wstring(it.left_top.x); retjson += L","; @@ -59,7 +36,7 @@ static void build_yolo_json(const op::vyolo_rec_t &items, std::wstring &retjson) retjson += L","; retjson += std::to_wstring(it.right_bottom.y); retjson += L"],\"confidence\":"; - retjson += std::to_wstring(it.confidence); + retjson += op::internal::json::FormatDouble(it.confidence); retjson += L"}"; } retjson += L"]}"; @@ -76,13 +53,9 @@ long op::Op::SetYoloEngine(const wchar_t *path_of_engine, const wchar_t *dll_nam return op::yolo::YoloDetector::getInstance()->init(engine, dll, vstr) == 0 ? 1 : 0; } void op::Op::YoloDetect(long x1, long y1, long x2, long y2, double conf, double iou, std::wstring &retjson, long *ret) { - retjson.clear(); + retjson = kYoloFailureJson; internal::set_result(ret, 0L); - if (m_context->bkproc.check_bind() && m_context->bkproc.RectConvert(x1, y1, x2, y2)) { - if (!m_context->bkproc.requestCapture(x1, y1, x2 - x1, y2 - y1, m_context->image_proc._src)) { - setlog("error requestCapture"); - return; - } + internal::with_captured_region(m_context.get(), x1, y1, x2, y2, [&]() { vyolo_rec_t res; const int n = op::yolo::YoloDetector::getInstance()->detect(m_context->image_proc._src.pdata, m_context->image_proc._src.width, @@ -97,11 +70,11 @@ void op::Op::YoloDetect(long x1, long y1, long x2, long y2, double conf, double } build_yolo_json(res, retjson); internal::set_result(ret, n); - } + }); } void op::Op::YoloDetectFromFile(const wchar_t *file_name, double conf, double iou, std::wstring &retjson, long *ret) { - retjson.clear(); + retjson = kYoloFailureJson; internal::set_result(ret, 0L); std::wstring fullpath; if (!Path2GlobalPath(file_name ? file_name : L"", m_context->curr_path, fullpath)) diff --git a/libop/opencv/OpenCvBridge.cpp b/libop/opencv/OpenCvBridge.cpp index 8efeb20..4ea8619 100644 --- a/libop/opencv/OpenCvBridge.cpp +++ b/libop/opencv/OpenCvBridge.cpp @@ -1,57 +1,13 @@ #include "OpenCvBridge.h" -#include "../runtime/RuntimeUtils.h" +#include "../base/JsonUtils.h" +#include "../base/Utils.h" #include -#include #include namespace opcv::bridge { -namespace { - -std::wstring EscapeJsonString(const std::wstring &value) { - std::wstring escaped; - escaped.reserve(value.size() + 8); - for (wchar_t ch : value) { - switch (ch) { - case L'\\': - escaped += L"\\\\"; - break; - case L'"': - escaped += L"\\\""; - break; - case L'\b': - escaped += L"\\b"; - break; - case L'\f': - escaped += L"\\f"; - break; - case L'\n': - escaped += L"\\n"; - break; - case L'\r': - escaped += L"\\r"; - break; - case L'\t': - escaped += L"\\t"; - break; - default: - escaped.push_back(ch); - break; - } - } - return escaped; -} - -std::wstring FormatJsonDouble(double value) { - std::wostringstream oss; - oss << std::fixed << std::setprecision(6) << value; - return oss.str(); -} - -} // namespace - MatchColorMode ParseColorMode(long color_mode) { return color_mode == 0 ? MatchColorMode::Color : MatchColorMode::Gray; } @@ -63,7 +19,8 @@ std::wstring BuildMatchJson(const MatchResult &match, bool ok) { std::wostringstream oss; oss << L"{\"ok\":1,\"x\":" << match.x << L",\"y\":" << match.y << L",\"width\":" << match.width - << L",\"height\":" << match.height << L",\"score\":" << FormatJsonDouble(match.score) << L"}"; + << L",\"height\":" << match.height << L",\"score\":" << op::internal::json::FormatDouble(match.score) + << L"}"; return oss.str(); } @@ -73,9 +30,9 @@ std::wstring BuildNamedMatchJson(const NamedMatchResult &match, bool ok) { } std::wostringstream oss; - oss << L"{\"ok\":1,\"name\":\"" << EscapeJsonString(match.name) << L"\",\"x\":" << match.match.x << L",\"y\":" - << match.match.y << L",\"width\":" << match.match.width << L",\"height\":" << match.match.height - << L",\"score\":" << FormatJsonDouble(match.match.score) << L"}"; + oss << L"{\"ok\":1,\"name\":\"" << op::internal::json::EscapeString(match.name) << L"\",\"x\":" + << match.match.x << L",\"y\":" << match.match.y << L",\"width\":" << match.match.width << L",\"height\":" + << match.match.height << L",\"score\":" << op::internal::json::FormatDouble(match.match.score) << L"}"; return oss.str(); } @@ -86,9 +43,10 @@ std::wstring BuildAllMatchesJson(const std::vector &matches, b if (i != 0) { oss << L","; } - oss << L"{\"name\":\"" << EscapeJsonString(matches[i].name) << L"\",\"x\":" << matches[i].match.x << L",\"y\":" - << matches[i].match.y << L",\"width\":" << matches[i].match.width << L",\"height\":" - << matches[i].match.height << L",\"score\":" << FormatJsonDouble(matches[i].match.score) << L"}"; + oss << L"{\"name\":\"" << op::internal::json::EscapeString(matches[i].name) << L"\",\"x\":" + << matches[i].match.x << L",\"y\":" << matches[i].match.y << L",\"width\":" + << matches[i].match.width << L",\"height\":" << matches[i].match.height + << L",\"score\":" << op::internal::json::FormatDouble(matches[i].match.score) << L"}"; } oss << L"]}"; return oss.str(); diff --git a/libop/opencv/TemplateMatcher.cpp b/libop/opencv/TemplateMatcher.cpp index 9fd7178..d18a5d5 100644 --- a/libop/opencv/TemplateMatcher.cpp +++ b/libop/opencv/TemplateMatcher.cpp @@ -1,6 +1,6 @@ #include "TemplateMatcher.h" #include "OpenCvHelpers.h" -#include "../runtime/ThreadPool.h" +#include "../base/ThreadPool.h" #include #include diff --git a/libop/window/DllInjector.cpp b/libop/window/DllInjector.cpp index 6093df9..ebde85d 100644 --- a/libop/window/DllInjector.cpp +++ b/libop/window/DllInjector.cpp @@ -1,7 +1,7 @@ // #include "stdafx.h" #include "DllInjector.h" -#include "runtime/WindowsHandle.h" +#include "base/WindowsHandle.h" namespace op { diff --git a/libop/window/DllInjector.h b/libop/window/DllInjector.h index ffea11b..c82240a 100644 --- a/libop/window/DllInjector.h +++ b/libop/window/DllInjector.h @@ -1,5 +1,5 @@ #pragma once -#include "../runtime/Types.h" +#include "../base/Types.h" namespace op { class DllInjector { diff --git a/libop/window/WindowProcess.cpp b/libop/window/WindowProcess.cpp index 5fb7fdc..454863f 100644 --- a/libop/window/WindowProcess.cpp +++ b/libop/window/WindowProcess.cpp @@ -1,6 +1,6 @@ #include "WindowService.h" -#include "runtime/WindowsHandle.h" +#include "base/WindowsHandle.h" #include #include diff --git a/libop/window/WindowService.h b/libop/window/WindowService.h index 9253717..49040f9 100644 --- a/libop/window/WindowService.h +++ b/libop/window/WindowService.h @@ -1,7 +1,7 @@ #pragma once #ifndef OP_WINDOW_WINDOW_SERVICE_H_ #define OP_WINDOW_WINDOW_SERVICE_H_ -#include "../runtime/Types.h" +#include "../base/Types.h" #undef FindWindow #undef FindWindowEx namespace op { diff --git a/libop/window/WindowState.cpp b/libop/window/WindowState.cpp index 727a09c..764b3f0 100644 --- a/libop/window/WindowState.cpp +++ b/libop/window/WindowState.cpp @@ -1,5 +1,5 @@ #include "WindowService.h" -#include "../runtime/WindowsHandle.h" +#include "../base/WindowsHandle.h" namespace op { diff --git a/libop/yolo/YoloDetector.cpp b/libop/yolo/YoloDetector.cpp index b40ac36..55e9139 100644 --- a/libop/yolo/YoloDetector.cpp +++ b/libop/yolo/YoloDetector.cpp @@ -1,6 +1,6 @@ #include "YoloDetector.h" #include "../network/HttpClient.h" -#include "../runtime/RuntimeUtils.h" +#include "../base/Utils.h" #include #include diff --git a/libop/yolo/YoloDetector.h b/libop/yolo/YoloDetector.h index 7642352..cea3221 100644 --- a/libop/yolo/YoloDetector.h +++ b/libop/yolo/YoloDetector.h @@ -1,5 +1,5 @@ #pragma once -#include "../runtime/Types.h" +#include "../base/Types.h" #include namespace op::yolo { diff --git a/python/pyop/_binding.py b/python/pyop/_binding.py index 5528f8c..b640172 100644 --- a/python/pyop/_binding.py +++ b/python/pyop/_binding.py @@ -264,6 +264,9 @@ def BindWindowEx(self, display_hwnd, input_hwnd, display, mouse, keypad, mode): def UnBindWindow(self): return _pyop.Op_UnBindWindow(self) + def LockInput(self, lock): + return _pyop.Op_LockInput(self, lock) + def GetBindWindow(self): return _pyop.Op_GetBindWindow(self) @@ -285,6 +288,21 @@ def MoveTo(self, x, y): def MoveToEx(self, x, y, w, h): return _pyop.Op_MoveToEx(self, x, y, w, h) + def MoveToSmooth(self, x, y, duration): + return _pyop.Op_MoveToSmooth(self, x, y, duration) + + def MoveToExSmooth(self, x, y, w, h, duration): + return _pyop.Op_MoveToExSmooth(self, x, y, w, h, duration) + + def MovePath(self, path, duration): + return _pyop.Op_MovePath(self, path, duration) + + def DragPath(self, path, duration): + return _pyop.Op_DragPath(self, path, duration) + + def SetMouseTrajectory(self, mode, min_duration, max_duration, jitter, start_delay, end_delay): + return _pyop.Op_SetMouseTrajectory(self, mode, min_duration, max_duration, jitter, start_delay, end_delay) + def LeftClick(self): return _pyop.Op_LeftClick(self) @@ -600,9 +618,48 @@ def GetDictCount(self, idx): def GetNowDict(self): return _pyop.Op_GetNowDict(self) + def SetBinaryPreprocess(self, mode, isolated_threshold, min_component_area, bridge_gap): + return _pyop.Op_SetBinaryPreprocess(self, mode, isolated_threshold, min_component_area, bridge_gap) + + def GetBinaryPreprocess(self): + return _pyop.Op_GetBinaryPreprocess(self) + def FetchWord(self, x1, y1, x2, y2, color, word): return _pyop.Op_FetchWord(self, x1, y1, x2, y2, color, word) + def FetchWordEx(self, x1, y1, x2, y2, color, sim, word): + return _pyop.Op_FetchWordEx(self, x1, y1, x2, y2, color, sim, word) + + def ExtractWordRects(self, x1, y1, x2, y2, color, sim, min_word_h): + return _pyop.Op_ExtractWordRects(self, x1, y1, x2, y2, color, sim, min_word_h) + + def ExtractWordRectsEx(self, x1, y1, x2, y2, color, sim, min_word_w, min_word_h, padding): + return _pyop.Op_ExtractWordRectsEx(self, x1, y1, x2, y2, color, sim, min_word_w, min_word_h, padding) + + def FetchWords(self, x1, y1, x2, y2, color, sim, words, min_word_h): + return _pyop.Op_FetchWords(self, x1, y1, x2, y2, color, sim, words, min_word_h) + + def FetchWordsEx(self, x1, y1, x2, y2, color, sim, words, min_word_w, min_word_h, padding): + return _pyop.Op_FetchWordsEx(self, x1, y1, x2, y2, color, sim, words, min_word_w, min_word_h, padding) + + def FetchWordsByRects(self, x1, y1, x2, y2, color, sim, words, rects): + return _pyop.Op_FetchWordsByRects(self, x1, y1, x2, y2, color, sim, words, rects) + + def GetBinaryPreview(self, x1, y1, x2, y2, color, sim): + return _pyop.Op_GetBinaryPreview(self, x1, y1, x2, y2, color, sim) + + def GetWordPreview(self, dict_info): + return _pyop.Op_GetWordPreview(self, dict_info) + + def CheckWordDict(self, dict_info): + return _pyop.Op_CheckWordDict(self, dict_info) + + def NormalizeWordDict(self, dict_info): + return _pyop.Op_NormalizeWordDict(self, dict_info) + + def RenameWordDict(self, dict_info, words): + return _pyop.Op_RenameWordDict(self, dict_info, words) + def GetWordsNoDict(self, x1, y1, x2, y2, color): return _pyop.Op_GetWordsNoDict(self, x1, y1, x2, y2, color) diff --git a/swig/op.i b/swig/op.i index b58a893..1e62070 100644 --- a/swig/op.i +++ b/swig/op.i @@ -1,5 +1,6 @@ #define OP_API #define _In_ +#define _In_reads_bytes_(x) #define _Out_ #define _Inout_ %module pyop @@ -18,6 +19,17 @@ %apply long long *OUTPUT {LONG_PTR *} %apply size_t *OUTPUT {size_t *} +%typemap(in) const void * (Py_buffer view) { + if (PyObject_GetBuffer($input, &view, PyBUF_SIMPLE) != 0) { + SWIG_exception_fail(SWIG_TypeError, "expected a bytes-like object"); + } + $1 = view.buf; +} + +%typemap(freearg) const void * { + PyBuffer_Release(&view$argnum); +} + %extend op::Op { void RunApp(const wchar_t *cmdline, long mode, long *ret) { unsigned long pid = 0; diff --git a/swig/op_wrap.cxx b/swig/op_wrap.cxx index f550de8..fde7e35 100644 --- a/swig/op_wrap.cxx +++ b/swig/op_wrap.cxx @@ -7261,6 +7261,46 @@ SWIGINTERN PyObject *_wrap_Op_UnBindWindow(PyObject *self, PyObject *args) { } +SWIGINTERN PyObject *_wrap_Op_LockInput(PyObject *self, PyObject *args) { + PyObject *resultobj = 0; + op::Op *arg1 = 0 ; + long arg2 ; + long *arg3 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + long val2 ; + int ecode2 = 0 ; + long temp3 ; + int res3 = SWIG_TMPOBJ ; + PyObject *swig_obj[2] ; + + arg3 = &temp3; + (void)self; + if (!SWIG_Python_UnpackTuple(args, "Op_LockInput", 2, 2, swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_LockInput" "', argument " "1"" of type '" "op::Op *""'"); + } + arg1 = reinterpret_cast< op::Op * >(argp1); + ecode2 = SWIG_AsVal_long(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Op_LockInput" "', argument " "2"" of type '" "long""'"); + } + arg2 = static_cast< long >(val2); + (arg1)->LockInput(arg2,arg3); + resultobj = SWIG_Py_Void(); + if (SWIG_IsTmpObj(res3)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg3)), 1); + } else { + int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_long, new_flags), 1); + } + return resultobj; +fail: + return NULL; +} + + SWIGINTERN PyObject *_wrap_Op_GetBindWindow(PyObject *self, PyObject *args) { PyObject *resultobj = 0; op::Op *arg1 = 0 ; @@ -7573,32 +7613,55 @@ SWIGINTERN PyObject *_wrap_Op_MoveToEx(PyObject *self, PyObject *args) { } -SWIGINTERN PyObject *_wrap_Op_LeftClick(PyObject *self, PyObject *args) { +SWIGINTERN PyObject *_wrap_Op_MoveToSmooth(PyObject *self, PyObject *args) { PyObject *resultobj = 0; op::Op *arg1 = 0 ; - long *arg2 = 0 ; + long arg2 ; + long arg3 ; + long arg4 ; + long *arg5 = 0 ; void *argp1 = 0 ; int res1 = 0 ; - long temp2 ; - int res2 = SWIG_TMPOBJ ; - PyObject *swig_obj[1] ; + long val2 ; + int ecode2 = 0 ; + long val3 ; + int ecode3 = 0 ; + long val4 ; + int ecode4 = 0 ; + long temp5 ; + int res5 = SWIG_TMPOBJ ; + PyObject *swig_obj[4] ; - arg2 = &temp2; + arg5 = &temp5; (void)self; - if (!args) SWIG_fail; - swig_obj[0] = args; + if (!SWIG_Python_UnpackTuple(args, "Op_MoveToSmooth", 4, 4, swig_obj)) SWIG_fail; res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_LeftClick" "', argument " "1"" of type '" "op::Op *""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_MoveToSmooth" "', argument " "1"" of type '" "op::Op *""'"); } arg1 = reinterpret_cast< op::Op * >(argp1); - (arg1)->LeftClick(arg2); + ecode2 = SWIG_AsVal_long(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Op_MoveToSmooth" "', argument " "2"" of type '" "long""'"); + } + arg2 = static_cast< long >(val2); + ecode3 = SWIG_AsVal_long(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Op_MoveToSmooth" "', argument " "3"" of type '" "long""'"); + } + arg3 = static_cast< long >(val3); + ecode4 = SWIG_AsVal_long(swig_obj[3], &val4); + if (!SWIG_IsOK(ecode4)) { + SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Op_MoveToSmooth" "', argument " "4"" of type '" "long""'"); + } + arg4 = static_cast< long >(val4); + (arg1)->MoveToSmooth(arg2,arg3,arg4,arg5); resultobj = SWIG_Py_Void(); - if (SWIG_IsTmpObj(res2)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg2)), 1); + if (SWIG_IsTmpObj(res5)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg5)), 1); } else { - int new_flags = SWIG_IsNewObj(res2) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg2), SWIGTYPE_p_long, new_flags), 1); + int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_long, new_flags), 1); } return resultobj; fail: @@ -7606,32 +7669,71 @@ SWIGINTERN PyObject *_wrap_Op_LeftClick(PyObject *self, PyObject *args) { } -SWIGINTERN PyObject *_wrap_Op_LeftDoubleClick(PyObject *self, PyObject *args) { +SWIGINTERN PyObject *_wrap_Op_MoveToExSmooth(PyObject *self, PyObject *args) { PyObject *resultobj = 0; op::Op *arg1 = 0 ; - long *arg2 = 0 ; + long arg2 ; + long arg3 ; + long arg4 ; + long arg5 ; + long arg6 ; + std::wstring *arg7 = 0 ; void *argp1 = 0 ; int res1 = 0 ; - long temp2 ; - int res2 = SWIG_TMPOBJ ; - PyObject *swig_obj[1] ; + long val2 ; + int ecode2 = 0 ; + long val3 ; + int ecode3 = 0 ; + long val4 ; + int ecode4 = 0 ; + long val5 ; + int ecode5 = 0 ; + long val6 ; + int ecode6 = 0 ; + std::wstring temp7 ; + int res7 = SWIG_TMPOBJ ; + PyObject *swig_obj[6] ; - arg2 = &temp2; + arg7 = &temp7; (void)self; - if (!args) SWIG_fail; - swig_obj[0] = args; + if (!SWIG_Python_UnpackTuple(args, "Op_MoveToExSmooth", 6, 6, swig_obj)) SWIG_fail; res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_LeftDoubleClick" "', argument " "1"" of type '" "op::Op *""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_MoveToExSmooth" "', argument " "1"" of type '" "op::Op *""'"); } arg1 = reinterpret_cast< op::Op * >(argp1); - (arg1)->LeftDoubleClick(arg2); + ecode2 = SWIG_AsVal_long(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Op_MoveToExSmooth" "', argument " "2"" of type '" "long""'"); + } + arg2 = static_cast< long >(val2); + ecode3 = SWIG_AsVal_long(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Op_MoveToExSmooth" "', argument " "3"" of type '" "long""'"); + } + arg3 = static_cast< long >(val3); + ecode4 = SWIG_AsVal_long(swig_obj[3], &val4); + if (!SWIG_IsOK(ecode4)) { + SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Op_MoveToExSmooth" "', argument " "4"" of type '" "long""'"); + } + arg4 = static_cast< long >(val4); + ecode5 = SWIG_AsVal_long(swig_obj[4], &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Op_MoveToExSmooth" "', argument " "5"" of type '" "long""'"); + } + arg5 = static_cast< long >(val5); + ecode6 = SWIG_AsVal_long(swig_obj[5], &val6); + if (!SWIG_IsOK(ecode6)) { + SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Op_MoveToExSmooth" "', argument " "6"" of type '" "long""'"); + } + arg6 = static_cast< long >(val6); + (arg1)->MoveToExSmooth(arg2,arg3,arg4,arg5,arg6,*arg7); resultobj = SWIG_Py_Void(); - if (SWIG_IsTmpObj(res2)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg2)), 1); + if (SWIG_IsTmpObj(res7)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_std_wstring((*arg7)), 1); } else { - int new_flags = SWIG_IsNewObj(res2) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg2), SWIGTYPE_p_long, new_flags), 1); + int new_flags = SWIG_IsNewObj(res7) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg7), SWIGTYPE_p_std__wstring, new_flags), 1); } return resultobj; fail: @@ -7639,98 +7741,346 @@ SWIGINTERN PyObject *_wrap_Op_LeftDoubleClick(PyObject *self, PyObject *args) { } -SWIGINTERN PyObject *_wrap_Op_LeftDown(PyObject *self, PyObject *args) { +SWIGINTERN PyObject *_wrap_Op_MovePath(PyObject *self, PyObject *args) { PyObject *resultobj = 0; op::Op *arg1 = 0 ; - long *arg2 = 0 ; + wchar_t *arg2 = 0 ; + long arg3 ; + long *arg4 = 0 ; void *argp1 = 0 ; int res1 = 0 ; - long temp2 ; - int res2 = SWIG_TMPOBJ ; - PyObject *swig_obj[1] ; + int res2 ; + wchar_t *buf2 = 0 ; + int alloc2 = 0 ; + long val3 ; + int ecode3 = 0 ; + long temp4 ; + int res4 = SWIG_TMPOBJ ; + PyObject *swig_obj[3] ; - arg2 = &temp2; + arg4 = &temp4; (void)self; - if (!args) SWIG_fail; - swig_obj[0] = args; + if (!SWIG_Python_UnpackTuple(args, "Op_MovePath", 3, 3, swig_obj)) SWIG_fail; res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_LeftDown" "', argument " "1"" of type '" "op::Op *""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_MovePath" "', argument " "1"" of type '" "op::Op *""'"); } arg1 = reinterpret_cast< op::Op * >(argp1); - (arg1)->LeftDown(arg2); + res2 = SWIG_AsWCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Op_MovePath" "', argument " "2"" of type '" "wchar_t const *""'"); + } + arg2 = reinterpret_cast< wchar_t * >(buf2); + ecode3 = SWIG_AsVal_long(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Op_MovePath" "', argument " "3"" of type '" "long""'"); + } + arg3 = static_cast< long >(val3); + (arg1)->MovePath((wchar_t const *)arg2,arg3,arg4); resultobj = SWIG_Py_Void(); - if (SWIG_IsTmpObj(res2)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg2)), 1); + if (SWIG_IsTmpObj(res4)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg4)), 1); } else { - int new_flags = SWIG_IsNewObj(res2) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg2), SWIGTYPE_p_long, new_flags), 1); + int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_long, new_flags), 1); } + if (alloc2 == SWIG_NEWOBJ) delete[] buf2; return resultobj; fail: + if (alloc2 == SWIG_NEWOBJ) delete[] buf2; return NULL; } -SWIGINTERN PyObject *_wrap_Op_LeftUp(PyObject *self, PyObject *args) { +SWIGINTERN PyObject *_wrap_Op_DragPath(PyObject *self, PyObject *args) { PyObject *resultobj = 0; op::Op *arg1 = 0 ; - long *arg2 = 0 ; + wchar_t *arg2 = 0 ; + long arg3 ; + long *arg4 = 0 ; void *argp1 = 0 ; int res1 = 0 ; - long temp2 ; - int res2 = SWIG_TMPOBJ ; - PyObject *swig_obj[1] ; + int res2 ; + wchar_t *buf2 = 0 ; + int alloc2 = 0 ; + long val3 ; + int ecode3 = 0 ; + long temp4 ; + int res4 = SWIG_TMPOBJ ; + PyObject *swig_obj[3] ; - arg2 = &temp2; + arg4 = &temp4; (void)self; - if (!args) SWIG_fail; - swig_obj[0] = args; + if (!SWIG_Python_UnpackTuple(args, "Op_DragPath", 3, 3, swig_obj)) SWIG_fail; res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_LeftUp" "', argument " "1"" of type '" "op::Op *""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_DragPath" "', argument " "1"" of type '" "op::Op *""'"); } arg1 = reinterpret_cast< op::Op * >(argp1); - (arg1)->LeftUp(arg2); + res2 = SWIG_AsWCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Op_DragPath" "', argument " "2"" of type '" "wchar_t const *""'"); + } + arg2 = reinterpret_cast< wchar_t * >(buf2); + ecode3 = SWIG_AsVal_long(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Op_DragPath" "', argument " "3"" of type '" "long""'"); + } + arg3 = static_cast< long >(val3); + (arg1)->DragPath((wchar_t const *)arg2,arg3,arg4); resultobj = SWIG_Py_Void(); - if (SWIG_IsTmpObj(res2)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg2)), 1); + if (SWIG_IsTmpObj(res4)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg4)), 1); } else { - int new_flags = SWIG_IsNewObj(res2) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg2), SWIGTYPE_p_long, new_flags), 1); + int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_long, new_flags), 1); } + if (alloc2 == SWIG_NEWOBJ) delete[] buf2; return resultobj; fail: + if (alloc2 == SWIG_NEWOBJ) delete[] buf2; return NULL; } -SWIGINTERN PyObject *_wrap_Op_MiddleClick(PyObject *self, PyObject *args) { +SWIGINTERN PyObject *_wrap_Op_SetMouseTrajectory(PyObject *self, PyObject *args) { PyObject *resultobj = 0; op::Op *arg1 = 0 ; - long *arg2 = 0 ; + long arg2 ; + long arg3 ; + long arg4 ; + long arg5 ; + long arg6 ; + long arg7 ; + long *arg8 = 0 ; void *argp1 = 0 ; int res1 = 0 ; - long temp2 ; - int res2 = SWIG_TMPOBJ ; - PyObject *swig_obj[1] ; + long val2 ; + int ecode2 = 0 ; + long val3 ; + int ecode3 = 0 ; + long val4 ; + int ecode4 = 0 ; + long val5 ; + int ecode5 = 0 ; + long val6 ; + int ecode6 = 0 ; + long val7 ; + int ecode7 = 0 ; + long temp8 ; + int res8 = SWIG_TMPOBJ ; + PyObject *swig_obj[7] ; - arg2 = &temp2; + arg8 = &temp8; (void)self; - if (!args) SWIG_fail; - swig_obj[0] = args; + if (!SWIG_Python_UnpackTuple(args, "Op_SetMouseTrajectory", 7, 7, swig_obj)) SWIG_fail; res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_MiddleClick" "', argument " "1"" of type '" "op::Op *""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_SetMouseTrajectory" "', argument " "1"" of type '" "op::Op *""'"); } arg1 = reinterpret_cast< op::Op * >(argp1); - (arg1)->MiddleClick(arg2); - resultobj = SWIG_Py_Void(); - if (SWIG_IsTmpObj(res2)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg2)), 1); - } else { - int new_flags = SWIG_IsNewObj(res2) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg2), SWIGTYPE_p_long, new_flags), 1); + ecode2 = SWIG_AsVal_long(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Op_SetMouseTrajectory" "', argument " "2"" of type '" "long""'"); + } + arg2 = static_cast< long >(val2); + ecode3 = SWIG_AsVal_long(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Op_SetMouseTrajectory" "', argument " "3"" of type '" "long""'"); + } + arg3 = static_cast< long >(val3); + ecode4 = SWIG_AsVal_long(swig_obj[3], &val4); + if (!SWIG_IsOK(ecode4)) { + SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Op_SetMouseTrajectory" "', argument " "4"" of type '" "long""'"); + } + arg4 = static_cast< long >(val4); + ecode5 = SWIG_AsVal_long(swig_obj[4], &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Op_SetMouseTrajectory" "', argument " "5"" of type '" "long""'"); + } + arg5 = static_cast< long >(val5); + ecode6 = SWIG_AsVal_long(swig_obj[5], &val6); + if (!SWIG_IsOK(ecode6)) { + SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Op_SetMouseTrajectory" "', argument " "6"" of type '" "long""'"); + } + arg6 = static_cast< long >(val6); + ecode7 = SWIG_AsVal_long(swig_obj[6], &val7); + if (!SWIG_IsOK(ecode7)) { + SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Op_SetMouseTrajectory" "', argument " "7"" of type '" "long""'"); + } + arg7 = static_cast< long >(val7); + (arg1)->SetMouseTrajectory(arg2,arg3,arg4,arg5,arg6,arg7,arg8); + resultobj = SWIG_Py_Void(); + if (SWIG_IsTmpObj(res8)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg8)), 1); + } else { + int new_flags = SWIG_IsNewObj(res8) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg8), SWIGTYPE_p_long, new_flags), 1); + } + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Op_LeftClick(PyObject *self, PyObject *args) { + PyObject *resultobj = 0; + op::Op *arg1 = 0 ; + long *arg2 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + long temp2 ; + int res2 = SWIG_TMPOBJ ; + PyObject *swig_obj[1] ; + + arg2 = &temp2; + (void)self; + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_LeftClick" "', argument " "1"" of type '" "op::Op *""'"); + } + arg1 = reinterpret_cast< op::Op * >(argp1); + (arg1)->LeftClick(arg2); + resultobj = SWIG_Py_Void(); + if (SWIG_IsTmpObj(res2)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg2)), 1); + } else { + int new_flags = SWIG_IsNewObj(res2) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg2), SWIGTYPE_p_long, new_flags), 1); + } + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Op_LeftDoubleClick(PyObject *self, PyObject *args) { + PyObject *resultobj = 0; + op::Op *arg1 = 0 ; + long *arg2 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + long temp2 ; + int res2 = SWIG_TMPOBJ ; + PyObject *swig_obj[1] ; + + arg2 = &temp2; + (void)self; + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_LeftDoubleClick" "', argument " "1"" of type '" "op::Op *""'"); + } + arg1 = reinterpret_cast< op::Op * >(argp1); + (arg1)->LeftDoubleClick(arg2); + resultobj = SWIG_Py_Void(); + if (SWIG_IsTmpObj(res2)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg2)), 1); + } else { + int new_flags = SWIG_IsNewObj(res2) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg2), SWIGTYPE_p_long, new_flags), 1); + } + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Op_LeftDown(PyObject *self, PyObject *args) { + PyObject *resultobj = 0; + op::Op *arg1 = 0 ; + long *arg2 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + long temp2 ; + int res2 = SWIG_TMPOBJ ; + PyObject *swig_obj[1] ; + + arg2 = &temp2; + (void)self; + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_LeftDown" "', argument " "1"" of type '" "op::Op *""'"); + } + arg1 = reinterpret_cast< op::Op * >(argp1); + (arg1)->LeftDown(arg2); + resultobj = SWIG_Py_Void(); + if (SWIG_IsTmpObj(res2)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg2)), 1); + } else { + int new_flags = SWIG_IsNewObj(res2) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg2), SWIGTYPE_p_long, new_flags), 1); + } + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Op_LeftUp(PyObject *self, PyObject *args) { + PyObject *resultobj = 0; + op::Op *arg1 = 0 ; + long *arg2 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + long temp2 ; + int res2 = SWIG_TMPOBJ ; + PyObject *swig_obj[1] ; + + arg2 = &temp2; + (void)self; + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_LeftUp" "', argument " "1"" of type '" "op::Op *""'"); + } + arg1 = reinterpret_cast< op::Op * >(argp1); + (arg1)->LeftUp(arg2); + resultobj = SWIG_Py_Void(); + if (SWIG_IsTmpObj(res2)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg2)), 1); + } else { + int new_flags = SWIG_IsNewObj(res2) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg2), SWIGTYPE_p_long, new_flags), 1); + } + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Op_MiddleClick(PyObject *self, PyObject *args) { + PyObject *resultobj = 0; + op::Op *arg1 = 0 ; + long *arg2 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + long temp2 ; + int res2 = SWIG_TMPOBJ ; + PyObject *swig_obj[1] ; + + arg2 = &temp2; + (void)self; + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_MiddleClick" "', argument " "1"" of type '" "op::Op *""'"); + } + arg1 = reinterpret_cast< op::Op * >(argp1); + (arg1)->MiddleClick(arg2); + resultobj = SWIG_Py_Void(); + if (SWIG_IsTmpObj(res2)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg2)), 1); + } else { + int new_flags = SWIG_IsNewObj(res2) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg2), SWIGTYPE_p_long, new_flags), 1); } return resultobj; fail: @@ -13389,16 +13739,14 @@ SWIGINTERN PyObject *_wrap_Op_SetMemDict(PyObject *self, PyObject *args) { PyObject *resultobj = 0; op::Op *arg1 = 0 ; long arg2 ; - wchar_t *arg3 = 0 ; + void *arg3 = 0 ; long arg4 ; long *arg5 = 0 ; void *argp1 = 0 ; int res1 = 0 ; long val2 ; int ecode2 = 0 ; - int res3 ; - wchar_t *buf3 = 0 ; - int alloc3 = 0 ; + Py_buffer view3 ; long val4 ; int ecode4 = 0 ; long temp5 ; @@ -13418,17 +13766,18 @@ SWIGINTERN PyObject *_wrap_Op_SetMemDict(PyObject *self, PyObject *args) { SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Op_SetMemDict" "', argument " "2"" of type '" "long""'"); } arg2 = static_cast< long >(val2); - res3 = SWIG_AsWCharPtrAndSize(swig_obj[2], &buf3, NULL, &alloc3); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Op_SetMemDict" "', argument " "3"" of type '" "wchar_t const *""'"); + { + if (PyObject_GetBuffer(swig_obj[2], &view3, PyBUF_SIMPLE) != 0) { + SWIG_exception_fail(SWIG_TypeError, "expected a bytes-like object"); + } + arg3 = view3.buf; } - arg3 = reinterpret_cast< wchar_t * >(buf3); ecode4 = SWIG_AsVal_long(swig_obj[3], &val4); if (!SWIG_IsOK(ecode4)) { SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Op_SetMemDict" "', argument " "4"" of type '" "long""'"); } arg4 = static_cast< long >(val4); - (arg1)->SetMemDict(arg2,(wchar_t const *)arg3,arg4,arg5); + (arg1)->SetMemDict(arg2,(void const *)arg3,arg4,arg5); resultobj = SWIG_Py_Void(); if (SWIG_IsTmpObj(res5)) { resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg5)), 1); @@ -13436,10 +13785,14 @@ SWIGINTERN PyObject *_wrap_Op_SetMemDict(PyObject *self, PyObject *args) { int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN | 0 ) : 0 ; resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_long, new_flags), 1); } - if (alloc3 == SWIG_NEWOBJ) delete[] buf3; + { + PyBuffer_Release(&view3); + } return resultobj; fail: - if (alloc3 == SWIG_NEWOBJ) delete[] buf3; + { + PyBuffer_Release(&view3); + } return NULL; } @@ -13699,16 +14052,14 @@ SWIGINTERN PyObject *_wrap_Op_GetNowDict(PyObject *self, PyObject *args) { } -SWIGINTERN PyObject *_wrap_Op_FetchWord(PyObject *self, PyObject *args) { +SWIGINTERN PyObject *_wrap_Op_SetBinaryPreprocess(PyObject *self, PyObject *args) { PyObject *resultobj = 0; op::Op *arg1 = 0 ; long arg2 ; long arg3 ; long arg4 ; long arg5 ; - wchar_t *arg6 = 0 ; - wchar_t *arg7 = 0 ; - std::wstring *arg8 = 0 ; + long *arg6 = 0 ; void *argp1 = 0 ; int res1 = 0 ; long val2 ; @@ -13719,63 +14070,202 @@ SWIGINTERN PyObject *_wrap_Op_FetchWord(PyObject *self, PyObject *args) { int ecode4 = 0 ; long val5 ; int ecode5 = 0 ; - int res6 ; - wchar_t *buf6 = 0 ; - int alloc6 = 0 ; - int res7 ; - wchar_t *buf7 = 0 ; - int alloc7 = 0 ; - std::wstring temp8 ; - int res8 = SWIG_TMPOBJ ; - PyObject *swig_obj[7] ; + long temp6 ; + int res6 = SWIG_TMPOBJ ; + PyObject *swig_obj[5] ; - arg8 = &temp8; + arg6 = &temp6; (void)self; - if (!SWIG_Python_UnpackTuple(args, "Op_FetchWord", 7, 7, swig_obj)) SWIG_fail; + if (!SWIG_Python_UnpackTuple(args, "Op_SetBinaryPreprocess", 5, 5, swig_obj)) SWIG_fail; res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_FetchWord" "', argument " "1"" of type '" "op::Op *""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_SetBinaryPreprocess" "', argument " "1"" of type '" "op::Op *""'"); } arg1 = reinterpret_cast< op::Op * >(argp1); ecode2 = SWIG_AsVal_long(swig_obj[1], &val2); if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Op_FetchWord" "', argument " "2"" of type '" "long""'"); + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Op_SetBinaryPreprocess" "', argument " "2"" of type '" "long""'"); } arg2 = static_cast< long >(val2); ecode3 = SWIG_AsVal_long(swig_obj[2], &val3); if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Op_FetchWord" "', argument " "3"" of type '" "long""'"); + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Op_SetBinaryPreprocess" "', argument " "3"" of type '" "long""'"); } arg3 = static_cast< long >(val3); ecode4 = SWIG_AsVal_long(swig_obj[3], &val4); if (!SWIG_IsOK(ecode4)) { - SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Op_FetchWord" "', argument " "4"" of type '" "long""'"); + SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Op_SetBinaryPreprocess" "', argument " "4"" of type '" "long""'"); } arg4 = static_cast< long >(val4); ecode5 = SWIG_AsVal_long(swig_obj[4], &val5); if (!SWIG_IsOK(ecode5)) { - SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Op_FetchWord" "', argument " "5"" of type '" "long""'"); + SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Op_SetBinaryPreprocess" "', argument " "5"" of type '" "long""'"); } arg5 = static_cast< long >(val5); - res6 = SWIG_AsWCharPtrAndSize(swig_obj[5], &buf6, NULL, &alloc6); - if (!SWIG_IsOK(res6)) { - SWIG_exception_fail(SWIG_ArgError(res6), "in method '" "Op_FetchWord" "', argument " "6"" of type '" "wchar_t const *""'"); - } - arg6 = reinterpret_cast< wchar_t * >(buf6); - res7 = SWIG_AsWCharPtrAndSize(swig_obj[6], &buf7, NULL, &alloc7); - if (!SWIG_IsOK(res7)) { - SWIG_exception_fail(SWIG_ArgError(res7), "in method '" "Op_FetchWord" "', argument " "7"" of type '" "wchar_t const *""'"); - } - arg7 = reinterpret_cast< wchar_t * >(buf7); - (arg1)->FetchWord(arg2,arg3,arg4,arg5,(wchar_t const *)arg6,(wchar_t const *)arg7,*arg8); + (arg1)->SetBinaryPreprocess(arg2,arg3,arg4,arg5,arg6); resultobj = SWIG_Py_Void(); - if (SWIG_IsTmpObj(res8)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_std_wstring((*arg8)), 1); + if (SWIG_IsTmpObj(res6)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg6)), 1); } else { - int new_flags = SWIG_IsNewObj(res8) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg8), SWIGTYPE_p_std__wstring, new_flags), 1); + int new_flags = SWIG_IsNewObj(res6) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg6), SWIGTYPE_p_long, new_flags), 1); } - if (alloc6 == SWIG_NEWOBJ) delete[] buf6; + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Op_GetBinaryPreprocess(PyObject *self, PyObject *args) { + PyObject *resultobj = 0; + op::Op *arg1 = 0 ; + long *arg2 = 0 ; + long *arg3 = 0 ; + long *arg4 = 0 ; + long *arg5 = 0 ; + long *arg6 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + long temp2 ; + int res2 = SWIG_TMPOBJ ; + long temp3 ; + int res3 = SWIG_TMPOBJ ; + long temp4 ; + int res4 = SWIG_TMPOBJ ; + long temp5 ; + int res5 = SWIG_TMPOBJ ; + long temp6 ; + int res6 = SWIG_TMPOBJ ; + PyObject *swig_obj[1] ; + + arg2 = &temp2; + arg3 = &temp3; + arg4 = &temp4; + arg5 = &temp5; + arg6 = &temp6; + (void)self; + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_GetBinaryPreprocess" "', argument " "1"" of type '" "op::Op *""'"); + } + arg1 = reinterpret_cast< op::Op * >(argp1); + (arg1)->GetBinaryPreprocess(arg2,arg3,arg4,arg5,arg6); + resultobj = SWIG_Py_Void(); + if (SWIG_IsTmpObj(res2)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg2)), 1); + } else { + int new_flags = SWIG_IsNewObj(res2) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg2), SWIGTYPE_p_long, new_flags), 1); + } + if (SWIG_IsTmpObj(res3)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg3)), 1); + } else { + int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_long, new_flags), 1); + } + if (SWIG_IsTmpObj(res4)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg4)), 1); + } else { + int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_long, new_flags), 1); + } + if (SWIG_IsTmpObj(res5)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg5)), 1); + } else { + int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_long, new_flags), 1); + } + if (SWIG_IsTmpObj(res6)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg6)), 1); + } else { + int new_flags = SWIG_IsNewObj(res6) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg6), SWIGTYPE_p_long, new_flags), 1); + } + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Op_FetchWord(PyObject *self, PyObject *args) { + PyObject *resultobj = 0; + op::Op *arg1 = 0 ; + long arg2 ; + long arg3 ; + long arg4 ; + long arg5 ; + wchar_t *arg6 = 0 ; + wchar_t *arg7 = 0 ; + std::wstring *arg8 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + long val2 ; + int ecode2 = 0 ; + long val3 ; + int ecode3 = 0 ; + long val4 ; + int ecode4 = 0 ; + long val5 ; + int ecode5 = 0 ; + int res6 ; + wchar_t *buf6 = 0 ; + int alloc6 = 0 ; + int res7 ; + wchar_t *buf7 = 0 ; + int alloc7 = 0 ; + std::wstring temp8 ; + int res8 = SWIG_TMPOBJ ; + PyObject *swig_obj[7] ; + + arg8 = &temp8; + (void)self; + if (!SWIG_Python_UnpackTuple(args, "Op_FetchWord", 7, 7, swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_FetchWord" "', argument " "1"" of type '" "op::Op *""'"); + } + arg1 = reinterpret_cast< op::Op * >(argp1); + ecode2 = SWIG_AsVal_long(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Op_FetchWord" "', argument " "2"" of type '" "long""'"); + } + arg2 = static_cast< long >(val2); + ecode3 = SWIG_AsVal_long(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Op_FetchWord" "', argument " "3"" of type '" "long""'"); + } + arg3 = static_cast< long >(val3); + ecode4 = SWIG_AsVal_long(swig_obj[3], &val4); + if (!SWIG_IsOK(ecode4)) { + SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Op_FetchWord" "', argument " "4"" of type '" "long""'"); + } + arg4 = static_cast< long >(val4); + ecode5 = SWIG_AsVal_long(swig_obj[4], &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Op_FetchWord" "', argument " "5"" of type '" "long""'"); + } + arg5 = static_cast< long >(val5); + res6 = SWIG_AsWCharPtrAndSize(swig_obj[5], &buf6, NULL, &alloc6); + if (!SWIG_IsOK(res6)) { + SWIG_exception_fail(SWIG_ArgError(res6), "in method '" "Op_FetchWord" "', argument " "6"" of type '" "wchar_t const *""'"); + } + arg6 = reinterpret_cast< wchar_t * >(buf6); + res7 = SWIG_AsWCharPtrAndSize(swig_obj[6], &buf7, NULL, &alloc7); + if (!SWIG_IsOK(res7)) { + SWIG_exception_fail(SWIG_ArgError(res7), "in method '" "Op_FetchWord" "', argument " "7"" of type '" "wchar_t const *""'"); + } + arg7 = reinterpret_cast< wchar_t * >(buf7); + (arg1)->FetchWord(arg2,arg3,arg4,arg5,(wchar_t const *)arg6,(wchar_t const *)arg7,*arg8); + resultobj = SWIG_Py_Void(); + if (SWIG_IsTmpObj(res8)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_std_wstring((*arg8)), 1); + } else { + int new_flags = SWIG_IsNewObj(res8) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg8), SWIGTYPE_p_std__wstring, new_flags), 1); + } + if (alloc6 == SWIG_NEWOBJ) delete[] buf6; if (alloc7 == SWIG_NEWOBJ) delete[] buf7; return resultobj; fail: @@ -13785,6 +14275,939 @@ SWIGINTERN PyObject *_wrap_Op_FetchWord(PyObject *self, PyObject *args) { } +SWIGINTERN PyObject *_wrap_Op_FetchWordEx(PyObject *self, PyObject *args) { + PyObject *resultobj = 0; + op::Op *arg1 = 0 ; + long arg2 ; + long arg3 ; + long arg4 ; + long arg5 ; + wchar_t *arg6 = 0 ; + double arg7 ; + wchar_t *arg8 = 0 ; + std::wstring *arg9 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + long val2 ; + int ecode2 = 0 ; + long val3 ; + int ecode3 = 0 ; + long val4 ; + int ecode4 = 0 ; + long val5 ; + int ecode5 = 0 ; + int res6 ; + wchar_t *buf6 = 0 ; + int alloc6 = 0 ; + double val7 ; + int ecode7 = 0 ; + int res8 ; + wchar_t *buf8 = 0 ; + int alloc8 = 0 ; + std::wstring temp9 ; + int res9 = SWIG_TMPOBJ ; + PyObject *swig_obj[8] ; + + arg9 = &temp9; + (void)self; + if (!SWIG_Python_UnpackTuple(args, "Op_FetchWordEx", 8, 8, swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_FetchWordEx" "', argument " "1"" of type '" "op::Op *""'"); + } + arg1 = reinterpret_cast< op::Op * >(argp1); + ecode2 = SWIG_AsVal_long(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Op_FetchWordEx" "', argument " "2"" of type '" "long""'"); + } + arg2 = static_cast< long >(val2); + ecode3 = SWIG_AsVal_long(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Op_FetchWordEx" "', argument " "3"" of type '" "long""'"); + } + arg3 = static_cast< long >(val3); + ecode4 = SWIG_AsVal_long(swig_obj[3], &val4); + if (!SWIG_IsOK(ecode4)) { + SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Op_FetchWordEx" "', argument " "4"" of type '" "long""'"); + } + arg4 = static_cast< long >(val4); + ecode5 = SWIG_AsVal_long(swig_obj[4], &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Op_FetchWordEx" "', argument " "5"" of type '" "long""'"); + } + arg5 = static_cast< long >(val5); + res6 = SWIG_AsWCharPtrAndSize(swig_obj[5], &buf6, NULL, &alloc6); + if (!SWIG_IsOK(res6)) { + SWIG_exception_fail(SWIG_ArgError(res6), "in method '" "Op_FetchWordEx" "', argument " "6"" of type '" "wchar_t const *""'"); + } + arg6 = reinterpret_cast< wchar_t * >(buf6); + ecode7 = SWIG_AsVal_double(swig_obj[6], &val7); + if (!SWIG_IsOK(ecode7)) { + SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Op_FetchWordEx" "', argument " "7"" of type '" "double""'"); + } + arg7 = static_cast< double >(val7); + res8 = SWIG_AsWCharPtrAndSize(swig_obj[7], &buf8, NULL, &alloc8); + if (!SWIG_IsOK(res8)) { + SWIG_exception_fail(SWIG_ArgError(res8), "in method '" "Op_FetchWordEx" "', argument " "8"" of type '" "wchar_t const *""'"); + } + arg8 = reinterpret_cast< wchar_t * >(buf8); + (arg1)->FetchWordEx(arg2,arg3,arg4,arg5,(wchar_t const *)arg6,arg7,(wchar_t const *)arg8,*arg9); + resultobj = SWIG_Py_Void(); + if (SWIG_IsTmpObj(res9)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_std_wstring((*arg9)), 1); + } else { + int new_flags = SWIG_IsNewObj(res9) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg9), SWIGTYPE_p_std__wstring, new_flags), 1); + } + if (alloc6 == SWIG_NEWOBJ) delete[] buf6; + if (alloc8 == SWIG_NEWOBJ) delete[] buf8; + return resultobj; +fail: + if (alloc6 == SWIG_NEWOBJ) delete[] buf6; + if (alloc8 == SWIG_NEWOBJ) delete[] buf8; + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Op_ExtractWordRects(PyObject *self, PyObject *args) { + PyObject *resultobj = 0; + op::Op *arg1 = 0 ; + long arg2 ; + long arg3 ; + long arg4 ; + long arg5 ; + wchar_t *arg6 = 0 ; + double arg7 ; + long arg8 ; + std::wstring *arg9 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + long val2 ; + int ecode2 = 0 ; + long val3 ; + int ecode3 = 0 ; + long val4 ; + int ecode4 = 0 ; + long val5 ; + int ecode5 = 0 ; + int res6 ; + wchar_t *buf6 = 0 ; + int alloc6 = 0 ; + double val7 ; + int ecode7 = 0 ; + long val8 ; + int ecode8 = 0 ; + std::wstring temp9 ; + int res9 = SWIG_TMPOBJ ; + PyObject *swig_obj[8] ; + + arg9 = &temp9; + (void)self; + if (!SWIG_Python_UnpackTuple(args, "Op_ExtractWordRects", 8, 8, swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_ExtractWordRects" "', argument " "1"" of type '" "op::Op *""'"); + } + arg1 = reinterpret_cast< op::Op * >(argp1); + ecode2 = SWIG_AsVal_long(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Op_ExtractWordRects" "', argument " "2"" of type '" "long""'"); + } + arg2 = static_cast< long >(val2); + ecode3 = SWIG_AsVal_long(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Op_ExtractWordRects" "', argument " "3"" of type '" "long""'"); + } + arg3 = static_cast< long >(val3); + ecode4 = SWIG_AsVal_long(swig_obj[3], &val4); + if (!SWIG_IsOK(ecode4)) { + SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Op_ExtractWordRects" "', argument " "4"" of type '" "long""'"); + } + arg4 = static_cast< long >(val4); + ecode5 = SWIG_AsVal_long(swig_obj[4], &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Op_ExtractWordRects" "', argument " "5"" of type '" "long""'"); + } + arg5 = static_cast< long >(val5); + res6 = SWIG_AsWCharPtrAndSize(swig_obj[5], &buf6, NULL, &alloc6); + if (!SWIG_IsOK(res6)) { + SWIG_exception_fail(SWIG_ArgError(res6), "in method '" "Op_ExtractWordRects" "', argument " "6"" of type '" "wchar_t const *""'"); + } + arg6 = reinterpret_cast< wchar_t * >(buf6); + ecode7 = SWIG_AsVal_double(swig_obj[6], &val7); + if (!SWIG_IsOK(ecode7)) { + SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Op_ExtractWordRects" "', argument " "7"" of type '" "double""'"); + } + arg7 = static_cast< double >(val7); + ecode8 = SWIG_AsVal_long(swig_obj[7], &val8); + if (!SWIG_IsOK(ecode8)) { + SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "Op_ExtractWordRects" "', argument " "8"" of type '" "long""'"); + } + arg8 = static_cast< long >(val8); + (arg1)->ExtractWordRects(arg2,arg3,arg4,arg5,(wchar_t const *)arg6,arg7,arg8,*arg9); + resultobj = SWIG_Py_Void(); + if (SWIG_IsTmpObj(res9)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_std_wstring((*arg9)), 1); + } else { + int new_flags = SWIG_IsNewObj(res9) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg9), SWIGTYPE_p_std__wstring, new_flags), 1); + } + if (alloc6 == SWIG_NEWOBJ) delete[] buf6; + return resultobj; +fail: + if (alloc6 == SWIG_NEWOBJ) delete[] buf6; + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Op_ExtractWordRectsEx(PyObject *self, PyObject *args) { + PyObject *resultobj = 0; + op::Op *arg1 = 0 ; + long arg2 ; + long arg3 ; + long arg4 ; + long arg5 ; + wchar_t *arg6 = 0 ; + double arg7 ; + long arg8 ; + long arg9 ; + long arg10 ; + std::wstring *arg11 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + long val2 ; + int ecode2 = 0 ; + long val3 ; + int ecode3 = 0 ; + long val4 ; + int ecode4 = 0 ; + long val5 ; + int ecode5 = 0 ; + int res6 ; + wchar_t *buf6 = 0 ; + int alloc6 = 0 ; + double val7 ; + int ecode7 = 0 ; + long val8 ; + int ecode8 = 0 ; + long val9 ; + int ecode9 = 0 ; + long val10 ; + int ecode10 = 0 ; + std::wstring temp11 ; + int res11 = SWIG_TMPOBJ ; + PyObject *swig_obj[10] ; + + arg11 = &temp11; + (void)self; + if (!SWIG_Python_UnpackTuple(args, "Op_ExtractWordRectsEx", 10, 10, swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_ExtractWordRectsEx" "', argument " "1"" of type '" "op::Op *""'"); + } + arg1 = reinterpret_cast< op::Op * >(argp1); + ecode2 = SWIG_AsVal_long(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Op_ExtractWordRectsEx" "', argument " "2"" of type '" "long""'"); + } + arg2 = static_cast< long >(val2); + ecode3 = SWIG_AsVal_long(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Op_ExtractWordRectsEx" "', argument " "3"" of type '" "long""'"); + } + arg3 = static_cast< long >(val3); + ecode4 = SWIG_AsVal_long(swig_obj[3], &val4); + if (!SWIG_IsOK(ecode4)) { + SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Op_ExtractWordRectsEx" "', argument " "4"" of type '" "long""'"); + } + arg4 = static_cast< long >(val4); + ecode5 = SWIG_AsVal_long(swig_obj[4], &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Op_ExtractWordRectsEx" "', argument " "5"" of type '" "long""'"); + } + arg5 = static_cast< long >(val5); + res6 = SWIG_AsWCharPtrAndSize(swig_obj[5], &buf6, NULL, &alloc6); + if (!SWIG_IsOK(res6)) { + SWIG_exception_fail(SWIG_ArgError(res6), "in method '" "Op_ExtractWordRectsEx" "', argument " "6"" of type '" "wchar_t const *""'"); + } + arg6 = reinterpret_cast< wchar_t * >(buf6); + ecode7 = SWIG_AsVal_double(swig_obj[6], &val7); + if (!SWIG_IsOK(ecode7)) { + SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Op_ExtractWordRectsEx" "', argument " "7"" of type '" "double""'"); + } + arg7 = static_cast< double >(val7); + ecode8 = SWIG_AsVal_long(swig_obj[7], &val8); + if (!SWIG_IsOK(ecode8)) { + SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "Op_ExtractWordRectsEx" "', argument " "8"" of type '" "long""'"); + } + arg8 = static_cast< long >(val8); + ecode9 = SWIG_AsVal_long(swig_obj[8], &val9); + if (!SWIG_IsOK(ecode9)) { + SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "Op_ExtractWordRectsEx" "', argument " "9"" of type '" "long""'"); + } + arg9 = static_cast< long >(val9); + ecode10 = SWIG_AsVal_long(swig_obj[9], &val10); + if (!SWIG_IsOK(ecode10)) { + SWIG_exception_fail(SWIG_ArgError(ecode10), "in method '" "Op_ExtractWordRectsEx" "', argument " "10"" of type '" "long""'"); + } + arg10 = static_cast< long >(val10); + (arg1)->ExtractWordRectsEx(arg2,arg3,arg4,arg5,(wchar_t const *)arg6,arg7,arg8,arg9,arg10,*arg11); + resultobj = SWIG_Py_Void(); + if (SWIG_IsTmpObj(res11)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_std_wstring((*arg11)), 1); + } else { + int new_flags = SWIG_IsNewObj(res11) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg11), SWIGTYPE_p_std__wstring, new_flags), 1); + } + if (alloc6 == SWIG_NEWOBJ) delete[] buf6; + return resultobj; +fail: + if (alloc6 == SWIG_NEWOBJ) delete[] buf6; + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Op_FetchWords(PyObject *self, PyObject *args) { + PyObject *resultobj = 0; + op::Op *arg1 = 0 ; + long arg2 ; + long arg3 ; + long arg4 ; + long arg5 ; + wchar_t *arg6 = 0 ; + double arg7 ; + wchar_t *arg8 = 0 ; + long arg9 ; + std::wstring *arg10 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + long val2 ; + int ecode2 = 0 ; + long val3 ; + int ecode3 = 0 ; + long val4 ; + int ecode4 = 0 ; + long val5 ; + int ecode5 = 0 ; + int res6 ; + wchar_t *buf6 = 0 ; + int alloc6 = 0 ; + double val7 ; + int ecode7 = 0 ; + int res8 ; + wchar_t *buf8 = 0 ; + int alloc8 = 0 ; + long val9 ; + int ecode9 = 0 ; + std::wstring temp10 ; + int res10 = SWIG_TMPOBJ ; + PyObject *swig_obj[9] ; + + arg10 = &temp10; + (void)self; + if (!SWIG_Python_UnpackTuple(args, "Op_FetchWords", 9, 9, swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_FetchWords" "', argument " "1"" of type '" "op::Op *""'"); + } + arg1 = reinterpret_cast< op::Op * >(argp1); + ecode2 = SWIG_AsVal_long(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Op_FetchWords" "', argument " "2"" of type '" "long""'"); + } + arg2 = static_cast< long >(val2); + ecode3 = SWIG_AsVal_long(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Op_FetchWords" "', argument " "3"" of type '" "long""'"); + } + arg3 = static_cast< long >(val3); + ecode4 = SWIG_AsVal_long(swig_obj[3], &val4); + if (!SWIG_IsOK(ecode4)) { + SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Op_FetchWords" "', argument " "4"" of type '" "long""'"); + } + arg4 = static_cast< long >(val4); + ecode5 = SWIG_AsVal_long(swig_obj[4], &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Op_FetchWords" "', argument " "5"" of type '" "long""'"); + } + arg5 = static_cast< long >(val5); + res6 = SWIG_AsWCharPtrAndSize(swig_obj[5], &buf6, NULL, &alloc6); + if (!SWIG_IsOK(res6)) { + SWIG_exception_fail(SWIG_ArgError(res6), "in method '" "Op_FetchWords" "', argument " "6"" of type '" "wchar_t const *""'"); + } + arg6 = reinterpret_cast< wchar_t * >(buf6); + ecode7 = SWIG_AsVal_double(swig_obj[6], &val7); + if (!SWIG_IsOK(ecode7)) { + SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Op_FetchWords" "', argument " "7"" of type '" "double""'"); + } + arg7 = static_cast< double >(val7); + res8 = SWIG_AsWCharPtrAndSize(swig_obj[7], &buf8, NULL, &alloc8); + if (!SWIG_IsOK(res8)) { + SWIG_exception_fail(SWIG_ArgError(res8), "in method '" "Op_FetchWords" "', argument " "8"" of type '" "wchar_t const *""'"); + } + arg8 = reinterpret_cast< wchar_t * >(buf8); + ecode9 = SWIG_AsVal_long(swig_obj[8], &val9); + if (!SWIG_IsOK(ecode9)) { + SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "Op_FetchWords" "', argument " "9"" of type '" "long""'"); + } + arg9 = static_cast< long >(val9); + (arg1)->FetchWords(arg2,arg3,arg4,arg5,(wchar_t const *)arg6,arg7,(wchar_t const *)arg8,arg9,*arg10); + resultobj = SWIG_Py_Void(); + if (SWIG_IsTmpObj(res10)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_std_wstring((*arg10)), 1); + } else { + int new_flags = SWIG_IsNewObj(res10) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg10), SWIGTYPE_p_std__wstring, new_flags), 1); + } + if (alloc6 == SWIG_NEWOBJ) delete[] buf6; + if (alloc8 == SWIG_NEWOBJ) delete[] buf8; + return resultobj; +fail: + if (alloc6 == SWIG_NEWOBJ) delete[] buf6; + if (alloc8 == SWIG_NEWOBJ) delete[] buf8; + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Op_FetchWordsEx(PyObject *self, PyObject *args) { + PyObject *resultobj = 0; + op::Op *arg1 = 0 ; + long arg2 ; + long arg3 ; + long arg4 ; + long arg5 ; + wchar_t *arg6 = 0 ; + double arg7 ; + wchar_t *arg8 = 0 ; + long arg9 ; + long arg10 ; + long arg11 ; + std::wstring *arg12 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + long val2 ; + int ecode2 = 0 ; + long val3 ; + int ecode3 = 0 ; + long val4 ; + int ecode4 = 0 ; + long val5 ; + int ecode5 = 0 ; + int res6 ; + wchar_t *buf6 = 0 ; + int alloc6 = 0 ; + double val7 ; + int ecode7 = 0 ; + int res8 ; + wchar_t *buf8 = 0 ; + int alloc8 = 0 ; + long val9 ; + int ecode9 = 0 ; + long val10 ; + int ecode10 = 0 ; + long val11 ; + int ecode11 = 0 ; + std::wstring temp12 ; + int res12 = SWIG_TMPOBJ ; + PyObject *swig_obj[11] ; + + arg12 = &temp12; + (void)self; + if (!SWIG_Python_UnpackTuple(args, "Op_FetchWordsEx", 11, 11, swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_FetchWordsEx" "', argument " "1"" of type '" "op::Op *""'"); + } + arg1 = reinterpret_cast< op::Op * >(argp1); + ecode2 = SWIG_AsVal_long(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Op_FetchWordsEx" "', argument " "2"" of type '" "long""'"); + } + arg2 = static_cast< long >(val2); + ecode3 = SWIG_AsVal_long(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Op_FetchWordsEx" "', argument " "3"" of type '" "long""'"); + } + arg3 = static_cast< long >(val3); + ecode4 = SWIG_AsVal_long(swig_obj[3], &val4); + if (!SWIG_IsOK(ecode4)) { + SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Op_FetchWordsEx" "', argument " "4"" of type '" "long""'"); + } + arg4 = static_cast< long >(val4); + ecode5 = SWIG_AsVal_long(swig_obj[4], &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Op_FetchWordsEx" "', argument " "5"" of type '" "long""'"); + } + arg5 = static_cast< long >(val5); + res6 = SWIG_AsWCharPtrAndSize(swig_obj[5], &buf6, NULL, &alloc6); + if (!SWIG_IsOK(res6)) { + SWIG_exception_fail(SWIG_ArgError(res6), "in method '" "Op_FetchWordsEx" "', argument " "6"" of type '" "wchar_t const *""'"); + } + arg6 = reinterpret_cast< wchar_t * >(buf6); + ecode7 = SWIG_AsVal_double(swig_obj[6], &val7); + if (!SWIG_IsOK(ecode7)) { + SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Op_FetchWordsEx" "', argument " "7"" of type '" "double""'"); + } + arg7 = static_cast< double >(val7); + res8 = SWIG_AsWCharPtrAndSize(swig_obj[7], &buf8, NULL, &alloc8); + if (!SWIG_IsOK(res8)) { + SWIG_exception_fail(SWIG_ArgError(res8), "in method '" "Op_FetchWordsEx" "', argument " "8"" of type '" "wchar_t const *""'"); + } + arg8 = reinterpret_cast< wchar_t * >(buf8); + ecode9 = SWIG_AsVal_long(swig_obj[8], &val9); + if (!SWIG_IsOK(ecode9)) { + SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "Op_FetchWordsEx" "', argument " "9"" of type '" "long""'"); + } + arg9 = static_cast< long >(val9); + ecode10 = SWIG_AsVal_long(swig_obj[9], &val10); + if (!SWIG_IsOK(ecode10)) { + SWIG_exception_fail(SWIG_ArgError(ecode10), "in method '" "Op_FetchWordsEx" "', argument " "10"" of type '" "long""'"); + } + arg10 = static_cast< long >(val10); + ecode11 = SWIG_AsVal_long(swig_obj[10], &val11); + if (!SWIG_IsOK(ecode11)) { + SWIG_exception_fail(SWIG_ArgError(ecode11), "in method '" "Op_FetchWordsEx" "', argument " "11"" of type '" "long""'"); + } + arg11 = static_cast< long >(val11); + (arg1)->FetchWordsEx(arg2,arg3,arg4,arg5,(wchar_t const *)arg6,arg7,(wchar_t const *)arg8,arg9,arg10,arg11,*arg12); + resultobj = SWIG_Py_Void(); + if (SWIG_IsTmpObj(res12)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_std_wstring((*arg12)), 1); + } else { + int new_flags = SWIG_IsNewObj(res12) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg12), SWIGTYPE_p_std__wstring, new_flags), 1); + } + if (alloc6 == SWIG_NEWOBJ) delete[] buf6; + if (alloc8 == SWIG_NEWOBJ) delete[] buf8; + return resultobj; +fail: + if (alloc6 == SWIG_NEWOBJ) delete[] buf6; + if (alloc8 == SWIG_NEWOBJ) delete[] buf8; + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Op_FetchWordsByRects(PyObject *self, PyObject *args) { + PyObject *resultobj = 0; + op::Op *arg1 = 0 ; + long arg2 ; + long arg3 ; + long arg4 ; + long arg5 ; + wchar_t *arg6 = 0 ; + double arg7 ; + wchar_t *arg8 = 0 ; + wchar_t *arg9 = 0 ; + std::wstring *arg10 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + long val2 ; + int ecode2 = 0 ; + long val3 ; + int ecode3 = 0 ; + long val4 ; + int ecode4 = 0 ; + long val5 ; + int ecode5 = 0 ; + int res6 ; + wchar_t *buf6 = 0 ; + int alloc6 = 0 ; + double val7 ; + int ecode7 = 0 ; + int res8 ; + wchar_t *buf8 = 0 ; + int alloc8 = 0 ; + int res9 ; + wchar_t *buf9 = 0 ; + int alloc9 = 0 ; + std::wstring temp10 ; + int res10 = SWIG_TMPOBJ ; + PyObject *swig_obj[9] ; + + arg10 = &temp10; + (void)self; + if (!SWIG_Python_UnpackTuple(args, "Op_FetchWordsByRects", 9, 9, swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_FetchWordsByRects" "', argument " "1"" of type '" "op::Op *""'"); + } + arg1 = reinterpret_cast< op::Op * >(argp1); + ecode2 = SWIG_AsVal_long(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Op_FetchWordsByRects" "', argument " "2"" of type '" "long""'"); + } + arg2 = static_cast< long >(val2); + ecode3 = SWIG_AsVal_long(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Op_FetchWordsByRects" "', argument " "3"" of type '" "long""'"); + } + arg3 = static_cast< long >(val3); + ecode4 = SWIG_AsVal_long(swig_obj[3], &val4); + if (!SWIG_IsOK(ecode4)) { + SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Op_FetchWordsByRects" "', argument " "4"" of type '" "long""'"); + } + arg4 = static_cast< long >(val4); + ecode5 = SWIG_AsVal_long(swig_obj[4], &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Op_FetchWordsByRects" "', argument " "5"" of type '" "long""'"); + } + arg5 = static_cast< long >(val5); + res6 = SWIG_AsWCharPtrAndSize(swig_obj[5], &buf6, NULL, &alloc6); + if (!SWIG_IsOK(res6)) { + SWIG_exception_fail(SWIG_ArgError(res6), "in method '" "Op_FetchWordsByRects" "', argument " "6"" of type '" "wchar_t const *""'"); + } + arg6 = reinterpret_cast< wchar_t * >(buf6); + ecode7 = SWIG_AsVal_double(swig_obj[6], &val7); + if (!SWIG_IsOK(ecode7)) { + SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Op_FetchWordsByRects" "', argument " "7"" of type '" "double""'"); + } + arg7 = static_cast< double >(val7); + res8 = SWIG_AsWCharPtrAndSize(swig_obj[7], &buf8, NULL, &alloc8); + if (!SWIG_IsOK(res8)) { + SWIG_exception_fail(SWIG_ArgError(res8), "in method '" "Op_FetchWordsByRects" "', argument " "8"" of type '" "wchar_t const *""'"); + } + arg8 = reinterpret_cast< wchar_t * >(buf8); + res9 = SWIG_AsWCharPtrAndSize(swig_obj[8], &buf9, NULL, &alloc9); + if (!SWIG_IsOK(res9)) { + SWIG_exception_fail(SWIG_ArgError(res9), "in method '" "Op_FetchWordsByRects" "', argument " "9"" of type '" "wchar_t const *""'"); + } + arg9 = reinterpret_cast< wchar_t * >(buf9); + (arg1)->FetchWordsByRects(arg2,arg3,arg4,arg5,(wchar_t const *)arg6,arg7,(wchar_t const *)arg8,(wchar_t const *)arg9,*arg10); + resultobj = SWIG_Py_Void(); + if (SWIG_IsTmpObj(res10)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_std_wstring((*arg10)), 1); + } else { + int new_flags = SWIG_IsNewObj(res10) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg10), SWIGTYPE_p_std__wstring, new_flags), 1); + } + if (alloc6 == SWIG_NEWOBJ) delete[] buf6; + if (alloc8 == SWIG_NEWOBJ) delete[] buf8; + if (alloc9 == SWIG_NEWOBJ) delete[] buf9; + return resultobj; +fail: + if (alloc6 == SWIG_NEWOBJ) delete[] buf6; + if (alloc8 == SWIG_NEWOBJ) delete[] buf8; + if (alloc9 == SWIG_NEWOBJ) delete[] buf9; + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Op_GetBinaryPreview(PyObject *self, PyObject *args) { + PyObject *resultobj = 0; + op::Op *arg1 = 0 ; + long arg2 ; + long arg3 ; + long arg4 ; + long arg5 ; + wchar_t *arg6 = 0 ; + double arg7 ; + std::wstring *arg8 = 0 ; + long *arg9 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + long val2 ; + int ecode2 = 0 ; + long val3 ; + int ecode3 = 0 ; + long val4 ; + int ecode4 = 0 ; + long val5 ; + int ecode5 = 0 ; + int res6 ; + wchar_t *buf6 = 0 ; + int alloc6 = 0 ; + double val7 ; + int ecode7 = 0 ; + std::wstring temp8 ; + int res8 = SWIG_TMPOBJ ; + long temp9 ; + int res9 = SWIG_TMPOBJ ; + PyObject *swig_obj[7] ; + + arg8 = &temp8; + arg9 = &temp9; + (void)self; + if (!SWIG_Python_UnpackTuple(args, "Op_GetBinaryPreview", 7, 7, swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_GetBinaryPreview" "', argument " "1"" of type '" "op::Op *""'"); + } + arg1 = reinterpret_cast< op::Op * >(argp1); + ecode2 = SWIG_AsVal_long(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Op_GetBinaryPreview" "', argument " "2"" of type '" "long""'"); + } + arg2 = static_cast< long >(val2); + ecode3 = SWIG_AsVal_long(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Op_GetBinaryPreview" "', argument " "3"" of type '" "long""'"); + } + arg3 = static_cast< long >(val3); + ecode4 = SWIG_AsVal_long(swig_obj[3], &val4); + if (!SWIG_IsOK(ecode4)) { + SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Op_GetBinaryPreview" "', argument " "4"" of type '" "long""'"); + } + arg4 = static_cast< long >(val4); + ecode5 = SWIG_AsVal_long(swig_obj[4], &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Op_GetBinaryPreview" "', argument " "5"" of type '" "long""'"); + } + arg5 = static_cast< long >(val5); + res6 = SWIG_AsWCharPtrAndSize(swig_obj[5], &buf6, NULL, &alloc6); + if (!SWIG_IsOK(res6)) { + SWIG_exception_fail(SWIG_ArgError(res6), "in method '" "Op_GetBinaryPreview" "', argument " "6"" of type '" "wchar_t const *""'"); + } + arg6 = reinterpret_cast< wchar_t * >(buf6); + ecode7 = SWIG_AsVal_double(swig_obj[6], &val7); + if (!SWIG_IsOK(ecode7)) { + SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Op_GetBinaryPreview" "', argument " "7"" of type '" "double""'"); + } + arg7 = static_cast< double >(val7); + (arg1)->GetBinaryPreview(arg2,arg3,arg4,arg5,(wchar_t const *)arg6,arg7,*arg8,arg9); + resultobj = SWIG_Py_Void(); + if (SWIG_IsTmpObj(res8)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_std_wstring((*arg8)), 1); + } else { + int new_flags = SWIG_IsNewObj(res8) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg8), SWIGTYPE_p_std__wstring, new_flags), 1); + } + if (SWIG_IsTmpObj(res9)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg9)), 1); + } else { + int new_flags = SWIG_IsNewObj(res9) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg9), SWIGTYPE_p_long, new_flags), 1); + } + if (alloc6 == SWIG_NEWOBJ) delete[] buf6; + return resultobj; +fail: + if (alloc6 == SWIG_NEWOBJ) delete[] buf6; + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Op_GetWordPreview(PyObject *self, PyObject *args) { + PyObject *resultobj = 0; + op::Op *arg1 = 0 ; + wchar_t *arg2 = 0 ; + std::wstring *arg3 = 0 ; + long *arg4 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + wchar_t *buf2 = 0 ; + int alloc2 = 0 ; + std::wstring temp3 ; + int res3 = SWIG_TMPOBJ ; + long temp4 ; + int res4 = SWIG_TMPOBJ ; + PyObject *swig_obj[2] ; + + arg3 = &temp3; + arg4 = &temp4; + (void)self; + if (!SWIG_Python_UnpackTuple(args, "Op_GetWordPreview", 2, 2, swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_GetWordPreview" "', argument " "1"" of type '" "op::Op *""'"); + } + arg1 = reinterpret_cast< op::Op * >(argp1); + res2 = SWIG_AsWCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Op_GetWordPreview" "', argument " "2"" of type '" "wchar_t const *""'"); + } + arg2 = reinterpret_cast< wchar_t * >(buf2); + (arg1)->GetWordPreview((wchar_t const *)arg2,*arg3,arg4); + resultobj = SWIG_Py_Void(); + if (SWIG_IsTmpObj(res3)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_std_wstring((*arg3)), 1); + } else { + int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_std__wstring, new_flags), 1); + } + if (SWIG_IsTmpObj(res4)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg4)), 1); + } else { + int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_long, new_flags), 1); + } + if (alloc2 == SWIG_NEWOBJ) delete[] buf2; + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) delete[] buf2; + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Op_CheckWordDict(PyObject *self, PyObject *args) { + PyObject *resultobj = 0; + op::Op *arg1 = 0 ; + wchar_t *arg2 = 0 ; + std::wstring *arg3 = 0 ; + long *arg4 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + wchar_t *buf2 = 0 ; + int alloc2 = 0 ; + std::wstring temp3 ; + int res3 = SWIG_TMPOBJ ; + long temp4 ; + int res4 = SWIG_TMPOBJ ; + PyObject *swig_obj[2] ; + + arg3 = &temp3; + arg4 = &temp4; + (void)self; + if (!SWIG_Python_UnpackTuple(args, "Op_CheckWordDict", 2, 2, swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_CheckWordDict" "', argument " "1"" of type '" "op::Op *""'"); + } + arg1 = reinterpret_cast< op::Op * >(argp1); + res2 = SWIG_AsWCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Op_CheckWordDict" "', argument " "2"" of type '" "wchar_t const *""'"); + } + arg2 = reinterpret_cast< wchar_t * >(buf2); + (arg1)->CheckWordDict((wchar_t const *)arg2,*arg3,arg4); + resultobj = SWIG_Py_Void(); + if (SWIG_IsTmpObj(res3)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_std_wstring((*arg3)), 1); + } else { + int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_std__wstring, new_flags), 1); + } + if (SWIG_IsTmpObj(res4)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg4)), 1); + } else { + int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_long, new_flags), 1); + } + if (alloc2 == SWIG_NEWOBJ) delete[] buf2; + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) delete[] buf2; + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Op_NormalizeWordDict(PyObject *self, PyObject *args) { + PyObject *resultobj = 0; + op::Op *arg1 = 0 ; + wchar_t *arg2 = 0 ; + std::wstring *arg3 = 0 ; + long *arg4 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + wchar_t *buf2 = 0 ; + int alloc2 = 0 ; + std::wstring temp3 ; + int res3 = SWIG_TMPOBJ ; + long temp4 ; + int res4 = SWIG_TMPOBJ ; + PyObject *swig_obj[2] ; + + arg3 = &temp3; + arg4 = &temp4; + (void)self; + if (!SWIG_Python_UnpackTuple(args, "Op_NormalizeWordDict", 2, 2, swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_NormalizeWordDict" "', argument " "1"" of type '" "op::Op *""'"); + } + arg1 = reinterpret_cast< op::Op * >(argp1); + res2 = SWIG_AsWCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Op_NormalizeWordDict" "', argument " "2"" of type '" "wchar_t const *""'"); + } + arg2 = reinterpret_cast< wchar_t * >(buf2); + (arg1)->NormalizeWordDict((wchar_t const *)arg2,*arg3,arg4); + resultobj = SWIG_Py_Void(); + if (SWIG_IsTmpObj(res3)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_std_wstring((*arg3)), 1); + } else { + int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_std__wstring, new_flags), 1); + } + if (SWIG_IsTmpObj(res4)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg4)), 1); + } else { + int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_long, new_flags), 1); + } + if (alloc2 == SWIG_NEWOBJ) delete[] buf2; + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) delete[] buf2; + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Op_RenameWordDict(PyObject *self, PyObject *args) { + PyObject *resultobj = 0; + op::Op *arg1 = 0 ; + wchar_t *arg2 = 0 ; + wchar_t *arg3 = 0 ; + std::wstring *arg4 = 0 ; + long *arg5 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + wchar_t *buf2 = 0 ; + int alloc2 = 0 ; + int res3 ; + wchar_t *buf3 = 0 ; + int alloc3 = 0 ; + std::wstring temp4 ; + int res4 = SWIG_TMPOBJ ; + long temp5 ; + int res5 = SWIG_TMPOBJ ; + PyObject *swig_obj[3] ; + + arg4 = &temp4; + arg5 = &temp5; + (void)self; + if (!SWIG_Python_UnpackTuple(args, "Op_RenameWordDict", 3, 3, swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_op__Op, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Op_RenameWordDict" "', argument " "1"" of type '" "op::Op *""'"); + } + arg1 = reinterpret_cast< op::Op * >(argp1); + res2 = SWIG_AsWCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Op_RenameWordDict" "', argument " "2"" of type '" "wchar_t const *""'"); + } + arg2 = reinterpret_cast< wchar_t * >(buf2); + res3 = SWIG_AsWCharPtrAndSize(swig_obj[2], &buf3, NULL, &alloc3); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Op_RenameWordDict" "', argument " "3"" of type '" "wchar_t const *""'"); + } + arg3 = reinterpret_cast< wchar_t * >(buf3); + (arg1)->RenameWordDict((wchar_t const *)arg2,(wchar_t const *)arg3,*arg4,arg5); + resultobj = SWIG_Py_Void(); + if (SWIG_IsTmpObj(res4)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_std_wstring((*arg4)), 1); + } else { + int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_std__wstring, new_flags), 1); + } + if (SWIG_IsTmpObj(res5)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg5)), 1); + } else { + int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_long, new_flags), 1); + } + if (alloc2 == SWIG_NEWOBJ) delete[] buf2; + if (alloc3 == SWIG_NEWOBJ) delete[] buf3; + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) delete[] buf2; + if (alloc3 == SWIG_NEWOBJ) delete[] buf3; + return NULL; +} + + SWIGINTERN PyObject *_wrap_Op_GetWordsNoDict(PyObject *self, PyObject *args) { PyObject *resultobj = 0; op::Op *arg1 = 0 ; @@ -15472,6 +16895,7 @@ static PyMethodDef SwigMethods[] = { { "Op_BindWindow", _wrap_Op_BindWindow, METH_VARARGS, NULL}, { "Op_BindWindowEx", _wrap_Op_BindWindowEx, METH_VARARGS, NULL}, { "Op_UnBindWindow", _wrap_Op_UnBindWindow, METH_O, NULL}, + { "Op_LockInput", _wrap_Op_LockInput, METH_VARARGS, NULL}, { "Op_GetBindWindow", _wrap_Op_GetBindWindow, METH_O, NULL}, { "Op_IsBind", _wrap_Op_IsBind, METH_O, NULL}, { "Op_GetCursorPos", _wrap_Op_GetCursorPos, METH_O, NULL}, @@ -15479,6 +16903,11 @@ static PyMethodDef SwigMethods[] = { { "Op_MoveR", _wrap_Op_MoveR, METH_VARARGS, NULL}, { "Op_MoveTo", _wrap_Op_MoveTo, METH_VARARGS, NULL}, { "Op_MoveToEx", _wrap_Op_MoveToEx, METH_VARARGS, NULL}, + { "Op_MoveToSmooth", _wrap_Op_MoveToSmooth, METH_VARARGS, NULL}, + { "Op_MoveToExSmooth", _wrap_Op_MoveToExSmooth, METH_VARARGS, NULL}, + { "Op_MovePath", _wrap_Op_MovePath, METH_VARARGS, NULL}, + { "Op_DragPath", _wrap_Op_DragPath, METH_VARARGS, NULL}, + { "Op_SetMouseTrajectory", _wrap_Op_SetMouseTrajectory, METH_VARARGS, NULL}, { "Op_LeftClick", _wrap_Op_LeftClick, METH_O, NULL}, { "Op_LeftDoubleClick", _wrap_Op_LeftDoubleClick, METH_O, NULL}, { "Op_LeftDown", _wrap_Op_LeftDown, METH_O, NULL}, @@ -15584,7 +17013,20 @@ static PyMethodDef SwigMethods[] = { { "Op_ClearDict", _wrap_Op_ClearDict, METH_VARARGS, NULL}, { "Op_GetDictCount", _wrap_Op_GetDictCount, METH_VARARGS, NULL}, { "Op_GetNowDict", _wrap_Op_GetNowDict, METH_O, NULL}, + { "Op_SetBinaryPreprocess", _wrap_Op_SetBinaryPreprocess, METH_VARARGS, NULL}, + { "Op_GetBinaryPreprocess", _wrap_Op_GetBinaryPreprocess, METH_O, NULL}, { "Op_FetchWord", _wrap_Op_FetchWord, METH_VARARGS, NULL}, + { "Op_FetchWordEx", _wrap_Op_FetchWordEx, METH_VARARGS, NULL}, + { "Op_ExtractWordRects", _wrap_Op_ExtractWordRects, METH_VARARGS, NULL}, + { "Op_ExtractWordRectsEx", _wrap_Op_ExtractWordRectsEx, METH_VARARGS, NULL}, + { "Op_FetchWords", _wrap_Op_FetchWords, METH_VARARGS, NULL}, + { "Op_FetchWordsEx", _wrap_Op_FetchWordsEx, METH_VARARGS, NULL}, + { "Op_FetchWordsByRects", _wrap_Op_FetchWordsByRects, METH_VARARGS, NULL}, + { "Op_GetBinaryPreview", _wrap_Op_GetBinaryPreview, METH_VARARGS, NULL}, + { "Op_GetWordPreview", _wrap_Op_GetWordPreview, METH_VARARGS, NULL}, + { "Op_CheckWordDict", _wrap_Op_CheckWordDict, METH_VARARGS, NULL}, + { "Op_NormalizeWordDict", _wrap_Op_NormalizeWordDict, METH_VARARGS, NULL}, + { "Op_RenameWordDict", _wrap_Op_RenameWordDict, METH_VARARGS, NULL}, { "Op_GetWordsNoDict", _wrap_Op_GetWordsNoDict, METH_VARARGS, NULL}, { "Op_GetWordResultCount", _wrap_Op_GetWordResultCount, METH_VARARGS, NULL}, { "Op_GetWordResultPos", _wrap_Op_GetWordResultPos, METH_VARARGS, NULL}, diff --git a/swig/pyop.py b/swig/pyop.py index 5528f8c..b640172 100644 --- a/swig/pyop.py +++ b/swig/pyop.py @@ -264,6 +264,9 @@ def BindWindowEx(self, display_hwnd, input_hwnd, display, mouse, keypad, mode): def UnBindWindow(self): return _pyop.Op_UnBindWindow(self) + def LockInput(self, lock): + return _pyop.Op_LockInput(self, lock) + def GetBindWindow(self): return _pyop.Op_GetBindWindow(self) @@ -285,6 +288,21 @@ def MoveTo(self, x, y): def MoveToEx(self, x, y, w, h): return _pyop.Op_MoveToEx(self, x, y, w, h) + def MoveToSmooth(self, x, y, duration): + return _pyop.Op_MoveToSmooth(self, x, y, duration) + + def MoveToExSmooth(self, x, y, w, h, duration): + return _pyop.Op_MoveToExSmooth(self, x, y, w, h, duration) + + def MovePath(self, path, duration): + return _pyop.Op_MovePath(self, path, duration) + + def DragPath(self, path, duration): + return _pyop.Op_DragPath(self, path, duration) + + def SetMouseTrajectory(self, mode, min_duration, max_duration, jitter, start_delay, end_delay): + return _pyop.Op_SetMouseTrajectory(self, mode, min_duration, max_duration, jitter, start_delay, end_delay) + def LeftClick(self): return _pyop.Op_LeftClick(self) @@ -600,9 +618,48 @@ def GetDictCount(self, idx): def GetNowDict(self): return _pyop.Op_GetNowDict(self) + def SetBinaryPreprocess(self, mode, isolated_threshold, min_component_area, bridge_gap): + return _pyop.Op_SetBinaryPreprocess(self, mode, isolated_threshold, min_component_area, bridge_gap) + + def GetBinaryPreprocess(self): + return _pyop.Op_GetBinaryPreprocess(self) + def FetchWord(self, x1, y1, x2, y2, color, word): return _pyop.Op_FetchWord(self, x1, y1, x2, y2, color, word) + def FetchWordEx(self, x1, y1, x2, y2, color, sim, word): + return _pyop.Op_FetchWordEx(self, x1, y1, x2, y2, color, sim, word) + + def ExtractWordRects(self, x1, y1, x2, y2, color, sim, min_word_h): + return _pyop.Op_ExtractWordRects(self, x1, y1, x2, y2, color, sim, min_word_h) + + def ExtractWordRectsEx(self, x1, y1, x2, y2, color, sim, min_word_w, min_word_h, padding): + return _pyop.Op_ExtractWordRectsEx(self, x1, y1, x2, y2, color, sim, min_word_w, min_word_h, padding) + + def FetchWords(self, x1, y1, x2, y2, color, sim, words, min_word_h): + return _pyop.Op_FetchWords(self, x1, y1, x2, y2, color, sim, words, min_word_h) + + def FetchWordsEx(self, x1, y1, x2, y2, color, sim, words, min_word_w, min_word_h, padding): + return _pyop.Op_FetchWordsEx(self, x1, y1, x2, y2, color, sim, words, min_word_w, min_word_h, padding) + + def FetchWordsByRects(self, x1, y1, x2, y2, color, sim, words, rects): + return _pyop.Op_FetchWordsByRects(self, x1, y1, x2, y2, color, sim, words, rects) + + def GetBinaryPreview(self, x1, y1, x2, y2, color, sim): + return _pyop.Op_GetBinaryPreview(self, x1, y1, x2, y2, color, sim) + + def GetWordPreview(self, dict_info): + return _pyop.Op_GetWordPreview(self, dict_info) + + def CheckWordDict(self, dict_info): + return _pyop.Op_CheckWordDict(self, dict_info) + + def NormalizeWordDict(self, dict_info): + return _pyop.Op_NormalizeWordDict(self, dict_info) + + def RenameWordDict(self, dict_info, words): + return _pyop.Op_RenameWordDict(self, dict_info, words) + def GetWordsNoDict(self, x1, y1, x2, y2, color): return _pyop.Op_GetWordsNoDict(self, x1, y1, x2, y2, color) diff --git a/tests/image_color_test.cpp b/tests/image_color_test.cpp index a23473f..7115fbb 100644 --- a/tests/image_color_test.cpp +++ b/tests/image_color_test.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -466,6 +467,28 @@ TEST(ImageColorTest, FindPicHonorsDirection) { } } +TEST(ImageColorTest, FindPicReturnsMinusOneWhenTemplateIsMissing) { + op::Op op; + long ret = 0; + auto pixels = MakePixels(8, 8); + SetMemBmp(op, 8, 8, pixels, ret); + ASSERT_EQ(ret, 1); + + long x = 123; + long y = 456; + op.FindPic(0, 0, 8, 8, L"missing_findpic_template", L"000000", 1.0, 0, &x, &y, &ret); + + EXPECT_EQ(ret, -1); + EXPECT_EQ(x, -1); + EXPECT_EQ(y, -1); + + int cx = 123; + int cy = 456; + EXPECT_EQ(OpFindPic(nullptr, 0, 0, 8, 8, L"missing_findpic_template", L"000000", 1.0, 0, &cx, &cy), -1); + EXPECT_EQ(cx, -1); + EXPECT_EQ(cy, -1); +} + TEST(ImageColorTest, SharedPicCacheIsGlobalAcrossObjects) { op::Op loader; op::Op matcher; @@ -547,6 +570,25 @@ TEST(ImageColorTest, SharedPicCacheIsGlobalAcrossObjects) { std::filesystem::remove(std::filesystem::path(file_path)); } +TEST(ImageColorTest, MissingPicSizeClearsOutputValues) { + op::Op op; + long width = 123; + long height = 456; + long ret = 99; + + op.GetPicSize(L"__missing_pic_size_template__.bmp", &width, &height, &ret); + + EXPECT_EQ(ret, 0); + EXPECT_EQ(width, 0); + EXPECT_EQ(height, 0); + + int c_width = 123; + int c_height = 456; + EXPECT_EQ(OpGetPicSize(nullptr, L"__missing_pic_size_template__.bmp", &c_width, &c_height), 0); + EXPECT_EQ(c_width, 0); + EXPECT_EQ(c_height, 0); +} + TEST(ImageColorTest, FindPicTransparentOddPointsCountsCenterMismatchOnce) { op::Op op; long ret = 0; @@ -956,6 +998,32 @@ TEST(ImageColorTest, BinaryPreprocessDoesNotChangeColorBlockSearch) { EXPECT_EQ(y, 0); } +TEST(ImageColorTest, ColorSearchFailurePathsClearOutputs) { + op::Op op; + long ret = 0; + auto pixels = MakePixels(6, 4); + SetMemBmp(op, 6, 4, pixels, ret); + ASSERT_EQ(ret, 1); + + long count = 123; + op.GetColorNum(0, 0, 6, 4, L"000000", 1.0, &count); + EXPECT_EQ(count, 0); + + long x = 123; + long y = 456; + ret = 99; + op.FindColorBlock(0, 0, 6, 4, L"000000", 1.0, 1, 1, 1, &x, &y, &ret); + EXPECT_EQ(ret, 0); + EXPECT_EQ(x, -1); + EXPECT_EQ(y, -1); + + int cx = 123; + int cy = 456; + EXPECT_EQ(OpFindColorBlock(nullptr, 0, 0, 6, 4, L"000000", 1.0, 1, 1, 1, &cx, &cy), 0); + EXPECT_EQ(cx, -1); + EXPECT_EQ(cy, -1); +} + TEST(ImageColorTest, FindColorBlockExClearsResultAndRejectsInvalidSize) { op::Op op; long ret = 0; @@ -1226,8 +1294,8 @@ TEST(ImageColorTest, SetMemDictSupportsOpTextEntryFormat) { EXPECT_EQ(y, 1); } -TEST(ImageColorTest, SetMemDictOverridesGlobalDictOnlyForCurrentObject) { - const auto path = std::filesystem::temp_directory_path() / L"op_setdict_global_private_override.txt"; +TEST(ImageColorTest, SetMemDictUpdatesGlobalDictForAllObjects) { + const auto path = std::filesystem::temp_directory_path() / L"op_setmemdict_global_update.txt"; { std::ofstream file(path, std::ios::binary); ASSERT_TRUE(file.is_open()); @@ -1235,28 +1303,78 @@ TEST(ImageColorTest, SetMemDictOverridesGlobalDictOnlyForCurrentObject) { } op::Op loader; - op::Op private_user; + op::Op memory_loader; op::Op global_user; long ret = 0; loader.SetDict(4, path.c_str(), &ret); ASSERT_EQ(ret, 1); - const char *private_text = "B$4,3,8$5E0E\n"; - private_user.SetMemDict(4, reinterpret_cast(private_text), static_cast(strlen(private_text)), + const char *memory_text = "B$4,3,8$5E0E\n"; + memory_loader.SetMemDict(4, memory_text, static_cast(strlen(memory_text)), &ret); ASSERT_EQ(ret, 1); std::wstring converted; - private_user.GetDict(4, 0, converted); + memory_loader.GetDict(4, 0, converted); EXPECT_EQ(converted, L"B$4,3,8$5E0E"); global_user.GetDict(4, 0, converted); - EXPECT_EQ(converted, L"A$11,3,10$78A0001E00"); + EXPECT_EQ(converted, L"B$4,3,8$5E0E"); std::error_code ec; std::filesystem::remove(path, ec); } +TEST(ImageColorTest, SetMemDictSupportsBinaryDictFileBytes) { + const auto path = std::filesystem::temp_directory_path() / L"op_setmemdict_binary_bytes.dict"; + + op::Op writer; + op::Op loader; + op::Op reader; + long ret = 0; + writer.ClearDict(6, &ret); + ASSERT_EQ(ret, 1); + writer.AddDict(6, L"A$4,3,8$5E0E", &ret); + ASSERT_EQ(ret, 1); + writer.SaveDict(6, path.c_str(), &ret); + ASSERT_EQ(ret, 1); + + std::ifstream file(path, std::ios::binary); + ASSERT_TRUE(file.is_open()); + std::vector bytes((std::istreambuf_iterator(file)), std::istreambuf_iterator()); + ASSERT_FALSE(bytes.empty()); + + loader.SetMemDict(6, bytes.data(), static_cast(bytes.size()), &ret); + ASSERT_EQ(ret, 1); + + std::wstring converted; + reader.GetDict(6, 0, converted); + EXPECT_EQ(converted, L"A$4,3,8$5E0E"); + + std::error_code ec; + std::filesystem::remove(path, ec); +} + +TEST(ImageColorTest, DictSlotSupportsZeroToNinetyNine) { + op::Op op; + long ret = 0; + const char *dict_text = "A$4,3,8$5E0E\n"; + + op.SetMemDict(99, dict_text, static_cast(strlen(dict_text)), &ret); + ASSERT_EQ(ret, 1); + op.UseDict(99, &ret); + EXPECT_EQ(ret, 1); + + long count = 0; + op.GetDictCount(99, &count); + EXPECT_EQ(count, 1); + + op.UseDict(100, &ret); + EXPECT_EQ(ret, 0); + op.SetMemDict(100, dict_text, static_cast(strlen(dict_text)), &ret); + EXPECT_EQ(ret, 0); +} + TEST(ImageColorTest, AddDictRejectsInvalidOpTextEntry) { op::Op op; long ret = 0; @@ -1286,7 +1404,10 @@ TEST(ImageColorTest, SetMemDictRejectsInvalidOpTextEntry) { long ret = 0; const char *op_text = "A$4,3,8$5E\n"; - op.SetMemDict(0, reinterpret_cast(op_text), static_cast(strlen(op_text)), &ret); + op.ClearDict(0, &ret); + ASSERT_EQ(ret, 1); + + op.SetMemDict(0, op_text, static_cast(strlen(op_text)), &ret); EXPECT_EQ(ret, 0); long count = -1; diff --git a/tests/mouse_keyboard_test.cpp b/tests/mouse_keyboard_test.cpp index 10a8d4c..04fff9d 100644 --- a/tests/mouse_keyboard_test.cpp +++ b/tests/mouse_keyboard_test.cpp @@ -529,6 +529,120 @@ TEST(MouseKeyTest, WindowsModeMouseMoveCarriesLeftButtonWhileHeld) { EXPECT_EQ(unbind_ret, 1); } +TEST(MouseKeyTest, WindowsModeSmoothMoveUsesMultipleSteps) { + op::Op op; + MouseEventWindow window; + ASSERT_TRUE(window.Create()); + + long ret = 0; + op.BindWindow((long)(intptr_t)window.hwnd, L"normal", L"windows", L"windows", 0, &ret); + ASSERT_EQ(ret, 1); + + op.MoveTo(10, 12, &ret); + ASSERT_EQ(ret, 1); + window.ResetCounts(); + + op.MoveToSmooth(120, 82, 0, &ret); + EXPECT_EQ(ret, 1); + EXPECT_GT(window.move_count, 1); + EXPECT_EQ(window.last_x, 120); + EXPECT_EQ(window.last_y, 82); + + std::wstring pos; + window.ResetCounts(); + op.MoveToExSmooth(80, 70, -8, -6, 0, pos); + ASSERT_FALSE(pos.empty()); + long x = 0; + long y = 0; + ASSERT_EQ(swscanf_s(pos.c_str(), L"%ld,%ld", &x, &y), 2); + EXPECT_GE(x, 73); + EXPECT_LE(x, 80); + EXPECT_GE(y, 65); + EXPECT_LE(y, 70); + EXPECT_GT(window.move_count, 1); + EXPECT_EQ(window.last_x, x); + EXPECT_EQ(window.last_y, y); + + long unbind_ret = 0; + op.UnBindWindow(&unbind_ret); + EXPECT_EQ(unbind_ret, 1); +} + +TEST(MouseKeyTest, WindowsModeMouseTrajectoryConfig) { + op::Op op; + MouseEventWindow window; + ASSERT_TRUE(window.Create()); + + long ret = 0; + op.BindWindow((long)(intptr_t)window.hwnd, L"normal", L"windows", L"windows", 0, &ret); + ASSERT_EQ(ret, 1); + + op.SetMouseTrajectory(1, 40, 100, 0, 10, 10, &ret); + EXPECT_EQ(ret, 1); + op.SetMouseTrajectory(3, 0, 0, 0, 0, 0, &ret); + EXPECT_EQ(ret, 0); + op.SetMouseTrajectory(2, 120, 80, 0, 0, 0, &ret); + EXPECT_EQ(ret, 0); + op.SetMouseTrajectory(2, 0, 0, 101, 0, 0, &ret); + EXPECT_EQ(ret, 0); + + op.MoveTo(10, 12, &ret); + ASSERT_EQ(ret, 1); + window.ResetCounts(); + + const auto start = std::chrono::steady_clock::now(); + op.MoveToSmooth(100, 12, 0, &ret); + const auto elapsed = std::chrono::duration_cast( + std::chrono::steady_clock::now() - start) + .count(); + EXPECT_EQ(ret, 1); + EXPECT_GE(elapsed, 45); + EXPECT_GT(window.move_count, 1); + EXPECT_EQ(window.last_x, 100); + EXPECT_EQ(window.last_y, 12); + + long unbind_ret = 0; + op.UnBindWindow(&unbind_ret); + EXPECT_EQ(unbind_ret, 1); +} + +TEST(MouseKeyTest, WindowsModeMovePathAndDragPath) { + op::Op op; + MouseEventWindow window; + ASSERT_TRUE(window.Create()); + + long ret = 0; + op.BindWindow((long)(intptr_t)window.hwnd, L"normal", L"windows", L"windows", 0, &ret); + ASSERT_EQ(ret, 1); + + op.MovePath(L"10,10|24,18|48,36", 0, &ret); + EXPECT_EQ(ret, 1); + EXPECT_GT(window.move_count, 3); + EXPECT_EQ(window.last_x, 48); + EXPECT_EQ(window.last_y, 36); + + op.MovePath(L"10,10", 0, &ret); + EXPECT_EQ(ret, 0); + op.MovePath(L"10,10|10,10", 0, &ret); + EXPECT_EQ(ret, 0); + op.MovePath(L"10,10|bad", 0, &ret); + EXPECT_EQ(ret, 0); + + window.ResetCounts(); + op.DragPath(L"12,14|30,32|50,40", 0, &ret); + EXPECT_EQ(ret, 1); + EXPECT_EQ(window.left_down, 1); + EXPECT_EQ(window.left_up, 1); + EXPECT_GT(window.move_count, 3); + EXPECT_EQ(window.move_with_left_count, window.move_count - 1); + EXPECT_EQ(window.last_x, 50); + EXPECT_EQ(window.last_y, 40); + + long unbind_ret = 0; + op.UnBindWindow(&unbind_ret); + EXPECT_EQ(unbind_ret, 1); +} + TEST(MouseKeyTest, WindowsModeMoveToKeepsClientCoordinatesAfterResize) { op::Op op; MouseEventWindow window; @@ -730,19 +844,20 @@ TEST(MouseKeyTest, DxModeMouseMoveCarriesLeftButtonWhileHeld) { op.MoveTo(48, 64, &ret); EXPECT_EQ(ret, 1); PumpMessagesFor(120); + // DX hook 会把 OP 消息转成普通鼠标消息;桌面环境下还可能夹进真实移动,所以只检查目标移动出现过。 EXPECT_GE(window.move_with_left_count, 1); - EXPECT_NE(window.last_move_wparam & MK_LBUTTON, static_cast(0)); - EXPECT_EQ(window.last_x, 48); - EXPECT_EQ(window.last_y, 64); + EXPECT_TRUE(window.HasMove(48, 64, MK_LBUTTON)); op.LeftUp(&ret); ASSERT_EQ(ret, 1); + PumpMessagesFor(80); + window.ResetCounts(); + op.MoveR(3, 4, &ret); EXPECT_EQ(ret, 1); PumpMessagesFor(120); - EXPECT_EQ(window.last_move_wparam & MK_LBUTTON, static_cast(0)); - EXPECT_EQ(window.last_x, 51); - EXPECT_EQ(window.last_y, 68); + EXPECT_EQ(window.move_with_left_count, 0); + EXPECT_TRUE(window.HasMove(51, 68, 0, MK_LBUTTON)); long unbind_ret = 0; op.UnBindWindow(&unbind_ret); @@ -764,26 +879,71 @@ TEST(MouseKeyTest, DxModeMoveToKeepsClientCoordinatesAfterResize) { ASSERT_TRUE(ResizeClient(window.hwnd, 640, 360)); PumpMessagesFor(80); + window.ResetCounts(); op.MoveTo(200, 200, &ret); EXPECT_EQ(ret, 1); PumpMessagesFor(120); - EXPECT_EQ(window.last_x, 200); - EXPECT_EQ(window.last_y, 200); + EXPECT_TRUE(window.HasMove(200, 200, 0)); + window.ResetCounts(); op.MoveR(20, -40, &ret); EXPECT_EQ(ret, 1); PumpMessagesFor(120); - EXPECT_EQ(window.last_x, 220); - EXPECT_EQ(window.last_y, 160); + EXPECT_TRUE(window.HasMove(220, 160, 0)); ASSERT_TRUE(ResizeClient(window.hwnd, 320, 180)); PumpMessagesFor(80); + window.ResetCounts(); + op.LeftClick(&ret); EXPECT_EQ(ret, 1); PumpMessagesFor(120); - EXPECT_EQ(window.last_x, 220); - EXPECT_EQ(window.last_y, 160); + EXPECT_TRUE(window.HasButton(WM_LBUTTONDOWN, 220, 160)); + EXPECT_TRUE(window.HasButton(WM_LBUTTONUP, 220, 160)); + + long unbind_ret = 0; + op.UnBindWindow(&unbind_ret); + EXPECT_EQ(unbind_ret, 1); +} + +TEST(MouseKeyTest, DxModeLockInputBlocksExternalMouseMessages) { + op::Op op; + MouseEventWindow window; + ASSERT_TRUE(window.Create()); + + long ret = 0; + op.BindWindow((long)(intptr_t)window.hwnd, L"normal", L"dx", L"windows", 0, &ret); + if (ret != 1) { + GTEST_SKIP() << "DX mouse bind unavailable on current environment"; + } + + op.LockInput(4, &ret); + EXPECT_EQ(ret, 0); + op.LockInput(3, &ret); + EXPECT_EQ(ret, 0); + + window.ResetCounts(); + ::SendMessageW(window.hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(7, 9)); + EXPECT_EQ(window.move_count, 1); + + op.LockInput(2, &ret); + ASSERT_EQ(ret, 1); + window.ResetCounts(); + ::SendMessageW(window.hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(11, 13)); + EXPECT_EQ(window.move_count, 0); + + op.MoveTo(30, 40, &ret); + EXPECT_EQ(ret, 1); + PumpMessagesFor(80); + EXPECT_GE(window.move_count, 1); + EXPECT_TRUE(window.HasMove(30, 40, 0)); + + op.LockInput(0, &ret); + EXPECT_EQ(ret, 1); + window.ResetCounts(); + ::SendMessageW(window.hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(15, 17)); + EXPECT_EQ(window.move_count, 1); long unbind_ret = 0; op.UnBindWindow(&unbind_ret); @@ -912,6 +1072,114 @@ TEST(MouseKeyTest, DxModeFeedsDirectInputBufferedData) { EXPECT_EQ(unbind_ret, 1); } +TEST(MouseKeyTest, DxModeFeedsDirectInputDeviceState) { + op::Op op; + MouseEventWindow window; + ASSERT_TRUE(window.Create()); + + long ret = 0; + op.BindWindow((long)(intptr_t)window.hwnd, L"normal", L"dx", L"dx", 0, &ret); + if (ret != 1) { + GTEST_SKIP() << "DX input bind unavailable on current environment"; + } + + DirectInputDevice mouse; + if (!mouse.Create(kTestGuidSysMouse, window.hwnd)) { + long unbind_ret = 0; + op.UnBindWindow(&unbind_ret); + GTEST_SKIP() << "DirectInput mouse unavailable on current environment"; + } + + op.MoveTo(20, 20, &ret); + ASSERT_EQ(ret, 1); + op.MoveR(5, 7, &ret); + ASSERT_EQ(ret, 1); + op.LeftDown(&ret); + ASSERT_EQ(ret, 1); + op.Wheel(WHEEL_DELTA, &ret); + ASSERT_EQ(ret, 1); + + DIMOUSESTATE mouse_state = {}; + ASSERT_TRUE(SUCCEEDED(mouse.device->GetDeviceState(sizeof(mouse_state), &mouse_state))); + EXPECT_EQ(mouse_state.lX, 25); + EXPECT_EQ(mouse_state.lY, 27); + EXPECT_EQ(mouse_state.lZ, WHEEL_DELTA); + EXPECT_EQ(mouse_state.rgbButtons[0], 0x80); + + DIMOUSESTATE consumed_state = {}; + ASSERT_TRUE(SUCCEEDED(mouse.device->GetDeviceState(sizeof(consumed_state), &consumed_state))); + EXPECT_EQ(consumed_state.lX, 0); + EXPECT_EQ(consumed_state.lY, 0); + EXPECT_EQ(consumed_state.lZ, 0); + EXPECT_EQ(consumed_state.rgbButtons[0], 0x80); + + op.MoveR(3, 4, &ret); + ASSERT_EQ(ret, 1); + op.XButton1Down(&ret); + ASSERT_EQ(ret, 1); + op.Wheel(-WHEEL_DELTA, &ret); + ASSERT_EQ(ret, 1); + + DIMOUSESTATE2 mouse_state2 = {}; + ASSERT_TRUE(SUCCEEDED(mouse.device->GetDeviceState(sizeof(mouse_state2), &mouse_state2))); + EXPECT_EQ(mouse_state2.lX, 3); + EXPECT_EQ(mouse_state2.lY, 4); + EXPECT_EQ(mouse_state2.lZ, -WHEEL_DELTA); + EXPECT_EQ(mouse_state2.rgbButtons[0], 0x80); + EXPECT_EQ(mouse_state2.rgbButtons[3], 0x80); + + op.XButton1Up(&ret); + EXPECT_EQ(ret, 1); + op.LeftUp(&ret); + EXPECT_EQ(ret, 1); + + long unbind_ret = 0; + op.UnBindWindow(&unbind_ret); + EXPECT_EQ(unbind_ret, 1); +} + +TEST(MouseKeyTest, DxModeLockInputBlocksExternalKeyboardMessages) { + SendStringWindow window; + ASSERT_TRUE(window.Create()); + + op::Op op; + long ret = 0; + op.BindWindow((long)(intptr_t)window.edit, L"normal", L"windows", L"dx", 0, &ret); + if (ret != 1) { + GTEST_SKIP() << "DX keyboard bind unavailable on current environment"; + } + + op.LockInput(2, &ret); + EXPECT_EQ(ret, 0); + + ::SetWindowTextW(window.edit, L""); + ::SendMessageW(window.edit, WM_CHAR, L'A', 1); + PumpMessagesFor(50); + EXPECT_EQ(window.GetEditText(), L"A"); + + ::SetWindowTextW(window.edit, L""); + op.LockInput(3, &ret); + ASSERT_EQ(ret, 1); + ::SendMessageW(window.edit, WM_CHAR, L'B', 1); + PumpMessagesFor(50); + EXPECT_EQ(window.GetEditText(), L""); + + op.KeyPressStr(L"C", 1, &ret); + EXPECT_EQ(ret, 1); + PumpMessagesFor(120); + EXPECT_EQ(window.GetEditText(), L"C"); + + op.LockInput(0, &ret); + EXPECT_EQ(ret, 1); + ::SendMessageW(window.edit, WM_CHAR, L'D', 1); + PumpMessagesFor(50); + EXPECT_EQ(window.GetEditText(), L"CD"); + + long unbind_ret = 0; + op.UnBindWindow(&unbind_ret); + EXPECT_EQ(unbind_ret, 1); +} + TEST(MouseKeyTest, DxModeKeyPressStrSupportsUnicodeFallback) { SendStringWindow window; ASSERT_TRUE(window.Create()); diff --git a/tests/opencv_test.cpp b/tests/opencv_test.cpp index c3e8e97..9ede5d3 100644 --- a/tests/opencv_test.cpp +++ b/tests/opencv_test.cpp @@ -1,5 +1,7 @@ #include "test_support.h" +#include "op_c_api.h" + #include "../libop/opencv/TemplateMatcher.h" #include @@ -416,6 +418,14 @@ TEST(OpenCvTest, ReportsVersion) { EXPECT_FALSE(version.empty()); } +TEST(OpenCvTest, CApiJsonMethodsReturnFailureJsonForInvalidHandle) { + EXPECT_EQ(L"{\"ok\":0}", std::wstring(OpCvMatchTemplate(nullptr, 0, 0, 10, 10, L"missing", 0.9, 0, 0, 0, 0))); + EXPECT_EQ(L"{\"ok\":0,\"results\":[]}", + std::wstring(OpCvConnectedComponents(nullptr, L"missing.bmp", 1.0))); + EXPECT_EQ(L"{\"ok\":0,\"results\":[]}", + std::wstring(OpCvMatchAllTemplates(nullptr, 0, 0, 10, 10, L"missing", 0.9, 0, 0, 0, 0))); +} + TEST(OpenCvTest, TemplateStoreAndMatchApis) { opcv::RemoveAllTemplates(); diff --git a/tests/test_support.cpp b/tests/test_support.cpp index 888a534..0a5b62c 100644 --- a/tests/test_support.cpp +++ b/tests/test_support.cpp @@ -365,25 +365,29 @@ LRESULT CALLBACK MouseEventWindow::WndProc(HWND hwnd, UINT msg, WPARAM wparam, L case WM_MOUSEMOVE: self->move_count++; self->last_move_wparam = wparam; - if (wparam & MK_LBUTTON) - self->move_with_left_count++; self->last_x = GET_X_LPARAM(lparam); self->last_y = GET_Y_LPARAM(lparam); + self->move_events.push_back({self->last_x, self->last_y, wparam}); + if (wparam & MK_LBUTTON) + self->move_with_left_count++; return 0; case WM_LBUTTONDOWN: self->left_down++; self->last_x = GET_X_LPARAM(lparam); self->last_y = GET_Y_LPARAM(lparam); + self->button_events.push_back({msg, self->last_x, self->last_y, wparam}); return 0; case WM_LBUTTONDBLCLK: self->left_double++; self->last_x = GET_X_LPARAM(lparam); self->last_y = GET_Y_LPARAM(lparam); + self->button_events.push_back({msg, self->last_x, self->last_y, wparam}); return 0; case WM_LBUTTONUP: self->left_up++; self->last_x = GET_X_LPARAM(lparam); self->last_y = GET_Y_LPARAM(lparam); + self->button_events.push_back({msg, self->last_x, self->last_y, wparam}); return 0; case WM_MBUTTONDOWN: self->middle_down++; @@ -404,16 +408,19 @@ LRESULT CALLBACK MouseEventWindow::WndProc(HWND hwnd, UINT msg, WPARAM wparam, L self->right_down++; self->last_x = GET_X_LPARAM(lparam); self->last_y = GET_Y_LPARAM(lparam); + self->button_events.push_back({msg, self->last_x, self->last_y, wparam}); return 0; case WM_RBUTTONDBLCLK: self->right_double++; self->last_x = GET_X_LPARAM(lparam); self->last_y = GET_Y_LPARAM(lparam); + self->button_events.push_back({msg, self->last_x, self->last_y, wparam}); return 0; case WM_RBUTTONUP: self->right_up++; self->last_x = GET_X_LPARAM(lparam); self->last_y = GET_Y_LPARAM(lparam); + self->button_events.push_back({msg, self->last_x, self->last_y, wparam}); return 0; case WM_XBUTTONDOWN: if (HIWORD(wparam) == XBUTTON1) @@ -576,6 +583,24 @@ void MouseEventWindow::SetTestCursor(HCURSOR cursor) { test_cursor = cursor; } +bool MouseEventWindow::HasMove(long x, long y, WPARAM required_state, WPARAM blocked_state) const { + for (const auto &event : move_events) { + if (event.x == x && event.y == y && (event.wparam & required_state) == required_state && + (event.wparam & blocked_state) == 0) { + return true; + } + } + return false; +} + +bool MouseEventWindow::HasButton(UINT message, long x, long y) const { + for (const auto &event : button_events) { + if (event.message == message && event.x == x && event.y == y) + return true; + } + return false; +} + void MouseEventWindow::ResetCounts() { left_down = 0; left_up = 0; @@ -627,6 +652,8 @@ void MouseEventWindow::ResetCounts() { last_x = 0; last_y = 0; last_move_wparam = 0; + move_events.clear(); + button_events.clear(); } MouseEventWindow::~MouseEventWindow() { diff --git a/tests/test_support.h b/tests/test_support.h index 7802587..39ba130 100644 --- a/tests/test_support.h +++ b/tests/test_support.h @@ -13,7 +13,7 @@ #include #include "../libop/hook/HookProtocol.h" -#include "../libop/runtime/Types.h" +#include "../libop/base/Types.h" #include "../include/libop.h" namespace test_support { @@ -49,6 +49,19 @@ struct SendStringWindow { ~SendStringWindow(); }; +struct MouseMoveEvent { + long x = 0; + long y = 0; + WPARAM wparam = 0; +}; + +struct MouseButtonEvent { + UINT message = 0; + long x = 0; + long y = 0; + WPARAM wparam = 0; +}; + struct MouseEventWindow { HWND hwnd = nullptr; int left_down = 0; @@ -104,10 +117,14 @@ struct MouseEventWindow { long last_x = 0; long last_y = 0; WPARAM last_move_wparam = 0; + std::vector move_events; + std::vector button_events; static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); bool Create(); void SetTestCursor(HCURSOR cursor); + bool HasMove(long x, long y, WPARAM required_state, WPARAM blocked_state = 0) const; + bool HasButton(UINT message, long x, long y) const; void ResetCounts(); ~MouseEventWindow(); }; diff --git a/tests/utils_test.cpp b/tests/utils_test.cpp index d04ae08..d6701f5 100644 --- a/tests/utils_test.cpp +++ b/tests/utils_test.cpp @@ -1,6 +1,6 @@ #include "test_support.h" -#include "../libop/runtime/ThreadPool.h" +#include "../libop/base/ThreadPool.h" #include diff --git a/tests/yolo_test.cpp b/tests/yolo_test.cpp index 65b6ed7..7f46b4a 100644 --- a/tests/yolo_test.cpp +++ b/tests/yolo_test.cpp @@ -1,5 +1,7 @@ #include "test_support.h" +#include "op_c_api.h" + using namespace test_support; TEST(YoloTest, SetYoloEngineAcceptsBaseUrlAndAliasArgs) { @@ -13,11 +15,16 @@ TEST(YoloTest, SetYoloEngineRejectsInvalidUrl) { EXPECT_EQ(0, op.SetYoloEngine(L"http://", L"", L"--timeout=5000")); } -TEST(YoloTest, YoloDetectFromFileReturnsEmptyForMissingFile) { +TEST(YoloTest, YoloDetectFromFileReturnsFailureJsonForMissingFile) { op::Op op; std::wstring json = L"not-empty"; long ret = 123; op.YoloDetectFromFile(L"__missing_yolo_input__.bmp", 0.25, 0.45, json, &ret); EXPECT_EQ(0, ret); - EXPECT_TRUE(json.empty()); + EXPECT_EQ(L"{\"ok\":0,\"code\":-1,\"results\":[]}", json); +} + +TEST(YoloTest, CApiYoloDetectReturnsFailureJsonForInvalidHandle) { + EXPECT_STREQ(L"{\"ok\":0,\"code\":-1,\"results\":[]}", + OpYoloDetectFromFile(nullptr, L"__missing_yolo_input__.bmp", 0.25, 0.45)); }