79992680c9
- README 对齐当前 C# / Avalonia 架构与安装方式 - docs: architecture / sequences / hooks-and-cli / interop / build-and-install
3.2 KiB
3.2 KiB
原生互操作与 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(一串 int,SAFEARRAY)存入状态。- 点击时:激活 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封送两个坑,都是编译过但运行崩)。