﻿DCX 便携包  v0.1.1 (win64)
======================================================================

构建信息
------------------------------------------------------------------------
  构建时间   2026-11-07 16:08
  本次变更   替换 dcx-host.exe（信息岛注册 / 第三条热键 / 第 5 页设置），
              新增 dcx-island.exe，更新 stop-dcx*.bat 与 start-dcx.bat；
              dcx-box.exe / dcx-search.exe / dcx_engine.dll 沿用 11-06 构建
  工具链     rustc 1.97.1 / cargo 1.97.1 (x86_64-pc-windows-msvc)
  构建配置   release：opt-level=3, lto, codegen-units=1, strip, panic=abort
  产物来源   宿主/应用/引擎由本仓库源码编译；wh_injector.exe 为外部注入器

怎么启动
------------------------------------------------------------------------
  双击 dcx-host.exe —— 这就是程序入口。
  只想留托盘、不弹设置窗口：双击 start-dcx.bat。

  它是 GUI 程序（无控制台窗口）：启动后通知区出现 DCX 图标，同时弹出
  设置窗口。托盘图标左键单击 = 打开设置，右键 = 「设置 / 退出」。
  设置窗口跑在独立进程里（dcx-host.exe --settings）：winit 一个进程只能有
  一个事件循环，因此设置窗口、收纳盒、文件检索、桌面信息岛各占自己的进程。
  关闭设置窗口不结束宿主；再开一次不会出现第二个设置窗口，只会把已开的
  那个提到前台。

  文件检索默认关闭、不常驻、不预建索引：在桌面任意位置按 Alt+S 唤起
  （设置 → 桌面整理 → 文件检索 可改键或改成开机常驻）。首次唤起立即显示
  窗口，后台建立全盘文件名索引，结果边建边出；关闭窗口即释放进程。

  桌面信息岛默认关闭：先在「设置中心 → 桌面信息岛」开启，屏幕顶部居中会
  出现常驻胶囊（时间、CPU/内存/磁盘/网络、当天任务、未读角标），点击胶囊
  或按 Alt+I 展开四个页签。它不占任务栏槽位，也不需要替换 dcx_engine.dll。

  想让它开机自启：把 dcx-host.exe 的快捷方式放进 shell:startup
  （资源管理器地址栏输入 shell:startup），并在快捷方式"目标"末尾加
  一个空格和 --no-settings，开机时只留托盘、不弹窗口。

目录内容
------------------------------------------------------------------------
  dcx-host.exe          宿主：托盘、设置窗口、圆角效果、弹窗去边框、
                              注入看门狗、应用启停、全局热键
  dcx-box.exe            独立应用：桌面收纳盒（由 host 按 apps.toml 拉起）
  dcx-search.exe         独立应用：文件检索（默认关闭，Alt+S 唤起）
  dcx-island.exe         独立应用：桌面信息岛（默认关闭，须在设置中心开启；
                              Alt+I 展开，必须与 host 同目录）
  start-dcx.bat          静默启动（只留托盘，不弹设置窗口）
  dcx_engine.dll          646,656 B：任务栏主题引擎，注入 explorer.exe
                              （含悬停放大与收纳盒槽位量测/预留）
  wh_injector.exe         124,416 B：注入器（VirtualAllocEx +
                              WriteProcessMemory + CreateRemoteThread）
  stop-dcx.bat          停宿主 + 三个独立应用；引擎仍留在 explorer 内
  stop-dcx-all.bat      一键退出全部 DCX 进程并解锁目录；换 dcx_engine.dll 时按提示重启资源管理器（/y 免询问）
  update-engine.bat     换引擎：停宿主 → 重启 explorer → 换 DLL → 重新注入
  recover-shell.bat     桌面壳（任务栏/桌面）消失时的恢复脚本
  settings.example.toml 配置项说明（不会被读取，仅作格式参考）

命令行参数（一般用不到）
------------------------------------------------------------------------
  dcx-host.exe                托盘 + 注入 + 设置窗口（默认）
  dcx-host.exe --no-settings  托盘 + 注入，不弹窗口（开机自启用这个）
  dcx-host.exe --selftest     空跑 1.5 秒后退出（自检，不注入）
  dcx-host.exe --settings     只开设置窗口（开发调试用）
  dcx-box.exe / dcx-search.exe / dcx-island.exe
                                独立应用，通常由宿主按 apps.toml 拉起；
                                手工双击可调试，命名互斥体保证单实例。
                                Alt+S / Alt+I 由宿主常驻监听，不依赖应用进程。
  --with-settings 仍被接受，等同默认行为（兼容旧脚本）。

  从 cmd / pwsh / Windows Terminal 运行带参数时会正常打印；双击或从
  资源管理器启动时没有可写的控制台，输出改写到
  %LOCALAPPDATA%\dcx\host.log（超过 512 KB 自动轮转为 host.log.old）。

功能清单
------------------------------------------------------------------------
  宿主 dcx-host.exe
    - 单实例：同名互斥体「Local\DCX.Host.Singleton」；重复启动直接退出，
      并把已有的设置窗口提到前台（避免两个托盘图标、两份配置互相覆盖）
    - 系统托盘：左键打开设置，右键「设置 / 退出」
    - 设置窗口（五页：任务栏样式 / 桌面整理 / 文件检索 / 桌面信息岛 /
      关于），改完即生效，无「保存」按钮
        · 下面「外观 / 尺寸与间距 / 行为」属「任务栏样式」页
        · 外观：形状（胶囊 / 卡片）、图标大小 50–125 %、快速预设
          （紧凑 / 标准 / 宽松）
        · 尺寸与间距：任务栏高度 30–44 px、图标水平间距 0–16 px、
          边缘留白 0–8 px、离底间距 0–16 px、最大宽度
          （默认 1895 px，可 1024–2048）
        · 行为：自动隐藏任务栏（走 shell 自身 ABM_SETSTATE，系统保存）
          开机自启（写 HKCU\...\Run，登录后只进托盘、不弹窗口）
        · 底部：恢复默认 / 重新应用 / 打开配置目录
        · 右上：浅色 / 深色（只影响设置窗口本身）
        · 左栏底部：引擎状态（已注入 / 未注入）
    - 统一窗口圆角（DWM 属性）
    - 弹窗去边框：开始菜单、托盘溢出、右键菜单等 1 px DWM 边框清除
    - 自动注入看门狗：每 5 s 扫描 explorer，未加载引擎则注入；
      explorer 重启后自动补回。另每 3 s 采样一次引擎状态给 UI
  引擎 dcx_engine.dll（注入 explorer.exe，改动任务栏 XAML）
    - WindowGlass Split 主题：胶囊 / 卡片形状、右胶囊时钟
      （日期折叠、时间 13 px 单行）
    - 去任务栏灰线：RootGrid 描边归零、全宽背景层折叠、
      Shell_TrayWnd 的 DWMWA_BORDER_COLOR 置为无边框色
    - 图标缩放 / 间距 / 高度 / 离底 / 最大宽度按 settings.toml 写入
    - 设置文件热重载：每秒轮询 mtime，重建规则并重放，无需重新注入
    - 收纳盒槽位（slot.rs）：从任务栏 XAML 量出「最后一个程序图标的右边缘」
      与托盘左边缘，每 250 ms 写 %LOCALAPPDATA%\dcx\box_slot.txt
      （2 s 心跳，宿主 3.5 s 读不到就判定引擎已退出）；
      同时给 TaskbarFrameRepeater 加 52 DIP 右边距，把槽位真正留出来
      （胶囊按内容宽度包裹该 repeater，所以是加宽而不是压缩图标）
  桌面收纳盒（宿主 box_ui + dcx-organizer）
    - 开启后任务栏「程序图标最后、托盘之前」固定一个按钮（44×42 命中区，
      静止无底板、悬停出 40×40 底板），悬停 110 ms 或点击展开目录弹层
    - 每行显示文件自身的图标（走系统 shell 图标：Word/PDF/PPT/快捷方式…），
      取不到图标时退回「扩展名色块」
    - 弹层宽度按分类标签行自适应（300–560 pt），标题栏可拖动到桌面任意位置，
      双击标题栏回到按钮上方；位置记在 %LOCALAPPDATA%\dcx\box_ui.txt
    - 展开方式可选：设置 → 桌面整理 →「悬停即展开」。关掉后只有点击才展开
    - 收纳 = 把桌面文件**物理移动**到独立收纳库（默认 文档\dcx收纳），
      桌面图标随之消失，文件本身不删除；从库内拖回桌面即移回桌面根目录
    - 分类是收纳库内的虚拟元数据：扩展名规则自动归类，手动拖拽/菜单写
      organizer.toml 的 overrides；分类不改文件内容
    - 库路径在「设置 → 桌面整理 → 收纳库目录」修改，改时会迁移已有文件
      并保留手动分类；支持列表/网格、排序、搜索、文件夹展开、拖放、
      右键菜单、新建文件夹、重命名、回收站删除
    - 配置 %LOCALAPPDATA%\dcx\organizer.toml
  文件检索 dcx-search.exe（默认关闭，Alt+S 唤起）
    - 双层架构：ignore::WalkParallel 冷启动一次建立内存文件名索引，
      notify（ReadDirectoryChangesW）增量维护；查询只查内存，切盘符不重扫
    - 内容检索才用 grep-searcher 逐行扫候选集：先按范围 / 分类 / 扩展名 /
      大小过滤；显式开启二进制检测（遇 NUL 退出），不启用 mmap
    - 搜索框右侧「文件名 / 内容」分段切换；路径下拉可切桌面 / 此电脑 /
      各盘符；7 个分类图标沿用收纳盒的扩展名规则
    - crossbeam 有界通道流式推送（256 条或 32 ms 一批），generation 取消旧
      查询；结果上限 2000 条，UI 每帧最多消费 4 批
    - 中文编码：BOM 嗅探 UTF-8/UTF-16；中文关键词无命中时回退 GB18030
    - 配置 %LOCALAPPDATA%\dcx\search.toml（host 与应用共读；写入走
      dcx_win32::config_file：命名互斥体锁 + ReplaceFileW 原子换入）；
      日志 search_trace.log / search_panic.log，热键占用提示
      search_hotkey_error.txt
    - 只读：不移动、不重命名、不删除任何文件；索引只驻留内存，不落盘明文
  桌面信息岛 dcx-island.exe（默认关闭，设置中心开启后 Alt+I 展开）
    - 单窗口单 viewport：紧凑胶囊与展开面板共用同一个窗口，窗口矩形随
      内容缩放，不会有大片透明区域吞掉桌面点击；不占任务栏槽位，不依赖
      box_slot.txt 预留协议
    - 紧凑态：时间 / 星期 / 日期、CPU / 内存 / 磁盘 / 网络、当前任务、
      未读角标；点击胶囊或按 Alt+I 展开
    - 面板四页签：任务（自动结转、Markdown 归档）、剪贴板（搜索 / 收藏 /
      备注 / 回写）、消息（统一收件箱与渠道诊断）、性能
    - 入站：微信 / 企业微信走任务栏关注信号（SHELLHOOK，不读聊天正文）；
      QQ 走 WinRT 通知监听并按 AUMID 过滤；邮箱走 IMAP 只同步未读邮件头
    - 出站：企业微信群机器人 webhook 与 SMTP 可推送任务提醒；QQ / 微信
      个人号没有官方出站接口，不支持发送
    - 授权码与 Webhook Key 只存 Windows 凭据管理器（目标名 DCX/island/*），
      不写 TOML、不写日志；剪贴板与通知内容全部本地保存
    - 配置 %LOCALAPPDATA%\dcx\island.toml；任务与剪贴板数据在
      island_tasks.json / island_clipboard.json；日志 island.log
  注入器 wh_injector.exe
    - 用法：wh_injector.exe <pid> <dll 绝对路径>，宿主自动调用

使用
------------------------------------------------------------------------
  1. 整个目录一起搬走，双击 dcx-host.exe。
  2. 改设置即时生效：写入 %LOCALAPPDATA%\dcx\settings.toml，
     引擎 1 秒内轮询到并热重载。
  3. 退出：托盘右键 →「退出」。
  4. 想手工改配置：照 settings.example.toml 的键改
     %LOCALAPPDATA%\dcx\settings.toml，保存后 1 秒内生效。

换引擎（dcx_engine.dll）
------------------------------------------------------------------------
  DLL 被 explorer 加载时文件是锁死的，运行中无法覆盖。流程：
    1. 把新 DLL 放到本目录下的 new\ 子目录（new\dcx_engine.dll）
    2. 双击 update-engine.bat
  脚本会停宿主 → 杀 explorer 让旧 DLL 卸载 → 覆盖 DLL →
  等壳回来 → 重新启动宿主（随即注入新引擎并开设置窗口）。
  没有 new\ 子目录时，它只重启 explorer，用于让宿主导回当前 DLL。

注意与已知限制
------------------------------------------------------------------------
  - 四个 exe 与 DLL / 注入器必须同目录：宿主按自身所在目录定位
    dcx-box.exe、dcx-search.exe、dcx-island.exe、dcx_engine.dll 与
    wh_injector.exe（开发期可用 DCX_INJECTOR / DCX_ENGINE_DLL 覆盖）。
  - 仅支持 x64 explorer.exe；32 位进程不加载本 DLL。
  - 任务栏高度上限 44 DIP：Shell_TrayWnd 自身窗口高 48 DIP，
    再高只会被屏幕边缘裁掉（窗口几何被 shell 内部否决，实测无解）。
  - 「高度 + 离底间距」合计不超过 44，两个滑杆互相限制。
  - 文件检索的全局热键在管理员权限窗口或全屏独占程序为前台时可能收不到
    （UIPI）；宿主未运行时热键无效。组合键被占用会在设置中心提示改键。
    首次唤起需要建立索引，大容量磁盘上首批结果会随扫描逐步出现。
  - 只作用于主任务栏；自动隐藏模式与自定义高度/离底组合未适配。
  - 桌面信息岛默认关闭，需先在「设置中心 → 桌面信息岛」开启；主开关关闭
    时 Alt+I 不会拉起窗口。它是独立进程的置顶悬浮窗，与自动隐藏任务栏
    的遮挡关系、125% DPI 下点击与绘制对齐仍待实机确认。
  - 微信 / 企业微信 / QQ 个人号只能做本地提醒聚合，没有官方出站发送接口；
    企业微信群机器人 webhook 与 SMTP 的凭据在设置中心「通知渠道·出站」
    卡片里显式保存，保存后可在岛内「消息」页查看渠道状态。
  - QQ 通知监听只读系统已授予的通知访问权限，不会弹系统授权框；若
    Windows 未授予通知访问权限，「消息」页会显示权限不足。
  - 引擎只匹配当前 Win11 任务栏视觉树，系统大版本更新后元素路径需重核。
  - 换 explorer 会话后必须重新注入，宿主看门狗会自动做（宿主需在运行）。
  - 收纳盒按钮只跟主任务栏；引擎未注入时按钮退化为按 ReBarWindow32 估算
    位置（会偏左，仍可用）。任务栏自动隐藏时按钮随栏一起消失。
  - 按钮是自绘的置顶窗口，位置由引擎量测决定；这两个环节任何一个失效，
    表现都是「槽位空着、看不见图标、点了没反应」：
      1) 引擎没注入 / box_slot.txt 过期 → 宿主日志会打 slot=None，
         按钮退回 ReBarWindow32 估算（会偏左）。
      2) 任务栏是 topmost，且每次滑出都会重新置顶 → 按钮被压在栏下面。
         现在宿主每帧用 WindowFromPoint 检查，被遮住才重新置顶。
      3) 双击启动时设置窗口会先占掉 winit 的事件循环（一个进程只能有一个），
         收纳盒窗口于是创建失败。现在设置窗口是独立进程
         （dcx-host.exe --settings），收纳盒 / 检索 / 信息岛各占自己的进程，
         每个进程只有一个事件循环，双击、托盘菜单、启动开设置都不再冲突。
      4) Dock 放大：悬停图标时整排会向右扩张，会压到按钮上。引擎已把放大的
         右界钳到"程序图标行静止时的右边缘"，贴近托盘的那几个图标放大时
         铺开幅度会略小一些，这是有意的。
    日志位置 %LOCALAPPDATA%\dcx\host.log，关键字 [dcx-box]。
  - 如果某个 Windows 版本对 TaskbarFrameRepeater 的边距反应异常，
    新建一个空文件 %LOCALAPPDATA%\dcx\no_reserve 即可关闭槽位预留
    （不用重新编译），按钮会退回「托盘前的空隙」里。

排障
------------------------------------------------------------------------
  - 设置窗口底部显示「引擎未注入」：
      确认 wh_injector.exe 与 dcx_engine.dll 在同目录；
      用管理员身份启动宿主（OpenProcess 需要提权）；
      或直接双击 update-engine.bat 重来一遍。
  - 宿主自己的日志：%LOCALAPPDATA%\dcx\host.log
      注入失败、找不到 DLL、重复启动等都在这里（每行带 pid 头）。
  - 规则是否真的写进 XAML：看引擎日志 %TEMP%\dcx-engine.log
      APPLIED / READBACK 行给出每个元素的写入计数与回读值。
  - 桌面壳消失（任务栏和桌面图标都没了）：
      任务管理器 → 文件 → 运行新任务 → 浏览到本目录的
      recover-shell.bat（先起 explorer 再起宿主）。
  - 设置中心里没有「桌面信息岛」页、或按 Alt+I 没反应：
      说明当前跑的还是旧 dcx-host.exe。本次替换二进制时没有重启正在
      运行的进程：先用托盘右键「退出」（或运行 stop-dcx-all.bat），
      再双击 dcx-host.exe 重启即可；四个 exe 必须与宿主同目录。
