# VB6 技能包

<!-- autos.skill.namespace: autos.skills.vb6 -->
<!-- autos.skill.description: Visual Basic 6.0 编程开发；可编写 aardio 控件。 -->
<!-- autos.skill.version: 0.2.5 -->
<!-- autos.skill.minAutos: 4.15 -->
<!-- autos.skill.disabled: false -->

## 定位与首选路线

以 **独立 VB6 EXE 开发/既有工程维护**为主，ActiveX DLL/OCX 与 aardio 组合为辅。复用已有 VB6 知识，不把 VB.NET、VBA7（LongPtr/PtrSafe）或 aardio 语法套入 VB6。纯 VB6 应用不能依赖 aardio 宿主才能运行。

0.2.2 修复备用 IDE 的 DAO350 缺失/未注册、跨会话编译器定位，并补齐原 mini 安装器的一项 IDE 配置；保留 Direct2D 薄画板与 ASCII/ANSI 编辑规则。验收范围见 SOURCES.md，不等于所有外部环境支持。

**自绘是重点：游戏、动画和简单按钮优先 Direct2D + DirectWrite 薄 Canvas，AI 直接写规则/几何/绘图，不造控件框架。** 先读 `knowledge/direct2d.md`；普通子库 `autos.skills.vb6.d2d.createProject(dir,{kind="canvas"或"pulse";name})` 生成当前 ANSI 的独立工程。随技能有开发 TLB，EXE 不带绘图引擎。复杂输入/列表等密集控件界面可用网页，不强迫自绘重造。

- 先用本技能的编译器定位，不自己扫描磁盘/重写定位器。**已有 VB6 就复用；找不到时自动走轻量备用部署**：读 `knowledge/setup.md`，`import autos.skills.vb6.setup` 后调用 `ensureCompiler()`。这是普通子库，不要再次 `load_skill`；直接使用本技能 `.res/core/` 的文件，不下载、不运行原安装 EXE、不升权。
- 维持既有 CRLF、Attribute、引用、FRX/CTX 配对与偏移；二进制资源不交给文本编辑器。编辑前备份，修改后编译与聚焦运行验证。
- VB6 String 本来就是 Unicode BSTR，不是 ANSI-only；源文件编码、ANSI 控件/API、路径/输入与 BSTR 分层理解。需要不能直接写入默认 ANSI 的 Unicode 常量时可用 ChrW$ 构造。
- **VB6 DLL/OCX 一律不用直接内存加载**：嵌入资源后先 `io.appData` 释放，再 `com.lite(path)` 磁盘免注册；已有外部组件直接磁盘加载。用户组件缓存用自己的厂商/应用目录，**`aardio/std` 仅供官方标准库**。路线与生命周期见 `knowledge/interop.md`。
- **发布文档面向产品，而不是开发工具清单**：不默认宣称“使用 VB6 开发”，不罗列调用过的接口、开发 TLB 或未确认的许可猜测。TLB 来源只在 TLB 旁的 `SOURCE.md` 简短记录；构建细节留开发文档。使用指南只写产品用法和必要的运行要求，不把开发依赖说明带进 EXE/DLL/OCX 的发布文档。
- 本技能的检查是文件/资源链接清单，不是完整 VB6 解析器、依赖验证或 IDE 调试器。项目类型 Exe/OleDll/Control；ActiveX EXE、复杂第三方许可、真实数据库、manifest 部署、真实 PMv2/IME/完整输入控件仍未验收。

## 处理 ANSI 编码

Autos 的文本与代码编辑工具只能处理 UTF-8 编码，但直接使用 Autos 工具通常可以大幅提升效率，并避免复杂的跨语言转义。

可选使用以下任何一种方法处理 ANSI 文本文件：

1. 你可以将 VB6 工程做成双镜像目录: 例如 `/vb-project`(ANSI 版本工程),`/vb-project.u8`(你直接编辑的 UTF-8 镜像版本)。
然后用 aardio 编写一个自动化构建工具，每次构建都将 `/vb-project.u8` 自动转换为 `/vb-project`并调用 VB6 编译或运行。
2. 直接编辑 `/vb-project`(ANSI 版本工程): 你可以用 save_files 工具直接写 UTF-8 编码的 VB 代码，然后用 `fsys.codepage.fromto(path,65001,0)` 将文件原地转换为 ANSI 编码。你也可以反过来用 `fsys.codepage.fromto(path,0,65001)` 临时将 VB 文件转换为 UTF-8 ，然后使用 Autos 强大的 edit_text_file, patch_text_file 工具编辑它。
3. 处理纯英文项目无需转换编码: **新源码不需要中文等非 ASCII 字符时，那你就应当保持纯 ASCII（含字符串/Attribute/VBP） 用 UTF-8 文件工具读写/编辑/精确补丁，一律英文写注释，不必要把事情搞复杂。**ASCII 是 ANSI/UTF-8 共用字节；保存为无 BOM、CRLF。中文交互可由 aardio 传入 Unicode BSTR，不必写进 VB6 源码。**旧源码如果仅在注释中包含少量非 ASCII 字符则应先转换为纯英文**。
4. ANSI 手术刀: 含非 ASCII 字符的既有 ANSI 源码才用 `textkit.ansi`（当前系统默认 ANSI），AI 处理 UTF-8 视图。不要用 UTF-8 工具直接改这种旧文件，不加入编码猜测/选择框架。现有模板生成器仍按其原契约保存 ANSI，不代表所有手写英文项目也需要它。
5. ASCII 开发/UTF-8 交付：在开发调试时始终使用英文，在编写代码时不用处理任何编码问题。仅在最后交付时将界面上的少量英文字符串改为中文。例如 将 button 上的 "click" 改成 "点我"。
6. 分离语言包：将界面文本分离到单独的语言包文件，代码始终仅处理英文 ASCII ，不用处理任何编码问题。

## 入口（短别名 + 可追溯）

```aardio
import autos.skills.vb6;
var vb = autos.skills.vb6;
import autos.skills.vb6.setup;
// Existing non-managed VB6 is reused; our old fallback is repaired when necessary.
var ready=autos.skills.vb6.setup.ensureCompiler();
if(!ready.ok) return ready;
var compilerPath=ready.compilerPath;

var project = vb.createProject("/MyVb6Project",{kind="gui";name="MyVb6App"});
if(!project.ok) return project;
var built = vb.build(project.projectPath,{compilerPath=compilerPath;timeoutMs=30000});
return built;
```

- `getCompiler(path?)`：显式 EXE 路径优先，随后 `process.cache.find` 与约定安装目录，再查备用目录、记忆路径与已激活 OLB 的同目录；返回路径或 `null,error`。只定位，不安装、不认证版本/编译能力；首次使用或修复我们的旧备用目录调用 `setup.ensureCompiler()`，不要因发现 EXE 就跳过必要修复。
- `createProject(targetDirectory,{kind;name})`：`gui/selftest/dll/ocx`，项目名 ASCII 标识符、最长 40。源码来自 `.res/templates/` 的 UTF-8 草稿，经 `textkit.ansi.save` 写为当前默认 ANSI、CRLF，无 BOM。拒绝已有目录；多个文件不是一个跨文件事务，失败时查看返回的目录，不自动删除用户资料。
- `inspectProject(vbp)`：返回普通表 `{ok;files;references;resources;fields;errors;warnings;artifactName}`。仅读取默认 ANSI 文件；清点源文件、FRX/CTX 链接是否存在及偏移是否越界；保留引用原文但不激活/验证 32 位依赖。不能把 `ok` 解读为可编译。
- `build(vbp,{compilerPath;timeoutMs=30000;buildRoot?})`：`VB6.EXE /MAKE /OUT /OUTDIR` + 数组 argv；每次新建 attempt/out/log，私有 `process.desktop` 与独立 `process.job.limitKill()`（挂起→纳入 Job→恢复），等待退出再清理。0.2.1 已将 `buildRoot`（包括 `/虚拟路径`）转成物理绝对路径后传给外部编译器，日志与产物位于同一 attempt。耗时操作放工作线程；不是沙箱，编译器可能自动尝试注册 COM。
- 构建成功条件：`built.ok`（正常退出码 0、本次新目录中的非空产物、进程树与桌面清理成功）。不凭日志字样或旧文件存在判成功；不自动把产物覆盖到发布目录/兼容性基准。
- 极少数清理失败会返回 `cleanupPending`（活 Job/桌面/进程对象），必须重试 `job.dispose`，确认残余进程退出并 free 后才 close 桌面；不要将其当普通成功结果或遗忘句柄。

## 源码编辑：ASCII 直编，ANSI 旧文件按需转换

已知为纯 ASCII 的 `.vbp/.bas/.cls/.frm/.ctl`，直接使用 `save_files/read_text_file/patch_text_file` 等 UTF-8 工具；不要为了英文源码再搭 ANSI 中转。若不需要中文，注释也写英文，避免中文或智能引号把文件变成非 ASCII。仍保留 CRLF、Attribute 与二进制资源配对。

以下 `textkit.ansi` 片段**只用于含非 ASCII 的 ANSI 源码**：

```aardio
import textkit.ansi;
var view = textkit.ansi.read(path="/MyVb6Project/MainForm.frm";lineNumbers=false);
if(!view.ok) return view;

var edit = textkit.ansi.edit(
    path="/MyVb6Project/MainForm.frm";
    operation="replace";
    oldText='Caption         =   "旧标题"';
    newText='Caption         =   "新标题"'
);
return edit; // 先检查 ok，再看 written / backupPath
```

`read/patch/edit/save` 都是 `{path;...}` → 结果表，固定 codepage=0；参数、视图、补丁与诊断均 UTF-8。局部改动用 patch/edit，新建或明确全文覆盖才用 save。SEARCH 必须复制唯一的原文（去展示行号），失败不模糊重试。

默认备份是 **原始 ANSI 字节**，恢复用 `io.copy(edit.backupPath,edit.path)`，不能用 UTF-8 文本工具读取备份再写回。dryRun 不写文件；read 的 LF 展示不是原文件全文备份；save 的父目录必须已存在，不自动改换行/加 BOM。NUL、FRX/CTX 等二进制不支持。本库遵循系统默认 ANSI 转换，不猜测/修复乱码，也不承诺异常原始字节整份转码后完全不变。

## 按需知识路由

资源位于 `io.joinpath(io.splitpath(io.libpath("autos.skills.vb6")).dir,".res")`，只读当前问题需要的文件：

| 任务 | 入口 |
| --- | --- |
| 自绘游戏/动画、轻量 Canvas（重点） | `knowledge/direct2d.md` → `d2d/README.md`；普通子库 `autos.skills.vb6.d2d`，无需再 load_skill |
| 独立 EXE、模板运行 | `knowledge/independent.md` |
| 编译器缺失、轻量备用部署/定制安装包 | `knowledge/setup.md`；普通子库 `autos.skills.vb6.setup`（无需再次加载技能） |
| 旧工程/资源维护、UI生命周期、错误清理 | `knowledge/maintenance.md` |
| 报错定位、罕见IDE启动安装弹窗 | `knowledge/diagnostics.md` |
| ADO/数据库任务（本地验证与接库边界） | `knowledge/ado.md` |
| DLL/OCX 免注册、BSTR/ByRef/数组/事件/宿主回调、锁与升级 | `knowledge/interop.md`；`com.lite` / `com.typeAttrs` / `com.tlbDoc` |
| 组合源码示例、独立EXE文件协作 | `examples/README.md`（先生成ANSI工程/构建，COM另进程加载） |
| ANSI 精确编辑 | `textkit.ansi` 库参考；上面的片段 |
| 来源与验收边界 | `SOURCES.md` |

默认流程：明确需求/工程路径与现有运行结果 → 定位编译器、检查工程 → 新建模板或按源码内容选 ASCII/ANSI 最小补丁 → 构建并看返回状态/日志 → 独立 EXE 自检/短 GUI 冒烟或独立进程 COM 验证 → 汇报证据和未验证边界。不操作用户既有 VB6 IDE 实例，不主动注册新 DLL/OCX，不把进程退出与“全部业务正确”混为一谈。
