Files
2026-10-24 13:02:19 +08:00

99 lines
6.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 2026-10-23
## 按键精灵 v2:全 C# 重做(Lua + 积木 + 录制 + 录屏)
用户反馈 v1(自定义 VB-like 脚本 + TreeView 假积木)未达预期,明确要求「整个项目用 C」——
即纯 C# 技术栈,不要网页方案。中途一度做了 WebView2 + Blockly,被要求停止并移除。
### 架构决策
- 脚本引擎:MoonSharp 2.0.0(纯托管,.NET 10 可用),替换自研 ScriptParser/ScriptEngine。
- 积木:`Forms/BlockCanvas.cs` 自绘 GDI+ 画布,圆角块、拖拽排序、容器嵌套、插入指示线、右键菜单。
- 录制:`Capture/InputRecorder.cs` WH_KEYBOARD_LL/WH_MOUSE_LL → 智能聚合成 Lua。
- 录屏:`Capture/ScreenRecorder.cs` GDI 抓帧 + JPEG + 手写 AVI(MJPG) 封装,无 ffmpeg 依赖。
- 删除旧 `Scripting/` 目录(ScriptParser/ScriptEngine/Blocks/AutomationTask)与 `Forms/BlockDesigner.cs`。
### 关键实现坑
- MoonSharp `Table["name"] = Delegate` 可直接赋值;CLR 回调抛异常会原样透传给 `DoString`,`pcall` 拦不住 → 用作 Abort 信号。
- `CoreModules` 枚举成员是 `String`/`Table`/`Math`(不是 StrLib/TableLib)。
- WinForms `UserControl.Text` 会遮蔽自定义属性;`LuaEditor` 改用 `Script` 属性。
- `SplitContainer` 构造期设 `SplitterDistance` 会因宽度未定抛异常,改在 `Layout` 里初始化。
- 积木模板里参数不要再手写引号(ArgKind 已负责加引号),否则 `keyPress(""A"")`。
- IDE 规则:`MainForm` 实现 ILuaHost 时与 `Control` 同名方法必须显式接口实现。
### 验收
- `dotnet build` 0 错误。
- 积木→Lua 生成、Lua 执行、语法错误中文提示、录屏 AVI 结构、主窗体 5 页渲染均已实测通过。
---
## v2.1 界面重构:四区布局(左任务列表 / 中详情 / 右插件 / 下日志)
用户要求按经典按键精灵布局重排,不要一堆平级标签页。
### 结构
- 左 248px:`ListBox` + `OwnerDrawFixed` 自绘任务卡(名称 + 循环/间隔 + 状态色条),右键新建/复制/删除/上下移/立即运行。
- 中:顶部任务属性条(名称/启用/无限/次数/间隔/来源/热键,改动实时回写) + `TabControl` 四页(脚本代码 / 积木编程 / 录制·录屏 / 内嵌浏览器)。
- 右 224px:插件面板 `FlowLayoutPanel`,17 项分 4 组(屏幕与定位 / 录制 / 脚本 / 系统与帮助),按钮宽 176 才不触发横向滚动条。
- 下:RichTextBox 日志跨全宽,错误红/成功绿,分割条可拖。
- 嵌套 `SplitContainer` ×3,均在 `Layout` 事件里一次性设 `SplitterDistance`。
### 新增
- `Forms/PickerForm.cs`:置顶坐标取色器,15×15 抓屏 7 倍 NearestNeighbor 放大 + 准星,实时坐标/HEX/RGB,复制坐标/颜色/写日志。
- `LuaTask` 增加 `Blocks`(积木 JSON)与 `Hotkey` 字段,任务切换时脚本与积木各自恢复。
- 插件:找图测试(全屏 MatchTemplate + 耗时/相似度)、窗口列表、打开图库/录像目录。
### 坑
- `ListBox.DataSource = BindingList<T>` 在句柄创建前绑定,`Items.Count` 恒为 0 → 改为手工 `Items.Clear/Add` 同步 + `_sync` 标志防重入。
- `Label.AutoSize=true` 在 `FlowLayoutPanel` 里会被压到 100px 宽截断文字 → 改 `AutoSize=false` + 固定宽 + `AutoEllipsis`。
- `Form.MainMenuStrip` 会把菜单塞到 Controls[0](最内层),工具栏 `Dock=Top` 会压到菜单上方 → 末尾 `Controls.SetChildIndex(menu, Count-1)` 强制菜单最外。
---
## v2.2 积木插片耦合造型 + 功能补位
用户反馈:积木要"插片耦合"样式(可理解)、各功能位置没做好。
### BlockCanvas 重写(Forms/BlockCanvas.cs)
- 几何:RowH=30 / NotchH=7 / WallW=22 / FootH=16 / ElseH=22;`TopEdge/BottomEdge/PuzzlePath/ContainerPath` 生成路径。
- 语句块 = 顶部凹槽 + 底部凸榫;相邻块 y 累加 RowH(无间隙)→ 凸榫嵌进凹槽,视觉咬合。
- 容器 = C 形路径(头 + 左壁 + 内腔 + 封口),内腔画浅色插槽底;空容器注册 Slot 行显示"把积木拖到这里"。
- 否则 = 内腔横向分隔条(整宽、块色加深)。
- 参数值 = 白色圆角插槽(SplitTitle 把 Title 按 {i} 拆段交替绘制固定文字/参数槽)。
- 命中用 _rows 倒序;End 行 Owner=末尾列表;Slot 行 Owner=空列表 → 拖入空容器可用。
### 坐标 bug(重要)
容器子块起点原为 innerTop+NotchH,而 InnerHeight 不含该偏移 → 子块总高比内腔多 7px,最后一块盖住底部封口。修复:子块从 innerTop 开始,elseY 同步去掉偏移。
### 主窗体补位
- 任务绑定启动热键:属性条 ComboBox(无/F1~F7)→ RebindTaskHotkeys() 注册 HK_TASK_BASE=200 起的动态 id,WndProc 派发 RunTaskByHotkey。
- 任务列表右侧画启用勾选框,点击直接切换(e.Y % 48 >= 16 判定行内区域)。
- 插件分组标题带类别色(▍ 前缀)。
- 积木页命令库 198 / 参数 230,画布 ~450px。
- 坑:构建时 exe 被残留进程锁定 → 先 taskkill 再 build。
---
## v2.3 脚本⇄积木双向转换 + 显示修复
用户反馈:截图圈了三处——属性条按钮被截、积木顶部被截、脚本和积木不该是两份代码。
### 双向转换(核心)
- 单一数据源 = task.Script。BlockCatalog.FromLua()(LuaBlocks.cs):行解析器,支持 for/while/if/elseif(嵌套进 else)/else/end、ifExists(do+local __ix 三行结构还原)、varSet/varAdd、目录模板匹配(TplCache:按函数名+返回值数+参数占位符构建,顶层逗号 SplitArgs 尊重引号括号)、认不出→ Key="lua" 自定义代码块(Template="{0}" Raw)。
- ToLua 去掉了日期头注释,否则往返不稳定。
- MainForm:_converting 互斥标志;切积木页 SelectedIndexChanged→SyncScriptToBlocks;_canvas.Changed→回写 _editor.Script;参数面板 TextBox/Combo 改动→_canvas.NotifyChanged()(新增公开方法,原 Changed 只在结构变化时发,改参数不触发是坑);LoadTaskDetail 旧数据迁移(只有 Blocks 无 Script 时转脚本);OpenBlocks 载入后同步转脚本。
### 显示修复
- 详情属性条 head 78→88、row2 28→34(按钮曾被截半)。
- 积木页工具条 WrapContents=true、Height=74(8 个按钮一行放不下)。
- BlockCanvas.LoadBlocks 加 AutoScrollPosition 归零(旧滚动位置把首块顶出视野)。
- 插件栏 224→234、按钮/分组标题 176→186。
- 坑:用户开着旧 exe 锁文件,taskkill 后再 build。
### v2.3 追修
- 用户再报:按钮底部仍被页签盖住 → head 88→96、row2 34→42 / Padding(2,2,0,0),按钮 28+m3 在 30 容器里溢出是根因。
- 用户报"没互相转换"→ LoadTaskDetail 改为任务载入后**无条件** SyncScriptToBlocks()(原来只靠 SelectedIndexChanged,且启动首载时画布为空)。实测三流程全通:启动切积木页 18 块、改参数回写 delay(999)、脚本加行切页出现 TAB 块。