热血江湖 YGOnline.exe —— 「窗口是否弹出」带日志版 时间:2026-09-28 15:1x 目标:D:\rxjh2025\client\YGOnline.exe(32位,无ASLR,模块基址恒 0x400000) ================================================================================ 【用途】在不改判定逻辑的前提下,把每一步读数写进挂机日志,方便回答: · 是 IFManager 没读到?还是槽偏移填错?还是窗口真没开? · 扫到几个内容面板?各自 vis 是几?命中哪一个? · 这个槽到底是哪个窗口?(日志里直接带类名) 【用法】把原来调 `窗口是否弹出 (槽偏移)` 的地方换成 `窗口是否弹出_日志 (槽偏移)`。 返回值、判定逻辑完全一致,只是多写日志。 【日志样例】槽 1236 正开着交易窗时: 15:12:03 [窗判] 槽 1236 (0x4D4) InterExchange 对象 1205504664 开始扫描 15:12:03 [窗判] 面板 +820 面板ID 6696 大小 220x300 可见 1 ★命中 15:12:03 [窗判] 槽 1236 结论:弹出 (空行) 槽 1256 组队窗关着时: 15:12:03 [窗判] 槽 1256 (0x4E8) InterParty 对象 929942064 开始扫描 15:12:03 [窗判] 面板 +816 面板ID 7030 大小 220x300 可见 0 15:12:03 [窗判] 槽 1256 结论:未弹出 (空行) 槽偏移填错 / 该槽没对象时: 15:12:03 [窗判] 槽 1300 (0x514) (无对象) 失败:该槽没有窗口对象 (空行) -------------------------------------------------------------------------------- 一、常量(沿用你已有的,无需改动) -------------------------------------------------------------------------------- .版本 2 .常量 IFManager基址, "25740828" .常量 窗口可见标志, "64" .常量 控件类型偏移, "8" .常量 面板类型码, "24" .常量 窗口子槽起点, "768" .常量 窗口子槽个数, "192" -------------------------------------------------------------------------------- 二、子程序 ① 读控件类名(日志内部用,读不到就返回空文本,不影响判定) -------------------------------------------------------------------------------- .版本 2 .子程序 读控件类名, 文本型 .参数 对象, 整数型 .局部变量 虚表, 整数型 .局部变量 定位器, 整数型 .局部变量 类型描述符, 整数型 .局部变量 名, 文本型 .局部变量 长度, 整数型 .如果真 (对象 ≤ 65536) 返回 (“”) .如果真结束 虚表 = 内存_读整数型 (全局_进程句柄, 对象) .如果真 (虚表 ≤ 65536) 返回 (“”) .如果真结束 定位器 = 内存_读整数型 (全局_进程句柄, 虚表 - 4) .如果真 (定位器 ≤ 65536) 返回 (“”) .如果真结束 类型描述符 = 内存_读整数型 (全局_进程句柄, 定位器 + 12) .如果真 (类型描述符 ≤ 65536) 返回 (“”) .如果真结束 名 = 内存_读文本型 (全局_进程句柄, 类型描述符 + 12) 长度 = 取文本长度 (名) .如果真 (长度 > 2) .如果真 (取文本右边 (名, 2) = “@@”) 名 = 取文本左边 (名, 长度 - 2) .如果真结束 .如果真结束 返回 (名) -------------------------------------------------------------------------------- 三、子程序 ② 窗口是否弹出_日志(★ 主交付,逐面板 + 结论) -------------------------------------------------------------------------------- .版本 2 .子程序 窗口是否弹出_日志, 逻辑型 .参数 槽偏移, 整数型 .局部变量 接口管理, 整数型 .局部变量 窗口对象, 整数型 .局部变量 子对象, 整数型 .局部变量 i, 整数型 .局部变量 面板偏移, 整数型 .局部变量 类型, 整数型 .局部变量 可见, 整数型 .局部变量 命中, 逻辑型 .局部变量 窗口名, 文本型 .局部变量 前缀, 文本型 .局部变量 行, 文本型 前缀 = 自定义时间 () + “[窗判] ” 接口管理 = 内存_读整数型 (全局_进程句柄, #IFManager基址) .如果真 (接口管理 ≤ 65536) 挂机信息.加入文本 (前缀 + “槽 ” + 到文本 (槽偏移) + “ 失败:IFManager 未读到(” + 到文本 (接口管理) + “)” + #换行符 + #换行符) 返回 (假) .如果真结束 窗口对象 = 内存_读整数型 (全局_进程句柄, 接口管理 + 槽偏移) .如果真 (窗口对象 ≤ 65536) 挂机信息.加入文本 (前缀 + “槽 ” + 到文本 (槽偏移) + “ (0x” + 取十六进制文本 (槽偏移) + “) 失败:该槽没有窗口对象” + #换行符 + #换行符) 返回 (假) .如果真结束 窗口名 = 读控件类名 (窗口对象) .如果真 (窗口名 = “”) 窗口名 = “(类名读取失败)” .如果真结束 挂机信息.加入文本 (前缀 + “槽 ” + 到文本 (槽偏移) + “ (0x” + 取十六进制文本 (槽偏移) + “) ” + 窗口名 + “ 对象 ” + 到文本 (窗口对象) + “ 开始扫描” + #换行符) 命中 = 假 .计次循环首 (#窗口子槽个数, i) 面板偏移 = #窗口子槽起点 + (i - 1) × 4 子对象 = 内存_读整数型 (全局_进程句柄, 窗口对象 + 面板偏移) .如果真 (子对象 > 65536) 类型 = 内存_读整数型 (全局_进程句柄, 子对象 + #控件类型偏移) .如果真 (类型 = #面板类型码) 可见 = 内存_读整数型 (全局_进程句柄, 子对象 + #窗口可见标志) 行 = 前缀 + “ 面板 +” + 到文本 (面板偏移) + “ 面板ID ” + 到文本 (内存_读整数型 (全局_进程句柄, 子对象 + 12)) + “ 大小 ” + 到文本 (内存_读整数型 (全局_进程句柄, 子对象 + 48)) + “x” + 到文本 (内存_读整数型 (全局_进程句柄, 子对象 + 52)) + “ 可见 ” + 到文本 (可见) .如果真 (可见 = 1) 命中 = 真 行 = 行 + “ ★命中” .如果真结束 挂机信息.加入文本 (行 + #换行符) .如果真结束 .如果真结束 .计次循环尾 () .如果 (命中) 挂机信息.加入文本 (前缀 + “槽 ” + 到文本 (槽偏移) + “ 结论:弹出” + #换行符 + #换行符) .否则 挂机信息.加入文本 (前缀 + “槽 ” + 到文本 (槽偏移) + “ 结论:未弹出” + #换行符 + #换行符) .如果结束 返回 (命中) -------------------------------------------------------------------------------- 四、子程序 ③ 窗口是否弹出_简报(挂机常开用,每次只写 1 行) -------------------------------------------------------------------------------- .版本 2 .子程序 窗口是否弹出_简报, 逻辑型 .参数 槽偏移, 整数型 .局部变量 接口管理, 整数型 .局部变量 窗口对象, 整数型 .局部变量 子对象, 整数型 .局部变量 i, 整数型 .局部变量 类型, 整数型 .局部变量 可见, 整数型 .局部变量 命中, 逻辑型 .局部变量 窗口名, 文本型 接口管理 = 内存_读整数型 (全局_进程句柄, #IFManager基址) .如果真 (接口管理 ≤ 65536) 挂机信息.加入文本 (自定义时间 () + “[窗判] 槽 ” + 到文本 (槽偏移) + “ 读不到 IFManager” + #换行符) 返回 (假) .如果真结束 窗口对象 = 内存_读整数型 (全局_进程句柄, 接口管理 + 槽偏移) .如果真 (窗口对象 ≤ 65536) 挂机信息.加入文本 (自定义时间 () + “[窗判] 槽 ” + 到文本 (槽偏移) + “ 无对象” + #换行符) 返回 (假) .如果真结束 命中 = 假 .计次循环首 (#窗口子槽个数, i) 子对象 = 内存_读整数型 (全局_进程句柄, 窗口对象 + #窗口子槽起点 + (i - 1) × 4) .如果真 (子对象 > 65536) 类型 = 内存_读整数型 (全局_进程句柄, 子对象 + #控件类型偏移) .如果真 (类型 = #面板类型码) 可见 = 内存_读整数型 (全局_进程句柄, 子对象 + #窗口可见标志) .如果真 (可见 = 1) 命中 = 真 跳出循环 () .如果真结束 .如果真结束 .如果真结束 .计次循环尾 () 窗口名 = 读控件类名 (窗口对象) 挂机信息.加入文本 (自定义时间 () + “[窗判] 槽 ” + 到文本 (槽偏移) + “ ” + 窗口名 + “ = ” + 选择文本 (命中, “弹出”, “未弹出”) + #换行符) 返回 (命中) 注:`选择文本` 是自定义的小工具(易语言自带 `选择` 命令同样可用): .版本 2 .子程序 选择文本, 文本型 .参数 条件, 逻辑型 .参数 真值, 文本型 .参数 假值, 文本型 .如果 (条件) 返回 (真值) .否则 返回 (假值) .如果结束 -------------------------------------------------------------------------------- 五、日志量说明(重要) -------------------------------------------------------------------------------- · 子程序② 每次调用写 2 ~ 16 行(InterMAIN 面板最多 14 个)。 面板是"每扫到一个类型码24就写一行",所以窗口越复杂日志越长。 · 子程序③ 恒为 1 行,适合挂机常开或循环里调。 · 日志控件(挂机信息)是慢操作:**别在 100ms 级的高频循环里用②**, 调试阶段用②,跑起来后换③,或干脆换回原来不带日志的 `窗口是否弹出`。 -------------------------------------------------------------------------------- 六、常见日志 → 病因对照表 -------------------------------------------------------------------------------- | 日志现象 | 病因 | 处理 | |---|---|---| | `失败:IFManager 未读到(0)` | 全局基址失效 / 没 attach 上进程 | 查 `#IFManager基址` 是否 25740828;确认句柄有效 | | `失败:该槽没有窗口对象` | 槽偏移填错,或该接口本次未创建 | 对照《槽偏移全表_0928.txt》核槽偏移 | | `(类名读取失败)` 但后面有面板、结论正常 | 只是 RTTI 读不到,**不影响判定** | 忽略,判定照常 | | `(无对象)` 出现但你认为窗口该在 | 该接口对象确实为 0(实测 0x3D0 小地图就是 0) | 正常,属未创建 | | 扫完 0 个面板、结论未弹出 | 该窗口没有"类型码 24 内容面板"(InterChat 0x3B0 就是这种) | 换专用判定,或不必判 | | 面板有 vis=1 但屏幕上看不到 | 可能是常驻竖条(InterNotice 的 +0x330/+0x334) | 用专用判定走孙辈:+0x338 → +0x330 | | 明明开着却判未弹出 | 面板偏移超出 0x300~0x5FC 扫描范围 | 扩大 #窗口子槽个数(当前 192 = 到 0x5FC) | ================================================================================