Files
notify/docs/interop.md
T
chuan 79992680c9 docs: 重写 README 并新增 docs 调用时序文档
- README 对齐当前 C# / Avalonia 架构与安装方式
- docs: architecture / sequences / hooks-and-cli / interop / build-and-install
2026-06-22 16:40:27 +08:00

40 lines
3.2 KiB
Markdown
Raw 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.
# 原生互操作与 AOT
所有 Win32 / COM 互操作都为 **NativeAOT** 准备:用 `LibraryImport`(源生成 P/Invoke)和 `[GeneratedComInterface]`(源生成 COM),**不用** `System.Drawing`、经典 `[ComImport]`、反射式封送(它们在 AOT 下不可用)。
| 文件 | 职责 | 关键点 |
|------|------|--------|
| `Win32.cs` | 基础 P/Invoke | `GetForegroundWindow``GetClassName`、工具窗口样式等 |
| `WindowActivator.cs` | 抢前台激活 | ALT 模拟 + `AttachThreadInput` + 多 API 组合,绕过防焦点抢占 |
| `WinTerminalTabs.cs` | WT 切标签 | 源生成 COM 调 UIAutomation,按 RuntimeId 定位标签 |
| `VirtualDesktopPinner.cs` | 跨虚拟桌面 | 未公开 COM `IVirtualDesktopPinnedApps.PinView` |
| `ProcessTree.cs` | 进程树上溯 | Toolhelp 快照,跳过 shell/运行时找调用方 App |
| `AppIcon.cs` | 取图标 | `ExtractIconEx` + GDI 读 BGRA 像素 → Avalonia 位图 |
| `Sound.cs` | 提示音 | winmm `PlaySound` 从内存异步播放 |
## 窗口激活(WindowActivator
Windows 限制后台进程抢焦点。组合技:还原最小化 → 模拟一次 ALT 抬起 → `AttachThreadInput` 把当前线程与前台/目标线程输入队列挂接 → `AllowSetForegroundWindow` + `SetWindowPos`/`BringWindowToTop`/`SwitchToThisWindow`/`SetForegroundWindow` 多管齐下 → 解除挂接。
## Windows Terminal 切标签(WinTerminalTabs
- `save` 时:检测前台窗口类是否 `CASCADIA_HOSTING_WINDOW_CLASS`;是则用 UIAutomation 找当前选中的 `TabItem`,取其 **RuntimeId**(一串 intSAFEARRAY)存入状态。
- 点击时:激活 WT 窗口后,枚举标签找到 RuntimeId 匹配的,调 `SelectionItemPattern.Select()`
- **AOT 要点**:接口用 `[GeneratedComInterface]`;未用到的 vtable 槽用占位方法按 SDK 头文件顺序补齐(顺序/GUID 均取自 `UIAutomationClient.h`);`IApplicationView` 当**裸 `IntPtr`** 传递,绕开现代 .NET 不支持的 `IInspectable` 封送。
## 跨虚拟桌面(VirtualDesktopPinner
-`CoCreateInstance` 拿 ImmersiveShell**必须 `CLSCTX_LOCAL_SERVER`**,否则 `REGDB_E_CLASSNOTREG`)→ `IApplicationViewCollection.GetViewForHwnd``IVirtualDesktopPinnedApps.PinView`
- GUID 随 Windows 版本变化(这里用 24H2 一套,实测 26200 仍匹配);整段 try/catch,失败自动退回"仅当前桌面"。
- 窗口刚打开时 shell 可能还没登记 view(`TYPE_E_ELEMENTNOTFOUND`),故短间隔重试。
## 取图标(AppIcon
`ExtractIconEx` 拿 HICON → `GetIconInfo` 取彩色位图 → `GetDIBits` 以 32bpp 自上而下读出 BGRA → 构造 `Avalonia.Media.Imaging.Bitmap`。老图标无 alpha(全 0)时补成不透明,避免整块透明。取不到则回退默认 Claude 图标。
## AOT 状态
- `csproj` 已开 `IsAotCompatible`(静态分析 0 警告);`PublishAot` 条件块 + `TrimmerRootAssembly`Ursa/Semi 整体保留)。
- **AOT 发布的原生链接需要 MSVC 工具链**(从 "Developer Command Prompt for VS" 跑,或用配好 vcvars 的脚本)。
- ⚠️ **build 通过 ≠ 能跑**:源生成 COM / UIAutomation 必须真机运行验证(本项目踩过 `CLSCTX``IInspectable` 封送两个坑,都是编译过但运行崩)。