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

6.9 KiB
Raw Permalink Blame History

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 块。