传统 AHK Gui 很适合快速做工具,但界面一旦需要统一主题、复杂布局、侧边栏、现代控件和更完整的视觉层次,代码会迅速变得难维护。AHK-XAML 的思路是让 AHK 继续负责业务和事件,用 XAML 与 WPF 负责界面结构和渲染。
本批资源包含 AutoHotkey v1 移植版,运行基线是 AutoHotkey v1 U64。它通过独立的 WPF daemon 进程工作:AHK 生成界面描述,C# WPF Host 创建窗口,事件和状态再通过 IPC 回到 AHK。它不是给传统 Gui 换一层皮肤,而是一套 AHK 到 WPF 的桥接框架。
它带来的实际能力
- 使用 Grid、StackPanel、DockPanel、ScrollViewer 等 WPF 布局;
- 统一使用颜色、字体、边框、圆角、阴影和控件模板;
- 通过链式 API 创建控件并绑定 AHK v1 回调;
- 提供侧边栏、标签页、Snackbar、Flyout 等常用组件;
- 可选接入 WebView2、AvalonEdit、文档组件和 shader 效果;
- 附带多个基础、组件展示和仿制界面示例。
ahk-xaml-main_V1\examples\clones\vscode_v1.ahk 示例演示图

先说清楚它和原生 WPF 的区别
底层确实由 WPF 渲染,但写代码时并不是在开发完整的 C# WPF 程序。原生 WPF 中的 DataContext、Binding、Command、DependencyProperty、MVVM、ObservableCollection 和设计器工作流,在这套封装里并没有原样提供。常用方式仍是 AHK 事件回调,加上 Query()、Update() 等接口更新界面。
因此它适合需要现代界面、组件化布局和中等复杂交互的 AHK 工具;只做几个输入框和按钮时,传统 AHK Gui 更轻。需要完整 MVVM、复杂数据绑定、第三方 WPF 控件生态和高频实时动画时,原生 C# WPF 仍然更合适。
v1 版本的边界
v1 移植版只支持外部 daemon,不支持进程内 CLR/WPF 托管。WebView2、AvalonEdit、文档编辑器和 DirectX 9 shader 默认关闭,启用前要按配置文件准备额外依赖。由于 v1 的 unset、类型和超级全局变量语义与 v2 不同,调用方还应避开项目保留的全局变量名。
当前素材中有多组经过解析和窗口启动检查的 v1 示例。新手建议从 Minimal 或下面的 minimal_wrapper 开始,先看控件创建、Track()、On() 和 Update(),再进入复杂组件与仿制界面。
示例运行时会启动配套 WPF daemon。结束 AHK 主脚本后,宿主进程应随之退出;若自行改造启动流程,要同时处理异常退出和进程清理。
打包库和示例的下载地址:
蓝奏云:https://wwbtw.lanzouu.com/isu4t3wswp2d 提取码:ahk6
百度网盘:https://pan.baidu.com/s/1dkOgcGNseyA0zCQwXwXIYQ?pwd=ahk6 提取码:ahk6
demo代码片段展示:
#Requires AutoHotkey v1.1.37+
#Persistent
#Include <XAML_GUI>
#Include <XAML_Components>
app := new XAML_GUI("Minimal AHK GUI")
app.sidebarPanel.Add("TextBlock").Text("QUICK SETTINGS").Margin("0,15,0,15").Foreground("{DynamicResource TextSub}").FontSize(11).FontWeight("Bold")
app.sidebarPanel.Toggle("TglCenter", "Center Align", false)
.Track()
.On("Click", Func("MinimalWrapper_OnToggleCenter"))
app.tabs.Visibility("Collapsed")
panel := app.main.Add("StackPanel").Grid_Row(1).Margin("40,20,40,20")
panel.Add("TextBlock").Name("TxtTitle").Text("Welcome to the Minimal UI!").Use("PageTitle").Margin("0,0,0,10")
panel.Add("TextBlock").Name("TxtDesc").Text("Notice how much heavy lifting is done for you. No DllCalls, no manual rendering, just clean, object-oriented UI building.").Use("BodyText").Margin("0,0,0,25")
panel.Add("TextBlock").Name("TxtLabel").Text("ENTER YOUR NAME").Foreground("{DynamicResource TextSub}").FontSize(11).FontWeight("Bold").Margin("0,0,0,8").HorizontalAlignment("Left")
panel.Add("TextBox").Name("TxtName").Width(300).HorizontalAlignment("Left").Margin("0,0,0,15").Track()
panel.Add("Button").Name("BtnSubmit").Content("Say Hello").Use("PrimaryBtn").Width(120).Height(32).HorizontalAlignment("Left")
.On("Click", Func("MinimalWrapper_OnSubmitClick"))
ui := app.Compile()
ui.xaml := StrReplace(ui.xaml, "Width=""940"" Height=""700""", "Width=""600"" Height=""420""")
app.Show()
return
MinimalWrapper_OnToggleCenter(state, ctrl, event) {
global app
isCenter := state.HasKey("TglCenter") && state["TglCenter"] == "True"
align := isCenter ? "Center" : "Left"
app.host.Update("TxtTitle", "TextAlignment", align)
app.host.Update("TxtDesc", "TextAlignment", align)
app.host.Update("TxtLabel", "HorizontalAlignment", align)
app.host.Update("TxtName", "HorizontalAlignment", align)
app.host.Update("BtnSubmit", "HorizontalAlignment", align)
}
MinimalWrapper_OnSubmitClick(state, ctrl, event) {
global app
name := state.HasKey("TxtName") && state["TxtName"] != "" ? state["TxtName"] : "Stranger"
app.ShowSnackbar("Hello there, " name "!")
}

评论(0)