Skip to content

Repository files navigation

AnyKey

AnyKey(任意键)

简体中文 | English

为 Windows 打造的高性能键位重映射工具 —— 图形界面配置、内核级输入拦截、多设备多应用映射。

AnyKey 把「键盘/鼠标该怎么响应」完全交给你定义。核心引擎用 Rust 编写,通过**自研 Windows 内核过滤驱动(UpperFilter)**在系统底层拦截并重注入键盘/鼠标输入;所有处理均在本机完成,无遥测、无网络上报

和同类工具比,不一样在哪

层切换、组合键、Leader 序列、TapDance 这些是重映射工具的基本功,不必重复。AnyKey 的差异在三点:

1. 图形界面配置,不用手写文件。 完整的图形界面,可以方便、直观地对按键进行设置。免去代码式配置文件的使用门槛。程序使用标准 JSON 文件保存配置。若不想用图形界面,也可以手动编写 JSON 文件实现按键设置。

2. 多设备、多应用支持。 每个设备都可以针对每个应用进行独特的映射设置。极大地方便宏键盘、多软件快捷键协调等场景。对设备的热插拔、睡眠唤醒做了针对性优化,确保连接稳定。

3. 「按住换层」手感专门调校。 任何按键都可以完美地兼容层切换键、修饰键等按住组合键的操作。深入设计的语义延迟解析系统保证按键无论怎么设置,每次输入都不误触。


关于测试模式

按正常方式加载驱动需要微软签名(EV 证书 + WHQL 认证),太贵了,暂不打算掏这笔钱。所以当前版本只能在 Windows 测试签名(Test Signing)模式下运行,桌面右下角会有常驻水印;等真的有必要的时候再考虑。介意的话先看安装一节的完整说明再决定。


1. 核心功能特性

  • Combo 组合键:同时按下两个键触发一个新键(如 q+w → Enter
  • TapDance 点按:单键 tap / hold / double-tap / double-hold 四种身份(如 Ctrl 快速按两下 → {home}
  • Layer 层切换:基础层 + 功能层;{fnX} 连发 / {bnX} 吞重复 / {tnX} 固定切换三种层激活语义
  • Leader 序列:常驻监听,随时直接键入序列触发动作,支持滑动超时、循环捕获与屏蔽模式
  • Defer 延迟决策:层键 hold 判定前延迟下游按键,松开后自动补发(链式依赖)
  • 宏支持RUN:(执行程序/URL/文件)、{Sleep N}(非阻塞延迟)、{Select N}{KeyName N}(重复按键)、MouseMove(x, y)
  • 鼠标全覆盖:5 键入管道(TD / Combo / 层切换),滚轮与移动透传
  • 内核驱动:UpperFilter 输入拦截,无设备数量上限、热插拔/休眠友好
  • 设备 + 应用感知运行时:不同设备/应用套用不同映射,输入状态按域跨设备共享
  • 设备白名单:按 VID/PID 过滤,未白名单设备完全透传
  • GUI 配置器:CustomTkinter 图形界面,所见即所得编辑配置
  • 失控安全网:引擎崩溃、心跳丢失、主线程死锁三道防线,含内核级紧急脱离快捷键

2. 安装方法

⚠️ 重要限制,安装前必读:AnyKey 的内核驱动未获得微软签名证书(签名太贵,暂时不打算搞——见开头的说明),因此只能在 Windows Test Signing(测试签名)模式下加载,且 Test Signing 与 Secure Boot 互斥——必须先在 UEFI 固件中关闭 Secure Boot。开启测试模式后桌面右下角会常驻「测试模式」水印;部分基于虚拟化的安全特性(HVCI / 内存完整性)会阻止未签名驱动加载,启用前需确认本机安全配置兼容。了解并接受以上风险后再继续安装。

获取方式二选一:从 GitHub Releases 下载发布包(zip)并解压到任意目录,或克隆仓库后按「从源码构建」自行编译。除内核驱动外,其余组件(GUI 配置器、系统托盘、引擎)均为免安装的独立可执行文件。

发布包解压后结构(zip 根即此三项):

├── anykey/                  程序本体:GUI 配置器 + 托盘 + Rust 引擎(免安装)
├── anykeyFilterDriver/      内核过滤驱动:.sys / .inf / .cer + 一键安装·卸载脚本
└── 安装驱动.bat             驱动安装启动器(双击即调起上面的安装脚本)

安装三步:

  1. 关闭 Secure Boot(完整步骤见下):

    先确认是否需要这一步:运行 msinfo32,看「系统摘要 → BIOS 模式」。
    显示 UEFI → 按下述步骤关闭 Secure Boot;显示 传统(Legacy) → 机器以旧式 BIOS
    方式启动,根本不存在 Secure Boot 选项,bcdedit 可直接执行,跳过本步方式一:从 Windows 进入 UEFI 设置(下面两条路殊途同归,任选其一)

    • 最快:点开开始菜单 → 电源按住 Shift 点「重启」,电脑直接进入蓝色恢复菜单
    • 或走设置:Windows 11 为 设置 → 系统 → 恢复 → 高级启动 → 立即重新启动,Windows 10 为 设置 → 更新和安全 → 恢复 → 高级启动 → 立即重新启动
    • 重启进入蓝色恢复菜单后:疑难解答 → 高级选项 → UEFI 固件设置 → 重启,电脑将直接进入主板 BIOS/UEFI 界面
    • Security / Boot / Authentication 页签(因主板品牌而异)找到 Secure Boot,设为 Disabled
    • F10(Save & Exit)保存并退出,电脑自动重启 方式二:开机按键直进 BIOS:建议在 Windows 里点「重启」而不是「关机」后再开机——开启了快速启动(Fast Startup)的电脑关机并非完整冷启动,BIOS 快捷键可能不响应。开机自检画面出现时反复按主板快捷键——台式机多为 Del,笔记本常见 F2,进入后同上找到 Secure Boot 关闭并保存。

    验证:回到 Windows 后运行 msinfo32,「系统摘要 → 安全启动状态」应显示为「」。

    注意

    • 开启了 BitLocker 的电脑,关闭 Secure Boot 时可能被要求输入 48 位恢复密钥——操作前先在 Microsoft 账户manage-bde -protectors -get C: 中查到密钥备用
    • Secure Boot 选项若呈灰色不可改,按以下顺序排查(最常见的原因在前):
      ① 需要先设置 BIOS 管理员密码——在 Security 页找 Supervisor / Administrator Password 设一个(品牌笔记本最常见),保存重启后再进 BIOS 试;
      ② BIOS 处于 CSM/Legacy 兼容模式——关闭 CSM(注意:仅当系统是 UEFI/GPT 方式安装的才能关,否则 Windows 将无法启动);
      ③ Secure Boot 密钥缺失(Key Management 显示 Setup Mode / Unloaded)——执行 Install/Restore Factory Keys 恢复出厂密钥;
      ④ 载入出厂默认值(Load Factory Defaults)或更新 BIOS 后再试
    • 不同品牌 BIOS 菜单差异较大,找不到时查主板/笔记本手册
  2. 运行驱动安装脚本:双击发布包根目录的 安装驱动.bat(或以管理员身份运行 anykeyFilterDriver/Install_AnyKey_Filter.bat)。脚本一次性完成全部安装:自动检测测试模式,未开启则自动执行 bcdedit /set testsigning onpnputil 注册键盘 + 鼠标两份 INF → 对当前已连接的键盘鼠标绑定 UpperFilter → 提示重启。只需运行一次,重启后测试签名与驱动同时生效。(若测试签名开启失败,通常是 Secure Boot 未关闭——按第 1 步关闭后重跑脚本即可。)

  3. 验证与使用:重启后桌面右下角出现「测试模式」水印即表示生效。运行 anykey/anykey-gui.exe 编辑配置、启动引擎,或通过托盘菜单控制。

手动备选:不想用脚本时,可自行以管理员身份执行 bcdedit /set testsigning on 并重启,再手动注册 INF。关闭测试模式:bcdedit /set testsigning off(同样需重启),关闭后可重新开启 Secure Boot。


3. 卸载方法

  1. 退出程序:通过系统托盘菜单「完全退出」级联关闭 GUI 配置器与引擎。
  2. 卸载驱动:以管理员身份运行 anykeyFilterDriver/Uninstall_AnyKey_Filter.bat(双击会自动请求管理员权限)。脚本完成解除 UpperFilter 绑定与 INF 注销后,需要重启电脑才能彻底生效。
  3. 可选——关闭测试模式:以管理员身份执行 bcdedit /set testsigning off 并重启,桌面水印消失,之后可在 UEFI 中重新开启 Secure Boot。
  4. 删除文件:直接删除解压目录即可(配置文件 anykey_config.json 在程序目录内,一并删除;如需保留键位配置,删除前备份该文件)。

4. 具体功能用法

4.1 失控安全防护

紧急脱离快捷键(LCtrl + Space + Esc):三键同时按住立即触发紧急关停——关闭拦截、清空输入队列、释放所有已按住的修饰键、重置状态。只认左 Ctrl(E0 前缀的右 Ctrl 不计),避免误触。因为它在驱动 ServiceCallback(DISPATCH_LEVEL,所有按键必经)里实现,引擎主线程死锁后用户态代码无法运行时,只有内核回调能兜底恢复。

AnyKey 是「输入网关」——引擎/驱动一旦卡死,整个键盘会锁死。因此内置三层互不共享检测信号的防护:

触发条件 机制 实现位置
Session 引擎进程退出/被杀 内核关句柄 → EvtFileCleanup → 立即关拦截 anykey_flt.c
Heartbeat 引擎心跳线程随死锁停摆 30s 无心跳 IOCTL → 紧急关停 anykey_flt.c + main.rs 心跳线程(5s/次)
紧急脱离快捷键 主线程死锁但心跳仍正常(自动层都不触发) 硬件级组合键,绕过引擎直接关停 过滤驱动内建

4.2 系统托盘

关闭主窗口后引擎仍在后台运行(托盘图标常驻)。托盘菜单:

  • 打开主窗口:重新调出 GUI 配置器
  • 帮助:快速查看使用说明
  • 暂停 / 恢复:临时停用/恢复全部映射(原始输入直通)
  • 重载设置:不重启引擎即可应用修改后的配置
  • 开机自启:写入注册表 Run 项,开机自动拉起托盘 + 引擎
  • 调试日志:打开引擎运行日志目录,排查映射问题时使用
  • 完全退出:级联关闭 GUI + 引擎 + 托盘

托盘图标区分运行中 / 已暂停两种状态,一眼可辨当前是否在拦截。

4.3 GUI 简介

GUI 是所见即所得的配置生成器,负责读写 anykey_config.json 并通过托盘下发 IPC 命令。窗口结构自上而下:

区域 内容
顶栏 状态横幅(引擎运行状态)、导入 / 导出配置、▶ 运行 / ⏸ 暂停?帮助
应用设置栏 「全局 / ● 已配置应用 / ○ 运行中进程」下拉(点开自动刷新进程列表)+ 浏览按钮(详见 4.3.6)
设备设置面板 设备列表 / 别名 / 设备开关 / 设备域 / 设备独立设置(详见 4.3.5)
主编辑区 三个页签:ComboTapdanceLeader;页签上方状态条显示当前编辑目标,右侧「导入 / 导出 / 删除」作用于当前页
按键速查 主编辑区下方的分类按钮面板(见下文)

层配置(Tapdance 页签内)带键盘可视化:每个键按 TD 设置四角着色(左上 tap / 右上 hold / 左下 dbl tap / 右下 dbl hold),已映射 / 选中 / 未映射底色不同,当前层哪里有映射一目了然。

双击输入框弹出大编辑窗口:页签里的输入框较窄,双击任意输入框会弹出一个大编辑窗口(约 500px 宽),长内容在这里看得全、改得舒服,改完点「确认」写回。

按键速查栏:主编辑区下方有两列分类按钮,把常用键名按 修饰 / 导航 / 编辑 / 锁定 / 虚拟键 / Fn / 鼠标按键 / 媒体 / 小键盘 九类整理好。点击按钮即把对应写法(如 {WheelUp}{Sleep 500}{NumpadEnter})追加到当前焦点输入框的光标处;双击弹出的大编辑窗口同样接收——先双击打开窗口,再点速查按钮即可边查边填。面板内容可滚动。

4.3.1 Combo 组合键

同时按下两个键(在 comboTime 时间窗内,默认200ms,可自行修改)触发一个自定义输出。

  • GUI 操作:Combo 页签内选择层、按键 1、按键 2,填写输出即可。有关层的设置见下文。
  • 时间窗可调:同按判定经常漏触发时可上调。
  • Combo 输出后直接结束,不与其他机制串接。
  • 支持按层生效:不同层可定义不同 Combo。

4.3.2 TapDance 点按

每个物理键在每一层都拥有独立的4种行为,共7项设置,在 Tapdance 页签的层配置表格(或键盘可视化点选)中逐键编辑:

字段 含义
tap 单击(按下即松开)输出
hold 长按输出
ms(长按阈值) hold 触发时间阈值
dbl tap 双击输出
ms(双击阈值) double tap 间隔阈值
dbl hold 双击时长按输出
ms(双击长按阈值) double hold 触发阈值
  • 某项留空则该触发方式不生效。
  • 三个全局阈值(holdTerm / doubleTapTerm / doubleHoldTerm)在层配置页统一设置,逐键阈值可覆盖全局。
  • 键盘键与鼠标键(左/右/中/侧键1/侧键2/滚轮)均适用。

4.3.3 Leader 序列系统

Leader 是一个常驻的键序列监听器。配置好后,引擎持续注视所有输入:在超时窗口内依次按下一段配置好的键序列(如 he),序列完成的瞬间即自动输出对应内容(如 hello)。也可以通过设置屏蔽键进入屏蔽模式,避免触发按键进入系统,只把结果输出。

配置项(Leader 页签)

说明
键序列 要匹配的按键顺序,(如 he
输出 序列完整命中后自动输出的内容
超时(ms) 序列相邻两键之间的等待时间上限,超时则该次输入作废、重新开始
公共超时 序列未单独设超时时的默认值(2000ms)
循环捕获 序列的输出是否回灌继续参与序列匹配

滑动超时:每条序列可单独设置超时,留空用公共超时。快速输入的短序列可设短值,长序列可放宽——等待时间始终从上一次按键重新起算,逐键滑动。

循环捕获:开启后,某条序列的输出会作为新的输入回灌驱动、继续参与后续序列的匹配,形成自驱动串联——前一条序列的输出可以恰好是另一条序列的开头,被接力捕获。目前该功能只在输出为单独一个键的时候有效,输出内容为一串连续文本时会失效。

屏蔽模式(可选)

  • 默认为非屏蔽:监听的同时每个按键照常发给系统,序列匹配在后台无感进行。例如设置he触发llo,组成hello
  • 若希望序列输入期间不被系统收到,可把某个键的输出设为虚拟键 {leader}(可以是combo,也可以是tapdance的任何输出设置):该键成为屏蔽开关——按下后进入屏蔽模式,其后所有按键也被直接吞掉(不再发给系统),直到成果匹配,或者输入无法匹配到任何序列,或者超时。如果成功则会输出设置的内容。例如设置em触发John@abc.com,如果直接输入em,会得到emJohn@abc.com,输入{leader}em则得到John@abc.com

常见搭配:输出中使用 {Select N}(通用宏,见 5.1)先选中光标前已有的内容,实现浏览器网址的那种自动填充,同时避免连续输入时候误触发多余的字符。

4.3.4 Layer 层切换

每层是一套独立按键映射,采用「基础层 base + 功能层 fn1/fn2...」模型。基础层是键盘默认的状态,你可以在这里修改键盘的基础映射。功能层可以设置一套独立的按键映射。支持无限多的功能层。

  • 如何激活层:进入功能层的方法是把某键的某个行为(combo / tap / hold / doubletap / doublehold)设为层切换虚拟键(如 hold={fn1}),该键即成为层激活键——任意键都行。
  • 层间叠加:可以多层多次堆叠。
  • 三种激活语义{fnX} / {bnX} / {tnX} 这三个虚拟按键用于激活层,具体的详细行为见 5.1

4.3.5 设备设置

设备设置面板管理所有接入的键盘鼠标设备:

  • 设备独立设置开关:开启后每台设备可拥有专属的一套映射(进入该设备后编辑的层 / TD / Combo 只对它生效),并且与其他设备共享基础配置。如果关闭,则所有设备都应用基础设置。
  • 设备域(状态共享范围):决定「在一台设备上切了层 / 按了修饰键,另一台设备跟不跟着变」。
    最典型的用途:让键盘和鼠标共享翻页——鼠标上按翻页键切到第 2 层,键盘打的字也变成第 2 层的内容;再翻回来,两边一起回来。默认就是这样的(全局域),不用额外设置。
    每台设备的域下拉有几个选项:
    • 全局(默认):所有设备共用一份状态。鼠标切层,键盘跟着变;键盘切层,鼠标也跟着变;
    • 独立:这台设备自己一份状态,切层不影响别的设备——比如外接宏键盘,它切到哪层是它自己的事,主键鼠不受影响;
    • 域2 / 域3 / 域4:额外的小分组——放进同一域的设备互相跟随,不同域之间互不影响。
      注意:域只共享「当前在第几层、按住了哪些修饰键」这类状态;各设备自己的按键映射规则还是各管各的。域下拉在开启该设备的「设备独立设置开关」后可用。
    • 觉得不够用,后边的数字可以自己写,理论上支持无限个域。
  • 设备列表:自动列出已连接的键盘 / 鼠标(含 VID/PID)。
  • 别名:给设备起好记的名字(如「客制化 68 键」「罗技 MX Master」)。
  • 设备开关(订阅)只打开的设备被引擎拦截处理,未勾选设备完全透传原始事件,该设置只在设备独立设置开关开启时候生效。
  • 设备识别:需要确认哪个设备是哪块键盘时,使用识别功能——驱动进入透传捕获态,镜像入队不吞键,你在目标键盘上按几个键即可定位。
  • 有些键盘鼠标会有多个设备名,并且windows系统会自带一些虚拟设备。所以设备列表会有一些额外的设备。
  • 已有按键设置或已有别名的设备,即使拔出也不会在列表中删除,会排列在列表后边。如果需要完全删除请清空该设备的按键设置并删除设备别名。

4.3.6 应用设置

应用设置用来让同一个按键在不同软件里干不同的事——比如 a 键平时输出 a,在 Excel 里变成粘贴。

界面:GUI 左侧栏、设备面板上方有一个「应用设置」小面板,就两行:

  • 第一行:「应用设置」标题,右边是「浏览...」按钮;
  • 第二行:一个下拉菜单,点开时自动列出当前正在运行的程序。

设置方式

  1. 在下拉里选中一个应用。列表分三段:全局(默认映射)、 开头的已配置应用、 开头的当前运行中的程序;
  2. 想配置的程序没在运行?点「浏览...」选中它的 .exe 文件即可;
  3. 选中应用后,去 Combo / Tapdance / Leader 页签正常编辑——这时编辑的规则只在该应用是前台窗口时生效;选「全局」时编辑的就是默认映射;
  4. 切换前台窗口时映射自动跟着切,无需手动操作。

叠加层级:完整配置由四层组成,从低到高逐层覆盖,按条目合并(某个键在高层单独配了就用高层的,没配就落回低层的):

全局(基础映射)
  └─ 应用覆盖          ← 选「全局 + 某应用」时编辑的
      └─ 设备覆盖       ← 选「某设备 + 全局」时编辑的
          └─ 设备+应用覆盖 ← 选「某设备 + 某应用」时编辑的(最高)

举例:全局配了 a→b,又给 excel 单独配了 a→c——平时按 a 出 b,Excel 前台时按 a 出 c。注意全局的 TD 计时参数(holdTerm 等)不可被应用覆盖。

边框颜色:键盘可视化和各页签里,每条规则用边框颜色标明它来自哪一层:

边框颜色 含义
全局基础映射
绿 设备覆盖
全局应用覆盖
设备+应用覆盖
新建、尚未保存的

边框粗细表示归属:粗边(2px)= 这条规则就存在于你当前选中的「设备 × 应用」范围里;细边(1px)= 从下层继承上来、仅供显示的。


5. 输出框设置说明

所有功能的「输出」字段(Combo 输出、TD 的 tap/hold/dt/dh、Leader 输出)共用同一套语法。

5.1 虚拟键与宏

层激活虚拟键

写法 行为 适用场景
{fnX} 按住期间每收到一次自动重复,就重发该键在目标层的 tap 值(可连发) 按住做方向键滚动
{bnX} 把自动重复吞掉,自身不再输出 按住只做修饰、自身不再发
{tnX} Toggle 固定层:触发即把当前层固定到 fnX,keyup 静默不翻回;层间叠加压栈,{tn0} 清空整栈切回 base;幂等 一键切到「剪辑层/游戏层」常驻

Leader 专用

写法 行为
{leader} Leader 屏蔽开关:设到某键的 hold / dbl-tap 上,按下后该键被吞,后续按键也被直接吞掉(序列输入不再发给系统,由 Leader 匹配输出)

带参宏

写法 行为
{Sleep N} 插入 N 毫秒非阻塞延迟(由 SleepTimer 实现,不阻塞管道),如 c{Sleep 200}v
{KeyName N} 把指定键 tap N 次,可带前缀/后缀:{a 2} = 按 a 两次;hira@126.com{left 12} = 先发文本再 Left tap 12 次
{Select N} 选中光标起 N 个已有字符,随后的输入会替换选中内容。通用宏、非 Leader 专属——典型用途是自动填充场景:先把光标前已有的旧文本选中,再让输出覆盖它,避免新内容拼接到旧文本后面(类似网页地址栏的自动填充行为)

运行外部命令

写法 行为
RUN: 前缀 ShellExecuteW 执行程序 / 文件夹 / URL / 文件,无 cmd 弹窗:RUN:calc.exeRUN:https://example.com注意 RUN: 后的空格不会被转义(是命令参数分隔符)

鼠标

写法 行为
{MouseLeft} {MouseRight} {MouseMiddle} {MouseSide1} {MouseSide2} 鼠标按键输出(走独立通道,按下/抬起完整配对)。旧写法 {LButton} 等仍兼容,保存时自动转为规范名
{WheelUp} {WheelDown} 滚轮(自含事件,不补 UP)
MouseMove(x, y) 相对移动,x 向右、y 向下为正,支持负值,如 MouseMove(-10, 0)

修饰键显式写法:组合用 {ctrl down}c{ctrl up}(不支持 ^c 这类前缀修饰符写法);需要区分左右时用单键写法 {LCtrl} {RCtrl} {LAlt} {RAlt} {LShift} {RShift} {LWin} {RWin}

任意键的 down / up 后缀:所有键都支持三种形态——{X} 按下并抬起(tap),{X down} 只按下不抬起,{X up} 只抬起。不限修饰键,普通键同样有效:{f down}{NumpadEnter down}{WheelUp up} 都合法。典型用途是精确控制按住的时机:

{LCtrl down}{Sleep 100}c{LCtrl up}     ← 先按住 Ctrl,稍等再按 c,确保组合生效
{a down}{Sleep 500}{a up}              ← 按住 a 半秒(游戏长按场景)

down / up 必须配对使用,只 down 不 up 键会一直处于按下状态。

媒体/系统键{Volume_Up} {Volume_Down} {Volume_Mute}{Media_Play_Pause} {Media_Next} {Media_Prev} {Media_Stop}{Browser_Back} {Browser_Forward} 等多字符系统键名。

小键盘{Numpad0} ~ {Numpad9}{NumpadAdd} {NumpadSub} {NumpadMul} {NumpadDiv} {NumpadDot} {NumpadEnter}(注意乘号是 NumpadMul,不是 NumpadMult)。

5.2 语法规则

输出框按以下规则解析,理解这几条就不会写出「看起来对但不生效」的输出:

  1. { } 包裹 = 按键;不包裹 = 纯文本{enter} 是按回车;hello 是逐字输入字符串 "hello"。
  2. 单字符自动包裹:裸写的单个 az09、基础符号(` - = [ ] \ ; ' , . /)会被 GUI 自动转成 {a} 这样的按键格式。
  3. 多字符键名必须包裹{Space}{Enter}{Left}{F1}……不包裹的多字符内容一律当文本输入。
  4. 缩写自动补全:GUI 会把常见缩写归一化为全名——{esc}{escape}{del}{delete}{pgup}{pageup}{pgdn}{pagedown}{prtsc}{printscreen}{bs}{backspace} 等。
  5. 空格自动转义:输出里的字面空格会被 GUI 自动替换为 {space}(因为引擎端会 trim 裸空格),你直接敲空格即可,不必手写 {space}
  6. 两种空格不转义(重要例外):
    • {...} 宏 token 内部的空格原样保留——{Sleep 200}{Select 12}{left 12} 的参数靠空格分隔,转义成 {Sleep{space}200} 引擎就识别不了了;
    • RUN: 开头的命令里的空格原样保留——如 RUN:C:\Program Files\app.exe 这类路径空格、命令行参数空格都是语法的一部分。
  7. 大小写:包裹内的小写键名统一归一为小写处理;要输出大写字母用文本或 Shift 显式写法。

6. 文件架构

仓库目录(依赖单向无循环):

AnyKey/
├── gui/                   GUI 配置器(Python + CustomTkinter)
│   ├── main.py            主窗口:顶栏 / 页签调度 / 配置读写
│   ├── layout.py          键盘可视化布局与键位显示
│   ├── components.py / dialogs.py / app_bar.py / scanner.py
├── lib/
│   └── config.py          配置模型与键名归一化(唯一规范化入口)
├── anykey-engine/         Rust 引擎(后端核心)
│   ├── src/               管道调度 Phase0-7 / Up1-8,Combo/TD/Layer/Leader/Defer
│   └── tests/             集成测试(单元 + 场景测试共 109 项)
├── anykey-tray/           Rust 系统托盘(引擎生命周期 / IPC / 开机自启)
├── anykey-filter-driver/  C 内核过滤驱动(WDK)
│   ├── sys/               驱动源码(anykey_flt.c / rawpdo.c / public.h)
│   ├── deploy/            发行脚本(一键安装·卸载 + INF + .cer)
│   └── build_driver.bat   驱动构建入口
├── assets/                图标与帮助文档(help.md)
├── build/                 构建链
│   ├── build.bat          一键七步总控(驱动→引擎→GUI→托盘→组装→签名→release)
│   ├── build_driver_release.py / build_engine_release.py / build_tray_release.py
│   ├── build_release_package.py   发行包组装 + zip
│   └── anykey.spec        PyInstaller 配置
├── docs/                  设计文档(DESIGN.md / code_map.md / 架构图 svg)
├── engines/rust/          引擎 exe 部署位置(构建产物,GUI 启动时加载)
├── scripts/               辅助脚本(测试场景生成等)
├── tests/                 Python 配置解析测试
├── requirements.txt       Python 依赖(customtkinter / Pillow / psutil / pywin32)
├── anykey_config.json     运行时配置(与 exe 同目录,GUI / Tray / Engine 三端共享的唯一真相)
└── LICENSE / SECURITY.md

关键边界(跨模组不变量):

  1. anykey_config.json 是 GUI / Tray / Engine 三端共享的唯一真相。
  2. 键名规范化只在 GUI(lib/config.py)做,引擎仅作防御层。
  3. 驱动 IOCTL / 结构体三方逐字节对齐:public.h(C) ↔ filter_driver.rs(Rust) ↔ driver.py(Python)。
  4. GUI 与 Tray 是独立进程,经 IPC 通信;Engine 是独立 Rust 进程,经 Filter Driver 与内核通讯。

7. 从源码构建

Rust 引擎

cd anykey-engine
cargo build --release          # 产物 target/release/anykey-engine.exe
cargo test                     # 单元测试 + 场景测试

内核驱动(需 VS2022 + WDK,工具链自动探测)

cd anykey-filter-driver
build_driver.bat               # WDK 编译 + 测试签名,产物在 BIN\X64\RELEASE\ANYKEY_FLT.SYS

Windows Kits 根目录、WDK/KMDF 版本、vcvars64.bat 与签名证书全部自动探测,脚本无需改动。
外部构建者最常撞到的是签名证书,需要时用环境变量覆盖即可:

环境变量 用途 默认行为
ANYKEY_SIGN_THUMBPRINT 签名证书指纹 作者测试证书若存在则直接用;否则自动创建 CN=AnyKey Test Driver(10 年有效期)
ANYKEY_WDK_VERSION 指定 WDK 版本(如 10.0.26100.0 优先 10.0.28000.0,不存在则取最新的 10.0.*
ANYKEY_KMDF_VERSION 指定 KMDF 版本(如 1.15 优先 1.15,不存在则取最新
ANYKEY_VCVARS vcvars64.bat 全路径 先用 vswhere 探测,再回退常见安装路径
WKROOT Windows Kits 10 根目录 自动探测

自动创建的测试证书是自签名的,不在受信任根中。测试模式下驱动仍可加载(test signing 不要求证书链源自受信任根);万一加载失败,把 deploy\anykey_flt.cer 导入「受信任的根证书颁发机构」后重试。

或经统一入口一步到位(编译 + 测试签名 + 部署到 deploy\ 发行目录:anykey_flt.sys + anykey_flt.cer)——这也是 build.bat 的第 1 步:

cd build
python build_driver_release.py

发布包(GUI + 托盘 + 引擎 + 驱动分发)

pip install pyinstaller                       # GUI 打包用;requirements.txt 只是运行依赖,不含打包工具
cd build
build.bat                                     # 一键构建全部,末步自动组装 release\ 标准目录
python build_release_package.py --zip 1.0.0   # 将 release\ 压缩为 AnyKey_v1.0.0.zip(GitHub Release 附件)

build.bat 第 4 步(GUI → exe)调用 PyInstaller,缺它会在这一步报 No module named PyInstaller

build.bat 七步流程:内核驱动(cl/link + 测试签名 → deploy\)→ Rust 引擎 → GUI(PyInstaller)→ Rust 托盘 → 组装 dist\AnyKey\ → 代码签名(有证书时)→ 组装 release\anykey\ + anykeyFilterDriver\ + 安装驱动.bat)。

Python 侧(GUI)

pip install -r requirements.txt
python -m gui.main             # 启动配置器

8. 测试

  • Rust 引擎:cargo test(单元测试 + 场景测试共 109 项,含集成测试 tests/ 目录)
  • Python:tests/ 下配置解析测试

9. 安全说明

AnyKey 包含内核级驱动组件。请仅从官方渠道(Release 页)下载并安装;安装前建议校验 Release 页提供的 SHA256 校验值。驱动仅拦截白名单内设备的事件,未白名单设备完全透传。

隐私:所有按键处理都在本机完成,无遥测、无网络上报、按键数据不离开你的设备。

失控兜底:三层防护(进程退出 Session 关拦截 / 30s 心跳看门狗 / 内核级 LCtrl+Space+Esc 紧急脱离),详见 4.1。


10. 文档


11. 路线图

  • 申请微软 EV 代码签名证书并完成 WHQL / Hardware Lab Kit 认证,使驱动可在正常签名模式加载、去除测试水印
  • 配置组(Profile)+ 云端同步(可选)
  • 宏录制(含鼠标轨迹)与回放
  • 设备页完善:设备级层映射
  • 界面进化:明暗主题、键盘热力图、Combo 冲突检测、CSV 批量导入导出
  • 鼠标手势(右键拖拽轨迹映射动作)
  • 社区分享平台 + 插件系统(开放 API)
  • 媒体/浏览器控制类键补全发送实现

12. 许可证

本项目采用 Apache License 2.0 开源协议。


13. 免责声明

本项目为个人/社区维护的开源工具。使用本工具可能导致系统输入行为变化,请在虚拟机或非关键环境先行测试;因使用不当造成的数据丢失或系统异常,项目作者不承担责任。

About

Keyboard & mouse remapping for Windows with a kernel filter driver — multi-device, per-app profiles, tap-dance/leader/layers, and an easy GUI config tool

Topics

Resources

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages