├── .github └── ISSUE_TEMPLATE │ ├── bug-report-CN.yml │ ├── config.yml │ └── feature-request-CN.yml ├── .gitignore ├── .vscode ├── extensions.json └── settings.json ├── InputTip.bat ├── LICENSE ├── README.md ├── scripts └── create-winget-manifest.ps1 └── src ├── AutoHotkey └── AutoHotkey64.exe ├── CHANGELOG.md ├── InputTip.JAB.JetBrains.ahk ├── InputTip.ahk ├── InputTipCursor └── default │ ├── CN │ ├── AppStarting.ani │ ├── Arrow.cur │ ├── Cross.cur │ ├── Hand.cur │ ├── Help.cur │ ├── IBeam.cur │ ├── No.cur │ ├── Pen.cur │ ├── SizeAll.cur │ ├── SizeNESW.cur │ ├── SizeNS.cur │ ├── SizeNWSE.cur │ ├── SizeWE.cur │ ├── UpArrow.cur │ └── Wait.ani │ ├── Caps │ ├── AppStarting.ani │ ├── Arrow.cur │ ├── Cross.cur │ ├── Hand.cur │ ├── Help.cur │ ├── IBeam.cur │ ├── No.cur │ ├── Pen.cur │ ├── SizeAll.cur │ ├── SizeNESW.cur │ ├── SizeNS.cur │ ├── SizeNWSE.cur │ ├── SizeWE.cur │ ├── UpArrow.cur │ └── Wait.ani │ └── EN │ ├── AppStarting.ani │ ├── Arrow.cur │ ├── Cross.cur │ ├── Hand.cur │ ├── Help.cur │ ├── IBeam.cur │ ├── No.cur │ ├── Pen.cur │ ├── SizeAll.cur │ ├── SizeNESW.cur │ ├── SizeNS.cur │ ├── SizeNWSE.cur │ ├── SizeWE.cur │ ├── UpArrow.cur │ └── Wait.ani ├── InputTipSymbol └── default │ ├── CN.png │ ├── Caps.png │ ├── EN.png │ ├── favicon-pause.png │ ├── favicon.png │ └── offer.png ├── files.ini ├── img └── favicon.ico ├── menu ├── JAB.ahk ├── about.ahk ├── app-offset.ahk ├── bw-list.ahk ├── check-update.ahk ├── config.ahk ├── cursor-mode.ahk ├── input-mode.ahk ├── startup.ahk ├── switch-window.ahk ├── symbol-pos.ahk └── tray-menu.ahk ├── utils ├── IME.ahk ├── app-list.ahk ├── app-update │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── check-version.ahk ├── create-gui.ahk ├── hotkey-gui.ahk ├── ini.ahk ├── options.ahk ├── show.ahk ├── tools.ahk ├── var.ahk └── verify-file.ahk └── version.txt /.github/ISSUE_TEMPLATE/bug-report-CN.yml: -------------------------------------------------------------------------------- 1 | name: "🐞 Bug 报告" 2 | description: 提交一个 Bug 报告 3 | title: "[Bug]: " 4 | labels: ["bug"] 5 | assignees: [abgox] 6 | body: 7 | - type: checkboxes 8 | id: checks 9 | attributes: 10 | label: 你应该确保已经完成了下面这些事情。 11 | options: 12 | - label: 你已经阅读了项目的 README 文件。 13 | required: true 14 | - label: 你已经在 [Issues](https://github.com/abgox/InputTip/issues) 中搜索了你遇到的问题,但没有找到相关 issue。 15 | required: true 16 | - label: 你已经查看了 [一些常见的使用问题](https://inputtip.abgox.com/FAQ/), 其中没有你遇到的问题。 17 | required: true 18 | - type: input 19 | id: version 20 | attributes: 21 | label: 当前使用的 InputTip 版本 22 | description: | 23 | - 在软件的托盘菜单中,点击 **关于** 进行查看。 24 | - 如果不是最新版本,请先更新。最新版本 25 | - 如果问题依然存在,再提交 issue。 26 | placeholder: v2.36.9 27 | validations: 28 | required: true 29 | - type: dropdown 30 | id: InputTip-type 31 | attributes: 32 | label: 你正在使用哪种类型的安装包? 33 | description: | 34 | [关于 zip 版本和 exe 版本的区别](https://inputtip.abgox.com/FAQ/zip-vs-exe) 35 | options: 36 | - zip 37 | - exe 38 | multiple: true 39 | validations: 40 | required: true 41 | - type: dropdown 42 | id: windows-version 43 | attributes: 44 | label: 你正在使用什么 Windows 系统版本? 45 | description: 如果是 Windows 10 以下的系统,请选择 `其他`, 并在最后的补充信息中说明具体系统版本。 46 | options: 47 | - Windows 11 48 | - Windows 10 49 | - 其他 50 | multiple: true 51 | validations: 52 | required: true 53 | - type: input 54 | id: exe 55 | attributes: 56 | label: 哪一个软件出现了问题?软件进程名叫什么? 57 | description: | 58 | - 使用 `托盘菜单` => `更改配置` => `其他杂项` => `实时获取当前激活的窗口进程信息` 59 | - 或者在 `任务管理器` 中找到出现问题的软件进程,右键点击进程名,点击 `打开文件所在的位置` 找到软件的运行进程 exe 文件。 60 | placeholder: wps.exe 61 | validations: 62 | required: true 63 | - type: textarea 64 | id: steps-to-reproduce 65 | attributes: 66 | label: bug 复现步骤 67 | placeholder: | 68 | 如何复现这个 bug? 69 | 描述尽量简单易懂。 70 | 如果可以,请提供截图、动图、录屏等来帮助理解这个问题发生的全过程。 71 | validations: 72 | required: true 73 | - type: textarea 74 | id: expected 75 | attributes: 76 | label: 期望结果 77 | placeholder: | 78 | 你认为它应该是什么样的? 79 | - type: textarea 80 | id: actually-happening 81 | attributes: 82 | label: 实际发生了什么? 83 | placeholder: | 84 | 描述尽量简单易懂。 85 | 如果可以,请提供截图、gif、录屏等来帮助理解这个问题发生的全过程。 86 | validations: 87 | required: true 88 | - type: textarea 89 | id: additional-info 90 | attributes: 91 | label: 还有其他你想要补充的信息吗? 92 | placeholder: | 93 | 提供应用的下载地址以方便测试。 94 | 你对这个问题有什么看法? 95 | ... 96 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: 官网 4 | url: https://inputtip.abgox.com/ 5 | about: 访问它获取更多信息 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request-CN.yml: -------------------------------------------------------------------------------- 1 | name: 💡 功能请求 2 | description: 请求一个新功能或功能增强 3 | title: "[Request]: " 4 | labels: ["feature"] 5 | assignees: [abgox] 6 | body: 7 | - type: textarea 8 | id: description 9 | attributes: 10 | label: 描述这个功能请求 11 | description: | 12 | - 目前 InputTip 存在哪些不足? 13 | - 详细描述你需要的功能需求或想法。 14 | - 你认为有哪些可行的实现方案作为参考? 15 | validations: 16 | required: true 17 | - type: dropdown 18 | id: windows-version 19 | attributes: 20 | label: 你正在使用什么 Windows 系统版本? 21 | description: 如果是 Windows 10 以前的系统,请选择 `其他`, 并在最后的补充信息中说明具体系统版本。 22 | options: 23 | - Windows 11 24 | - Windows 10 25 | - 其他 26 | multiple: true 27 | validations: 28 | required: true 29 | - type: textarea 30 | id: additional-info 31 | attributes: 32 | label: 还有其他你想要补充的信息吗? 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | src/InputTipCursor/default 2 | src/InputTipSymbol/default 3 | src/InputTip.ini 4 | src/InputTip.exe 5 | src/InputTip.JAB.JetBrains.exe 6 | test/** 7 | 8 | src/utils/app-update/target/* 9 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "thqby.vscode-autohotkey2-lsp", 4 | "zero-plusplus.vscode-autohotkey-debug" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | "[ahk]": { 4 | "editor.defaultFormatter": "thqby.vscode-autohotkey2-lsp" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /InputTip.bat: -------------------------------------------------------------------------------- 1 | REM InputTip.bat 2 | start "" /min "%~dp0\src\AutoHotkey\AutoHotkey64.exe" "%~dp0\src\InputTip.ahk" 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 abgox 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 |

InputTip

3 |

4 | 5 |

6 | Github | 7 | Gitee 8 |

9 | 10 |

11 | 12 | license 13 | 14 | 15 | version 16 | 17 | 18 | code size 19 | 20 | 21 | repo size 22 | 23 | 24 | created 25 | 26 |

27 | 28 | --- 29 | 30 | > [!Tip] 31 | > 32 | > - InputTip 使用 [AutoHotkey(AHK)](https://github.com/AutoHotkey/AutoHotkey) 语言编写 33 | > - [InputTip 可能被错误判断为病毒程序或游戏外挂](https://inputtip.abgox.com/FAQ/about-virus) 34 | > - [推荐使用 zip 版本](https://inputtip.abgox.com/FAQ/zip-vs-exe) 35 | > - InputTip 只适用于 **Windows** 系统(**Win10** 以上可用,以下未知) 36 | > - `托盘菜单` 指的是在底部任务栏右边的 InputTip 软件托盘菜单 37 | > - 在 README、[官网](https://inputtip.abgox.com)、[常见问题(FAQ)](https://inputtip.abgox.com/FAQ/) 等帮助文档中提及的 `托盘菜单` 指的都是通过鼠标右键点击 `托盘菜单` 38 | 39 | ### 介绍 40 | 41 | - 一个实时的输入法状态提示工具 42 | 43 | - [多种状态提示方案](#关于状态提示方案) 44 | - 使用多套鼠标样式,根据输入法状态加载不同的鼠标样式 45 | - 根据输入法状态在输入光标附近显示不同的 [符号](#关于符号) 46 | - 切换不同应用窗口时,自动切换到指定的输入法状态 47 | - 指定按键强制切换输入法状态 48 | - 详细便捷的配置菜单 49 | - 所有的配置变动,都只应该在 `托盘菜单` 中进行 50 | - 不要手动修改 `InputTip.ini` 文件 51 | 52 | [**如果 `InputTip` 对你有所帮助,请考虑给它一个 Star**](#stars) 53 | 54 | ### 新的变化 55 | 56 | - 请查阅 [更新日志](./src/CHANGELOG.md) 57 | 58 | ### 常见问题 59 | 60 | - 如果有使用问题,请先确认当前使用的 `InputTip` 是最新版本 version 61 | - 在 `托盘菜单` => `关于` 中查看当前版本号 62 | - 如果不是最新版本,你应该先更新到最新版本,检查问题是否仍然存在 63 | - 然后查看相关的文档 64 | - 本页面中包含的内容 65 | - [常见问题(FAQ)](https://inputtip.abgox.com/FAQ/) 66 | - [输入法和应用窗口兼容情况](#兼容情况) 67 | - [issues](https://github.com/abgox/InputTip/issues) 68 | - ... 69 | - 如果仍有问题,可以前往 [QQ 反馈交流群(451860327)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=ZfHFP_gIMyY6kZvqRmJhrsMlvnLDjLf6&authKey=lXo50SvLgudu%2BettInNZdb2OXGjs%2BxsoqsKIB88Vcq%2FjMb9uEW5thwU5Nm85KNX4&noverify=0&group_code=451860327) 或 [腾讯频道](https://pd.qq.com/s/gyers18g6?businessType=5) 交流反馈 70 | 71 | ### 演示 72 | 73 | ![demo](https://inputtip.abgox.com/releases/v2/demo.gif) 74 | 75 | ### 安装 76 | 77 | > [!Tip] 78 | > 79 | > - [关于 zip 与 exe 版本的区别以及相关说明](https://inputtip.abgox.com/FAQ/zip-vs-exe) 80 | > - 配置文件所在位置 81 | > - zip 版本: 解压后的 `src` 目录下的 `InputTip.ini` 82 | > - exe 版本: `InputTip.exe` 同级目录下的 `InputTip.ini` 83 | 84 | - zip 版本 85 | 86 | - 下载仓库的最新代码压缩包 `InputTip-main.zip` 87 | - 在仓库的 Releases 中下载 `InputTip.zip` 88 | - [前往官网下载 InputTip.zip](https://inputtip.abgox.com/download) 89 | - 使用 [Scoop](https://scoop.sh/) 安装 90 | 91 | ```shell 92 | scoop bucket add abgox-bucket https://github.com/abgox/abgox-bucket 93 | ``` 94 | 95 | ```shell 96 | scoop install abgox-bucket/InputTip-zip 97 | ``` 98 | 99 | - exe 版本 100 | 101 | - 在仓库的 Releases 中下载 `InputTip.exe` 102 | 103 | - 使用 [WinGet](https://learn.microsoft.com/windows/package-manager/winget/) 安装 104 | 105 | ```shell 106 | winget install abgox.InputTip 107 | ``` 108 | 109 | - 使用 [Scoop](https://scoop.sh/) 安装 110 | 111 | ```shell 112 | scoop bucket add abgox-bucket https://github.com/abgox/abgox-bucket 113 | ``` 114 | 115 | ```shell 116 | scoop install abgox-bucket/InputTip 117 | ``` 118 | 119 | ### 使用 120 | 121 | 1. 完成 [安装](#安装) 后,运行对应文件即可 122 | 123 | - zip 版本: 运行解压后的目录下的 `InputTip.bat` 124 | - exe 版本: 运行 `InputTip.exe` 125 | 126 | 2. 设置开机自启动: `托盘菜单` => `开机自启动` 127 | 128 | - 建议使用 `任务计划程序` 或 `注册表` 129 | - `应用快捷方式` 可能会无效,详情请查看 [关于开机自启动](https://inputtip.abgox.com/FAQ/startup) 130 | 131 | 3. 设置 `所有配置菜单的字体大小` 132 | 133 | - 你可以设置字体大小来解决屏幕过小导致菜单显示不完全或屏幕过大导致菜单显示过小的问题 134 | - `更改配置` => `其他杂项` => `所有配置菜单的字体大小` 135 | 136 | 4. [设置鼠标样式](https://inputtip.abgox.com/FAQ/cursor-style) 137 | 138 | - `托盘菜单` => `更改配置` => `鼠标样式`,在下拉列表中选择鼠标样式文件夹路径 139 | - 比如默认的中文鼠标样式文件夹路径: `InputTipCursor\default\CN` 140 | - [更多已适配的鼠标样式](https://inputtip.abgox.com/download/extra) 141 | - [自定义鼠标样式](#自定义鼠标样式) 142 | 143 | 5. 更多相关配置在 `托盘菜单` 中查看 144 | 145 | 6. [关于更新检查](https://inputtip.abgox.com/FAQ/check-update)、[自定义托盘菜单图标](https://inputtip.abgox.com/FAQ/custom-tray-menu-icon)、[白名单机制](https://inputtip.abgox.com/FAQ/white-list)、[运行项目源代码](https://inputtip.abgox.com/FAQ/run-source-code)、... 146 | 147 |
148 | 一个通过方块符号实现的有趣的配置 149 | 150 | 151 |
152 | 153 | ### 编译 154 | 155 | > [!Tip] 156 | > 你可以自行查看源代码并编译 `InputTip` 157 | 158 | > [!Warning] 159 | > 160 | > 如果修改了项目代码,需要先编译 `InputTip.JAB.JetBrains.ahk`,再编译 `InputTip.ahk` 161 | 162 | 1. 克隆项目仓库到本地 163 | 164 | - 完成项目克隆后,你也可以直接运行目录下的 `InputTip.bat` 来使用 `InputTip` 165 | - [Github](https://github.com/abgox/InputTip) 166 | 167 | ```shell 168 | git clone --depth 1 https://github.com/abgox/InputTip.git 169 | ``` 170 | 171 | - [Gitee](https://gitee.com/abgox/InputTip) 172 | 173 | ```shell 174 | git clone --depth 1 https://gitee.com/abgox/InputTip.git 175 | ``` 176 | 177 | 2. 安装 [AutoHotkey v2](https://www.autohotkey.com/) 178 | 3. 打开 `AutoHotKey Dash` 179 | 4. 点击左边的 `Compile`,等待编译器下载完成 180 | 5. 重新点击左边的 `Compile` 181 | 6. 将 `src\InputTip.ahk` 拖入弹出的编译窗口中 182 | 7. 点击左下角的 `Convert` 完成编译 183 | - 注意: [编译后的 InputTip.exe 文件可能会被误判为病毒程序](https://inputtip.abgox.com/FAQ/about-virus),请自行处理 184 | 8. 运行编译后的 `InputTip.exe` 185 | 186 | ### 卸载 187 | 188 | - 所有相关的文件或目录 189 | 190 | - zip 版本 191 | 192 | - 解压后的整个 `InputTip-main` 目录 193 | - 鼠标样式文件夹 `src\InputTipCursor` 194 | - 图片符号文件夹 `src\InputTipSymbol` 195 | - 配置文件 `src\InputTip.ini` 196 | 197 | - exe 版本 198 | - 软件本体 `InputTip.exe` 199 | - 鼠标样式文件夹 `InputTipCursor` 200 | - 图片符号文件夹 `InputTipSymbol` 201 | - 配置文件 `InputTip.ini` 202 | 203 | --- 204 | 205 | 1. 取消 `开机自启动`: `托盘菜单` => `设置` => `开机自启动` 206 | 2. 退出: `托盘菜单` => `退出` 207 | - 如果修改了鼠标样式,可以通过 `更改配置` => `显示形式` => `1. 要不要修改鼠标样式` 设置为 `【否】`,会尝试进行恢复 208 | - 如果未完全恢复,请根据弹窗提示信息进行操作 209 | 3. 删除以上所有文件或目录 210 | 211 | ### 关于状态提示方案 212 | 213 | 1. `鼠标样式方案` 214 | 215 | - 使用多套鼠标样式,根据输入法状态加载不同的鼠标样式 216 | - 默认使用 [多彩水滴 Oreo 光标](https://zhutix.com/ico/oreo-cu) 217 | - 默认中文状态为 **红色**,英文状态为 **蓝色**,大写锁定为 **绿色** 218 | - 在 [更多已适配的鼠标样式](https://inputtip.abgox.com/download/extra) 中有提供它们的左手镜像版本 219 | - [自定义鼠标样式](#自定义鼠标样式) 220 | 221 | 2. `符号显示方案` 222 | 223 | - 根据输入法状态在输入光标附近显示不同的 [符号](#关于符号) 224 | - 默认使用 [白名单机制](https://inputtip.abgox.com/FAQ/white-list/) 225 | - 需要注意: 226 | - 此方案涉及到获取应用窗口中的输入光标位置信息 227 | - InputTip 将通过指定的光标获取模式尝试获取到输入光标位置信息 228 | - 你可以通过 `设置光标获取模式` 显示指定应用使用哪种模式 229 | - 如果获取不到: 230 | - 符号无法显示 231 | - 这就只能使用 `鼠标样式方案` 或者 `设置符号显示位置` 232 | - 获取到了,但符号位置有偏差(此应用中,所有窗口的偏差相同): 233 | - 符号会显示,但符号显示的位置有偏差 234 | - 由于偏差相同,可以通过 `偏移量`、`设置特殊偏移量` 解决 235 | - 获取到了,但符号位置有偏差(此应用中,有窗口的偏差不同): 236 | - 符号会显示,但符号显示的位置有偏差 237 | - 由于偏差不同,无论如何设置,都会有窗口出现位置错误,目前无解 238 | - 参考示例: [vscode v1.100 版本中编辑界面和终端界面符号位置有偏差](https://github.com/abgox/InputTip/issues/172) 239 | 240 | ### 如何在 JetBrains 系列 IDE 中使用 InputTip 241 | 242 | > [!Tip] 243 | > 244 | > - 如果只使用 `鼠标样式方案`,不需要进行以下步骤 245 | > - https://inputtip.abgox.com/FAQ/use-inputtip-in-jetbrains 246 | > - [通过 AutoHotkey 官方论坛中 Descolada 大佬给出的解决方案实现](https://www.autohotkey.com/boards/viewtopic.php?t=130941#p576439) 247 | > - 如果有其他 JAB 程序,也可以按照此步骤进行设置 248 | 249 | 1. 打开 Java Access Bridge (java 访问桥) 250 | 251 | - 如果以下命令不存在,请 [下载并安装 OpenJDK JRE](https://adoptium.net/temurin/releases/?os=windows&arch=x64&package=jre&version=8) 或其他 JDK 252 | - 如果以下命令不能正常运行,请检查环境变量是否配置正确 253 | 254 | ```shell 255 | java -version 256 | ``` 257 | 258 | ```shell 259 | jabswitch -enable 260 | ``` 261 | 262 | 2. `托盘菜单` => `启用 JAB/JetBrains IDE 支持` 263 | 264 | 3. `托盘菜单` => `设置光标获取模式`,将 JetBrains IDE 应用添加到其中的 `JAB` 列表中 265 | 266 | 4. 如果未生效,请依次尝试以下操作并查看是否生效 267 | 268 | - 重启正在运行的 JetBrains IDE 269 | - 重启 InputTip : `托盘菜单` => `重启` 270 | - 重启系统 271 | 272 | > [!Tip] 273 | > 如果有多块屏幕,副屏幕上可能有坐标偏差,需要通过 `托盘菜单` => `设置特殊偏移量` 手动调整 274 | 275 | ### 关于符号 276 | 277 | > [!Tip] 278 | > 279 | > - 部分应用窗口可能无法准确获取到输入光标位置,会导致符号无法显示 280 | > - [应用窗口兼容情况](https://inputtip.abgox.com/FAQ/support-app-list) 会记录这些特别的应用窗口 281 | > - 你可以使用 `v2.33.0` 版本中新增的 `设置符号显示位置` 来解决此问题 282 | > - 以 `WPS` 为例 283 | > - 使用 `设置符号显示位置`,根据窗口提示,将它添加到其中,即可实现在鼠标附近显示 284 | > - 这是一个折中的处理方案,此前的 `v1` 版本就一直使用它,稳定性非常好 285 | 286 | #### 图片符号 287 | 288 | > [!Tip] 289 | > 290 | > https://inputtip.abgox.com/FAQ/symbol-picture 291 | 292 | - `InputTipSymbol\default` 文件夹中包含了默认的图片符号 293 | - 当 `托盘菜单` 中 `更改配置` => `显示形式` => `2. 显示什么类型的符号`,选择 `显示图片符号` 时,会显示对应的图片符号 294 | - 你也可以自己制作符号图片,或者将喜欢的符号图片放入 `InputTipSymbol` 目录下 295 | - 不应该放到 `default` 文件夹下 296 | - 图片必须是 `.png` 格式 297 | - [更多的符号图片](https://inputtip.abgox.com/download/extra) 298 | - 设置方法: `托盘菜单` => `更改配置` => `图片符号`,在对应的下拉列表中选择图片路径 299 | - 如果选择第一个空白路径,则不会显示对应状态的图片符号 300 | 301 | #### 方块符号 302 | 303 | > [!Tip] 304 | > 305 | > https://inputtip.abgox.com/FAQ/symbol-block 306 | 307 | - 当 `托盘菜单` 中 `更改配置` => `显示形式` => `2. 显示什么类型的符号`,选择 `显示方块符号` 时,会在输入光标附近显示不同颜色的方块符号 308 | - 默认中文状态为 **红色**,英文状态为 **蓝色**,大写锁定为 **绿色** 309 | - 方块符号相关的配置: `托盘菜单` => `更改配置` => `方块符号` 310 | - 当其中的方块符号的颜色设置修改为空时,则不会显示该状态的方块符号 311 | - 比如: 你只希望在中文状态下显示方块符号,那么就将 `英文状态时方块符号的颜色` 和 `大写锁定时方块符号的颜色` 的值都设置为空 312 | 313 | #### 文本符号 314 | 315 | > [!Tip] 316 | > 317 | > https://inputtip.abgox.com/FAQ/symbol-text 318 | 319 | - 当 `托盘菜单` 中 `更改配置` => `显示形式` => `2. 显示什么类型的符号`,选择 `显示文本符号` 时,会显示对应的文本符号 320 | - 默认中文状态为 `中`,英文状态为 `英`,大写锁定为 `大` 321 | - 文本符号相关的配置: `托盘菜单` => `更改配置` => `文本符号` 322 | - 当其中的文本字符的值为空时,则不会显示该状态的文本符号 323 | - 比如: 你只希望在中文状态下显示文本字符,那么就将 `英文状态时的文本字符` 和 `大写锁定时的文本字符` 的值都设置为空 324 | 325 | ### 自定义鼠标样式 326 | 327 | > [!Tip] 328 | > 329 | > - 也可以直接下载 [已经适配的鼠标样式](https://inputtip.abgox.com/download/extra) 来使用 330 | > - `InputTip.exe` 启动后,会在同级目录下生成 `InputTipCursor` 目录,其中包括 `default` 文件夹 331 | > - `default` 用于存放中文/英文/大写锁定状态的 **默认** 鼠标样式 332 | 333 | 1. 你需要在 `InputTipCursor` 目录下创建一个文件夹 334 | 335 | - 文件夹中只能包含鼠标样式文件(后缀名为 `.cur` 或 `.ani`) 336 | 337 | - 必须使用以下表格中的文件名(大小写都可以) 338 | 339 | - 每个文件都不是必须的,但建议至少添加 `Arrow`,`IBeam`,`Hand` 340 | 341 | | 文件名(类型) | 说明 | 342 | | :----------: | :-----------------------------: | 343 | | Arrow | 普通选择 | 344 | | IBeam | 文本选择/文本输入 | 345 | | Hand | 链接选择 | 346 | | AppStarting | 后台工作 | 347 | | Wait | 忙碌 | 348 | | SizeAll | 移动 | 349 | | SizeNWSE | 对角线调整大小 1 (左上 => 右下) | 350 | | SizeNESW | 对角线调整大小 2 (左下 => 右上) | 351 | | SizeWE | 水平调整大小 | 352 | | SizeNS | 垂直调整大小 | 353 | | No | 无法(禁用) | 354 | | Help | 帮助选择 | 355 | | Cross | 精度选择 | 356 | | UpArrow | 备用选择 | 357 | | Pin | 位置选择 | 358 | | Person | 人员选择 | 359 | | Pen | 手写 | 360 | 361 | - 详情参考 [微软文档: 关于光标(游标)](https://learn.microsoft.com/windows/win32/menurc/about-cursors) 362 | 363 | 2. `托盘菜单` => `更改配置` => `鼠标样式` => 在下拉列表中选择对应文件夹目录路径 364 | 365 | > [!Warning] 366 | > 367 | > - 你应该尽量让三种状态下的鼠标样式文件夹中包含的鼠标样式文件的数量和类型是一致的 368 | > - 比如: 369 | > - 如果中文状态的目录路径下有 `IBeam.cur` 或 `IBeam.ani` 文件,英文状态或大写锁定的目录路径下没有。 370 | > - 则切换到中文状态时,会加载中文状态的 `IBeam.cur` 371 | > - 但是再切换到英文或大写锁定时,`IBeam` 类型的鼠标样式不会变化,因为英文和大写锁定缺少对应的样式文件 372 | 373 | ### 兼容情况 374 | 375 | #### [应用窗口兼容情况](https://inputtip.abgox.com/FAQ/support-app-list) 376 | 377 | #### 输入法兼容情况 378 | 379 | > [!Tip] 380 | > 381 | > InputTip 使用 **【通用】** 和 **【自定义】** 模式兼容各类输入法,默认使用 **【通用】** 模式 382 | 383 | - **【通用】** 384 | 385 | - [微信输入法](https://z.weixin.qq.com/) 386 | - [搜狗输入法](https://shurufa.sogou.com/),[搜狗五笔输入法](https://wubi.sogou.com/) 387 | - [QQ 输入法](https://qq.pinyin.cn/) 388 | - [百度输入法](https://shurufa.baidu.com/) 389 | - 微软拼音,微软五笔,微软仓颉... 390 | - [冰凌输入法](https://icesofts.com/) 391 | - [手心输入法](https://www.xinshuru.com/): 使用 `Shift` 切换中英文状态无法正常识别,需要参照下方的使用方式 392 | 393 | - 首先,确保输入法状态正确 394 | - 通过 `Shift` 将输入法状态切换为中文,然后不再使用 `Shift` 切换状态(此时可以在手心输入法设置中关闭 `Shift` 切换功能) 395 | - 后续只能使用 `Ctrl + Space` 进行中英文状态切换,否则状态识别有误 396 | - 其次,修改 InputTip 的配置 397 | - `托盘菜单` => `设置输入法模式` => `指定内部实现切换输入法状态的方式`,选择 `模拟输入 Ctrl + Space` 398 | 399 | - 小鹤音形输入法 400 | - 需要使用 [多多输入法生成器](https://duo.ink/ddimegen/ddimegen-desc.html) 生成 401 | - 使用 [多多输入法生成器](https://duo.ink/ddimegen/ddimegen-desc.html) 生成的输入法都可用 402 | - [小小输入法](http://yongim.ysepan.com/) 403 | - [华宇拼音输入法](https://pinyin.thunisoft.com/) 404 | - [影子输入法](https://gitee.com/orz707/Yzime) 405 | - 需要关闭影子输入法中的 `tsf` 406 | - 在键盘布局中,选择一个能正常识别状态的输入法(建议选择微信输入法、搜狗输入法等) 407 | - 然后正常使用影子输入法即可 408 | - [可可五笔](https://suke.kim/) 409 | - 谷歌输入法 410 | - ... 411 | 412 | - **【自定义】** 413 | 414 | - 一个万能的模式,根据规则列表依次匹配,需要根据实际情况添加一条或多条规则 415 | - 详情参考: [关于【自定义】模式](https://inputtip.abgox.com/FAQ/custom-input-mode) 416 | - 可以通过 `设置输入法模式` => `自定义` 使用以下已知可用的规则配置: 417 | 418 | - `如果所有规则都不匹配,应该判断为` 这个配置项选择 `中文状态` (`英文状态` 相反) 419 | 420 | - [小鹤音形](https://flypy.com/download/) 421 | 422 | - 经过测试,`v10.11.4` 版本中,添加以下规则即可 423 | 424 | | 顺序 | 状态码规则 | 切换码规则 | 输入法状态 | 425 | | :--: | :--------: | :--------: | :--------: | 426 | | 1 | | 257 | 英文 | 427 | 428 | - [小狼毫(rime)输入法](https://rime.im/download/) 429 | 430 | - 经过测试,`v0.16.1` 版本中,添加以下规则即可 431 | 432 | | 顺序 | 状态码规则 | 切换码规则 | 输入法状态 | 433 | | :--: | :--------: | :--------: | :--------: | 434 | | 1 | | 偶数 | 英文 | 435 | 436 | - [讯飞输入法](https://srf.xunfei.cn/) 437 | 438 | - 经过测试,`v3.0` 版本中,添加以下规则即可 439 | 440 | | 顺序 | 状态码规则 | 切换码规则 | 输入法状态 | 441 | | :--: | :--------: | :--------: | :--------: | 442 | | 1 | 奇数 | | 英文 | 443 | 444 | ### 参考项目 445 | 446 | - [ImTip - aardio](https://github.com/aardio/ImTip) 447 | - [KBLAutoSwitch - flyinclouds](https://github.com/flyinclouds/KBLAutoSwitch) 448 | - [AutoHotkeyScripts - Tebayaki](https://github.com/Tebayaki/AutoHotkeyScripts) 449 | - [language-indicator - yakunins](https://github.com/yakunins/language-indicator) 450 | - [RedDot - Autumn-one](https://github.com/Autumn-one/RedDot) 451 | - [InputTip v1](../v1) 在鼠标附近显示带文字的方块符号,后来 [InputTip v2](./) 版本默认通过不同颜色的鼠标样式来区分 452 | - 之后看到了 [RedDot - Autumn-one](https://github.com/Autumn-one/RedDot) 和 [language-indicator - yakunins](https://github.com/yakunins/language-indicator) 的设计,通过不同颜色加上小符号来判断不同输入法状态 453 | - InputTip 也参照了这样的设计,因为这样的实现很简单,其实就是 [InputTip v1](../v1) 中带文字的方块符号,去掉文字,加上不同的背景颜色 454 | 455 | ### Stars 456 | 457 | **如果 `InputTip` 对你有所帮助,请考虑给它一个 Star** 458 | 459 | 460 | 461 | 462 | stargazer-widget 463 | 464 | 465 | 466 | ### 赞赏支持 467 | 468 | > [!Tip] 469 | > 470 | > 这里是 [赞赏名单](https://inputtip.abgox.com/sponsor),非常感谢所有赞助者! 471 | 472 | Buy Me a Coffee at ko-fi.com 473 | 474 | ![赞赏支持](https://me.abgox.com/support.png) 475 | -------------------------------------------------------------------------------- /scripts/create-winget-manifest.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | $outPath = "winget-manifest" 3 | ) 4 | 5 | $template_yaml = '# yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.9.0.schema.json 6 | 7 | PackageIdentifier: abgox.InputTip 8 | PackageVersion: {{ version }} 9 | DefaultLocale: zh-CN 10 | ManifestType: version 11 | ManifestVersion: 1.9.0 12 | ' 13 | 14 | $template_installer_yaml = '# yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.9.0.schema.json 15 | 16 | PackageIdentifier: abgox.InputTip 17 | PackageVersion: {{ version }} 18 | UpgradeBehavior: uninstallPrevious 19 | ReleaseDate: {{ release_date }} 20 | Installers: 21 | # From GitHub repository 22 | - Architecture: x64 23 | InstallerType: portable 24 | InstallerUrl: https://github.com/abgox/InputTip/releases/download/v{{ version }}/InputTip.exe 25 | InstallerSha256: {{ sha256 }} 26 | # From Gitee repository 27 | - Architecture: x64 28 | InstallerLocale: zh-CN 29 | InstallerType: portable 30 | InstallerUrl: https://gitee.com/abgox/InputTip/releases/download/v{{ version }}/InputTip.exe 31 | InstallerSha256: {{ sha256 }} 32 | ManifestType: installer 33 | ManifestVersion: 1.9.0 34 | ' 35 | 36 | $template_locale_en_yaml = '# yaml-language-server: $schema=https://aka.ms/winget-manifest.locale.1.9.0.schema.json 37 | 38 | PackageIdentifier: abgox.InputTip 39 | PackageVersion: {{ version }} 40 | PackageLocale: en-US 41 | Publisher: abgox 42 | PublisherUrl: https://github.com/abgox 43 | PublisherSupportUrl: https://github.com/abgox/InputTip/issues 44 | Author: abgox 45 | PackageName: InputTip 46 | PackageUrl: https://inputtip.abgox.com/ 47 | License: MIT License 48 | LicenseUrl: https://github.com/abgox/InputTip/blob/main/LICENSE 49 | Copyright: Copyright (c) 2023-present abgox 50 | CopyrightUrl: https://github.com/abgox/InputTip/blob/main/LICENSE 51 | ShortDescription: An input method status tip tool. 52 | Tags: 53 | - autohotkey 54 | - cursor 55 | - ime 56 | - input 57 | - inputmethod 58 | - tip 59 | ReleaseNotesUrl: https://github.com/abgox/InputTip/releases/tag/v{{ version }} 60 | Documentations: 61 | - DocumentLabel: README (GitHub) 62 | DocumentUrl: https://github.com/abgox/InputTip/blob/main/README.md 63 | - DocumentLabel: README (Gitee) 64 | DocumentUrl: https://gitee.com/abgox/InputTip/blob/main/README.md 65 | - DocumentLabel: Some Frequently Asked Questions & Tips (FAQ) 66 | DocumentUrl: https://inputtip.abgox.com/FAQ/ 67 | - DocumentLabel: README 68 | DocumentUrl: https://inputtip.abgox.com/v2/ 69 | ManifestType: locale 70 | ManifestVersion: 1.9.0 71 | ' 72 | 73 | 74 | $template_locale_zh_yaml = '# yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.9.0.schema.json 75 | 76 | PackageIdentifier: abgox.InputTip 77 | PackageVersion: {{ version }} 78 | PackageLocale: zh-CN 79 | Publisher: abgox 80 | PublisherUrl: https://gitee.com/abgox 81 | PublisherSupportUrl: https://pd.qq.com/s/gyers18g6?businessType=5 82 | Author: abgox 83 | PackageName: InputTip 84 | PackageUrl: https://inputtip.abgox.com/ 85 | License: MIT License 86 | LicenseUrl: https://gitee.com/abgox/InputTip/blob/main/LICENSE 87 | Copyright: Copyright (c) 2023-present abgox 88 | CopyrightUrl: https://gitee.com/abgox/InputTip/blob/main/LICENSE 89 | ShortDescription: 一个输入法状态实时提示工具。 90 | Tags: 91 | - autohotkey 92 | - 光标 93 | - 鼠标 94 | - 鼠标指针 95 | - 输入 96 | - 输入法 97 | - 状态 98 | - 提示 99 | - 实时 100 | - 工具 101 | ReleaseNotesUrl: https://gitee.com/abgox/InputTip/releases/tag/v{{ version }} 102 | Documentations: 103 | - DocumentLabel: README (GitHub) 104 | DocumentUrl: https://github.com/abgox/InputTip/blob/main/README.md 105 | - DocumentLabel: README (Gitee) 106 | DocumentUrl: https://gitee.com/abgox/InputTip/blob/main/README.md 107 | - DocumentLabel: 一些常见问题及使用技巧 (FAQ) 108 | DocumentUrl: https://inputtip.abgox.com/FAQ/ 109 | - DocumentLabel: README 110 | DocumentUrl: https://inputtip.abgox.com/v2/ 111 | ManifestType: defaultLocale 112 | ManifestVersion: 1.9.0 113 | ' 114 | 115 | $version = (Invoke-RestMethod -uri "https://raw.githubusercontent.com/abgox/InputTip/refs/heads/main/src/version.txt").Trim() 116 | 117 | function replaceContent($content, [System.Collections.Generic.List[array]]$replaceList) { 118 | foreach ($replace in $replaceList) { 119 | $content = $content -replace $replace[0], $replace[1] 120 | } 121 | return $content 122 | } 123 | 124 | Invoke-WebRequest -uri "https://github.com/abgox/InputTip/releases/download/v$version/InputTip.exe" -OutFile "abgox.InputTip.exe" 125 | 126 | $sha256 = Get-FileHash "abgox.InputTip.exe" 127 | 128 | Remove-Item "abgox.InputTip.exe" -ErrorAction SilentlyContinue 129 | 130 | $replaceMap = @( 131 | @("{{ version }}", $version), 132 | @("{{ release_date }}", (Get-Date -Format "yyyy-MM-dd")), 133 | @("{{ sha256 }}", $sha256.Hash) 134 | ) 135 | 136 | $tempate = @( 137 | @{ 138 | fileName = "abgox.InputTip.yaml" 139 | content = replaceContent $template_yaml $replaceMap 140 | }, 141 | @{ 142 | fileName = "abgox.InputTip.installer.yaml" 143 | content = replaceContent $template_installer_yaml $replaceMap 144 | }, 145 | @{ 146 | fileName = "abgox.InputTip.locale.en-US.yaml" 147 | content = replaceContent $template_locale_en_yaml $replaceMap 148 | }, 149 | @{ 150 | fileName = "abgox.InputTip.locale.zh-CN.yaml" 151 | content = replaceContent $template_locale_zh_yaml $replaceMap 152 | } 153 | ) 154 | 155 | $out = Join-Path $outPath $version 156 | New-Item -ItemType Directory -Force -Path $out | Out-Null 157 | foreach ($item in $tempate) { 158 | $filePath = Join-Path $out $item.fileName 159 | $item.content | Out-File $filePath -Force -Encoding utf8 160 | } 161 | 162 | # $envList = @{ 163 | # new_branch = "abgox.InputTip-$version" 164 | # commit_msg = "New version: abgox.InputTip version $version" 165 | # pr_title = "New version: abgox.InputTip version $version" 166 | # pr_body = "Pull Request created by the publish action of [InputTip](https://github.com/abgox/InputTip)." 167 | # } 168 | 169 | # $envList | ConvertTo-Json | Out-File "$PSScriptRoot\..\out-winget-env.json" 170 | -------------------------------------------------------------------------------- /src/AutoHotkey/AutoHotkey64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/AutoHotkey/AutoHotkey64.exe -------------------------------------------------------------------------------- /src/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # v2 版本更新日志 4 | 5 | - 没有特别说明的版本都是修复问题 6 | 7 | ## 2.38.0 8 | 9 | - 为 `显示实时的状态码和切换码` 添加快捷键设置 10 | - 当出现基于状态错误的问题时,需要通过 `显示实时的状态码和切换码` 来排查问题 11 | - 但是手动点击 `显示实时的状态码和切换码` 按钮可能会导致问题因为点击行为消失,难以再次复现 12 | - 这种情况,就应该直接使用快捷键,快速显示并排查问题 13 | - 为 `指定内部实现切换输入法状态的方式` 新增选项: `模拟输入 Ctrl+Space` 14 | - 优化了 `托盘菜单` 中的设置顺序 15 | - 将快捷键设置逻辑抽离为一个公共方法 16 | - 其他的修复和优化 17 | 18 | ## 2.37.5 19 | 20 | - 优化了中英文状态切换函数 21 | - 修复了可能在托盘菜单中添加多个准备静默更新提示的问题 22 | - 修改配置项: `Shift 键是否可以正常切换输入法状态` => `指定内部实现切换输入法状态的方式` 23 | - 其他的修复和优化 24 | 25 | ## 2.37.4 26 | 27 | - 优化和修复了 `设置输入法模式` 相关内容 28 | - 修复了 `【自定义】` 模式下,指定多个数字无效的问题 29 | - 优化了配置菜单布局和 `关于自定义` 标签页中的帮助说明 30 | - 优化了创建快捷方式到桌面的功能 31 | - 在 zip 版本中,创建的快捷方式不再指向 InputTip.bat 32 | - 如果终端进程卡死,InputTip.bat 无法立即运行 33 | - 其他的修复和优化 34 | 35 | ## 2.37.3 36 | 37 | - 重新添加强制显示托盘菜单图标 38 | - 自重启无法完全解决托盘菜单未显示的问题 39 | - 优化了初始化引导 40 | - 如果直接关闭初始化引导,再次启动会重新进入初始化引导 41 | - 其他的修复和优化 42 | 43 | ## 2.37.2 44 | 45 | - 移除强制显示托盘菜单图标,通过自重启解决 46 | - 优化了 `设置开机自启动` 47 | - 其他的修复和优化 48 | 49 | ## 2.37.1 50 | 51 | - 修复了通过任务计划程序自启动时,托盘图标无法显示的问题 52 | - `创建快捷方式到桌面` 将根据不同情况创建更合适的快捷方式 53 | 54 | ## 2.37.0 55 | 56 | - 添加了 `自动静默更新` 57 | - 设置: `托盘菜单` => `设置更新检查` => `启用静默更新` 58 | - 优化了 `设置开机自启动` 的 `「任务计划程序」` 59 | - 现在创建的任务计划 `abgox.InputTip.noUAC` 会自带开机自启动,不再通过 `shell:startup`(自启动文件夹) 实现 60 | - `托盘菜单` 中的 `以管理员模式启动` 更名为 `以管理员权限启动` 61 | - 优化了部分配置菜单的文本描述、布局等 62 | - 优化了部分检查更新的相关逻辑 63 | - 其他的修复和优化 64 | 65 | ## 2.36.10 66 | 67 | - 修复了一个变量类型错误导致的报错 68 | - 将版本号写入配置文件,避免使用非内置更新导致更新时的配置迁移变化无法触发 69 | - 其他的修复和优化 70 | 71 | ## 2.36.9 72 | 73 | - 优化了设置符号独立配置的配置菜单的布局 74 | - 修复了更新时的配置迁移 75 | - 其他的修复和优化 76 | 77 | ## 2.36.8 78 | 79 | - 优化了 exe 版本的更新逻辑 80 | - exe 版本使用 [AutoHotkey 2.0.19](https://github.com/AutoHotkey/AutoHotkey/releases/tag/v2.0.19) 进行编译 81 | - 在 [AutoHotkey 2.0.19](https://github.com/AutoHotkey/AutoHotkey/releases/tag/v2.0.19) 中有对内存相关的修复 82 | - 这或许能解决极少数情况下可能出现的 `Invalid memory read/write` 的报错 83 | - 其他的修复和优化 84 | 85 | ## 2.36.7 86 | 87 | - 为 zip 版本更新时的文件下载添加待下载数量及进度提示 88 | - 修复了特殊偏移量失效的问题 89 | 90 | ## 2.36.6 91 | 92 | - 修复了在 `设置特殊偏移量` 中,点击列表中空白区域导致的报错 93 | - 修复了多块屏幕下,当鼠标不在指定的屏幕中,相应的特殊偏移量失效的问题 94 | - 修复了当 JAB 程序(`InputTip.JAB.JetBrains.exe`)存在旧版本时,勾选 `启用 JAB/JetBrains IDE 支持` 后,没有使用新版本的 JAB 程序的问题 95 | 96 | ## 2.36.5 97 | 98 | - 修复了 zip 版本中的 JAB 相关功能,未明确指定 ahk 运行环境的问题 99 | - `firefox.exe`(火狐浏览器) 默认的光标获取模式从 `GUI_UIA` 修改为 `MSAA` 100 | - https://inputtip.abgox.com/FAQ/support-app-list 101 | - 其他的修复和优化 102 | 103 | ## 2.36.4 104 | 105 | - 修复了运行路径带有空格时可能出现的运行错误 106 | - 其他的修复和优化 107 | 108 | ## 2.36.3 109 | 110 | - 修复了 `无键盘和鼠标左键点击操作时,符号在多少毫秒后隐藏` 的符号隐藏问题 111 | - 现在,符号隐藏后,移动鼠标,不会再出现符号闪烁 112 | - 其他的修复和优化 113 | 114 | ## 2.36.2 115 | 116 | - 修复了 zip 版本的 `开机自启动` => `「应用快捷方式」` 无效的问题 117 | - 完善了 zip 版本的版本更新校验相关逻辑 118 | - 完善了必要文件丢失的相关处理逻辑 119 | - 其他的修复和优化 120 | 121 | ## 2.36.1 122 | 123 | - 改进了 `设置输入模式` 中的 `自定义` 124 | - 现在的 `自定义` 可以创建多条规则,并按照顺序匹配规则,如果匹配成功,将判断输入法为对应状态 125 | - 你可以选择一个兜底的状态,如果所有规则都无法匹配,将判断为这个状态 126 | - 也就是: 由使用者根据系统返回的状态码和切换码,通过规则匹配告诉 InputTip 当前是什么状态 127 | - 修复了 `重启` 后可能存在两个托盘图标的问题 128 | - 其他的修复和优化 129 | 130 | ## 2.36.0 131 | 132 | - 优化和修复了当通过项目源代码启动 InputTip 时的代码逻辑 133 | - 修复了无法正常使用 `启用 JAB/JetBrains IDE 支持` 的问题 134 | - 在 `托盘菜单` 中添加 `以管理员模式启动`,默认关闭,点击它即可开启 135 | - 优化了版本更新逻辑 136 | - 修复了添加任务计划程序时可能出现的错误覆写 137 | - 完善了一些配置菜单的窗口标题 138 | - 在 `托盘菜单` 中添加 `创建快捷方式到桌面` 139 | - 移除项目中的 exe 程序文件,仅保留 AutoHotkey64.exe 作为 ahk 运行环境 140 | - 添加 InputTip.bat 文件,用于更简单的启动 InputTip.ahk 141 | - 其他的修复和优化 142 | 143 | ## 2.35.9 144 | 145 | - 优化了按键次数统计 146 | - 设置: `托盘菜单` => `更改配置` => `其他杂项` => `是否开启按键次数统计` 147 | - 现在,通过软件内置更新功能进行更新,按键次数也不会丢失导致从 0 重新计数 148 | - 优化了软件更新的 GUI 显示 149 | - 其他的修复和优化 150 | 151 | ## 2.35.8 152 | 153 | - 优化了按键次数统计 154 | - 设置: `托盘菜单` => `更改配置` => `其他杂项` => `是否开启按键次数统计` 155 | - 现在,如果是通过以下方式导致 InputTip 重启,按键次数不会丢失导致从 0 重新计数 156 | - `托盘菜单` => `重启` 157 | - `托盘菜单` => `暂停/运行快捷键` 158 | - `托盘菜单` => `设置状态切换快捷键` 159 | - 其他的修复和优化 160 | 161 | ## 2.35.7 162 | 163 | - 使用 Rust 重写更新程序,减小 exe 程序文件大小 164 | - 修复了更新检查可能存在的版本比对问题 165 | - 优化了一些配置菜单文本描述 166 | - 不再自动创建基于 `任务计划程序` 的 `InputTip.lnk` 快捷方式 167 | - 通过 `托盘菜单` => `开机自启动` => `「任务计划程序」` 设置,会在 `shell:startup` (开机自启动目录) 创建这个特殊的快捷方式 168 | - 不再自动更新 `开机自启动` 169 | - `2.35.7` 之前的版本,每次启动时,都会去检查并重新设置 `开机自启动` 的程序路径等 170 | - 这是为了确保如果移动了软件所在位置,不需要重新设置 `开机自启动` 171 | - 但这并不合理,大多数情况下,软件所在位置不会也不应该频繁移动 172 | - 因此,`2.35.7` 及以上版本,如果移动了软件所在位置,需要自行重新设置 `开机自启动` 173 | - 其他的修复和优化 174 | 175 | ## 2.35.6 176 | 177 | - 使用 [AutoHotkey 2.0.18](https://github.com/AutoHotkey/AutoHotkey/releases/tag/v2.0.18) 重新编译,降低病毒误判概率 178 | 179 | ## 2.35.5 180 | 181 | - 修复了 `指定窗口自动切换状态` 失效的问题 182 | - 在 `2.35.3` 中对于此问题的修复有所遗漏,此版本修复遗漏的情况 183 | - 将配置菜单的字体从 `微软雅黑` 修改为 `Microsoft YaHei` (兼容性更好的字体名称) 184 | 185 | ## 2.35.4 186 | 187 | - 优化了托盘图标的加载逻辑 188 | - 在 **运行** 状态时,托盘图标加载的是 `InputTipSymbol\default\favicon.png` 189 | - 在 **暂停** 状态时,托盘图标加载的是 `InputTipSymbol\default\favicon-pause.png` 190 | - 可以通过替换这两个图片来实现自定义托盘图标的效果 191 | - `favicon.png` 和 `favicon-pause.png` 文件不存在时,重启 InputTip 会重新生成默认的图标图片 192 | 193 | ## 2.35.3 194 | 195 | - 修复了 `指定窗口自动切换状态` 失效的问题 196 | - 失效场景: 通过 `设置状态切换快捷键` 设置了 `Shift`/`LShift`/`RShift` 作为单键快捷键时 197 | - 修正了配置菜单的文本描述错误 198 | 199 | ## 2.35.2 200 | 201 | - 当在 `设置符号显示位置` 的 `哪些应用窗口中的符号需要显示在鼠标附近` 中选择 `在任意应用窗口中` 时,不再需要添加白名单 202 | - 修复了更新检查的一些问题 203 | - 在 `设置更新检查` 菜单中添加了 `立即检查更新` 按钮 204 | - 优化一些配置菜单的文本显示 205 | 206 | ## 2.35.1 207 | 208 | - 修复了一个变量问题 209 | 210 | ## 2.35.0 211 | 212 | - 添加配置项 `符号的垂直偏移量的参考原点` 213 | - 设置: `托盘菜单` => `更改配置` => `显示形式` => `符号的垂直偏移量的参考原点` 214 | - 现在,图片/方块/文本符号默认显示在输入光标上方,如果希望显示在下方,建议更改此配置为 `输入光标下方`,然后修改对应的偏移量 215 | - 因为使用 `输入光标下方` 可以避免当窗口内容进行缩放时,符号位置的显示偏差问题([相关 issue](https://github.com/abgox/InputTip/issues/145)) 216 | - 修复了 `设置状态切换快捷键` 的以下问题 217 | 218 | - 当使用 `设置单键` 时,以 `LShift` 和 `RShift` 为例 219 | - 当设置 `LShift` 强制切换中文,`RShift` 强制切换英文时 220 | - 当状态为英文时,如果想要输入大写字母,按下 `LShift` + 任意字母后,会意外触发强制切换,使状态变为中文 221 | 222 | - 添加了对符号显示的窗口边缘检测 223 | - 如果因为内容滚动等场景,符号的实际显示位置在窗口之外时,符号会直接隐藏 224 | - 其他的修复和优化 225 | 226 | ## 2.34.5 227 | 228 | - 优化了当符号显示在鼠标附近时的显示逻辑 229 | - 当鼠标移动到任务栏上时,符号仍然保持显示 230 | - 优化一些配置菜单的文本描述 231 | 232 | ## 2.34.4 233 | 234 | - 优化一些配置菜单的文本描述 235 | 236 | ## 2.34.3 237 | 238 | - 优化了 `软件暂停` 239 | - `2.34.0` 中的 `软件暂停` 会取消所有 InputTip 产生的快捷键,但 `暂停/运行快捷键` 应该保留 240 | - 在此版本中,当软件暂停时,只会取消三个状态切换的快捷键(如果未设置就没有) 241 | - 而 `暂停/运行快捷键` 会被保留,再次按下时 InputTip 会恢复运行 242 | 243 | ## 2.34.2 244 | 245 | - 修复了当 InputTip 所在路径或 exe 文件名含有空格时,自动更新失效的问题 246 | 247 | ## 2.34.1 248 | 249 | - 修复了当使用符号显示在鼠标附近时,符号闪烁的问题 250 | - 修复了自动更新的问题 251 | - 其他的修复和优化 252 | 253 | ## 2.34.0 254 | 255 | - 在 `托盘菜单` => `更改配置` => `显示形式` => `2. 显示什么类型的符号` 下方添加一个配置 256 | - `当鼠标悬浮在符号上时,符号是否需要隐藏`,这是一个复选框,它默认勾选 257 | - 如果因为鼠标悬浮在符号上,出现了符号闪烁,可以取消勾选它 258 | - 优化了 `软件暂停` 259 | - `2.34.0` 之前的版本,`软件暂停` 只是暂停了线程,但是快捷键没有被取消 260 | - `2.34.0` 版本则会完全暂停,包括暂停线程和取消所有 InputTip 产生的快捷键 261 | - 其他的修复和优化 262 | 263 | ## 2.33.4 264 | 265 | - 修复 JAB 进程中的变量未引入导致的报错 266 | 267 | ## 2.33.3 268 | 269 | - 优化字体配置 270 | - 现在,字体相关配置会根据系统已安装的字体,生成下拉列表自由选择或输入 271 | - 需要注意,下拉列表中的字体,不一定有效,你可能需要检查是否为字体全称 272 | - 有些名称需要去掉末尾的 `Regular`/ `Bold`/... 才会生效 273 | - 其他的修复和优化 274 | 275 | ## 2.33.2 276 | 277 | - 抑制了当更新检查的网络访问被拒绝时的报错 278 | - 移除了一个不合理的特性 279 | - 对于显示符号的窗口,当鼠标不在此窗口中时,符号会被隐藏 280 | - 这是一个不合理的特性 281 | - 对于一些很小的窗口,如 `PowerToys Run`(`PowerToys.PowerLauncher.exe`),这个特性反而导致许多应该显示的情况被意外隐藏 282 | 283 | ## 2.33.1 284 | 285 | - 修复了在以下情况时,处于对应状态未隐藏的问题 286 | 287 | - `图片符号`: 当路径选择为空时 288 | - `方块符号`: 当颜色设置为空时 289 | - `文本符号`: 将文本设置为空时 290 | 291 | - 改进了 `设置特殊偏移量` 292 | 293 | - 现在可以通过 `批量设置` 同时设置多个屏幕 294 | 295 | - 其他的修复和优化 296 | 297 | ## 2.33.0 298 | 299 | - `托盘菜单` 中的变化 300 | 301 | - 添加了 `设置符号显示位置` 302 | 303 | - 对于一些特别的无法正常显示符号的应用窗口,它是一个折中的解决方案 304 | 305 | - 更新了 `设置状态切换快捷键` 中的 `设置单键` 的按键列表 306 | - 更新了 `更改配置` 中的 `更多杂项` 307 | - 添加了对托盘菜单悬浮提示的文本模板自定义 308 | - 添加了按键次数统计以及文本模板自定义 309 | 310 | - 其他的修复和优化 311 | 312 | ## 2.32.0 313 | 314 | - 在 `托盘菜单` 中添加了 `更改用户信息` 315 | 316 | - 域用户需要修改用户名,才能正常使用 `开机自启动` 中的 `任务计划程序` 317 | 318 | - 检查到新版本后的 `确认更新` 不再依赖 powershell 319 | 320 | - 如果无法调用 powershell,依赖 `powershell` 的以下相关功能会自动禁用 321 | 322 | - `开机自启动` 中的 `任务计划程序` 323 | - `启用 JAB/JetBrains IDE 支持` 324 | 325 | - 其他的修复和优化 326 | 327 | ## 2.31.0 328 | 329 | - 新增 330 | 331 | 1. 当鼠标悬浮在符号上时,符号立即隐藏 332 | - 此功能在 `2.28.0` 中由于存在问题被移除,现在重新添加 333 | 2. 在 `设置输入法模式` 的 `自定义` 中,添加了 `状态码规则`、`切换码规则` 和 `以哪一种状态作为判断依据` 334 | 3. 为符号添加了不同状态下符号的独立配置 335 | 4. 新增了应用暂停时的软件图标 336 | 337 | - 变动 338 | 339 | 1. 将 `设置输入法模式` 中的 `讯飞输入法` 和 `手心输入法` 模式合并到 `自定义` 中 340 | - 现在只有两种输入法模式: `通用` 和 `自定义` 341 | 2. 文本符号中所有配置独立,不再依赖方块符号中的配置 342 | - `2.31.0` 之前的版本,文本符号的透明度、偏移量、边框样式、背景颜色由方块符号中的相同配置决定 343 | 3. 统一配置项的值的计算,部分之前跟随 `DPI` 缩放的配置项不再跟随 `DPI` 缩放 344 | - 这会导致从版本更改后符号可能会变小,你需要重新调整宽高大小 345 | 4. 不再使用 powershell 对鼠标样式文件夹解压缩 346 | - 但是这也导致了 `InputTip.exe` 变大了许多,不过也只有大约 6 MB 左右 347 | 348 | - 所有代码完成重构 349 | - 其他的修复和优化 350 | 351 | ## 2.30.2 352 | 353 | - 修复了在极少数情况下(如 UAC 弹窗时),触发报错(拒绝访问)的问题 354 | - 其他的修复和优化 355 | 356 | ## 2.30.1 357 | 358 | - 修复了 `符号显示白名单` 添加应用进程时会在 `InputTip.ini` 中写入两次的问题 359 | - 其他的修复和优化 360 | 361 | ## 2.30.0 362 | 363 | - 在 `更改配置` 中的 `其他杂项` 中添加了 `实时显示当前激活的窗口进程信息` 364 | - 为各个列表添加了个数统计 365 | - 移除了软件内部的禁用名单 366 | - 禁用名单中的应用进程不是所有系统环境都有问题的,统一禁用不合理 367 | - 如果你仍继续使用黑名单,也应该由你自行添加 368 | - 当选择 `使用「黑」名单` 时,会弹出警告窗口提醒 369 | - 修复了 `设置光标获取模式` 中的一些问题 370 | - 优化了许多菜单的显示和操作逻辑 371 | - 其他的修复和优化 372 | 373 | ## 2.29.0 374 | 375 | - 添加了 `设置光标获取模式` 376 | - 现在,你可以指定应用使用哪种光标获取模式 377 | - 如果所有模式都不可用,则表示在此窗口中获取不到光标位置,暂时无法解决 378 | - `添加 JetBrains IDE 应用` 合并到其中 379 | - 将 JetBrains IDE 应用添加到 `JAB` 列表中即可 380 | - 添加了 `设置特殊偏移量` 381 | - 你可以指定应用在不同屏幕下的特殊偏移量 382 | - `设置 JetBrains 系统 IDE 的偏移量` 合并到其中 383 | - 由于 `设置 JetBrains 系统 IDE 的偏移量` 不好迁移,可能需要通过 `设置特殊偏移量` 重新设置 384 | - 在 `更改配置` 中添加了 `其他杂项` 标签页 385 | - 其中包含配置: `所有配置菜单的字体大小` 386 | - 其他的修复和优化 387 | 388 | ## 2.28.6 389 | 390 | - 完善了自动切换的逻辑 391 | - 修复了当设置快捷键切换状态后,频繁按下多次快捷键,状态切换有误的问题 392 | - 优化了「指定窗口自动切换状态」配置菜单 393 | - 当添加应用进程时,如果白名单中不存在,则同步添加到白名单中 394 | - 其他的修复和优化 395 | 396 | ## 2.28.5 397 | 398 | - 限制同一个配置菜单只能存在一个,避免出现多个相同菜单,导致修改冲突 399 | - 优化了部分布局和描述 400 | - 其他的修复和优化 401 | 402 | ## 2.28.4 403 | 404 | - 修复了当应用进程列表为空时,双击列表会出现意外行为导致错误的问题 405 | - 优化了部分布局和描述 406 | 407 | ## 2.28.3 408 | 409 | - 修复了配置修改没有实时生效的问题 410 | - 限制更新检测可设置的时间范围,避免程序错误 411 | 412 | ## 2.28.2 413 | 414 | - 修复了白名单机制对于 InputTip 自身创建的窗口无效的问题 415 | - 修复了点击 `托盘菜单` 中的 `暂停/运行` 时的问题 416 | - 修复和优化了部分配置菜单的布局和描述 417 | 418 | ## 2.28.1 419 | 420 | - 修复黑名单机制的版本迁移 421 | - 对于旧版本更新到新版本,还是沿用黑名单机制,白名单机制需要重新设置 422 | - 将 `托盘菜单` 中的 `忽略更新` 修改 `设置更新检测` 423 | - 修复虚拟机系统环境中,获取目录路径错乱的问题 424 | - 修复设置状态自动切换时,意外写入的一个配置项 app_add 425 | 426 | ## 2.28.0 427 | 428 | > [!warning] 429 | > 430 | > `v2.28.0` 会默认使用白名单机制 431 | 432 | - 托盘菜单中的配置项变化 433 | - `暂停软件运行` 修改为 `暂停/运行` 434 | - `设置快捷键` => `设置状态切换快捷键` 435 | - `设置自动切换` => `指定窗口自动切换状态` 436 | - `符号显示黑名单` => `符号显示黑/白名单` 437 | - 添加了白名单机制 438 | - 添加了 `暂停/运行快捷键`,可以通过它设置快捷键,快速暂停和运行 `InputTip` 439 | - 优化了 `设置输入法模式` 440 | - 将 `模式1 - 通用` 和 `模式2 - 通用` 合并为 `通用模式` 441 | - 现在,可以配置获取输入法状态的超时时间,也可以自定义状态码和切换码 442 | - 理论上来说,你可以通过自定义状态码和切换码,不再局限于中英文状态提示,而是任意两种语言状态提示 443 | - 修改了 `无操作时,符号在多少毫秒后隐藏` 这个配置的运行逻辑。 444 | - 之前,符号隐藏后,**下次键盘操作** 或 **窗口切换** 时会再次显示符号,这有些不合理。 445 | - 现在,符号隐藏后,**下次键盘操作** 或 **点击鼠标左键** 时会再次显示符号 446 | - 移除了方块符号自定义边框样式的功能 447 | - 渲染效果差,不稳定。 448 | - 建议使用 `图片符号` 代替,自己制作带边框的符号。 449 | - 对于需要添加应用进程的菜单,优化了界面布局 450 | - 现在添加进程和移除进程在同一个 Tab 页中,查看操作更方便 451 | - 添加显示更多按钮,可以获取到更多的正在运行的进程进行快捷添加,包含后台运行的、无窗口或隐藏窗口的进程 452 | - 优化了配置菜单 453 | - 不再通过重启软件来加载最新配置 454 | - 部分符号没有跟随输入法状态更新的情况,是因为软件重启导致的。 455 | - 现在所有配置修改,都会实时生效,能立即看到最新效果,更改配置更方便 456 | - 调整源代码文件目录结构,代码重构 457 | - 优化性能 458 | - 其他的修复和优化 459 | 460 | ## 2.27.2 461 | 462 | - 修复了运行 `InputTip.exe` 时,任务栏的一些 bug 463 | - 其他的修复和优化 464 | 465 | ## 2.27.0 466 | 467 | - 鼠标样式不再通过打开文件夹去设置,而是会动态的生成下拉列表进行选择,图片符号同理。 468 | - 这会导致鼠标样式和图片符号会重置为默认,请重新自定义 469 | - 默认的图片符号已经修改,如果想使用新的默认图片符号,请删除 `InputTipSymbol\default` 目录并重启 `InputTip.exe` 470 | - 修改了部分配置项的默认值 471 | - 其他的修复和优化 472 | 473 | ## 2.26.5 474 | 475 | - 修复了在 JetBrains 系列 IDE 中,图片符号不显示的问题 476 | - 其他的修复和优化 477 | 478 | ## 2.26.2 479 | 480 | - 修复了直接通过项目仓库运行 `InputTip.ahk` 的一些使用问题 481 | - 其他的修复和优化 482 | 483 | ## 2.26.1 484 | 485 | - 修复了当使用 `无操作时,符号在多少毫秒后隐藏` 这个配置后,意外导致 CPU 占用过高的问题 486 | 487 | ## 2.26.0 488 | 489 | - 在 `更改配置` 中添加 `每多少毫秒后更新符号的显示位置和状态` 配置 490 | - 在获取光标位置的方法中,使用更多的方法兜底 491 | - 修正部分变量命名拼写错误 492 | 493 | ## 2.25.0 494 | 495 | - 添加多种设置开机自启动的方式 496 | - 任务计划程序 497 | - 快捷方式 498 | - 注册表 499 | - 修改了 `设置输入法模式` 中的模式名称,使其更容易理解 500 | - `模式1` => `模式1 - 通用` 501 | - `模式2` => `模式2 - 通用` 502 | - `模式3` => `模式3 - 讯飞输入法` 503 | - `模式4` => `模式4 - 手心输入法` 504 | - 修复当使用 `暂停软件运行` 时,符号可能有残留的问题 505 | 506 | ## 2.24.1 507 | 508 | - 修复了 `InputTip.exe` 运行后,相关文件无法正常释放出来的问题 509 | 510 | ## 2.24.0 511 | 512 | - 在托盘菜单中,添加 `暂停软件运行`、 `打开软件所在目录` 和 `添加 JetBrains IDE 应用` 513 | - 将 `InputTipCursor` 下的 `CN_Default`、`EN_Default`、`Caps_Default` 放入 `default` 目录下 514 | - JetBrains IDE 支持所需要的 `InputTip.JAB.JetBrains.exe` 现在和 `InputTip.exe` 放在同一目录下,不再放入 `InputTipSymbol` 目录中 515 | - 修复了当电脑没有连接电源时,无法正常自启动的问题 516 | - 其他的修复和优化 517 | 518 | ## 2.23.0 519 | 520 | - 在托盘菜单的 `设置快捷键` 中,添加 `设置单键` 521 | - 比如: 你可以将 `LShift`(左侧的 `Shift`) 设置为切换中文, `RShift`(右侧的 `Shift`) 设置为切换英文 522 | 523 | ## 2.22.4 524 | 525 | - 将托盘菜单中的 `指定隐藏符号的应用` 修改为 `符号显示黑名单` 526 | - `指定隐藏符号的应用` 这个名字有点难以理解,换个更容易理解的名字 527 | - 调整了托盘菜单中配置项的顺序 528 | - 其他的修复和优化 529 | 530 | ## 2.22.0 531 | 532 | - 兼容 JetBrains IDE 系列产品 533 | - [如何在 JetBrains IDE 系列产品中使用 `InputTip`](../../README.md#如何在-jetbrains-系列-ide-中使用-inputtip) 534 | - [通过 AutoHotkey 官方论坛中 Descolada 大佬给出的解决方案实现](https://www.autohotkey.com/boards/viewtopic.php?t=130941#p576439) 535 | 536 | ## 2.21.7 537 | 538 | - 此版本将 `AutoHotkey` 从 `v2.1-alpha` 退回到 `v2.0` 539 | 540 | ## 2.21.0 541 | 542 | - `InputTip.exe` 运行后,会自动生成一个 `InputTip.lnk` 的快捷方式 543 | - 通过运行这个快捷方式来运行 `InputTip.exe`,就不会出现 `UAC` 权限提示弹窗了 544 | - 你可以将这个快捷方式复制到任何地方,你的桌面上、自动化流程中... 545 | - 如果此快捷方式意外被删除,你又需要它,请运行 `InputTip.exe` 来重新生成它 546 | - 如果此快捷方式无法正常运行,请删除它,然后运行 `InputTip.exe` 来重新生成它 547 | - 同时,也更改了实现 `开机自启动` 的方式 548 | - 不再使用修改注册表的方式,已经修改了注册表的,也会在这个版本从注册表中移除 549 | - 现在,当你勾选了托盘菜单中的 `开机自启动` 时,会自动将 `InputTip.lnk` 这个快捷方式复制一份到开机自启动目录中 550 | - 如果开机没有正常自启动,请取消并重新勾选 `开机自启动` 551 | - 因此,`开机自启动` 也不会再出现 `UAC` 权限提示弹窗了 552 | - 优化了 `更改配置` 界面 553 | - 其他的修复和优化 554 | 555 | ## 2.20.0 556 | 557 | - 现在,当第一次启动 `InputTip` 时,会显示一个弹窗,需要用户确认是否修改鼠标样式 558 | - 之前的版本,没有任何提示,直接修改了用户的鼠标样式,这确实让部分用户感到疑惑 559 | - 虽然根据输入法状态修改鼠标样式是 `InputTip` 的核心功能之一,但部分用户只是需要符号显示 560 | - 这里的第一次启动指的是还没有产生 `InputTip.ini` 文件 561 | - 所以只有一开始就使用 `2.20.0` 及以上版本的用户才有效 562 | 563 | ## 2.19.0 564 | 565 | - 在托盘菜单中添加 `忽略更新` 566 | - 当有更新弹窗时,在更新弹窗底部添加一个 `忽略更新` 按钮 567 | 568 | ## 2.18.3 569 | 570 | - 统一命名,将 `文本字符` 更名为 `文本符号` 571 | - 将 `指定隐藏方块符号的应用` 更名为 `指定隐藏符号的应用` 572 | 573 | ## 2.18.0 574 | 575 | - 添加了 `图片符号`,通过图片加载的方式自定义符号 576 | - 由于通过 `AutoHotkey` 的 `Gui` 去画符号,限制很大,也不够灵活 577 | - 而通过图片加载的方式,更加的 DIY,更加的自由、灵活 578 | - `InputTip` 只需要负责加载图片,至于什么样的图片,由用户自定义 579 | - 你可以用自己喜欢的符号图片 580 | - 你也可以自己去制作一个符号图片 581 | - 默认使用的是圆点符号图片 582 | - 图片显示的偏移量、大小、自动隐藏等都应该在 `更改配置` 中的 `图片符号` 页进行配置 583 | - 由于这种方式最灵活,显示效果也不错,就默认启用了 584 | - 启用它后,方块符号就不显示了,如果想继续使用方块符号,你需要在 `更改配置` 中将 `显示形式` 页中的 `是否显示图片符号` 设置为 `0` 585 | 586 | ## 2.17.5 587 | 588 | - 一个特别的修复版本 589 | - 理论上,此版本后,应该不会再出现崩溃、自动输入、自动删除、闪退等意外现象了 590 | 591 | ## 2.17.0 592 | 593 | - 移除托盘菜单中的 `设置特殊软件` 594 | - 将其中的 `隐藏输入法状态方块符号提示` 提取到外部,成为一级菜单,更名为 `指定隐藏方块符号的应用` 595 | - 至于其中的 `隐藏中文英状态方块符号提示`,这个很鸡肋,基本无用,就直接移除了 596 | - 其他的修复和优化 597 | 598 | ## 2.16.0 599 | 600 | - 为方块符号添加了一个配置项 `方块符号在多少毫秒后隐藏` 601 | 602 | - 默认为 `0`,表示不隐藏,实时显示 603 | - 当值不为 `0`,则此值被认为是指定的毫秒时间,在这个时间后,方块符号将会隐藏 604 | - 方块符号隐藏后,在当前软件窗口的任何鼠标操作都不会再显示方块符号,直到下一次键盘按键操作或者切换到其他软件窗口才会重新显示 605 | 606 | - 将托盘菜单中的 `设置方块符号边框样式` 合并到 `更改配置` 中 607 | - 其他的修复和优化 608 | 609 | ## 2.15.0 610 | 611 | - 解决了多屏幕下的坐标偏差 612 | 613 | - 不过也有限制: 副屏幕的缩放率和主屏幕需要保持一致 614 | - 比如: 主屏幕缩放率 `200%`,副屏幕缩放率也必须是 `200%` 615 | 616 | - 移除了托盘菜单中的 `设置特殊偏移量` 617 | - 现在多屏幕的坐标偏差已经解决,不再需要它 618 | - 对于缩放率不一致的情况下,偏差大小变化没有规律,也不是一个固定值,即使设置了它,也没有作用。 619 | 620 | ## 2.14.0 621 | 622 | - 将托盘菜单中的 `设置鼠标样式` 和 `下载鼠标样式包` 合并到 `更改配置` 中 623 | - 优化 `更改配置` 的菜单界面,现在通过不同的 Tab 菜单来区分不同的配置项 624 | - 添加显示字符相关的配置 625 | - 在 `更改配置中`,将 `是否显示字符` 修改为 `1`,就会在方块中显示状态字符,默认为 `中`/`英`/`大` 626 | - 详细的配置项在 `更改配置` 中的 `文本符号` 菜单中查看、修改 627 | - 添加了 `文本符号` 配置后,`InputTip` v1 版本基本无用了,所以 v1 版本应该不再更新了 628 | - 修复了在 微软 OneNote 中的问题 629 | - 不过,修复后,有时候会获取不到窗口相关光标位置信息,符号也就无法显示了 630 | - 如果是这种情况,就没有办法了,只能暂时依赖鼠标样式的改变了 631 | 632 | ## 2.13.0 633 | 634 | - 在托盘菜单中添加 `设置强制切换快捷键` 635 | - 个人更推荐 `设置自动切换`,进入不同应用,自动切换状态,不需要额外的快捷键 636 | - 因为 `InputTip` 是为了减少输入法状态切换的按键操作,`设置强制切换快捷键` 反而会增加按键操作 637 | - 不过,部分场景中可能也确实需要这样的功能,所以还是决定添加它 638 | - 其他的修复和优化 639 | 640 | ## 2.12.0 641 | 642 | - 在`设置方块符号边框样式` 中,添加了 `自定义边框样式` 643 | - 更改配置时,配置菜单中不再显示配置项的名称,而是显示中文描述 644 | - 其他的修复和优化 645 | 646 | ## 2.11.0 647 | 648 | - 在托盘菜单中添加 `设置方块符号边框样式`,有几种边框样式可以选择 649 | - 个人感觉 `样式1` 比较不错,就作为默认值了,如果喜欢以前没有边框的版本,选择 `去掉边框样式` 即可 650 | 651 | ## 2.10.0 652 | 653 | - 在托盘菜单中添加 `设置自动切换`,现在可以设置指定应用自动切换到英文/中文/大写锁定状态 654 | - 其他的修复和优化 655 | 656 | ## 2.9.0 657 | 658 | - 在托盘菜单中添加 `设置特殊偏移量`,用于解决在缩放大于 `125%` 的副屏上可能导致的显示位置误差 659 | - 其他的修复和优化 660 | 661 | ## 2.8.0 662 | 663 | - 添加配置修改校验,避免错误配置导致程序报错 664 | - 其他的修复和优化 665 | 666 | ## 2.7.2 667 | 668 | - 将 `模式2` 作为默认模式 669 | - 一些 `模式1` 无法识别的窗口,`模式2` 可以识别 670 | - 不是一开始就使用 `2.7.2` 及以上版本的,也可以切换到 `模式2` 尝试一下 671 | - 如果切换到 `模式2` 有效,就推荐一直使用 `模式2` 672 | 673 | ## 2.7.1 674 | 675 | - 由于不是所有的输入法都无法在记事本和 everything 中获取到中英文状态 676 | - 直接把 `notepad.exe,everything.exe` 赋值给 `app_hide_CN_EN` 配置是不合理的 677 | - 应该由用于自己去设置 `app_hide_CN_EN` 配置项 678 | - 通过底部任务栏右侧的 `InputTip` 托盘图标,鼠标右键点击它,选择 `设置特殊软件` 679 | - 所以现在将 `app_hide_CN_EN` 配置的默认值更改为空 680 | - 不是一开始就使用 `2.7.1` 及以上版本的,你可以先去除掉 `notepad.exe,everything.exe`这个值,检查一下是否可以正常工作 681 | 682 | ## 2.7.0 683 | 684 | - 更改了配置项 685 | - `window_no_display` => `app_hide_CN_EN` 686 | - `window_no_display` 的值会复制给 `app_hide_CN_EN` 687 | - 添加了一个配置项: 688 | - `app_hide_state` 689 | - 在任务栏底部右侧的软件托盘菜单中添加了一个子菜单 `设置特殊软件` 690 | - 可以在它的子项中,快速的设置 `app_hide_CN_EN` 和 `app_hide_state` 691 | - 提高了处理逻辑的阈值时间,解决有时状态更新不及时的问题 692 | - 其他的修复和优化 693 | 694 | ## 2.6.0 695 | 696 | - 添加 `模式4` 以兼容手心输入法 697 | 698 | ## 2.5.0 699 | 700 | - 提高了处理逻辑的阈值时间,解决有时状态更新不及时、方块卡在原地的问题 701 | - 修改两个默认配置的值 702 | - `offset_x`: `15` => `5` 703 | - `offset_y`: `-15` => `0` 704 | - 正常来说,这样的默认值可能更合理一些 705 | - 你甚至可以将 `symbol_height` 高度设置为光标的高度,将 `symbol_width` 调小,你就可以获得一个光标形状的符号,而不是方块。 706 | - 修改了模式切换的菜单显示 707 | - 其他的修复和优化 708 | 709 | ## 2.4.0 710 | 711 | - 通过模式切换兼容更多输入法,包括百度、小狼毫(rime)、谷歌等输入法 712 | - 修改了菜单文字显示的效果,减少了字重,减少了字体显示问题 713 | - 由于不同的网络环境,可能无法访问到 [官网](https://inputtip.abgox.com),所以给一些可能访问不到的地址,添加 `Github` 和 `Gitee` 地址 714 | - 其他的修复和优化 715 | 716 | ## 2.3.0 717 | 718 | - 添加了一个方块符号,在输入光标附近根据输入法状态改变颜色,作为除了鼠标以外的另一个提示方式 719 | - 添加了许多的配置项 720 | - 添加了自动更新机制 721 | - 当启动 `InputTip.exe` 时,会异步的检查更新,如果有新版本,会提示确认更新 722 | - 如果确认更新就会自动下载新版本替代旧版本并重启 723 | - 其他的修复和优化 724 | 725 | ## 2.2.0 726 | 727 | - 当开始大写锁定时,鼠标样式将会切换为绿色(默认) 728 | - 你也可以自定义它 729 | - 此版本没有考虑到版本迁移的问题 730 | - 如果直接将 2.2.0 的 exe 文件覆盖 2.1.0 的 exe 文件,可能会导致应用无效 731 | - 因为 InputTipCursor 需要新添加两个目录 Caps 和 Caps_Default 732 | - 建议先将 InputTipCursor 目录移动到别处,让 InputTip.exe 重新创建此目录 733 | - 其他的修复和优化 734 | 735 | ## 2.1.0 736 | 737 | - 添加鼠标样式的设置 738 | - 延长了轮询间隔 739 | - 添加了一个可选的鼠标样式文件 Pen 740 | - 改进和修复了一些其他问题 741 | 742 | ## 2.0.0 743 | 744 | - v1 版本中通过显示内容的方式来提示当前输入法的中英文状态,这在某些时候会觉得有些碍眼 745 | - v2 版本中不再使用此方式,而是通过两套光标样式,切换输入法状态时,光标样式会随之切换 746 | -------------------------------------------------------------------------------- /src/InputTip.JAB.JetBrains.ahk: -------------------------------------------------------------------------------- 1 | ; InputTip 2 | 3 | #Include ./utils/options.ahk 4 | 5 | #NoTrayIcon 6 | ;@AHK2Exe-SetName InputTip.JAB 7 | ;@Ahk2Exe-SetOrigFilename InputTip.JAB.JetBrains.ahk 8 | ;@AHK2Exe-SetDescription InputTip.JAB - 一个输入法状态提示工具 9 | 10 | #Include ./utils/IME.ahk 11 | #Include ./utils/ini.ahk 12 | #Include ./utils/app-list.ahk 13 | #Include ./utils/var.ahk 14 | #Include ./utils/tools.ahk 15 | 16 | /** 17 | * 跳过非 JAB/JetBrains IDE 程序,交由 InputTip 处理 18 | * @param exe_str 进程字符串,如 ":webstorm64.exe:" 19 | * @returns {1 | 0} 是否需要跳过 20 | */ 21 | needSkip(exe_str) { 22 | return showCursorPos || !InStr(modeList.JAB, exe_str) 23 | } 24 | 25 | returnCanShowSymbol(&left, &top, &right, &bottom) { 26 | try { 27 | GetCaretPosFromJAB(&left, &top, &right, &bottom) 28 | } catch { 29 | left := 0 30 | top := 0 31 | right := 0 32 | bottom := 0 33 | return 0 34 | } 35 | try { 36 | s := isWhichScreen(screenList) 37 | if (s != "") { 38 | left += app_offset.%exe_name%.%s.num%.x 39 | top += app_offset.%exe_name%.%s.num%.y 40 | } 41 | } 42 | return left 43 | } 44 | 45 | /** 46 | * Gets the position of the caret with UIA, Acc or CaretGetPos. 47 | * @link https://www.reddit.com/r/AutoHotkey/comments/ysuawq/get_the_caret_location_in_any_program/ 48 | * @link https://www.autohotkey.com/boards/viewtopic.php?t=130941#p576439 49 | * @param X Value is set to the screen X-coordinate of the caret 50 | * @param Y Value is set to the screen Y-coordinate of the caret 51 | * @param W Value is set to the width of the caret 52 | * @param H Value is set to the height of the caret 53 | */ 54 | GetCaretPosFromJAB(&X?, &Y?, &W?, &H?) { 55 | static JAB := InitJAB() ; Source: https://github.com/Elgin1/Java-Access-Bridge-for-AHK 56 | if JAB && (hWnd := WinExist("A")) && DllCall(JAB.module "\isJavaWindow", "ptr", hWnd, "CDecl Int") { 57 | if JAB.firstRun 58 | Sleep(200), JAB.firstRun := 0 59 | prevThreadDpiAwarenessContext := DllCall("SetThreadDpiAwarenessContext", "ptr", -2, "ptr") 60 | DllCall(JAB.module "\getAccessibleContextWithFocus", "ptr", hWnd, "Int*", &vmID := 0, JAB.acType "*", &ac := 0, "Cdecl Int") "`n" 61 | DllCall(JAB.module "\getCaretLocation", "Int", vmID, JAB.acType, ac, "Ptr", Info := Buffer(16, 0), "Int", 0, "Cdecl Int") 62 | DllCall(JAB.module "\releaseJavaObject", "Int", vmId, JAB.acType, ac, "CDecl") 63 | DllCall("SetThreadDpiAwarenessContext", "ptr", prevThreadDpiAwarenessContext, "ptr") 64 | X := NumGet(Info, 0, "Int"), Y := NumGet(Info, 4, "Int"), W := NumGet(Info, 8, "Int"), H := NumGet(Info, 12, "Int") 65 | hMonitor := DllCall("MonitorFromWindow", "ptr", hWnd, "int", 2, "ptr") ; MONITOR_DEFAULTTONEAREST 66 | DllCall("Shcore.dll\GetDpiForMonitor", "ptr", hMonitor, "int", 0, "uint*", &dpiX := 0, "uint*", &dpiY := 0) 67 | if dpiX 68 | X := DllCall("MulDiv", "int", X, "int", dpiX, "int", 96, "int"), Y := DllCall("MulDiv", "int", Y, "int", dpiX, "int", 96, "int") 69 | if X || Y || W || H 70 | return 71 | } 72 | InitJAB() { 73 | ret := {}, ret.firstRun := 1, ret.module := A_PtrSize = 8 ? "WindowsAccessBridge-64.dll" : "WindowsAccessBridge-32.dll", ret.acType := "Int64" 74 | ret.DefineProp("__Delete", { call: (this) => DllCall("FreeLibrary", "ptr", this) }) 75 | if !(ret.ptr := DllCall("LoadLibrary", "Str", ret.module, "ptr")) && A_PtrSize = 4 { 76 | ; try legacy, available only for 32-bit 77 | ret.acType := "Int", ret.module := "WindowsAccessBridge.dll", ret.ptr := DllCall("LoadLibrary", "Str", ret.module, "ptr") 78 | } 79 | if !ret.ptr 80 | return ; Failed to load library. Make sure you are running the script in the correct bitness and/or Java for the architecture is installed. 81 | DllCall(ret.module "\Windows_run", "Cdecl Int") 82 | return ret 83 | } 84 | } 85 | 86 | ; 如果有修改代码的需求,你应该写在此行之前 87 | ; 此行之后的逻辑代码,都会因为 show.ahk 中的死循环而无效 88 | #Include ./utils/show.ahk 89 | -------------------------------------------------------------------------------- /src/InputTipCursor/default/CN/AppStarting.ani: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/CN/AppStarting.ani -------------------------------------------------------------------------------- /src/InputTipCursor/default/CN/Arrow.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/CN/Arrow.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/CN/Cross.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/CN/Cross.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/CN/Hand.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/CN/Hand.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/CN/Help.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/CN/Help.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/CN/IBeam.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/CN/IBeam.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/CN/No.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/CN/No.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/CN/Pen.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/CN/Pen.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/CN/SizeAll.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/CN/SizeAll.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/CN/SizeNESW.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/CN/SizeNESW.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/CN/SizeNS.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/CN/SizeNS.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/CN/SizeNWSE.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/CN/SizeNWSE.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/CN/SizeWE.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/CN/SizeWE.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/CN/UpArrow.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/CN/UpArrow.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/CN/Wait.ani: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/CN/Wait.ani -------------------------------------------------------------------------------- /src/InputTipCursor/default/Caps/AppStarting.ani: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/Caps/AppStarting.ani -------------------------------------------------------------------------------- /src/InputTipCursor/default/Caps/Arrow.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/Caps/Arrow.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/Caps/Cross.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/Caps/Cross.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/Caps/Hand.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/Caps/Hand.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/Caps/Help.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/Caps/Help.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/Caps/IBeam.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/Caps/IBeam.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/Caps/No.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/Caps/No.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/Caps/Pen.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/Caps/Pen.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/Caps/SizeAll.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/Caps/SizeAll.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/Caps/SizeNESW.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/Caps/SizeNESW.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/Caps/SizeNS.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/Caps/SizeNS.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/Caps/SizeNWSE.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/Caps/SizeNWSE.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/Caps/SizeWE.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/Caps/SizeWE.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/Caps/UpArrow.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/Caps/UpArrow.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/Caps/Wait.ani: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/Caps/Wait.ani -------------------------------------------------------------------------------- /src/InputTipCursor/default/EN/AppStarting.ani: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/EN/AppStarting.ani -------------------------------------------------------------------------------- /src/InputTipCursor/default/EN/Arrow.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/EN/Arrow.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/EN/Cross.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/EN/Cross.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/EN/Hand.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/EN/Hand.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/EN/Help.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/EN/Help.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/EN/IBeam.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/EN/IBeam.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/EN/No.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/EN/No.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/EN/Pen.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/EN/Pen.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/EN/SizeAll.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/EN/SizeAll.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/EN/SizeNESW.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/EN/SizeNESW.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/EN/SizeNS.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/EN/SizeNS.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/EN/SizeNWSE.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/EN/SizeNWSE.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/EN/SizeWE.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/EN/SizeWE.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/EN/UpArrow.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/EN/UpArrow.cur -------------------------------------------------------------------------------- /src/InputTipCursor/default/EN/Wait.ani: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipCursor/default/EN/Wait.ani -------------------------------------------------------------------------------- /src/InputTipSymbol/default/CN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipSymbol/default/CN.png -------------------------------------------------------------------------------- /src/InputTipSymbol/default/Caps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipSymbol/default/Caps.png -------------------------------------------------------------------------------- /src/InputTipSymbol/default/EN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipSymbol/default/EN.png -------------------------------------------------------------------------------- /src/InputTipSymbol/default/favicon-pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipSymbol/default/favicon-pause.png -------------------------------------------------------------------------------- /src/InputTipSymbol/default/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipSymbol/default/favicon.png -------------------------------------------------------------------------------- /src/InputTipSymbol/default/offer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/InputTipSymbol/default/offer.png -------------------------------------------------------------------------------- /src/files.ini: -------------------------------------------------------------------------------- 1 | # InputTip: url=path 2 | [Files] 3 | src/menu/about.ahk=menu/about.ahk 4 | src/menu/app-offset.ahk=menu/app-offset.ahk 5 | src/menu/bw-list.ahk=menu/bw-list.ahk 6 | src/menu/check-update.ahk=menu/check-update.ahk 7 | src/menu/config.ahk=menu/config.ahk 8 | src/menu/cursor-mode.ahk=menu/cursor-mode.ahk 9 | src/menu/input-mode.ahk=menu/input-mode.ahk 10 | src/menu/JAB.ahk=menu/JAB.ahk 11 | src/menu/startup.ahk=menu/startup.ahk 12 | src/menu/switch-window.ahk=menu/switch-window.ahk 13 | src/menu/symbol-pos.ahk=menu/symbol-pos.ahk 14 | src/menu/tray-menu.ahk=menu/tray-menu.ahk 15 | src/utils/hotkey-gui.ahk=utils/hotkey-gui.ahk 16 | src/utils/app-list.ahk=utils/app-list.ahk 17 | src/utils/check-version.ahk=utils/check-version.ahk 18 | src/utils/create-gui.ahk=utils/create-gui.ahk 19 | src/utils/IME.ahk=utils/IME.ahk 20 | src/utils/ini.ahk=utils/ini.ahk 21 | src/utils/show.ahk=utils/show.ahk 22 | src/utils/tools.ahk=utils/tools.ahk 23 | src/utils/var.ahk=utils/var.ahk 24 | src/utils/verify-file.ahk=utils/verify-file.ahk 25 | src/CHANGELOG.md=CHANGELOG.md 26 | src/InputTip.ahk=InputTip.ahk 27 | src/InputTip.JAB.JetBrains.ahk=InputTip.JAB.JetBrains.ahk 28 | .gitignore=../.gitignore 29 | InputTip.bat=../InputTip.bat 30 | README.md=../README.md 31 | LICENSE=../LICENSE 32 | src/version.txt=version.txt 33 | src/utils/options.ahk=utils/options.ahk 34 | -------------------------------------------------------------------------------- /src/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abgox/InputTip/b6d198058709b9ff75e3148299179e3349c1256c/src/img/favicon.ico -------------------------------------------------------------------------------- /src/menu/JAB.ahk: -------------------------------------------------------------------------------- 1 | ; InputTip 2 | 3 | fn_JAB(item, *) { 4 | global enableJABSupport := !enableJABSupport 5 | writeIni("enableJABSupport", enableJABSupport) 6 | A_TrayMenu.ToggleCheck(item) 7 | if (enableJABSupport) { 8 | if (runJAB()) { 9 | return 10 | } 11 | createGui(JABGui).Show() 12 | JABGui(info) { 13 | g := createGuiOpt("InputTip - 启用 JAB/JetBrains IDE 支持") 14 | g.AddText(, "已经成功启用了 JAB/JetBrains IDE 支持,你还需要进行以下操作步骤: ") 15 | 16 | if (info.i) { 17 | return g 18 | } 19 | w := info.w 20 | bw := w - g.MarginX * 2 21 | 22 | g.AddEdit("xs -VScroll ReadOnly cGray w" w, "1. 开启 Java Access Bridge`n2. 点击下方的或「托盘菜单」中的「设置光标获取模式」`n3. 将 JetBrains IDE 或其他 JAB 应用进程添加到其中的「JAB」列表中`n4. 如果未生效,请重启正在使用的 JetBrains IDE 或其他 JAB 应用`n5. 如果仍未生效,请重启 InputTip 或重启系统`n6. 有多块屏幕时,副屏幕上可能有坐标偏差,需要通过「设置特殊偏移量」调整") 23 | g.AddLink(, '详细操作步骤,请查看: 官网 Github Gitee') 24 | g.AddButton("xs w" w, "「设置光标获取模式」").OnEvent("Click", fn_cursor_mode) 25 | g.AddButton("xs w" w, "「设置特殊偏移量」").OnEvent("Click", fn_app_offset) 26 | y := g.AddButton("xs w" w, "我知道了") 27 | y.Focus() 28 | y.OnEvent("Click", e_close) 29 | e_close(*) { 30 | g.Destroy() 31 | } 32 | gc.w.enableJABGui := g 33 | return g 34 | } 35 | } else { 36 | if (gc.w.enableJABGui) { 37 | gc.w.enableJABGui.Destroy() 38 | gc.w.enableJABGui := "" 39 | } 40 | SetTimer(killAppTimer, -1) 41 | killAppTimer() { 42 | try { 43 | killJAB(1, A_IsCompiled || A_IsAdmin) 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/menu/about.ahk: -------------------------------------------------------------------------------- 1 | ; InputTip 2 | 3 | fn_about(*) { 4 | if (gc.w.aboutGui) { 5 | gc.w.aboutGui.Destroy() 6 | gc.w.aboutGui := "" 7 | } 8 | createGui(aboutGui).Show() 9 | aboutGui(info) { 10 | g := createGuiOpt("InputTip - " (A_IsCompiled ? "exe 版本" : "zip 版本") " - " (A_IsAdmin ? "以管理员权限启动" : "以当前用户权限启动")) 11 | 12 | g.AddText("Center w" info.w, "InputTip - 一个输入法状态实时提示工具") 13 | tab := g.AddTab3("-Wrap", ["关于项目", "赞赏支持", "参考项目", "其他项目"]) 14 | tab.UseTab(1) 15 | g.AddText("Section", '版本号: ') 16 | g.AddEdit("yp ReadOnly cRed", currentVersion) 17 | g.AddText("xs", '开发者: ') 18 | g.AddLink("yp", 'abgox') 19 | g.AddText("xs", 'QQ 号: ') 20 | g.AddEdit("yp ReadOnly", '1151676611') 21 | g.AddLink("xs", 'QQ 群: ') 22 | g.AddEdit("yp ReadOnly", '451860327') 23 | g.AddLink("xs", '点击加入【QQ 群】交流反馈') 24 | g.AddLink("yp", '点击加入【腾讯频道】交流反馈') 25 | 26 | if (info.i) { 27 | g.AddText("xs", "-------------------------------------------------------------------------------") 28 | return g 29 | } 30 | w := info.w 31 | bw := w - g.MarginX * 2 32 | 33 | g.AddText("xs", "-------------------------------------------------------------------------------------") 34 | g.AddLink("xs", '1. 官网: https://inputtip.abgox.com') 35 | g.AddLink("xs", '2. Github: https://github.com/abgox/InputTip') 36 | g.AddLink("xs", '3. Gitee: https://gitee.com/abgox/InputTip') 37 | tab.UseTab(2) 38 | g.AddLink("Section", '- 赞赏我ko-fi.com 、微信支付宝赞赏支持') 39 | g.AddLink("xs", '- 建议附上你的留言并标明 InputTip,它们将显示在 赞赏名单 中') 40 | g.AddText("xs", "- 非常感谢你赞赏支持我的工作,希望 InputTip 能真正带给你帮助!") 41 | g.AddPicture("h-1 w" w / 5 * 3, "InputTipSymbol/default/offer.png") 42 | tab.UseTab(3) 43 | g.AddLink("Section", '1. ImTip - aardio') 44 | g.AddLink("xs", '2. KBLAutoSwitch - flyinclouds') 45 | g.AddLink("xs", '3. AutoHotkeyScripts - Tebayaki') 46 | g.AddLink("xs", '4. RedDot - Autumn-one') 47 | g.AddLink("xs", '5. language-indicator - yakunins') 48 | g.AddText("xs", '- InputTip v1 是在鼠标附近显示带文字的方块符号') 49 | g.AddText("xs", '- InputTip v2 默认通过不同颜色的鼠标样式来区分') 50 | g.AddText("xs", '- 后来参照了 RedDot 和 language-indicator 的设计') 51 | g.AddText("xs", '- 因为实现很简单,就是去掉 v1 中方块符号的文字,加上不同的背景颜色') 52 | 53 | tab.UseTab(4) 54 | g.AddLink("Section cRed w" bw, '关于我的其他项目,可以通过访问 我的主页GithubGitee 等方式去了解') 55 | g.AddLink("Section w" bw, '1. PSCompletions : 一个 PowerShell 补全模块,它能让你在 PowerShell 中更简单、更方便地使用命令补全。') 56 | g.AddLink("Section w" bw, '2. ...') 57 | 58 | tab.UseTab(0) 59 | btn := g.AddButton("Section w" w, "关闭") 60 | btn.Focus() 61 | btn.OnEvent("Click", e_close) 62 | e_close(*) { 63 | g.Destroy() 64 | } 65 | gc.w.aboutGui := g 66 | return g 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/menu/app-offset.ahk: -------------------------------------------------------------------------------- 1 | ; InputTip 2 | 3 | fn_app_offset(*) { 4 | fn_common({ 5 | gui: "appOffsetGui", 6 | config: "app_offset", 7 | tab: ["设置特殊偏移量", "关于"], 8 | tip: "你首先应该点击上方的「关于」查看具体的操作说明 ", 9 | list: "特殊偏移量列表", 10 | color: "cRed", 11 | about: '1. 如何使用这个配置菜单?`n`n - 上方的列表页显示的是当前系统正在运行的应用进程(仅前台窗口)`n - 为了便于操作,白名单中的应用进程也会添加到列表中`n - 双击列表中任意应用进程,就可以将其添加到「特殊偏移量列表」中`n - 如果需要更多的进程,请点击右下角的「显示更多进程」以显示后台和隐藏进程`n - 也可以点击右下角的「通过输入进程名称手动添加」直接添加进程名称`n`n - 下方是「特殊偏移量列表」,可以设置指定应用在不同屏幕下的符号显示偏移量`n - 双击列表中任意应用进程,会弹出偏移量设置窗口,或者点击窗口底部按钮移除它`n`n2. 如何设置偏移量?`n`n - 当双击任意应用进程后,会弹出偏移量设置窗口`n - 通过屏幕标识和坐标信息,判断是哪一块屏幕,然后设置对应的偏移量`n - 偏移量的修改实时生效,你可以立即在对应窗口中看到效果`n - 如何通过坐标信息判断屏幕?`n - 假设你有两块屏幕,主屏幕在左边,副屏幕在右边`n - 那么副屏幕的左上角 X 坐标一定大于或等于主屏幕的右下角 X 坐标', 12 | link: '相关链接: 关于特殊偏移量', 13 | addConfirm: "", 14 | addConfirm2: "", 15 | addConfirm3: "", 16 | addConfirm4: "如果此应用不在白名单中,则会同步添加到白名单中", 17 | rmConfirm: "", 18 | rmConfirm2: "", 19 | rmConfirm3: "", 20 | }, 21 | handleFn, addClickFn, rmClickFn, addFn 22 | ) 23 | handleFn(*) { 24 | gc.appOffsetGui_LV_rm_title.Text := "特殊偏移量列表 ( " gc.appOffsetGui_LV_rm.GetCount() " 个 )" 25 | writeIni("app_offset", "") 26 | global app_offset := {} 27 | restartJAB() 28 | } 29 | 30 | addClickFn(LV, RowNumber, tipList) { 31 | handleClick(LV, RowNumber, tipList, "add") 32 | } 33 | rmClickFn(LV, RowNumber, tipList) { 34 | handleClick(LV, RowNumber, tipList, "rm") 35 | } 36 | addFn(tipList) { 37 | addApp("xxx.exe") 38 | addApp(v) { 39 | if (gc.w.subGui) { 40 | gc.w.subGui.Destroy() 41 | gc.w.subGui := "" 42 | } 43 | createGui(addGui).Show() 44 | addGui(info) { 45 | g := createGuiOpt("InputTip - 设置特殊偏移量") 46 | text := "每次只能添加一个应用进程名称" 47 | if (useWhiteList) { 48 | text .= "`n如果它不在白名单中,则会同步添加到白名单中" 49 | } 50 | g.AddText("cRed", text) 51 | g.AddText("Section", "应用进程名称: ") 52 | 53 | if (info.i) { 54 | return g 55 | } 56 | w := info.w 57 | bw := w - g.MarginX * 2 58 | 59 | gc._exe_name := g.AddEdit("yp") 60 | gc._exe_name.Value := v 61 | g.AddButton("xs w" bw, "添加").OnEvent("Click", e_yes) 62 | e_yes(*) { 63 | exe_name := gc._exe_name.value 64 | g.Destroy() 65 | if (!RegExMatch(exe_name, "^.*\.\w{3}$") || RegExMatch(exe_name, '[\\/:*?\"<>|]')) { 66 | if (gc.w.subGui) { 67 | gc.w.subGui.Destroy() 68 | gc.w.subGui := "" 69 | } 70 | createGui(errGui).Show() 71 | errGui(info) { 72 | g := createGuiOpt("InputTip - 警告") 73 | g.AddText("cRed", exe_name) 74 | g.AddText("yp", "是一个错误的应用进程名称") 75 | g.AddText("xs cRed", '正确的应用进程名称是 xxx.exe 这样的格式`n同时文件名中不能包含这些英文符号 \ / : * ? " < >|') 76 | 77 | if (info.i) { 78 | return g 79 | } 80 | w := info.w 81 | bw := w - g.MarginX * 2 82 | 83 | y := g.AddButton("xs w" bw, "重新输入") 84 | y.Focus() 85 | y.OnEvent("click", e_close) 86 | e_close(*) { 87 | g.Destroy() 88 | addApp(exe_name) 89 | } 90 | gc.w.subGui := g 91 | return g 92 | } 93 | return 94 | } 95 | isExist := 0 96 | for v in app_offset.OwnProps() { 97 | if (v = exe_name) { 98 | isExist := 1 99 | break 100 | } 101 | } 102 | if (isExist) { 103 | if (gc.w.subGui) { 104 | gc.w.subGui.Destroy() 105 | gc.w.subGui := "" 106 | } 107 | createGui(existGui).Show() 108 | existGui(info) { 109 | g := createGuiOpt("InputTip - 警告") 110 | g.AddText("cRed", exe_name) 111 | g.AddText("yp", "这个应用进程已经存在了") 112 | 113 | if (info.i) { 114 | return g 115 | } 116 | w := info.w 117 | bw := w - g.MarginX * 2 118 | 119 | g.AddButton("xs w" bw, "重新输入").OnEvent("click", e_close) 120 | e_close(*) { 121 | g.Destroy() 122 | addApp(exe_name) 123 | } 124 | gc.w.subGui := g 125 | return g 126 | } 127 | } else { 128 | handleClick("", "", tipList, "input", exe_name) 129 | } 130 | } 131 | gc.w.subGui := g 132 | return g 133 | } 134 | } 135 | } 136 | 137 | handleClick(LV, RowNumber, tipList, action, app := "") { 138 | if (!RowNumber) { 139 | return 140 | } 141 | fn_write_offset() { 142 | try { 143 | gc.appOffsetGui_LV_rm_title.Text := "特殊偏移量列表 ( " gc.appOffsetGui_LV_rm.GetCount() " 个 )" 144 | } 145 | _app_offset := "" 146 | for v in app_offset.OwnProps() { 147 | _info := v "|" 148 | for s in app_offset.%v%.OwnProps() { 149 | _info .= s "/" app_offset.%v%.%s%.x "/" app_offset.%v%.%s%.y "*" 150 | } 151 | _app_offset .= ":" SubStr(_info, 1, StrLen(_info) - 1) 152 | } 153 | writeIni("app_offset", SubStr(_app_offset, 2)) 154 | restartJAB() 155 | } 156 | 157 | global app_offset 158 | screenList := getScreenInfo() 159 | if (action != "input") { 160 | app := LV.GetText(RowNumber) 161 | } 162 | if (action = "add" || action = "input") { 163 | isExist := 0 164 | for v in app_offset.OwnProps() { 165 | if (v = app) { 166 | isExist := 1 167 | break 168 | } 169 | } 170 | if (!isExist) { 171 | gc.appOffsetGui_LV_rm.Add(, app) 172 | autoHdrLV(gc.appOffsetGui_LV_rm) 173 | } 174 | if (action = "add") { 175 | LV.Delete(RowNumber) 176 | autoHdrLV(LV) 177 | } 178 | app_offset.%app% := {} 179 | for v in screenList { 180 | app_offset.%app%.%v.num% := { x: 0, y: 0 } 181 | } 182 | SetTimer(timer, -1) 183 | timer(*) { 184 | fn_write_offset() 185 | updateWhiteList(app) 186 | } 187 | } 188 | 189 | if (gc.w.offsetGui) { 190 | gc.w.offsetGui.Destroy() 191 | gc.w.offsetGui := "" 192 | } 193 | createGui(setOffsetGui).Show() 194 | setOffsetGui(info) { 195 | g := createGuiOpt("InputTip - 设置 " app " 的特殊偏移量") 196 | g.AddText(, "正在设置") 197 | g.AddText("yp cRed", app) 198 | g.AddText("yp", "的特殊偏移量") 199 | pages := [] 200 | for v in screenList { 201 | pages.push("屏幕 " v.num) 202 | } 203 | tab := g.AddTab3("xs -Wrap", pages) 204 | 205 | for v in screenList { 206 | tab.UseTab(v.num) 207 | if (v.num = v.main) { 208 | g.AddText(, "这是主屏幕(主显示器),屏幕标识: " v.num) 209 | } else { 210 | g.AddText(, "这是副屏幕(副显示器),屏幕标识: " v.num) 211 | } 212 | 213 | g.AddText(, "屏幕坐标信息(X,Y): 左上角(" v.left ", " v.top "),右下角(" v.right ", " v.bottom ")") 214 | 215 | x := 0, y := 0 216 | try { 217 | x := app_offset.%app%.%v.num%.x 218 | y := app_offset.%app%.%v.num%.y 219 | } catch { 220 | app_offset.%app%.%v.num% := { x: 0, y: 0 } 221 | } 222 | 223 | g.AddText("Section", "水平方向的偏移量: ") 224 | _ := g.AddEdit("yp") 225 | _.Value := x 226 | _.__num := v.num 227 | _.OnEvent("Change", e_change_offset_x) 228 | e_change_offset_x(item, *) { 229 | app_offset.%app%.%item.__num%.x := returnNumber(item.value) 230 | fn_write_offset() 231 | } 232 | g.AddText("xs", "垂直方向的偏移量: ") 233 | _ := g.AddEdit("yp") 234 | _.Value := y 235 | _.__num := v.num 236 | _.OnEvent("Change", e_change_offset_y) 237 | e_change_offset_y(item, *) { 238 | app_offset.%app%.%item.__num%.y := returnNumber(item.value) 239 | fn_write_offset() 240 | } 241 | } 242 | 243 | if (info.i) { 244 | return g 245 | } 246 | w := info.w 247 | bw := w - g.MarginX * 2 248 | 249 | tab.UseTab(0) 250 | if (action = "rm") { 251 | _ := g.AddButton("Section w" bw, "将它移除") 252 | _.OnEvent("Click", e_rm) 253 | e_rm(*) { 254 | close() 255 | exe_name := LV.GetText(RowNumber) 256 | LV.Delete(RowNumber) 257 | autoHdrLV(LV) 258 | try { 259 | gc.%tipList.gui "_LV_add"%.Add(, exe_name, WinGetTitle("ahk_exe " exe_name)) 260 | autoHdrLV(gc.%tipList.gui "_LV_add"%) 261 | } 262 | app_offset.DeleteProp(app) 263 | fn_write_offset() 264 | } 265 | } 266 | _ := g.AddButton("Section w" bw, "批量设置") 267 | _._exe_name := app 268 | _.OnEvent("Click", e_setAll) 269 | e_setAll(item, *) { 270 | close() 271 | createGui(setAllGui).Show() 272 | setAllGui(info) { 273 | offset := { x: 0, y: 0 } 274 | g := createGuiOpt("InputTip - 批量设置 " item._exe_name " 在多个屏幕的特殊偏移量") 275 | g.AddText("cRed", "如果偏移量为空,将自动设置为 0") 276 | 277 | if (info.i) { 278 | return g 279 | } 280 | 281 | g.AddText("Section", "水平方向的偏移量: ") 282 | _ := g.AddEdit("yp") 283 | _.Value := 0 284 | _._o := "x" 285 | _.OnEvent("Change", e_change_offset) 286 | 287 | g.AddText("xs", "垂直方向的偏移量: ") 288 | _ := g.AddEdit("yp") 289 | _.Value := 0 290 | _._o := "y" 291 | _.OnEvent("Change", e_change_offset) 292 | e_change_offset(item, *) { 293 | offset.%item._o% := item.value 294 | } 295 | g.AddText("xs cRed", "所有勾选的屏幕将使用上方的偏移量设置") 296 | 297 | flag := 0 298 | for i, v in screenList { 299 | opt := i = 1 ? "xs" : "yp" 300 | if (flag = 5) { 301 | opt := "xs" 302 | flag := 0 303 | } 304 | _ := g.AddCheckbox(opt " v" v.num, "屏幕 " v.num) 305 | _.Value := 1 306 | _._v_num := v.num 307 | _.OnEvent("Click", e_check) 308 | e_check(item, *) { 309 | offset.%item._v_num% := item.Value 310 | } 311 | flag++ 312 | } 313 | g.AddButton("xs w" w, "确认").OnEvent("Click", e_yes) 314 | e_yes(item, *) { 315 | info := g.Submit() 316 | for v in screenList { 317 | if (info.%v.num%) { 318 | app_offset.%app%.%v.num%.x := returnNumber(offset.x) 319 | app_offset.%app%.%v.num%.y := returnNumber(offset.y) 320 | } 321 | } 322 | fn_write_offset() 323 | } 324 | return g 325 | } 326 | } 327 | g.OnEvent("Close", close) 328 | close(*) { 329 | g.Destroy() 330 | } 331 | gc.w.offsetGui := g 332 | return g 333 | } 334 | } 335 | } 336 | -------------------------------------------------------------------------------- /src/menu/bw-list.ahk: -------------------------------------------------------------------------------- 1 | ; InputTip 2 | 3 | fn_bw_list(*) { 4 | if (gc.w.bwListGui) { 5 | gc.w.bwListGui.Destroy() 6 | gc.w.bwListGui := "" 7 | } 8 | createGui(bwListGui).Show() 9 | bwListGui(info) { 10 | g := createGuiOpt("InputTip - 设置符号显示的黑/白名单") 11 | g.AddText("cRed", "白名单机制: 只有在「白」名单中的应用进程窗口会尝试显示符号`n黑名单机制: 不在「黑」名单中的应用进程窗口都会尝试显示符号") 12 | g.AddLink("cGray", '如果使用 白名单机制,为了便于配置,InputTip 提供了同步添加机制`n当使用以下配置菜单时,添加的应用进程会同步添加到「白」名单中`n -「设置光标获取模式」`n -「设置特殊偏移量」`n -「指定窗口自动切换状态」') 13 | g.AddText(, "选择符号显示的名单机制: ") 14 | 15 | if (info.i) { 16 | return g 17 | } 18 | w := info.w 19 | bw := w - g.MarginX * 2 20 | 21 | gc._bw_list := g.AddDropDownList("yp AltSubmit Choose" useWhiteList + 1, ["使用「黑」名单", "使用「白」名单"]) 22 | gc._bw_list.OnEvent("Change", e_change_list) 23 | e_change_list(item, *) { 24 | if (useWhiteList = item.value) { 25 | if (gc.w.subGui) { 26 | gc.w.subGui.Destroy() 27 | gc.w.subGui := "" 28 | } 29 | createGui(warningGui).Show() 30 | warningGui(info) { 31 | gc._bw_list.Value := useWhiteList + 1 32 | _g := createGuiOpt("InputTip - 警告") 33 | _g.AddText(, "确定要使用「黑」名单吗?") 34 | _g.AddText("cRed", "和「白」名单相比,「黑」名单存在以下缺点`n1. 对电脑的性能消耗更高`n2. 需要你承担未知的可能存在的窗口兼容性代价") 35 | _g.AddLink("cGray", '详情请查看 为什么建议使用白名单机制') 36 | 37 | if (info.i) { 38 | return _g 39 | } 40 | w := info.w 41 | bw := w - _g.MarginX * 2 42 | 43 | _g.AddButton("w" bw, "【是】我确定要使用「黑」名单").OnEvent("Click", e_yes) 44 | _ := _g.AddButton("w" bw, "【否】不,我只是不小心点到了") 45 | _.OnEvent("Click", e_no) 46 | _.Focus() 47 | e_yes(*) { 48 | _g.Destroy() 49 | gc._bw_list.Value := 1 50 | writeIni("useWhiteList", 0) 51 | global useWhiteList := 0 52 | restartJAB() 53 | } 54 | e_no(*) { 55 | _g.Destroy() 56 | } 57 | gc.w.subGui := _g 58 | return _g 59 | } 60 | } else { 61 | value := item.value - 1 62 | writeIni("useWhiteList", value) 63 | global useWhiteList := value 64 | restartJAB() 65 | } 66 | } 67 | _c := g.AddButton("xs w" bw, "设置「白」名单") 68 | _c.Focus() 69 | _c.OnEvent("Click", set_white_list) 70 | set_white_list(*) { 71 | g.Destroy() 72 | fn_white_list() 73 | } 74 | g.AddButton("xs w" bw, "设置「黑」名单").OnEvent("Click", set_black_list) 75 | set_black_list(*) { 76 | g.Destroy() 77 | fn_common({ 78 | gui: "blackListGui", 79 | config: "app_hide_state", 80 | tab: ["设置黑名单", "关于"], 81 | tip: "你首先应该点击上方的「关于」查看具体的操作说明 ", 82 | list: "符号显示黑名单", 83 | color: "cRed", 84 | about: '1. 如何使用这个配置菜单?`n`n - 上方的列表页显示的是当前系统正在运行的应用进程(仅前台窗口)`n - 为了便于操作,白名单中的应用进程也会添加到列表中`n - 双击列表中任意应用进程,就可以将其添加到「符号显示黑名单」中`n - 如果需要更多的进程,请点击右下角的「显示更多进程」以显示后台和隐藏进程`n - 也可以点击右下角的「通过输入进程名称手动添加」直接添加进程名称`n`n - 下方是「符号显示黑名单」应用进程列表,如果使用黑名单机制,它将生效`n - 双击列表中任意应用进程,就可以将它移除`n`n - 黑名单机制: 只有不在黑名单中的应用进程窗口才会显示符号`n - 使用黑名单,可能会有一些特殊窗口的兼容性问题`n - 建议使用白名单机制,最好少用黑名单机制`n`n2. 如何快速添加应用进程?`n`n - 每次双击应用进程后,会弹出操作窗口,需要选择添加/移除或取消`n - 如果你确定当前操作不需要取消,可以在操作窗口弹出后,按下空格键快速确认', 85 | link: '相关链接: 白名单机制', 86 | addConfirm: "是否要将", 87 | addConfirm2: "添加到「符号显示黑名单」中?", 88 | addConfirm3: "添加后,黑名单机制下,在此应用窗口中时,不会显示符号", 89 | rmConfirm: "是否要将", 90 | rmConfirm2: "从「符号显示黑名单」中移除?", 91 | rmConfirm3: "移除后,黑名单机制下,在此应用窗口中时,会显示符号", 92 | }, 93 | fn 94 | ) 95 | fn(value) { 96 | global app_hide_state := ":" value ":" 97 | gc.blackListGui_LV_rm_title.Text := "符号显示黑名单 ( " gc.blackListGui_LV_rm.GetCount() " 个 )" 98 | restartJAB() 99 | } 100 | } 101 | gc.w.bwListGui := g 102 | return g 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/menu/check-update.ahk: -------------------------------------------------------------------------------- 1 | ; InputTip 2 | 3 | fn_check_update(*) { 4 | if (gc.w.checkUpdateGui) { 5 | gc.w.checkUpdateGui.Destroy() 6 | gc.w.checkUpdateGui := "" 7 | } 8 | gc.checkUpdateDelay := checkUpdateDelay 9 | 10 | createGui(checkUpdateGui).Show() 11 | checkUpdateGui(info) { 12 | g := createGuiOpt("InputTip - 设置更新检查") 13 | line := "--------------------------------------------------------------------------" 14 | tab := g.AddTab3("-Wrap", ["设置更新检查", "关于"]) 15 | tab.UseTab(1) 16 | g.AddText("Section cRed", "你首先应该点击上方的「关于」或官网查看相关的详细帮助说明") 17 | 18 | if (info.i) { 19 | g.AddText("cGray", "点击后,如果没有更新弹窗且不是网络问题,则当前是最新版本") 20 | return g 21 | } 22 | w := info.w 23 | bw := w - g.MarginX * 2 24 | 25 | g.AddText("xs", line) 26 | g.AddText(, "1. 每隔多少分钟检查一次版本更新: ") 27 | 28 | _ := g.AddEdit("yp Number Limit5") 29 | _.Value := readIni("checkUpdateDelay", 1440) 30 | _.Focus() 31 | _.OnEvent("Change", e_setIntervalTime) 32 | e_setIntervalTime(item, *) { 33 | value := item.value 34 | if (value != "") { 35 | if (value > 50000) { 36 | value := 50000 37 | } 38 | writeIni("checkUpdateDelay", value) 39 | global checkUpdateDelay := value 40 | if (checkUpdateDelay) { 41 | checkUpdate() 42 | } 43 | } 44 | } 45 | g.AddText("xs", "2. 是否启用自动静默更新: ") 46 | _ := g.AddDropDownList("yp", [" 禁用静默更新", " 启用静默更新"]) 47 | _.Value := readIni("silentUpdate", 0) + 1 48 | _.OnEvent("Change", e_setSilentUpdate) 49 | e_setSilentUpdate(item, *) { 50 | value := item.value - 1 51 | writeIni("silentUpdate", value) 52 | global silentUpdate := value 53 | } 54 | g.AddText("xs", line) 55 | g.AddButton("xs w" bw, "立即检查版本更新").OnEvent("Click", e_check_update) 56 | g.AddText("cGray", "点击后,如果没有更新弹窗且不是网络问题,则当前就是最新版本") 57 | e_check_update(*) { 58 | g.Destroy() 59 | checkUpdate(1, 1, 1, 0) 60 | } 61 | aboutText := '1. 关于「每隔多少分钟检查一次版本更新」`n - 单位: 分钟,默认 1440 分钟(1 天)`n - 避免程序错误,可以设置的最大范围是 0-50000 分钟`n - 如果为 0,则表示不检查版本更新`n - 如果不为 0,在 InputTip 启动时,会立即检查一次`n - 如果大于 50000,则生效的值是 50000`n`n2. 关于「是否启用自动静默更新」`n - 前提条件:「每隔多少分钟检查一次版本更新」的值不为 0`n - 启用后,不再弹出更新弹框,而是利用空闲时间自动更新`n - 空闲时间: 3 分钟内没有鼠标或键盘操作`n`n3. 关于「立即检查版本更新」`n - 点击这个按钮后,会立即检查一次版本更新`n - 如果没有更新弹窗且不是网络问题,则表示当前就是最新版本' 62 | lineN := "10" 63 | if (!A_IsCompiled) { 64 | g.AddButton("xs w" bw, "与源代码仓库同步").OnEvent("Click", e_get_update) 65 | g.AddText("cGray", "点击后,不检查版本,直接从源代码仓库中下载最新的源代码文件") 66 | e_get_update(*) { 67 | g.Destroy() 68 | getRepoCode(0, 0) 69 | } 70 | aboutText .= '`n`n4. 关于「与源代码仓库同步」`n - 点击这个按钮后,会从源代码仓库中下载最新的源代码文件`n - 不管是否有版本更新,都会下载最新的源代码文件' 71 | lineN := "13" 72 | } 73 | tab.UseTab(2) 74 | g.AddEdit("ReadOnly w" bw " r" lineN, aboutText) 75 | g.AddLink(, '相关链接: 关于更新检查') 76 | tab.UseTab(0) 77 | g.OnEvent("Close", e_close) 78 | e_close(*) { 79 | g.Destroy() 80 | if (gc.checkUpdateDelay = 0 && checkUpdateDelay != 0) { 81 | checkUpdate(1, 1) 82 | } 83 | } 84 | gc.w.checkUpdateGui := g 85 | return g 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/menu/cursor-mode.ahk: -------------------------------------------------------------------------------- 1 | ; InputTip 2 | 3 | fn_cursor_mode(*) { 4 | showGui() 5 | showGui(deep := "") { 6 | if (gc.w.cursorModeGui) { 7 | gc.w.cursorModeGui.Destroy() 8 | gc.w.cursorModeGui := "" 9 | try { 10 | gc.w.subGui.Destroy() 11 | gc.w.subGui := "" 12 | } 13 | } 14 | createGui(modeGui).Show() 15 | modeGui(info) { 16 | g := createGuiOpt("InputTip - 设置光标获取模式") 17 | tab := g.AddTab3("-Wrap", ["设置光标获取模式", "关于"]) 18 | tab.UseTab(1) 19 | g.AddText("Section cRed", "你首先应该点击上方的「关于」查看具体的操作说明 ") 20 | 21 | if (info.i) { 22 | return g 23 | } 24 | w := info.w 25 | bw := w - g.MarginX * 2 26 | 27 | gc.LV_add := g.AddListView("-LV0x10 -Multi r7 NoSortHdr Sort Grid w" w, ["应用进程列表", "窗口标题", "应用进程文件所在位置"]) 28 | gc.LV_add.OnEvent("DoubleClick", e_add) 29 | e_add(LV, RowNumber) { 30 | handleClick(LV, RowNumber, "add") 31 | } 32 | res := [] 33 | for v in modeNameList { 34 | res.Push(readIni("cursor_mode_" v, "")) 35 | } 36 | res := ":" arrJoin(res, ":") ":" 37 | temp := ":" 38 | DetectHiddenWindows deep 39 | gc.LV_add.Opt("-Redraw") 40 | for v in WinGetList() { 41 | try { 42 | exe_name := ProcessGetName(WinGetPID("ahk_id " v)) 43 | if (!InStr(temp, ":" exe_name ":") && !InStr(res, ":" exe_name ":")) { 44 | temp .= exe_name ":" 45 | gc.LV_add.Add(, exe_name, WinGetTitle("ahk_id " v), WinGetProcessPath("ahk_id " v)) 46 | } 47 | } 48 | } 49 | for v in StrSplit(readIni("app_show_state", ''), ":") { 50 | if (!InStr(temp, ":" v ":") && !InStr(res, ":" v ":")) { 51 | temp .= v ":" 52 | try { 53 | gc.LV_add.Add(, v, WinGetTitle("ahk_exe " v), WinGetProcessPath("ahk_exe " v)) 54 | } catch { 55 | gc.LV_add.Add(, v) 56 | } 57 | } 58 | } 59 | gc.LV_add.Opt("+Redraw") 60 | DetectHiddenWindows 1 61 | 62 | addItem(mode) { 63 | gc.%"LV_" mode%.Opt("-Redraw") 64 | valueArr := StrSplit(readIni("cursor_mode_" mode, ""), ":") 65 | temp := ":" 66 | for v in valueArr { 67 | if (Trim(v) && !InStr(temp, ":" v ":")) { 68 | gc.%"LV_" mode%.Add(, v) 69 | temp .= v ":" 70 | } 71 | } 72 | gc.%"LV_" mode%.Opt("+Redraw") 73 | gc.%mode "_title"%.Value .= " ( " gc.%"LV_" mode%.GetCount() " 个 )" 74 | autoHdrLV(gc.%"LV_" mode%) 75 | } 76 | 77 | for i, v in modeNameList { 78 | opt := i = 1 || i = 5 ? "xs" : "yp" 79 | if (i = 1) { 80 | for value in [1, 2, 3, 4] { 81 | o := value = 1 ? "xs" : "yp" 82 | item := modeNameList[value] 83 | gc.%item "_title"% := g.AddText(o " w" bw / 4, item) 84 | } 85 | } 86 | if (i = 5) { 87 | for value in [5, 6, 7, 8] { 88 | o := value = 5 ? "xs" : "yp" 89 | item := modeNameList[value] 90 | gc.%item "_title"% := g.AddText(o " w" bw / 4, item) 91 | } 92 | } 93 | gc.%"LV_" v% := g.AddListView(opt " cRed -Hdr -LV0x10 -Multi r5 NoSortHdr Sort Grid w" bw / 4, [v]) 94 | addItem(v) 95 | gc.%"LV_" v%.ModifyCol(1, "AutoHdr") 96 | gc.%"LV_" v%.OnEvent("DoubleClick", e_mode) 97 | gc.%"LV_" v%._mode := v 98 | e_mode(LV, RowNumber) { 99 | handleClick(LV, RowNumber, LV._mode) 100 | } 101 | } 102 | 103 | handleClick(LV, RowNumber, from) { 104 | if (!RowNumber) { 105 | return 106 | } 107 | exe_name := LV.GetText(RowNumber) 108 | if (gc.w.subGui) { 109 | gc.w.subGui.Destroy() 110 | gc.w.subGui := "" 111 | } 112 | createGui(addGui).Show() 113 | addGui(info) { 114 | _handle(to) { 115 | g.Destroy() 116 | gc.%"LV_" from%.Delete(RowNumber) 117 | autoHdrLV(gc.%"LV_" from%) 118 | if (from != "add") { 119 | v := gc.%from "_title"%.Value 120 | gc.%from "_title"%.Value := SubStr(v, 1, InStr(v, " ")) "( " gc.%"LV_" from%.GetCount() " 个 )" 121 | 122 | config := "cursor_mode_" from 123 | value := readIni(config, "") 124 | res := "" 125 | for v in StrSplit(value, ":") { 126 | if (Trim(v) && v != exe_name) { 127 | res .= ":" v 128 | } 129 | } 130 | writeIni(config, SubStr(res, 2)) 131 | } 132 | config := "cursor_mode_" to 133 | value := readIni(config, "") 134 | 135 | if (!InStr(":" value ":", ":" exe_name ":")) { 136 | gc.%"LV_" to%.Add(, exe_name) 137 | autoHdrLV(gc.%"LV_" to%) 138 | v := gc.%to "_title"%.Value 139 | gc.%to "_title"%.Value := SubStr(v, 1, InStr(v, " ")) "( " gc.%"LV_" to%.GetCount() " 个 )" 140 | if (value) { 141 | writeIni(config, value ":" exe_name) 142 | } else { 143 | writeIni(config, exe_name) 144 | } 145 | } 146 | updateWhiteList(exe_name) 147 | updateCursorMode(config != "cursor_mode_JAB") 148 | } 149 | g := createGuiOpt("InputTip - 添加") 150 | g.AddText(, "要将进程") 151 | g.AddText("yp cRed", exe_name) 152 | g.AddText("yp", "添加到哪一个光标获取模式中?") 153 | if (useWhiteList) { 154 | g.AddText("xs cRed", "如果此应用不在白名单中,则会同步添加到白名单中") 155 | } 156 | 157 | if (info.i) { 158 | return g 159 | } 160 | w := info.w 161 | bw := w - g.MarginX * 2 162 | 163 | for i, v in modeNameList { 164 | opt := i = 1 || i = 5 ? "xs" : "yp" 165 | if (v = from) { 166 | opt .= " Disabled" 167 | } 168 | _ := g.AddButton(opt " w" bw / 4, v) 169 | _._mode := v 170 | _.OnEvent("Click", e_mode) 171 | e_mode(item, *) { 172 | _handle(item._mode) 173 | } 174 | } 175 | if (from != "add") { 176 | g.AddButton("xs w" w, "将它移除").OnEvent("Click", e_rm) 177 | e_rm(*) { 178 | g.Destroy() 179 | LV.Delete(RowNumber) 180 | autoHdrLV(LV) 181 | v := gc.%from "_title"%.Value 182 | gc.%from "_title"%.Value := SubStr(v, 1, InStr(v, " ")) "( " gc.%"LV_" from%.GetCount() " 个 )" 183 | try { 184 | gc.LV_add.Add(, exe_name, WinGetTitle("ahk_exe " exe_name)) 185 | autoHdrLV(gc.LV_add) 186 | } 187 | config := "cursor_mode_" from 188 | value := readIni(config, "") 189 | result := "" 190 | for v in StrSplit(value, ":") { 191 | if (Trim(v) && v != exe_name) { 192 | result .= ":" v 193 | } 194 | } 195 | writeIni(config, SubStr(result, 2)) 196 | updateCursorMode(config != "cursor_mode_JAB") 197 | } 198 | } 199 | 200 | g.AddButton("xs w" w, "取消操作").OnEvent("Click", e_no) 201 | e_no(*) { 202 | g.Destroy() 203 | } 204 | gc.w.subGui := g 205 | return g 206 | } 207 | } 208 | 209 | g.AddButton("xs w" w / 3, "刷新此界面").OnEvent("Click", e_refresh) 210 | e_refresh(*) { 211 | fn_close() 212 | showGui(deep) 213 | } 214 | 215 | g.AddButton("yp w" w / 3, "通过输入进程名称手动添加").OnEvent("Click", e_add_by_hand) 216 | e_add_by_hand(*) { 217 | addApp("xxx.exe") 218 | addApp(v) { 219 | if (gc.w.subGui) { 220 | gc.w.subGui.Destroy() 221 | gc.w.subGui := "" 222 | } 223 | createGui(addGui).Show() 224 | addGui(info) { 225 | g := createGuiOpt("InputTip - 设置光标获取模式") 226 | text := "每次只能添加一个应用进程名称" 227 | if (useWhiteList) { 228 | text .= "`n如果它不在白名单中,则会同步添加到白名单中 " 229 | } 230 | g.AddText("cRed", text) 231 | g.AddText("Section", "应用进程名称: ") 232 | gc._exe_name := g.AddEdit("yp", "") 233 | gc._exe_name.Value := v 234 | g.AddText("xs cGray", "你想要将它添加到哪一个光标获取模式中?") 235 | 236 | if (info.i) { 237 | return g 238 | } 239 | w := info.w 240 | bw := w - g.MarginX * 2 241 | 242 | for i, v in modeNameList { 243 | opt := i = 1 || i = 5 ? "xs" : "yp" 244 | _ := g.AddButton(opt " w" bw / 4, v) 245 | _._mode := v 246 | _.OnEvent("Click", e_handle) 247 | } 248 | e_handle(item, *) { 249 | to := item._mode 250 | exe_name := gc._exe_name.value 251 | g.Destroy() 252 | if (!RegExMatch(exe_name, "^.*\.\w{3}$") || RegExMatch(exe_name, '[\\/:*?\"<>|]')) { 253 | if (gc.w.subGui) { 254 | gc.w.subGui.Destroy() 255 | gc.w.subGui := "" 256 | } 257 | createGui(errGui).Show() 258 | errGui(info) { 259 | g := createGuiOpt("InputTip - 警告") 260 | g.AddText("cRed", exe_name) 261 | g.AddText("yp", "是一个错误的应用进程名称") 262 | g.AddText("xs cRed", '正确的应用进程名称是 xxx.exe 这样的格式`n同时文件名中不能包含这些英文符号 \ / : * ? " < >|') 263 | 264 | if (info.i) { 265 | return g 266 | } 267 | w := info.w 268 | bw := w - g.MarginX * 2 269 | 270 | y := g.AddButton("xs w" bw, "重新输入") 271 | y.Focus() 272 | y.OnEvent("click", e_close) 273 | e_close(*) { 274 | g.Destroy() 275 | addApp(exe_name) 276 | } 277 | gc.w.subGui := g 278 | return g 279 | } 280 | return 281 | } 282 | 283 | config := "cursor_mode_" to 284 | value := readIni(config, "") 285 | 286 | if (InStr(":" value ":", ":" exe_name ":")) { 287 | if (gc.w.subGui) { 288 | gc.w.subGui.Destroy() 289 | gc.w.subGui := "" 290 | } 291 | createGui(existGui).Show() 292 | existGui(info) { 293 | g := createGuiOpt("InputTip - 警告") 294 | g.AddText("cRed", exe_name) 295 | g.AddText("yp", "这个应用进程已经存在了") 296 | 297 | if (info.i) { 298 | return g 299 | } 300 | w := info.w 301 | bw := w - g.MarginX * 2 302 | 303 | g.AddButton("xs w" bw, "重新输入").OnEvent("click", e_close) 304 | e_close(*) { 305 | g.Destroy() 306 | addApp(exe_name) 307 | } 308 | gc.w.subGui := g 309 | return g 310 | } 311 | return 312 | } 313 | 314 | gc.%"LV_" to%.Add(, exe_name) 315 | autoHdrLV(gc.%"LV_" to%) 316 | v := gc.%to "_title"%.Value 317 | gc.%to "_title"%.Value := SubStr(v, 1, InStr(v, " ")) "( " gc.%"LV_" to%.GetCount() " 个 )" 318 | if (value) { 319 | writeIni(config, value ":" exe_name) 320 | } else { 321 | writeIni(config, exe_name) 322 | } 323 | updateWhiteList(exe_name) 324 | updateCursorMode(config != "cursor_mode_JAB") 325 | } 326 | gc.w.subGui := g 327 | return g 328 | } 329 | } 330 | } 331 | if (deep) { 332 | g.AddButton("yp w" w / 3, "显示更少进程(仅前台窗口)").OnEvent("Click", e_less_window) 333 | e_less_window(*) { 334 | fn_close() 335 | showGui("") 336 | } 337 | } else { 338 | g.AddButton("yp w" w / 3, "显示更多进程(后台窗口)").OnEvent("Click", e_more_window) 339 | e_more_window(*) { 340 | fn_close() 341 | showGui(1) 342 | } 343 | } 344 | autoHdrLV(gc.LV_add) 345 | tab.UseTab(2) 346 | g.AddEdit("ReadOnly -VScroll w" w, '1. 如何使用这个配置菜单?`n`n - 上方的列表页显示的是当前系统正在运行的应用进程(仅前台窗口)`n - 为了便于操作,白名单中的应用进程也会添加到列表中`n - 双击列表中任意应用进程,就可以将其添加到下方任意列表中`n - 如果需要更多的进程,请点击下方的「显示更多进程」以显示后台和隐藏进程`n - 也可以点击下方的「通过输入进程名称手动添加」直接添加进程名称`n`n - 下方分别是 InputTip 的多种光标获取模式`n - 不用在意这些模式是啥,只要记住,哪个能用,就用哪个即可`n - 如果想了解相关内容,请查看下方相关链接`n - 这几个模式列表中的应用进程会使用对应的模式尝试去获取光标位置`n - 双击列表中任意应用进程,就可以将它移除或者添加到其他列表中`n - 白名单机制下,选择添加且此应用不在白名单中,则会同步添加到白名单中`n`n2. 什么时候需要去添加?`n`n - 当你发现一个应用窗口,无法获取到光标位置,或者有兼容性问题时`n - 就可以尝试将其添加到下方的各个列表中,看哪个模式是可用的且无兼容性问题的`n - 如果所有模式都不可用,则表示在此窗口中获取不到光标位置,暂时无法解决`n - 如果已知都不可用,记得移除这个应用进程`n - 此时,可以尝试使用「设置符号显示位置」这个配置菜单,让符号显示在鼠标附近`n`n3. JetBrains 系列 IDE`n`n - JetBrains 系列 IDE 需要添加到「JAB」列表中`n - 如果未生效,请检查是否完成「启用 JAB/JetBrains IDE 支持」中的所有操作步骤') 347 | g.AddLink(, '相关链接: 关于光标获取模式') 348 | g.OnEvent("Close", fn_close) 349 | fn_close(*) { 350 | g.Destroy() 351 | try { 352 | gc.w.subGui.Destroy() 353 | gc.w.subGui := "" 354 | } 355 | } 356 | gc.w.cursorModeGui := g 357 | return g 358 | } 359 | } 360 | } 361 | -------------------------------------------------------------------------------- /src/menu/input-mode.ahk: -------------------------------------------------------------------------------- 1 | ; InputTip 2 | 3 | fn_input_mode(*) { 4 | if (gc.w.inputModeGui) { 5 | gc.w.inputModeGui.Destroy() 6 | gc.w.inputModeGui := "" 7 | try { 8 | gc.w.customModeGui.Destroy() 9 | gc.w.customModeGui := "" 10 | } 11 | try { 12 | gc.w.shiftSwitchGui.Destroy() 13 | gc.w.shiftSwitchGui := "" 14 | } 15 | } 16 | createGui(inputModeGui).Show() 17 | inputModeGui(info) { 18 | global mode := readIni("mode", 1, "InputMethod") 19 | 20 | g := createGuiOpt("InputTip - 设置输入法模式") 21 | gc.modeList := ["【自定义】", "【通用】"] 22 | tab := g.AddTab3("-Wrap", ["基础配置", "自定义", "关于自定义", "关于切换输入法状态"]) 23 | tab.UseTab(1) 24 | g.AddText("Section cRed", "如果【通用】模式不可用,需要点击上方的「自定义」标签页去配置【自定义】模式") 25 | 26 | if (info.i) { 27 | return g 28 | } 29 | w := info.w 30 | bw := w - g.MarginX * 2 31 | 32 | g.AddText(, "1. 当前使用的输入法模式:") 33 | gc.mode := g.AddText("yp cRed w" w / 2) 34 | gc.mode.Value := gc.modeList[mode + 1] 35 | g.AddEdit("xs ReadOnly cGray w" w, "输入法模式只有【通用】和【自定义】,这里显示的模式会根据实际的配置情况自动变化") 36 | g.AddText("xs", "2. 设置获取输入法状态的超时时间: ") 37 | timeout := g.AddEdit("yp Number Limit5") 38 | timeout.Focus() 39 | timeout.OnEvent("Change", e_setTimeout) 40 | e_setTimeout(item, *) { 41 | value := item.value 42 | if (value = "") { 43 | return 44 | } 45 | writeIni("checkTimeout", value, "InputMethod") 46 | global checkTimeout := value 47 | restartJAB() 48 | } 49 | timeout.Value := checkTimeout 50 | g.AddEdit("xs ReadOnly cGray -VScroll w" w, "单位:毫秒,默认 500 毫秒`n每次切换输入法状态,InputTip 会从系统获取新的输入法状态`n如果超过了这个时间,则认为获取失败,直接判断为英文状态`n它可能是有时识别不到输入法状态的原因,遇到问题可以尝试调节它") 51 | g.AddText("xs", "3. 指定内部实现切换输入法状态的方式: ") 52 | gc.switchStatus := g.AddDropDownList("yp Choose" switchStatus + 1, ["内部调用 DLL", "模拟输入 LShift", "模拟输入 RShift", "模拟输入 Ctrl+Space"]) 53 | gc.switchStatus.OnEvent("Change", e_switchStatus) 54 | e_switchStatus(item, *) { 55 | value := item.value - 1 56 | writeIni("switchStatus", value) 57 | global switchStatus := value 58 | restartJAB() 59 | } 60 | g.AddEdit("xs ReadOnly cGray -VScroll w" w, "如果想修改这个配置,需要先通过上方的「关于切换输入法状态」标签页了解详情") 61 | tab.UseTab(2) 62 | 63 | g.AddText("Section ReadOnly cRed -VScroll w" w, "首先需要点击上方的「关于自定义」标签页,查看帮助说明,了解如何设置") 64 | g.AddText("xs cGray", "如果添加了至少一条规则,则自动变为【自定义】模式,反之变回【通用】模式") 65 | 66 | g.AddText("Section", "如果所有规则都不匹配,应该判断为: ") 67 | g.AddDropDownList("yp Choose" baseStatus + 1, [" 英文状态", " 中文状态"]).OnEvent("Change", e_changeBaseStatus) 68 | e_changeBaseStatus(item, *) { 69 | value := item.Value - 1 70 | writeIni("baseStatus", value, "InputMethod") 71 | global baseStatus := value 72 | } 73 | 74 | gc.input_mode_LV := _ := g.AddListView("xs -LV0x10 -Multi r4 NoSortHdr Grid w" w, ["匹配的顺序", "状态码规则", "切换码规则", "输入法状态"]) 75 | fn_reloading_LV(_) 76 | 77 | _.OnEvent("DoubleClick", e_edit) 78 | e_edit(LV, RowNumber) { 79 | fn_edit(LV, RowNumber) 80 | } 81 | 82 | g.AddButton("xs w" w, "添加规则").OnEvent("Click", e_addRule) 83 | e_addRule(*) { 84 | fn_edit(gc.input_mode_LV, modeRules.Length + 1, 1) 85 | } 86 | 87 | fn_edit(LV, RowNumber, add := 0) { 88 | if (!RowNumber) { 89 | return 90 | } 91 | if (add) { 92 | ruleInfo := { 93 | statusRule: "", 94 | conversionRule: "", 95 | status: !baseStatus, 96 | } 97 | typeText := "添加" 98 | } else { 99 | rule := modeRules[RowNumber] 100 | r := StrSplit(rule, "*") 101 | 102 | ruleInfo := { 103 | statusRule: r[1], 104 | conversionRule: r[2], 105 | status: r[3], 106 | } 107 | typeText := "编辑" 108 | } 109 | 110 | createGui(editRuleGui).Show() 111 | editRuleGui(info) { 112 | g := createGuiOpt("InputTip - " typeText "规则") 113 | 114 | _gc := { 115 | statusNum: "", 116 | statusRule: "", 117 | conversionNum: "", 118 | conversionRule: "", 119 | order: RowNumber, 120 | } 121 | 122 | g.AddText(, "1. 匹配的顺序: ") 123 | 124 | num := 1 125 | list := [] 126 | while (num <= modeRules.Length + add) { 127 | list.Push(" " num) 128 | num++ 129 | } 130 | _ := g.AddDropDownList("yp r9", list) 131 | _.Value := _gc.order 132 | _.OnEvent("Change", e_changeOrder) 133 | e_changeOrder(item, *) { 134 | _gc.order := Trim(item.Value) 135 | } 136 | 137 | g.AddText("xs", "2. 输入法状态: ") 138 | _ := g.AddDropDownList("yp", ["英文", "中文"]) 139 | _.value := ruleInfo.status + 1 140 | _.OnEvent("Change", e_changeStatus) 141 | e_changeStatus(item, *) { 142 | v := item.Value 143 | ruleInfo.status := v - 1 144 | } 145 | 146 | g.AddText("xs", "3. 状态码规则: ") 147 | g.AddText("xs", " - 指定数字: ") 148 | 149 | _gc.statusNum := _ := g.AddEdit("yp", "") 150 | 151 | if (info.i) { 152 | return g 153 | } 154 | w := info.w 155 | bw := w - g.MarginX * 2 156 | 157 | if (!InStr(ruleInfo.statusRule, "oddNum") && !InStr(ruleInfo.statusRule, "evenNum")) { 158 | _.Value := ruleInfo.statusRule 159 | } 160 | _.OnEvent("Change", e_statusMode) 161 | e_statusMode(item, *) { 162 | ruleInfo.statusRule := item.value 163 | _gc.statusRule.value := 0 164 | } 165 | 166 | g.AddText("xs", " - 指定规律: ") 167 | 168 | _gc.statusRule := _ := g.AddDropDownList("yp", ["", "使用奇数", "使用偶数"]) 169 | if (ruleInfo.statusRule == "oddNum") { 170 | _.Value := 2 171 | } else if (ruleInfo.statusRule == "evenNum") { 172 | _.Value := 3 173 | } 174 | _.OnEvent("Change", e_statusRule) 175 | e_statusRule(item, *) { 176 | v := item.Value 177 | if (v == 2) { 178 | ruleInfo.statusRule := "oddNum" 179 | } else if (v == 3) { 180 | ruleInfo.statusRule := "evenNum" 181 | } else { 182 | ruleInfo.statusRule := "" 183 | } 184 | _gc.statusNum.value := "" 185 | } 186 | 187 | g.addText("xs", "4. 切换码规则: ") 188 | g.AddText("xs", " - 指定数字: ") 189 | _gc.conversionNum := _ := g.AddEdit("yp", "") 190 | if (!InStr(ruleInfo.conversionRule, "oddNum") && !InStr(ruleInfo.conversionRule, "evenNum")) { 191 | _.Value := ruleInfo.conversionRule 192 | } 193 | _.OnEvent("Change", e_conversionMode) 194 | e_conversionMode(item, *) { 195 | ruleInfo.conversionRule := item.value 196 | _gc.conversionRule.value := 0 197 | } 198 | 199 | g.AddText("xs", " - 指定规律: ") 200 | _gc.conversionRule := _ := g.AddDropDownList("yp", ["", "使用奇数", "使用偶数"]) 201 | if (ruleInfo.conversionRule == "oddNum") { 202 | _.Value := 2 203 | } else if (ruleInfo.conversionRule == "evenNum") { 204 | _.Value := 3 205 | } 206 | _.OnEvent("Change", e_conversionRule) 207 | e_conversionRule(item, *) { 208 | v := item.Value 209 | if (v == 2) { 210 | ruleInfo.conversionRule := "oddNum" 211 | } else if (v == 3) { 212 | ruleInfo.conversionRule := "evenNum" 213 | } else { 214 | ruleInfo.conversionRule := "" 215 | } 216 | _gc.conversionNum.value := "" 217 | } 218 | 219 | g.AddButton("xs w" bw, "完成" typeText).OnEvent("Click", e_set) 220 | e_set(*) { 221 | g.Destroy() 222 | 223 | ; 状态码 224 | sm := ruleInfo.statusRule 225 | ; 切换码 226 | cm := ruleInfo.conversionRule 227 | ; 输入法状态 228 | status := ruleInfo.status 229 | 230 | if (add) { 231 | modeRules.InsertAt(_gc.order, sm "*" cm "*" status) 232 | } else { 233 | if (_gc.order != RowNumber) { 234 | modeRules.RemoveAt(RowNumber) 235 | modeRules.InsertAt(_gc.order, sm "*" cm "*" status) 236 | } else { 237 | modeRules[RowNumber] := sm "*" cm "*" status 238 | } 239 | } 240 | 241 | global modeRule := arrJoin(modeRules, ":") 242 | writeIni("modeRule", modeRule, "InputMethod") 243 | if (modeRules.Length) { 244 | global mode := 0 245 | writeIni("mode", 0, "InputMethod") 246 | gc.mode.Value := gc.modeList[1] 247 | } 248 | 249 | fn_reloading_LV(LV) 250 | } 251 | if (!add) { 252 | g.AddButton("xs w" bw, "删除此条规则").OnEvent("Click", e_del) 253 | e_del(*) { 254 | g.Destroy() 255 | LV.Delete(RowNumber) 256 | autoHdrLV(LV) 257 | modeRules.RemoveAt(RowNumber) 258 | if (!modeRules.Length) { 259 | global mode := 1 260 | writeIni("mode", 1, "InputMethod") 261 | gc.mode.Value := gc.modeList[2] 262 | } 263 | global modeRule := arrJoin(modeRules, ":") 264 | writeIni("modeRule", modeRule, "InputMethod") 265 | fn_reloading_LV(LV) 266 | } 267 | } 268 | 269 | return g 270 | } 271 | } 272 | 273 | fn_reloading_LV(LV) { 274 | LV.Delete() 275 | LV.Opt("-Redraw") 276 | 277 | for i, v in modeRules { 278 | r := StrSplit(v, "*") 279 | LV.Add(, i, generateCol(r*)*) 280 | } 281 | LV.Opt("+Redraw") 282 | autoHdrLV(LV) 283 | } 284 | 285 | /** 286 | * 生成列信息 287 | * @param sm 状态码 288 | * @param cm 切换码 289 | * @param status 输入法状态 290 | * @returns {Array} 列信息 291 | */ 292 | generateCol(sm, cm, status) { 293 | colList := [] 294 | colList.Push(sm == "oddNum" ? "奇数" : sm == "evenNum" ? "偶数" : sm) 295 | colList.Push(cm == "oddNum" ? "奇数" : cm == "evenNum" ? "偶数" : cm) 296 | colList.Push(status ? "中文" : "英文") 297 | return colList 298 | } 299 | 300 | gc.status_btn := g.AddButton("xs w" w, "显示实时的状态码和切换码(双击设置快捷键)") 301 | gc.status_btn.OnEvent("Click", showCode) 302 | gc.status_btn.OnEvent("DoubleClick", showCodeHotkey) 303 | showCodeHotkey(*) { 304 | gc.status_btn.Text := "显示实时的状态码和切换码(双击设置快捷键)" 305 | gc.timer := 0 306 | 307 | setHotKeyGui([{ 308 | config: "hotkey_ShowCode", 309 | tip: "显示实时的状态码和切换码" 310 | }], "显示实时的状态码和切换码") 311 | } 312 | 313 | tab.UseTab(3) 314 | g.AddText("cRed", "使用【自定义】模式之前,务必仔细阅读下方的帮助说明,查看相关链接") 315 | g.AddEdit("Section r12 ReadOnly w" w, "1. 为什么需要【自定义】模式`n - InputTip 是通过系统返回的状态码和切换码来判断当前的输入法状态的`n - 对于多数常用的输入法来说【通用】模式是可以正常识别的`n - 但是部分输入法会使系统返回的状态码和切换码很特殊,无法统一处理`n - 在这种情况下,就需要用户通过规则来告诉 InputTip 当前的输入法状态`n`n2. 【自定义】模式的工作机制`n - InputTip 会从系统获取到当前的状态码和切换码,通过定义的规则列表进行顺序匹配`n - 每一条规则对应一种输入法状态,如果匹配成功,则判断为此状态`n - 因此,如果你同时使用多个输入法,可以尝试通过【自定义】模式实现兼容`n`n3. 默认状态`n -「如果所有规则都不匹配,应该判断为」这个配置项会指定一个默认状态`n - 如果规则列表中的所有规则都没有匹配成功,就会使用这个默认状态`n`n4. 规则列表`n - 规则列表就是上方的「自定义」标签页中的表格`n - 添加规则: 点击「添加规则」按钮,在弹窗中进行规则设置`n - 修改规则: 双击规则列表中已经存在的任意一条规则,在弹窗中进行规则修改`n - 删除规则: 双击规则列表中已经存在的任意一条规则,在弹窗中点击「删除此条规则」`n`n5. 规则设置`n - 点击「显示实时的状态码和切换码」,通过切换输入法状态,查看不同状态下的区别`n - 当点击「添加规则」按钮后,会出现一个规则设置弹窗`n - 弹窗中包含 4 个设置: 匹配的顺序、输入法状态、状态码规则、切换码规则`n - 匹配的顺序:用来指定这一条规则在规则列表中的顺序`n - 其余 3 个设置会在下方逐个解释`n`n6. 规则设置 —— 输入法状态`n - 它用来指定这一条规则对应的输入法状态`n - 当这一条规则匹配成功后,InputTip 就会认为当前输入法状态为这一状态`n`n7. 规则设置 —— 状态码规则、切换码规则`n - 有两种形式可以选择: 指定数字或指定规律`n - 这两种形式只能选择其中一种,它们会在下方进行详细解释`n - 需要注意的是,你可以同时设置状态码规则和切换码规则`n - 如果同时设置,则表示此条规则需要状态码规则和切换码规则都匹配`n`n8. 规则设置 —— 指定数字`n - 你可以填入一个或多个数字,只要其中有一个数字匹配成功即可`n - 如果是多个数字,需要使用 / 连接 (如: 1/3/5)`n - 如: 你希望当状态码为 1 时匹配到这条规则,在「状态码规则」中填入 1 即可`n - 如: 你希望当切换码为 1 或 3 时匹配到这条规则,在「切换码规则」中填入 1/3 即可`n`n9. 规则设置 —— 指定规律`n - 由于部分输入法会使系统返回的状态码和切换码很特殊,呈现某种规律`n - 比如随机奇数,这种情况无法通过指定数字来表示,因为不可能填入所有的奇数`n - 对于这种情况,就可以通过指定规律来实现,在下拉列表中选择对应规律即可`n - 如: 你希望当状态码为随机奇数时匹配到这条规则,选择「使用奇数」即可") 316 | g.AddLink(, '相关链接: 自定义模式 输入法兼容情况') 317 | 318 | tab.UseTab(4) 319 | g.AddEdit("Section r13 ReadOnly w" w, "1. 「指定内部实现切换输入法状态的方式」`n - InputTip 中的以下功能需要 InputTip 来切换输入法状态`n -「设置状态切换快捷键」`n -「指定窗口自动切换状态」`n - 比如通过「设置状态切换快捷键」设置了 LShift 来切换英文状态`n - LShift 就是键盘左侧的 Shift 键,以此类推`n - 当按下 LShift 后,如果当前状态不是英文,就需要 InputTip 自动切换输入法状态`n - 配置项有 3 个可选值,你需要根据实际情况,选择合适的方式`n - 模拟输入 LShift`n - 模拟输入 RShift`n - 内部调用 DLL`n`n2. 可选值 —— 模拟输入 LShift`n - 当需要切换输入法状态时,InputTip 会模拟输入一个 LShift 键`n - 这相当于 InputTip 帮你按了一次键盘左侧的 Shift 键`n - 只要使用的输入法可以通过左侧的 Shift 键切换输入法状态,就应该使用它`n`n3. 可选值 —— 模拟输入 RShift`n - 当需要切换输入法状态时,InputTip 会模拟输入一个 RShift 键`n - 这相当于 InputTip 帮你按了一次键盘右侧的 Shift 键`n - 只要使用的输入法可以通过右侧的 Shift 键切换输入法状态,就应该使用它`n`n4. 可选值 —— 内部调用 DLL`n - 当需要切换输入法状态时,InputTip 会直接调用 DLL 接口去设置输入法状态`n - 这种方式是一种强行设置行为,可能会导致以下问题,不建议使用`n - 对于部分输入法可能无效`n - 当需要设置为中文状态时,没有中文状态的键盘(如: 美式键盘),也会被强行设置`n - 这会导致基于此的鼠标样式和符号出现暂时的显示错误") 320 | g.AddLink(, '相关链接: 输入法兼容情况') 321 | g.OnEvent("Close", e_close) 322 | e_close(*) { 323 | g.Destroy() 324 | gc.timer := 0 325 | try { 326 | gc.w.customModeGui.Destroy() 327 | gc.w.customModeGui := "" 328 | } 329 | try { 330 | gc.w.shiftSwitchGui.Destroy() 331 | gc.w.shiftSwitchGui := "" 332 | } 333 | } 334 | gc.w.inputModeGui := g 335 | return g 336 | } 337 | } 338 | -------------------------------------------------------------------------------- /src/menu/startup.ahk: -------------------------------------------------------------------------------- 1 | ; InputTip 2 | 3 | fn_startup(item, *) { 4 | ; 注册表: 开机自启动 5 | HKEY_startup := "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run" 6 | 7 | global isStartUp 8 | if (isStartUp) { 9 | if (gc.w.updateUserGui) { 10 | gc.w.updateUserGui.Destroy() 11 | gc.w.updateUserGui := "" 12 | } 13 | if (gc.w.subGui) { 14 | gc.w.subGui.Destroy() 15 | gc.w.subGui := "" 16 | } 17 | if (isStartUp != 2 && !A_IsAdmin) { 18 | createTipGui([{ 19 | opt: "cRed", 20 | text: "你需要以管理员权限运行来取消「开机自启动」`n设置: 「托盘菜单」=>「以管理员权限启动」", 21 | }], "InputTip - 错误").Show() 22 | 23 | return 24 | } 25 | 26 | try { 27 | FileDelete(A_Startup "/" fileLnk) 28 | } 29 | try { 30 | RegDelete(HKEY_startup, "abgox - " A_ScriptName) 31 | } 32 | try { 33 | Run('schtasks /delete /tn "abgox.InputTip.noUAC" /f', , "Hide") 34 | } 35 | 36 | A_TrayMenu.Uncheck(item) 37 | isStartUp := 0 38 | writeIni("isStartUp", isStartUp) 39 | 40 | if (gc.w.startupGui) { 41 | gc.w.startupGui.Destroy() 42 | gc.w.startupGui := "" 43 | } 44 | createGui(cancelGui).Show() 45 | cancelGui(info) { 46 | g := createGuiOpt("InputTip - 取消开机自启动") 47 | g.AddText(, "InputTip 的") 48 | g.AddText("yp cRed", "开机自启动") 49 | g.AddText("yp", "已取消") 50 | g.AddText("xs", "可通过「托盘菜单」=>「开机自启动」再次启用") 51 | 52 | if (info.i) { 53 | return g 54 | } 55 | w := info.w 56 | bw := w - g.MarginX * 2 57 | 58 | y := g.AddButton("w" w, "我知道了") 59 | y.Focus() 60 | y.OnEvent("Click", e_yes) 61 | e_yes(*) { 62 | g.Destroy() 63 | } 64 | gc.w.startupGui := g 65 | return g 66 | } 67 | } else { 68 | if (gc.w.startupGui) { 69 | gc.w.startupGui.Destroy() 70 | gc.w.startupGui := "" 71 | } 72 | createGui(startupGui).Show() 73 | startupGui(info) { 74 | g := createGuiOpt("InputTip - 设置开机自启动") 75 | tab := g.AddTab3("-Wrap", ["设置开机自启动", "关于"]) 76 | tab.UseTab(1) 77 | g.AddText("Section cRed", "你首先应该点击上方的「关于」或官网查看相关的详细帮助说明") 78 | g.AddText("xs cRed", "如果移动了软件所在位置,需要重新设置才有效`n") 79 | 80 | if (info.i) { 81 | return g 82 | } 83 | w := info.w 84 | bw := w - g.MarginX * 2 85 | 86 | if (A_IsAdmin) { 87 | btnOpt := '' 88 | tip := "推荐:「任务计划程序」>「注册表」>「应用快捷方式」`n由于权限或系统限制等因素,「应用快捷方式」可能无效" 89 | } else { 90 | btnOpt := ' Disabled ' 91 | tip := "当前不是以管理员权限运行,「任务计划程序」和「注册表」禁用`n你可以使用「托盘菜单」=>「以管理员权限启动」来使它们可用" 92 | } 93 | 94 | btn := g.AddButton("Section w" bw btnOpt, "「任务计划程序」") 95 | 96 | btn.Focus() 97 | btn.OnEvent("Click", e_useTask) 98 | e_useTask(*) { 99 | if (A_IsCompiled) { 100 | flag := createScheduleTask(A_ScriptFullPath, "abgox.InputTip.noUAC", [0], , , 1) 101 | } else { 102 | flag := createScheduleTask(A_AhkPath, "abgox.InputTip.noUAC", [A_ScriptFullPath, 0], , , 1) 103 | } 104 | 105 | if (flag) { 106 | fn_update_user(A_UserName) 107 | isStartUp := 1 108 | ; FileCreateShortcut("C:\WINDOWS\system32\schtasks.exe", A_Startup "\" fileLnk, , "/run /tn `"abgox.InputTip.noUAC`"", fileDesc, favicon, , , 7) 109 | fn_handle() 110 | } else { 111 | fn_err_msg("添加任务计划程序失败!") 112 | } 113 | } 114 | g.AddButton("xs w" bw btnOpt, "「注册表」").OnEvent("Click", e_useReg) 115 | e_useReg(*) { 116 | isStartUp := 3 117 | try { 118 | v := A_IsCompiled ? A_ScriptFullPath : '"' A_AhkPath '" "' A_ScriptFullPath '"' 119 | RegWrite(v, "REG_SZ", HKEY_startup, "abgox - " A_ScriptName) 120 | fn_handle() 121 | } catch { 122 | fn_err_msg("添加注册表失败!") 123 | } 124 | } 125 | btn := g.AddButton("xs w" bw, "「应用快捷方式」") 126 | if (!A_IsAdmin) { 127 | btn.Focus() 128 | } 129 | btn.OnEvent("Click", e_useLnk) 130 | e_useLnk(*) { 131 | isStartUp := 2 132 | if (A_IsCompiled) { 133 | FileCreateShortcut(A_ScriptFullPath, A_Startup "\" fileLnk, , , fileDesc, favicon, , , 7) 134 | } else { 135 | FileCreateShortcut(A_AhkPath, A_Startup "\" fileLnk, , '"' A_ScriptFullPath '"', fileDesc, favicon, , , 7) 136 | } 137 | fn_handle() 138 | } 139 | 140 | g.AddText("cGray", tip) 141 | 142 | fn_handle(*) { 143 | g.Destroy() 144 | A_TrayMenu.Check(item) 145 | writeIni("isStartUp", isStartUp) 146 | } 147 | fn_err_msg(msg, *) { 148 | createTipGui([{ 149 | opt: "cRed", 150 | text: msg, 151 | }, { 152 | opt: "cRed", 153 | text: "你需要考虑使用其他方式设置开机自启动" 154 | }], "InputTip - 错误").Show() 155 | } 156 | tab.UseTab(2) 157 | g.AddText("cRed", "这里有多种方式设置开机自启动,请选择有效的方式") 158 | g.AddEdit("ReadOnly r9 w" bw, "1. 关于「任务计划程序」`n - 会创建一个任务计划程序 abgox.InputTip.noUAC`n - 系统启动后,会通过它自动运行 InputTip`n - 它可以直接避免每次启动都弹出管理员授权(UAC)窗口`n`n2. 关于「注册表」`n - 会将程序路径写入注册表`n - 系统启动后,会通过它自动运行 InputTip`n`n3. 关于「应用快捷方式」`n - 它会在 shell:startup 目录下创建一个普通的快捷方式`n - 系统启动后,会通过它自动运行 InputTip`n - 注意: 由于权限或系统电源计划限制等因素,它可能无效`n`n4. 关于管理员授权(UAC)窗口`n - 注意: 只有「任务计划程序」能直接避免此窗口弹出`n - 「注册表」或「应用快捷方式」需要修改系统设置`n - 系统设置 =>「更改用户账户控制设置」=>「从不通知」") 159 | g.AddLink(, '相关链接: 关于开机自启动 用户账户控制设置(微软帮助)') 160 | 161 | gc.w.startupGui := g 162 | return g 163 | } 164 | } 165 | } 166 | 167 | /** 168 | * 创建/更新任务计划程序 169 | * @param {String} path 要执行的应用程序 170 | * @param {String} taskName 任务计划名称 171 | * @param {Array} args 运行参数 172 | * @param {Highest | Limited} runLevel 运行级别 173 | * @param {1 | 0} isWait 是否等待完成 174 | * @param {1 | 0} needStartUp 是否需要开机启动 175 | * @returns {1 | 0} 是否创建成功 176 | */ 177 | createScheduleTask(path, taskName, args := [], runLevel := "Highest", isWait := 0, needStartUp := 0, *) { 178 | if (A_IsAdmin) { 179 | cmd := 'powershell -NoProfile -Command $action = New-ScheduledTaskAction -Execute "`'\"' path '\"`'" ' 180 | if (args.Length) { 181 | cmd .= '-Argument ' "'" 182 | for v in args { 183 | cmd .= '\"' v '\" ' 184 | } 185 | cmd .= "'" 186 | } 187 | cmd .= ';$principal = New-ScheduledTaskPrincipal -UserId "' userName '" -RunLevel ' runLevel ';$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -DontStopOnIdleEnd -ExecutionTimeLimit 10 -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1);' 188 | if (needStartUp) { 189 | cmd .= '$trigger = New-ScheduledTaskTrigger -AtLogOn;$task = New-ScheduledTask -Action $action -Principal $principal -Settings $settings -Trigger $trigger;' 190 | } else { 191 | cmd .= '$task = New-ScheduledTask -Action $action -Principal $principal -Settings $settings;' 192 | } 193 | cmd .= 'Register-ScheduledTask -TaskName ' taskName ' -InputObject $task -Force;' 194 | try { 195 | isWait ? RunWait(cmd, , "Hide") : Run(cmd, , "Hide") 196 | return 1 197 | } catch { 198 | return 0 199 | } 200 | } 201 | return 0 202 | } 203 | -------------------------------------------------------------------------------- /src/menu/switch-window.ahk: -------------------------------------------------------------------------------- 1 | ; InputTip 2 | 3 | fn_switch_window(*) { 4 | showGui() 5 | showGui(deep := "") { 6 | if (gc.w.windowToggleGui) { 7 | gc.w.windowToggleGui.Destroy() 8 | gc.w.windowToggleGui := "" 9 | try { 10 | gc.w.subGui.Destroy() 11 | gc.w.subGui := "" 12 | } 13 | } 14 | createGui(switchWindowGui).Show() 15 | switchWindowGui(info) { 16 | g := createGuiOpt("InputTip - 设置指定窗口状态自动切换") 17 | tab := g.AddTab3("-Wrap", ["设置状态自动切换", "关于"]) 18 | tab.UseTab(1) 19 | g.AddText("Section cRed", "你首先应该点击上方的「关于」查看具体的操作说明 ") 20 | 21 | if (info.i) { 22 | return g 23 | } 24 | w := info.w 25 | bw := w - g.MarginX * 2 26 | 27 | gc.LV_add := g.AddListView("-LV0x10 -Multi r7 NoSortHdr Sort Grid w" bw, ["应用进程列表", "窗口标题", "应用进程文件所在位置"]) 28 | fn_dbClick(LV, RowNumber) { 29 | handleClick(LV, RowNumber, LV._type) 30 | } 31 | gc.LV_add.OnEvent("DoubleClick", fn_dbClick) 32 | gc.LV_add._type := "add" 33 | 34 | res := [] 35 | for v in ["app_CN", "app_EN", "app_Caps"] { 36 | res.Push(readIni(v, "")) 37 | } 38 | res := ":" arrJoin(res, ":") ":" 39 | temp := ":" 40 | DetectHiddenWindows deep 41 | gc.LV_add.Opt("-Redraw") 42 | for v in WinGetList() { 43 | try { 44 | exe_name := ProcessGetName(WinGetPID("ahk_id " v)) 45 | if (!InStr(temp, ":" exe_name ":") && !InStr(res, ":" exe_name ":")) { 46 | temp .= exe_name ":" 47 | gc.LV_add.Add(, exe_name, WinGetTitle("ahk_id " v), WinGetProcessPath("ahk_id " v)) 48 | } 49 | } 50 | } 51 | for v in StrSplit(readIni("app_show_state", ''), ":") { 52 | if (!InStr(temp, ":" v ":") && !InStr(res, ":" v ":")) { 53 | temp .= v ":" 54 | try { 55 | gc.LV_add.Add(, v, WinGetTitle("ahk_exe " v), WinGetProcessPath("ahk_exe " v)) 56 | } catch { 57 | gc.LV_add.Add(, v) 58 | } 59 | } 60 | } 61 | gc.LV_add.Opt("+Redraw") 62 | DetectHiddenWindows 1 63 | 64 | addItem(state) { 65 | gc.%"LV_" state%.Opt("-Redraw") 66 | valueArr := StrSplit(readIni("app_" state, ""), ":") 67 | temp := ":" 68 | for v in valueArr { 69 | if (Trim(v) && !InStr(temp, ":" v ":")) { 70 | gc.%"LV_" state%.Add(, v) 71 | temp .= v ":" 72 | } 73 | } 74 | gc.%"LV_" state%.Opt("+Redraw") 75 | gc.%state "_title"%.Value .= " ( " gc.%"LV_" state%.GetCount() " 个 )" 76 | autoHdrLV(gc.%"LV_" state%) 77 | } 78 | 79 | gc.CN_title := g.AddText("xs w" bw / 3, "中文状态") 80 | gc.EN_title := g.AddText("yp w" bw / 3, "英文状态") 81 | gc.Caps_title := g.AddText("yp w" bw / 3, "大写锁定") 82 | 83 | if (symbolType = 3) { 84 | c := symbolConfig.textSymbol_CN_color ? "c" StrReplace(symbolConfig.textSymbol_CN_color, "#") : "" 85 | } else { 86 | c := symbolConfig.CN_color ? "c" StrReplace(symbolConfig.CN_color, "#") : "" 87 | } 88 | try { 89 | gc.LV_CN := g.AddListView("xs -Hdr -LV0x10 -Multi r5 NoSortHdr Sort Grid w" bw / 3 " " c, ["中文状态"]) 90 | } catch { 91 | gc.LV_CN := g.AddListView("xs -Hdr -LV0x10 -Multi r5 NoSortHdr Sort Grid w" bw / 3, ["中文状态"]) 92 | } 93 | addItem("CN") 94 | autoHdrLV(gc.LV_CN) 95 | gc.LV_CN.OnEvent("DoubleClick", fn_dbClick) 96 | gc.LV_CN._type := "CN" 97 | 98 | if (symbolType = 3) { 99 | c := symbolConfig.textSymbol_EN_color ? "c" StrReplace(symbolConfig.textSymbol_EN_color, "#") : "" 100 | } else { 101 | c := symbolConfig.EN_color ? "c" StrReplace(symbolConfig.EN_color, "#") : "" 102 | } 103 | try { 104 | gc.LV_EN := g.AddListView("yp -Hdr -LV0x10 -Multi r5 NoSortHdr Sort Grid w" bw / 3 " " c, ["英文状态"]) 105 | } catch { 106 | gc.LV_EN := g.AddListView("yp -Hdr -LV0x10 -Multi r5 NoSortHdr Sort Grid w" bw / 3, ["英文状态"]) 107 | } 108 | addItem("EN") 109 | autoHdrLV(gc.LV_EN) 110 | gc.LV_EN.OnEvent("DoubleClick", fn_dbClick) 111 | gc.LV_EN._type := "EN" 112 | 113 | if (symbolType = 3) { 114 | c := symbolConfig.textSymbol_Caps_color ? "c" StrReplace(symbolConfig.textSymbol_Caps_color, "#") : "" 115 | } else { 116 | c := symbolConfig.Caps_color ? "c" StrReplace(symbolConfig.Caps_color, "#") : "" 117 | } 118 | try { 119 | gc.LV_Caps := g.AddListView("yp -Hdr -LV0x10 -Multi r5 NoSortHdr Sort Grid w" bw / 3 " " c, ["大写锁定"]) 120 | } catch { 121 | gc.LV_Caps := g.AddListView("yp -Hdr -LV0x10 -Multi r5 NoSortHdr Sort Grid w" bw / 3, ["大写锁定"]) 122 | } 123 | addItem("Caps") 124 | autoHdrLV(gc.LV_Caps) 125 | gc.LV_Caps.OnEvent("DoubleClick", fn_dbClick) 126 | gc.LV_Caps._type := "Caps" 127 | 128 | handleClick(LV, RowNumber, from) { 129 | if (!RowNumber) { 130 | return 131 | } 132 | exe_name := LV.GetText(RowNumber) 133 | if (gc.w.subGui) { 134 | gc.w.subGui.Destroy() 135 | gc.w.subGui := "" 136 | } 137 | createGui(addGui).Show() 138 | addGui(info) { 139 | _handle(to) { 140 | g.Destroy() 141 | gc.%"LV_" from%.Delete(RowNumber) 142 | autoHdrLV(gc.%"LV_" from%) 143 | if (from != "add") { 144 | gc.%from "_title"%.Value := SubStr(gc.%from "_title"%.Value, 1, 4) " ( " gc.%"LV_" from%.GetCount() " 个 )" 145 | config := "app_" from 146 | value := readIni(config, "") 147 | res := "" 148 | for v in StrSplit(value, ":") { 149 | if (Trim(v) && v != exe_name) { 150 | res .= ":" v 151 | } 152 | } 153 | writeIni(config, SubStr(res, 2)) 154 | } 155 | config := "app_" to 156 | value := readIni(config, "") 157 | 158 | if (!InStr(":" value ":", ":" exe_name ":")) { 159 | gc.%"LV_" to%.Add(, exe_name) 160 | autoHdrLV(gc.%"LV_" to%) 161 | gc.%to "_title"%.Value := SubStr(gc.%to "_title"%.Value, 1, 4) " ( " gc.%"LV_" to%.GetCount() " 个 )" 162 | if (value) { 163 | writeIni(config, value ":" exe_name) 164 | } else { 165 | writeIni(config, exe_name) 166 | } 167 | } 168 | updateWhiteList(exe_name) 169 | 170 | global app_CN := ":" readIni('app_CN', '') ":" 171 | global app_EN := ":" readIni('app_EN', '') ":" 172 | global app_Caps := ":" readIni('app_Caps', '') ":" 173 | } 174 | g := createGuiOpt("InputTip - 添加") 175 | g.AddText(, "要将进程") 176 | g.AddText("yp cRed", exe_name) 177 | g.AddText("yp", "添加到哪一个自动切换列表中?") 178 | if (useWhiteList) { 179 | g.AddText("xs cRed", "如果此应用不在白名单中,则会同步添加到白名单中") 180 | } 181 | 182 | if (info.i) { 183 | return g 184 | } 185 | w := info.w 186 | bw := w - g.MarginX * 2 187 | 188 | fn_CN(*) { 189 | _handle("CN") 190 | } 191 | fn_EN(*) { 192 | _handle("EN") 193 | } 194 | fn_Caps(*) { 195 | _handle("Caps") 196 | } 197 | 198 | switch from { 199 | case "add": 200 | g.AddButton("xs w" bw, "「中文状态」").OnEvent("Click", fn_CN) 201 | g.AddButton("xs w" bw, "「英文状态」").OnEvent("Click", fn_EN) 202 | g.AddButton("xs w" bw, "「大写锁定」").OnEvent("Click", fn_Caps) 203 | case "CN": 204 | g.AddButton("xs Disabled w" bw, "「中文状态」").OnEvent("Click", fn_CN) 205 | g.AddButton("xs w" bw, "「英文状态」").OnEvent("Click", fn_EN) 206 | g.AddButton("xs w" bw, "「大写锁定」").OnEvent("Click", fn_Caps) 207 | g.AddButton("xs w" bw, "将它移除").OnEvent("Click", fn_rm) 208 | case "EN": 209 | g.AddButton("xs w" bw, "「中文状态」").OnEvent("Click", fn_CN) 210 | g.AddButton("xs Disabled w" bw, "「英文状态」").OnEvent("Click", fn_EN) 211 | g.AddButton("xs w" bw, "「大写锁定」").OnEvent("Click", fn_Caps) 212 | g.AddButton("xs w" bw, "将它移除").OnEvent("Click", fn_rm) 213 | case "Caps": 214 | g.AddButton("xs w" bw, "「中文状态」").OnEvent("Click", fn_CN) 215 | g.AddButton("xs w" bw, "「英文状态」").OnEvent("Click", fn_EN) 216 | g.AddButton("xs Disabled w" bw, "「大写锁定」").OnEvent("Click", fn_Caps) 217 | g.AddButton("xs w" bw, "将它移除").OnEvent("Click", fn_rm) 218 | } 219 | fn_rm(*) { 220 | g.Destroy() 221 | LV.Delete(RowNumber) 222 | autoHdrLV(LV) 223 | gc.%from "_title"%.Value := SubStr(gc.%from "_title"%.Value, 1, 4) " ( " gc.%"LV_" from%.GetCount() " 个 )" 224 | try { 225 | gc.LV_add.Add(, exe_name, WinGetTitle("ahk_exe " exe_name)) 226 | autoHdrLV(gc.LV_add) 227 | } 228 | config := "app_" from 229 | value := readIni(config, "") 230 | result := "" 231 | for v in StrSplit(value, ":") { 232 | if (Trim(v) && v != exe_name) { 233 | result .= ":" v 234 | } 235 | } 236 | writeIni(config, SubStr(result, 2)) 237 | 238 | global app_CN := ":" readIni('app_CN', '') ":" 239 | global app_EN := ":" readIni('app_EN', '') ":" 240 | global app_Caps := ":" readIni('app_Caps', '') ":" 241 | } 242 | g.AddButton("xs w" bw, "取消操作").OnEvent("Click", no) 243 | no(*) { 244 | g.Destroy() 245 | } 246 | gc.w.subGui := g 247 | return g 248 | } 249 | } 250 | 251 | g.AddButton("xs w" bw / 3, "刷新此界面").OnEvent("Click", e_refresh) 252 | e_refresh(*) { 253 | fn_close() 254 | showGui(deep) 255 | } 256 | 257 | g.AddButton("yp w" bw / 3, "通过输入进程名称手动添加").OnEvent("Click", e_add_by_hand) 258 | e_add_by_hand(*) { 259 | addApp("xxx.exe") 260 | addApp(v) { 261 | if (gc.w.subGui) { 262 | gc.w.subGui.Destroy() 263 | gc.w.subGui := "" 264 | } 265 | createGui(addGui).Show() 266 | addGui(info) { 267 | g := createGuiOpt("InputTip - 设置状态自动切换") 268 | text := "每次只能添加一个应用进程名称" 269 | if (useWhiteList) { 270 | text .= "`n如果它不在白名单中,则会同步添加到白名单中" 271 | } 272 | g.AddText("cRed", text) 273 | g.AddText("Section", "应用进程名称: ") 274 | gc._exe_name := g.AddEdit("yp") 275 | gc._exe_name.Value := v 276 | g.AddText("xs cGray", "你想要将它添加到哪个自动切换列表中?") 277 | if (info.i) { 278 | return g 279 | } 280 | w := info.w 281 | bw := w - g.MarginX * 2 282 | 283 | g.AddButton("xs w" bw, "「中文状态」").OnEvent("Click", fn_CN) 284 | g.AddButton("xs w" bw, "「英文状态」").OnEvent("Click", fn_EN) 285 | g.AddButton("xs w" bw, "「大写锁定」").OnEvent("Click", fn_Caps) 286 | fn_CN(*) { 287 | _handle("CN") 288 | } 289 | fn_EN(*) { 290 | _handle("EN") 291 | } 292 | fn_Caps(*) { 293 | _handle("Caps") 294 | } 295 | 296 | _handle(to) { 297 | exe_name := gc._exe_name.value 298 | g.Destroy() 299 | if (!RegExMatch(exe_name, "^.*\.\w{3}$") || RegExMatch(exe_name, '[\\/:*?\"<>|]')) { 300 | if (gc.w.subGui) { 301 | gc.w.subGui.Destroy() 302 | gc.w.subGui := "" 303 | } 304 | createGui(errGui).Show() 305 | errGui(info) { 306 | g := createGuiOpt("InputTip - 警告") 307 | g.AddText("cRed", exe_name) 308 | g.AddText("yp", "是一个错误的应用进程名称") 309 | g.AddText("xs cRed", '正确的应用进程名称是 xxx.exe 这样的格式`n同时文件名中不能包含这些英文符号 \ / : * ? " < >|') 310 | 311 | if (info.i) { 312 | return g 313 | } 314 | w := info.w 315 | bw := w - g.MarginX * 2 316 | 317 | y := g.AddButton("xs w" bw, "重新输入") 318 | y.Focus() 319 | y.OnEvent("click", e_close) 320 | e_close(*) { 321 | g.Destroy() 322 | addApp(exe_name) 323 | } 324 | gc.w.subGui := g 325 | return g 326 | } 327 | return 328 | } 329 | 330 | config := "app_" to 331 | value := readIni(config, "") 332 | 333 | if (InStr(":" value ":", ":" exe_name ":")) { 334 | if (gc.w.subGui) { 335 | gc.w.subGui.Destroy() 336 | gc.w.subGui := "" 337 | } 338 | createGui(existGui).Show() 339 | existGui(info) { 340 | g := createGuiOpt("InputTip - 警告") 341 | g.AddText("cRed", exe_name) 342 | g.AddText("yp", "这个应用进程已经存在了") 343 | 344 | if (info.i) { 345 | return g 346 | } 347 | w := info.w 348 | bw := w - g.MarginX * 2 349 | 350 | g.AddButton("xs w" bw, "重新输入").OnEvent("click", e_close) 351 | e_close(*) { 352 | g.Destroy() 353 | addApp(exe_name) 354 | } 355 | gc.w.subGui := g 356 | return g 357 | } 358 | return 359 | } 360 | 361 | gc.%"LV_" to%.Add(, exe_name) 362 | autoHdrLV(gc.%"LV_" to%) 363 | if (value) { 364 | writeIni(config, value ":" exe_name) 365 | } else { 366 | writeIni(config, exe_name) 367 | } 368 | updateWhiteList(exe_name) 369 | global app_CN := ":" readIni('app_CN', '') ":" 370 | global app_EN := ":" readIni('app_EN', '') ":" 371 | global app_Caps := ":" readIni('app_Caps', '') ":" 372 | } 373 | gc.w.subGui := g 374 | return g 375 | } 376 | } 377 | } 378 | if (deep) { 379 | g.AddButton("yp w" bw / 3, "显示更少进程(仅前台窗口)").OnEvent("Click", e_less_window) 380 | e_less_window(*) { 381 | fn_close() 382 | showGui("") 383 | } 384 | } else { 385 | g.AddButton("yp w" bw / 3, "显示更多进程(后台窗口)").OnEvent("Click", e_more_window) 386 | e_more_window(*) { 387 | fn_close() 388 | showGui(1) 389 | } 390 | } 391 | autoHdrLV(gc.LV_add) 392 | tab.UseTab(2) 393 | g.AddEdit("ReadOnly -VScroll w" w, "1. 如何使用这个配置菜单?`n`n - 上方的列表页显示的是当前系统正在运行的应用进程(仅前台窗口)`n - 为了便于操作,白名单中的应用进程也会添加到列表中`n - 双击列表中任意应用进程,就可以将其添加到下方任意列表中`n - 如果需要更多的进程,请点击下方的「显示更多进程」以显示后台和隐藏进程`n - 也可以点击下方的「通过输入进程名称手动添加」直接添加进程名称`n`n - 下方分别是中文、英文、大写锁定这三个自动切换列表`n - 在自动切换列表中的应用窗口被激活时,会自动切换到对应的输入法状态`n - 如果对自动切换的逻辑不理解,请查看下方的相关链接`n - 双击列表中任意应用进程,就可以将它移除或者添加到其他列表中`n - 白名单机制下,选择添加且此应用不在白名单中,则会同步添加到白名单中`n`n2. 需要特别注意:`n - 自动切换生效的前提是当前选择的输入法可以切换状态`n - 以【美式键盘 ENG】为例`n - 它只有英文状态和大写锁定,所以只有英文状态的和大写锁定的自动切换有效") 394 | g.AddLink(, '相关链接: 关于指定窗口自动切换状态') 395 | 396 | g.OnEvent("Close", fn_close) 397 | fn_close(*) { 398 | g.Destroy() 399 | try { 400 | gc.w.subGui.Destroy() 401 | gc.w.subGui := "" 402 | } 403 | } 404 | gc.w.windowToggleGui := g 405 | return g 406 | } 407 | } 408 | } 409 | -------------------------------------------------------------------------------- /src/menu/symbol-pos.ahk: -------------------------------------------------------------------------------- 1 | ; InputTip 2 | 3 | fn_symbol_pos(*) { 4 | if (gc.w.symbolPosGui) { 5 | gc.w.symbolPosGui.Destroy() 6 | gc.w.symbolPosGui := "" 7 | } 8 | createGui(symbolPos).Show() 9 | symbolPos(info) { 10 | g := createGuiOpt("InputTip - 设置符号的显示位置") 11 | g.AddLink("cRed", '在 InputTip 的 v1 版本中,通过在鼠标附近显示符号,没有发现兼容性问题`n而 v2 中,部分窗口始终无法获取到光标位置,因此决定在 v2 中添加此特性`n详情请查看: 应用窗口兼容情况') 12 | g.AddLink("cGray", '- 选择「在任意应用窗口中」,这样就实现了 v1 版本中同样的效果`n- 选择「仅指定应用窗口」,则还需要点击下方的按钮去添加应用进程`n- 建议减小「更改配置」中的「每多少毫秒更新符号的显示位置和状态」') 13 | g.AddText(, "哪些应用窗口中的符号需要显示在鼠标附近: ") 14 | 15 | if (info.i) { 16 | return g 17 | } 18 | w := info.w 19 | bw := w - g.MarginX * 2 20 | 21 | g.AddDropDownList("yp AltSubmit Choose" showCursorPos + 1, [" 仅指定应用窗口", " 在任意应用窗口中"]).OnEvent("Change", e_change) 22 | e_change(item, *) { 23 | value := item.value - 1 24 | writeIni("showCursorPos", value) 25 | global showCursorPos := value 26 | restartJAB() 27 | } 28 | g.AddText("xs", "符号显示在鼠标附近时的水平偏移量: ") 29 | _ := g.AddEdit("yp") 30 | _.Value := readIni("showCursorPos_x", 0) 31 | _._config := "showCursorPos_x" 32 | _.OnEvent("Change", fn_offset) 33 | g.AddText("xs", "符号显示在鼠标附近时的垂直偏移量: ") 34 | _ := g.AddEdit("yp") 35 | _.Value := readIni("showCursorPos_y", -20) 36 | _._config := "showCursorPos_y" 37 | _.OnEvent("Change", fn_offset) 38 | fn_offset(item, *) { 39 | writeIni(item._config, returnNumber(item.value)) 40 | global showCursorPos_x := readIni("showCursorPos_x", 0) 41 | global showCursorPos_y := readIni("showCursorPos_y", -20) 42 | } 43 | 44 | _c := g.AddButton("xs w" bw, "设置符号显示在鼠标附近的应用") 45 | _c.Focus() 46 | _c.OnEvent("Click", set_app_list) 47 | set_app_list(*) { 48 | g.Destroy() 49 | fn_common({ 50 | gui: "setShowPosGui", 51 | config: "showCursorPosList", 52 | tab: ["设置符号显示在鼠标附近的应用", "关于"], 53 | tip: "你首先应该点击上方的「关于」查看具体的操作说明 ", 54 | list: "符号显示在鼠标附近的应用列表", 55 | color: "cRed", 56 | about: '1. 如何使用这个配置菜单?`n`n - 上方的列表页显示的是当前系统正在运行的应用进程(仅前台窗口)`n - 为了便于操作,白名单中的应用进程也会添加到列表中`n - 双击列表中任意应用进程,就可以将其添加到「符号显示在鼠标附近的应用列表」中`n - 如果需要更多的进程,请点击右下角的「显示更多进程」以显示后台和隐藏进程`n - 也可以点击右下角的「通过输入进程名称手动添加」直接添加进程名称`n`n - 下方是「符号显示在鼠标附近的应用列表」`n - 双击列表中任意应用进程,就可以将它移除`n`n2. 为什么要添加这个列表?`n - 因为在少数应用中始终无法获取到输入光标位置,从而无法实现在输入光标附近显示符号`n - 而 v1 版本中,在鼠标附近显示符号的方案,在这种情况下也算是一种折中的解决方案`n`n3. 如何快速添加应用进程?`n`n - 每次双击应用进程后,会弹出操作窗口,需要选择添加/移除或取消`n - 如果你确定当前操作不需要取消,可以在操作窗口弹出后,按下空格键快速确认', 57 | link: '相关链接: 关于符号显示位置', 58 | addConfirm: "是否要将", 59 | addConfirm2: "添加到「符号显示在鼠标附近的应用列表」中?", 60 | addConfirm3: "添加后,在此应用窗口中时,符号会显示在鼠标附近", 61 | rmConfirm: "是否要将", 62 | rmConfirm2: "从「符号显示在鼠标附近的应用列表」中移除?", 63 | rmConfirm3: "移除后,在此应用窗口中时,符号会显示在输入光标附近", 64 | }, 65 | fn 66 | ) 67 | fn(value) { 68 | global showCursorPosList := ":" value ":" 69 | gc.setShowPosGui_LV_rm_title.Text := "符号显示在鼠标附近的应用列表 ( " gc.setShowPosGui_LV_rm.GetCount() " 个 )" 70 | restartJAB() 71 | } 72 | } 73 | gc.w.symbolPosGui := g 74 | return g 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/utils/IME.ahk: -------------------------------------------------------------------------------- 1 | ; InputTip 2 | 3 | /** 4 | * @link https://github.com/Tebayaki/AutoHotkeyScripts/blob/main/lib/IME.ahk 5 | * @Tip 有所修改,外部必须提供变量 checkTimeout,modeRule,baseStatus 6 | * @example 7 | * checkTimeout := 1000 ; 超时时间(单位:毫秒) 8 | * modeRules := [] ; 状态规则 9 | * baseStatus := 0 ; 默认状态为英文 10 | * IME.GetInputMode() ; 获取当前输入法输入模式 11 | * IME.SetInputMode(!IME.GetInputMode()) ; 切换当前输入法输入模式 12 | */ 13 | class IME { 14 | /** 15 | * 获取当前输入法输入模式 16 | * @param hwnd 17 | * @returns {1 | 0} 1:中文,0:英文 18 | */ 19 | static GetInputMode(hwnd := this.GetFocusedWindow()) { 20 | if (mode = 1) { 21 | if (!this.GetOpenStatus(hwnd)) { 22 | return 0 23 | } 24 | return this.GetConversionMode(hwnd) & 1 25 | } 26 | 27 | ; 存储默认状态,如果都不匹配,就返回预先指定的默认状态 28 | status := baseStatus 29 | 30 | ; 系统返回的状态码 31 | statusMode := this.GetOpenStatus(hwnd) 32 | ; 系统返回的切换码 33 | conversionMode := this.GetConversionMode(hwnd) 34 | 35 | for v in modeRules { 36 | r := StrSplit(v, "*") 37 | 38 | ; 状态码规则 39 | sm := r[1] 40 | ; 切换码规则 41 | cm := r[2] 42 | ; 匹配状态 43 | s := r[3] 44 | 45 | if (matchRule(statusMode, sm) && matchRule(conversionMode, cm)) { 46 | ; 匹配成功 47 | status := s 48 | break 49 | } 50 | } 51 | 52 | /** 53 | * 匹配规则 54 | * @param value 系统返回的状态值 55 | * @param ruleValue 规则定义的状态值 56 | * @returns {1 | 0} 是否匹配成功 57 | */ 58 | matchRule(value, ruleValue) { 59 | ; 规则为空,默认匹配成功 60 | if (ruleValue == "") { 61 | return 1 62 | } 63 | 64 | if (ruleValue == "evenNum") { ; 如果值是偶数 65 | isMatch := !(value & 1) 66 | } else if (ruleValue == "oddNum") { ; 如果值是奇数 67 | isMatch := value & 1 68 | } else { 69 | isMatch := InStr("/" ruleValue "/", "/" value "/") 70 | } 71 | return isMatch 72 | } 73 | return status 74 | } 75 | 76 | /** 77 | * 系统返回的状态码和切换码 78 | * @param hwnd 79 | * @returns {Object} 系统返回的状态码和切换码 80 | */ 81 | static CheckInputMode(hwnd := this.GetFocusedWindow()) { 82 | return { 83 | statusMode: this.GetOpenStatus(hwnd), 84 | conversionMode: this.GetConversionMode(hwnd) 85 | } 86 | } 87 | 88 | /** 89 | * 切换到指定的输入法状态 90 | * @param mode 要切换的指定输入法状态(1:中文,0:英文) 91 | * @param hwnd 92 | */ 93 | static SetInputMode(mode, hwnd := this.GetFocusedWindow()) { 94 | if mode { 95 | this.SetOpenStatus(true, hwnd) 96 | switch this.GetKeyboardLayout(hwnd) { 97 | case 0x08040804: 98 | this.SetConversionMode(1025, hwnd) 99 | case 0x04110411: 100 | this.SetConversionMode(9, hwnd) 101 | } 102 | } 103 | else { 104 | this.SetOpenStatus(false, hwnd) 105 | } 106 | } 107 | 108 | static ToggleInputMode(hwnd := this.GetFocusedWindow()) { 109 | this.SetInputMode(!this.GetInputMode(hwnd), hwnd) 110 | } 111 | 112 | static GetOpenStatus(hwnd := this.GetFocusedWindow()) { 113 | try { 114 | DllCall("SendMessageTimeoutW", "ptr", DllCall("imm32\ImmGetDefaultIMEWnd", "ptr", hwnd, "ptr"), "uint", 0x283, "ptr", 0x5, "ptr", 0, "uint", 0, "uint", checkTimeout, "ptr*", &status := 0) 115 | return status 116 | } catch { 117 | return 0 118 | } 119 | } 120 | 121 | static SetOpenStatus(status, hwnd := this.GetFocusedWindow()) { 122 | try { 123 | DllCall("SendMessageTimeoutW", "ptr", DllCall("imm32\ImmGetDefaultIMEWnd", "ptr", hwnd, "ptr"), "uint", 0x283, "ptr", 0x6, "ptr", status, "uint", 0, "uint", checkTimeout, "ptr*", 0) 124 | } 125 | } 126 | 127 | static GetConversionMode(hwnd := this.GetFocusedWindow()) { 128 | try { 129 | DllCall("SendMessageTimeoutW", "ptr", DllCall("imm32\ImmGetDefaultIMEWnd", "ptr", hwnd, "ptr"), "uint", 0x283, "ptr", 0x1, "ptr", 0, "uint", 0, "uint", checkTimeout, "ptr*", &mode := 0) 130 | return mode 131 | } catch { 132 | return 0 133 | } 134 | } 135 | 136 | static SetConversionMode(mode, hwnd := this.GetFocusedWindow()) { 137 | try { 138 | DllCall("SendMessageTimeoutW", "ptr", DllCall("imm32\ImmGetDefaultIMEWnd", "ptr", hwnd, "ptr"), "uint", 0x283, "ptr", 0x2, "ptr", mode, "uint", 0, "uint", checkTimeout, "ptr*", 0) 139 | } 140 | } 141 | 142 | static GetKeyboardLayout(hwnd := this.GetFocusedWindow()) { 143 | return DllCall("GetKeyboardLayout", "uint", DllCall("GetWindowThreadProcessId", "ptr", hwnd, "ptr", 0, "uint"), "ptr") 144 | } 145 | 146 | static SetKeyboardLayout(hkl, hwnd := this.GetFocusedWindow()) { 147 | SendMessage(0x50, 1, hkl, hwnd) 148 | } 149 | 150 | static GetKeyboardLayoutList() { 151 | if cnt := DllCall("GetKeyboardLayoutList", "int", 0, "ptr", 0) { 152 | list := [] 153 | buf := Buffer(cnt * A_PtrSize) 154 | loop DllCall("GetKeyboardLayoutList", "int", cnt, "ptr", buf) { 155 | list.Push(NumGet(buf, (A_Index - 1) * A_PtrSize, "ptr")) 156 | } 157 | return list 158 | } 159 | } 160 | 161 | static LoadKeyboardLayout(hkl) { 162 | return DllCall("LoadKeyboardLayoutW", "str", Format("{:08x}", hkl), "uint", 0x101) 163 | } 164 | 165 | static UnloadKeyboardLayout(hkl) { 166 | return DllCall("UnloadKeyboardLayout", "ptr", hkl) 167 | } 168 | 169 | static GetFocusedWindow() { 170 | if foreHwnd := WinExist("A") { 171 | guiThreadInfo := Buffer(A_PtrSize == 8 ? 72 : 48) 172 | NumPut("uint", guiThreadInfo.Size, guiThreadInfo) 173 | DllCall("GetGUIThreadInfo", "uint", DllCall("GetWindowThreadProcessId", "ptr", foreHwnd, "ptr", 0, "uint"), "ptr", guiThreadInfo) 174 | if focusedHwnd := NumGet(guiThreadInfo, A_PtrSize == 8 ? 16 : 12, "ptr") { 175 | return focusedHwnd 176 | } 177 | return foreHwnd 178 | } 179 | return 0 180 | } 181 | } 182 | 183 | /** 184 | * 判断当前输入法状态是否为中文 185 | * @returns {1 | 0} 输入法是否为中文 186 | * @example 187 | * DetectHiddenWindows 1 ; 前置条件(不为1,可能判断有误) 188 | * ;... 189 | * MsgBox isCN() 190 | */ 191 | isCN() { 192 | return IME.GetInputMode() 193 | } 194 | 195 | /** 196 | * 将输入法状态切换为中文 197 | * @param pressKey 触发此函数的按键,如果非按键触发,则为空 198 | * @example 199 | * SetStoreCapsLockMode 0 ; 前置条件,确保大写锁定可切换 200 | * ; ... 201 | * switch_CN() 202 | */ 203 | switch_CN(pressKey := "", *) { 204 | ; 当按下 shift + 任意键,取消强制切换 205 | if (pressKey && InStr(hotkey_CN, "shift") && A_TimeIdleKeyboard < 200 && !InStr(A_PriorKey, "shift")) { 206 | return 207 | } 208 | if (GetKeyState("CapsLock", "T")) { 209 | SendInput("{CapsLock}") 210 | } 211 | Sleep(50) 212 | if (switchStatus) { 213 | if (!isCN()) { 214 | SendInput(switchStatusList[switchStatus]) 215 | } 216 | } else { 217 | IME.SetInputMode(1) 218 | } 219 | } 220 | /** 221 | * 将输入法状态切换为英文 222 | * @param pressKey 触发此函数的按键,如果非按键触发,则为空 223 | * @example 224 | * SetStoreCapsLockMode 0 ; 前置条件,确保大写锁定可切换 225 | * ; ... 226 | * switch_EN() 227 | */ 228 | switch_EN(pressKey := "", *) { 229 | ; 当按下 shift + 任意键,取消强制切换 230 | if (pressKey && InStr(hotkey_EN, "shift") && A_TimeIdleKeyboard < 200 && !InStr(A_PriorKey, "shift")) { 231 | return 232 | } 233 | if (GetKeyState("CapsLock", "T")) { 234 | SendInput("{CapsLock}") 235 | } 236 | Sleep(50) 237 | if (switchStatus) { 238 | if (isCN()) { 239 | SendInput(switchStatusList[switchStatus]) 240 | } 241 | } else { 242 | IME.SetInputMode(0) 243 | } 244 | } 245 | /** 246 | * 将输入法状态切换为大写锁定 247 | * @param pressKey 触发此函数的按键,如果非按键触发,则为空 248 | * @example 249 | * SetStoreCapsLockMode 0 ; 前置条件,确保大写锁定可切换 250 | * ; ... 251 | * switch_Caps() 252 | */ 253 | switch_Caps(pressKey := "", *) { 254 | ; 当按下 shift + 任意键,取消强制切换 255 | if (pressKey && InStr(hotkey_Caps, "shift") && A_TimeIdleKeyboard < 200 && !InStr(A_PriorKey, "shift")) { 256 | return 257 | } 258 | if (!GetKeyState("CapsLock", "T")) { 259 | SendInput("{CapsLock}") 260 | } 261 | } 262 | -------------------------------------------------------------------------------- /src/utils/app-list.ahk: -------------------------------------------------------------------------------- 1 | ; InputTip 2 | 3 | modeNameList := ["HOOK", "UIA", "GUI_UIA", "MSAA", "HOOK_DLL", "WPF", "ACC", "JAB"] 4 | 5 | ; 内部的默认模式应用列表,优先级最低,会被通过「设置光标获取模式」设置的配置覆盖 6 | defaultModeList := { 7 | HOOK: [], 8 | UIA: [ 9 | ; Word 10 | "WINWORD.EXE", 11 | ; 终端 12 | "WindowsTerminal.exe", 13 | "wt.exe", 14 | ; 一个文件管理器 15 | "OneCommander.exe", 16 | ; 有道词典 17 | "YoudaoDict.exe", 18 | ; 19 | "Mempad.exe", 20 | ; 任务管理器 21 | "Taskmgr.exe", 22 | ], 23 | ; 先后调用 GUI 和 UIA 24 | GUI_UIA: [ 25 | ; PowerPoint(PPT) 26 | "POWERPNT.EXE", 27 | ; 28 | "Notepad++.exe", 29 | ; Visual Studio 30 | "devenv.exe", 31 | ; 腾讯会议 32 | "WeMeetApp.exe", 33 | ; 微信 34 | "Weixin.exe", 35 | ], 36 | MSAA: [ 37 | ; 火狐浏览器 38 | "firefox.exe", 39 | ; Excel 40 | "EXCEL.EXE", 41 | ; 钉钉 42 | "DingTalk.exe", 43 | ; 记事本 44 | "Notepad.exe", 45 | "Notepad3.exe", 46 | ; 快速启动 47 | "Quicker.exe", 48 | ; 49 | "skylark.exe", 50 | ; 字幕编辑器 51 | "aegisub32.exe", 52 | "aegisub64.exe", 53 | "aegisub.exe", 54 | ; 图片文字识别 55 | "PandaOCR.exe", 56 | "PandaOCR.Pro.exe", 57 | ; 音速启动 58 | "VStart6.exe", 59 | ; Tim 60 | "TIM.exe", 61 | ; PowerToys 快速启动器 62 | "PowerToys.PowerLauncher.exe", 63 | ; 邮箱 64 | "Foxmail.exe", 65 | ], 66 | ; 需要调用有兼容性问题(32位)的 dll 67 | HOOK_DLL: [ 68 | ; 微信 69 | "WeChat.exe", 70 | ], 71 | WPF: [ 72 | ; Windows PowerShell ISE 73 | "powershell_ise.exe", 74 | ], 75 | ACC: [], 76 | ; 需要使用 Java Access Bridge 77 | JAB: [] 78 | } 79 | -------------------------------------------------------------------------------- /src/utils/app-update/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "app-update" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /src/utils/app-update/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "app-update" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /src/utils/app-update/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::process::Command; 2 | use std::{env, fs}; 3 | 4 | fn main() { 5 | let args: Vec = std::env::args().collect(); 6 | 7 | if args.len() < 4 { 8 | eprintln!( 9 | "Usage: {} ", 10 | args[0] 11 | ); 12 | std::process::exit(1); 13 | } 14 | 15 | let process_name = &args[1]; 16 | let target_exe_path = &args[2]; 17 | let key_count = &args[3]; 18 | let dir = env::current_dir() 19 | .expect("Failed to get current directory") 20 | .join("InputTipSymbol") 21 | .join("default"); 22 | 23 | // 终止当前正在运行的 InputTip 进程 24 | Command::new("taskkill") 25 | .args(&["/f", "/im", process_name]) 26 | .status() 27 | .expect("Failed to execute taskkill"); 28 | 29 | // 将新版本的 exe 文件复制到目标路径 30 | let new_version_path = dir.join("abgox-InputTip-new-version.exe"); 31 | fs::copy(&new_version_path, target_exe_path).expect("Failed to copy new version"); 32 | 33 | // 删除源文件 34 | fs::remove_file(&new_version_path).expect("Failed to delete source file"); 35 | 36 | // 创建一个 txt 文件,用于标记更新完成 37 | let done_file_path = dir.join("abgox-InputTip-update-version-done.txt"); 38 | fs::write(done_file_path, "").expect("Failed to create done file"); 39 | 40 | // 运行 InputTip.exe 41 | Command::new(target_exe_path) 42 | .arg(key_count) 43 | .spawn() 44 | .expect("Failed to start target executable"); 45 | } 46 | -------------------------------------------------------------------------------- /src/utils/create-gui.ahk: -------------------------------------------------------------------------------- 1 | ; InputTip 2 | 3 | /** 4 | * - 创建 Gui 对象。 5 | * - 能够获取窗口最终的坐标和宽高,方便配置控件(如按钮宽度)。 6 | * - 原理: 通过先执行一次隐藏显示来获取信息,相当于实际会运行两次 7 | * @param {Func} callback 8 | * - 回调函数接受形参 `info` 9 | * - `info.x`,`info.y`,`info.w`,`info.h`: 最终计算得到的窗口坐标和宽高。 10 | * - 当执行隐藏显示时,`info.i` 为 `1`,否则为 `0` 11 | * @returns {Gui} 返回 Gui 对象 12 | * @example 13 | * createGui(helloGui).Show() 14 | * helloGui(info) { 15 | * g := createGuiOpt() 16 | * g.AddText(, "xxxxxxxxxxxxxxxxxxx") 17 | * ; 第一次隐藏显示,可以通过它在合适的地方直接返回,减少多余的执行 18 | * if (info.i) { 19 | * return g 20 | * } 21 | * w := info.w 22 | * bw := w - g.MarginX * 2 23 | * ; 其他控件... 24 | * g.AddButton("w" bw, "确定") 25 | * return g 26 | * } 27 | */ 28 | createGui(callback) { 29 | g := callback({ x: 0, y: 0, w: 0, h: 0, i: 1 }) 30 | g.Show("Hide") 31 | g.GetPos(&x, &y, &w, &h) 32 | g.Destroy() 33 | return callback({ x: x, y: y, w: w, h: h, i: 0 }) 34 | } 35 | 36 | /** 37 | * @param title Gui 标题 38 | * @param {Array} fontOption 字体配置(如: ["s12", "Microsoft YaHei"]) 39 | * - 这里为了方便 InputTip 使用,默认值使用了外部的 fontOpt 变量 40 | * @param {String} guiOption Gui 初始化配置 41 | * @returns {Gui} 返回 Gui 对象 42 | */ 43 | createGuiOpt(title := fileDesc, fontOption := fontOpt, guiOption := "AlwaysOnTop") { 44 | g := Gui(guiOption, title) 45 | g.SetFont(fontOption*) 46 | return g 47 | } 48 | 49 | 50 | /** 51 | * 创建一个提示 Gui 52 | * @param {Array} Tips 显示的提示信息 53 | * @param {String} title Gui 标题 54 | * @param {String} btnText 按钮文本 55 | * @returns {Gui} 返回 Gui 对象 56 | */ 57 | createTipGui(Tips, title := "InputTip - 提示", btnText := "我知道了") { 58 | if (gc.w.subGui) { 59 | gc.w.subGui.Destroy() 60 | gc.w.subGui := "" 61 | } 62 | tipGui(info) { 63 | g := createGuiOpt(title) 64 | 65 | for v in Tips { 66 | g.AddLink(v.opt, v.text) 67 | } 68 | 69 | if (info.i) { 70 | return g 71 | } 72 | w := info.w 73 | 74 | btn := g.AddButton("xs w" w, btnText) 75 | btn.OnEvent("Click", e_close) 76 | btn.Focus() 77 | e_close(*) { 78 | g.Destroy() 79 | } 80 | gc.w.subGui := g 81 | return g 82 | } 83 | return createGui(tipGui) 84 | } 85 | -------------------------------------------------------------------------------- /src/utils/hotkey-gui.ahk: -------------------------------------------------------------------------------- 1 | ; InputTip 2 | 3 | /** 4 | * 设置快捷键 5 | * @param keyConfigList 配置项 6 | * @param label 窗口标题 7 | * @example 8 | * setHotKeyGui([{ 9 | * config: "hotkey_Pause", ; 要写入的配置项 10 | * preTip: "设置快捷键", ; 快捷键功能描述前缀,可省略 11 | * tip: "暂停/运行" ; 快捷键功能描述 12 | * }], "软件暂停/运行") 13 | */ 14 | setHotKeyGui(keyConfigList, label := "") { 15 | if (gc.w.hotKeyGui) { 16 | gc.w.hotKeyGui.Destroy() 17 | gc.w.hotKeyGui := "" 18 | } 19 | line := "------------------------------------------------------------------------------------" 20 | createGui(hotKeyGui).Show() 21 | hotKeyGui(info) { 22 | g := createGuiOpt("InputTip - 设置快捷键" (label ? " —— " label : "")) 23 | tab := g.AddTab3("-Wrap", ["设置单键", "设置组合快捷键", "手动输入快捷键"]) 24 | tab.UseTab(1) 25 | g.AddText("Section", "1.") 26 | g.AddText("yp cRed", "快捷键设置不会实时生效,需要点击下方的「确定」后生效") 27 | g.AddText("xs", "2. LShift 指的是左边的 Shift 键,RShift 指的是右边的 Shift 键,其他按键以此类推") 28 | g.AddText("xs", "3. 使用单键不会覆盖原本的按键功能,因为是在单键抬起时才会触发") 29 | 30 | if (info.i) { 31 | return g 32 | } 33 | w := info.w 34 | bw := w - g.MarginX * 2 35 | 36 | g.AddLink("xs", "4. 如果要移除快捷键,请选择「无」") 37 | g.AddLink("xs", '5. 点击查看完整的按键名称对应表`n' line) 38 | 39 | keyList := [] 40 | keyList.Push(["无", "Esc", "Shift", "LShift", "RShift", "Ctrl", "LCtrl", "RCtrl", "Alt", "LAlt", "RAlt"]*) 41 | keyList.Push(["MButton", "LButton", "RButton"]*) 42 | keyList.Push(["Space", "Tab", "Enter", "Backspace", "Delete", "Insert", "Home", "End", "PgUp", "PgDn", "Up", "Down", "Left", "Right"]*) 43 | 44 | i := 0 45 | while (i <= 9) { 46 | keyList.Push("Numpad" i) 47 | i++ 48 | } 49 | keyList.Push(["NumpadDot", "NumLock", "NumpadDiv", "NumpadMult", "NumpadAdd", "NumpadSub", "NumpadEnter"]*) 50 | 51 | i := 1 52 | while (i <= 24) { 53 | keyList.Push("F" i) 54 | i++ 55 | } 56 | 57 | for v in keyConfigList { 58 | try { 59 | g.AddText("xs", v.preTip) 60 | g.AddText("yp cRed", v.tip) 61 | } catch { 62 | g.AddText("xs cRed", v.tip) 63 | } 64 | 65 | g.AddText("yp", ":") 66 | 67 | _ := gc.%v.config% := g.AddDropDownList("yp r9", keyList) 68 | _._config := v.config 69 | _._with := v.config "_win" 70 | _.OnEvent("Change", e_change_hotkey) 71 | 72 | config := readIni(v.config, "") 73 | if (config ~= "^~\w+\sUp$") { 74 | try { 75 | _.Text := Trim(StrReplace(StrReplace(config, "~", ""), "Up", "")) 76 | if (!_.Value) { 77 | _.Value := 1 78 | } 79 | } catch { 80 | _.Text := "无" 81 | } 82 | } else { 83 | _.Text := "无" 84 | } 85 | } 86 | e_change_hotkey(item, *) { 87 | static last := "" 88 | if (last = item.value) { 89 | return 90 | } 91 | last := item.value 92 | 93 | ; 同步修改到「设置组合快捷键」和「手动输入快捷键」 94 | if (item.Text = "无") { 95 | key := "" 96 | } else { 97 | key := "~" item.Text " Up" 98 | } 99 | gc.%item._config "2"%.Value := "" 100 | gc.%item._config "3"%.Value := key 101 | gc.%item._with%.Value := 0 102 | } 103 | tab.UseTab(2) 104 | g.AddText("Section", "1.") 105 | g.AddText("yp cRed", "快捷键设置不会实时生效,需要点击下方的「确定」后生效") 106 | g.AddText("xs", "2. 直接按下快捷键即可设置,除非快捷键被占用,需要使用「手动输入快捷键」") 107 | g.AddText("xs", "3. 使用 Backspace(退格键) 或 Delete(删除键) 可以清除快捷键") 108 | g.AddText("xs", "4. 通过勾选右边的 Win 键来表示快捷键中需要加入 Win 修饰键`n" line) 109 | 110 | for v in keyConfigList { 111 | try { 112 | g.AddText("xs", v.preTip) 113 | g.AddText("yp cRed", v.tip) 114 | } catch { 115 | g.AddText("xs cRed", v.tip) 116 | } 117 | g.AddText("yp", ":") 118 | value := readIni(v.config, '') 119 | _ := gc.%v.config "2"% := g.AddHotkey("yp", StrReplace(value, "#", "")) 120 | _._config := v.config 121 | _._with := v.config "_win" 122 | _.OnEvent("Change", e_change_hotkey1) 123 | gc.%_._with% := g.AddCheckbox("yp", "Win 键") 124 | gc.%_._with%._config := v.config 125 | gc.%_._with%.OnEvent("Click", e_win_key) 126 | gc.%_._with%.Value := InStr(value, "#") ? 1 : 0 127 | } 128 | e_change_hotkey1(item, *) { 129 | ; 同步修改到「设置单键」和「手动输入快捷键」 130 | gc.%item._config%.Text := "无" 131 | v := item.value 132 | if (gc.%item._with%.Value) { 133 | v := "#" v 134 | } 135 | gc.%item._config "3"%.Value := v 136 | } 137 | e_win_key(item, *) { 138 | ; 同步修改到「设置单键」和「手动输入快捷键」 139 | gc.%item._config%.Text := "无" 140 | v := gc.%item._config "2"%.Value 141 | gc.%item._config "3"%.Value := item.value ? "#" v : v 142 | } 143 | tab.UseTab(3) 144 | g.AddText("Section", "1.") 145 | g.AddText("yp cRed", "快捷键设置不会实时生效,需要点击下方的「确定」后生效") 146 | g.AddText("xs", "2.") 147 | g.AddText("yp cRed", "优先使用「设置单键」或「设置组合快捷键」设置,除非因为快捷键占用无法设置") 148 | g.AddText("xs", '3. 这里会回显它们的设置,建议先使用它们,然后回到此处适当修改') 149 | g.AddLink("xs", '3. 你需要首先查看 如何手动输入快捷键`n' line) 150 | for v in keyConfigList { 151 | try { 152 | g.AddText("xs", v.preTip) 153 | g.AddText("yp cRed", v.tip) 154 | } catch { 155 | g.AddText("xs cRed", v.tip) 156 | } 157 | g.AddText("yp", ":") 158 | _ := gc.%v.config "3"% := g.AddEdit("yp") 159 | _._config := v.config 160 | _._with := v.config "_win" 161 | _.Value := readIni(v.config, '') 162 | _.OnEvent("Change", e_change_hotkey2) 163 | } 164 | e_change_hotkey2(item, *) { 165 | gc.%item._with%.Value := InStr(item.value, "#") ? 1 : 0 166 | ; 当输入的快捷键符合单键时,同步修改 167 | if (item.value ~= "^~\w+\sUp$") { 168 | try { 169 | gc.%item._config%.Text := Trim(StrReplace(StrReplace(item.value, "~", ""), "Up", "")) 170 | } catch { 171 | gc.%item._config%.Text := "无" 172 | } 173 | gc.%item._config "2"%.Value := "" 174 | } else { 175 | gc.%item._config%.Text := "无" 176 | ; 当输入的快捷键符合组合快捷键时,同步修改 177 | try { 178 | gc.%item._config "2"%.Value := StrReplace(item.value, "#", "") 179 | } catch { 180 | gc.%item._config "2"%.Value := "" 181 | } 182 | } 183 | } 184 | tab.UseTab(0) 185 | g.AddButton("Section w" bw, "确定").OnEvent("Click", e_yes) 186 | e_yes(*) { 187 | for v in keyConfigList { 188 | key := gc.%v.config "3"%.Value 189 | writeIni(v.config, key) 190 | } 191 | fn_restart() 192 | } 193 | g.OnEvent("Close", e_close) 194 | e_close(*) { 195 | g.Destroy() 196 | } 197 | gc.w.hotKeyGui := g 198 | return g 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /src/utils/ini.ahk: -------------------------------------------------------------------------------- 1 | ; InputTip 2 | 3 | /** 4 | * 读取配置文件 5 | * @param {String}key 配置文件中的键名 6 | * @param default 默认值 7 | * @param {"InputMethod" | "Config-v2"} section 配置文件中的分区名 8 | * @param {String} path 配置文件的路径 9 | * @returns {String} 配置文件中的值 10 | */ 11 | readIni(key, default, section := "Config-v2", path := "InputTip.ini") { 12 | try { 13 | return IniRead(path, section, key) 14 | } catch { 15 | try { 16 | IniWrite('"' default '"', path, section, key) 17 | } catch { 18 | createTipGui([{ 19 | opt: "cRed", 20 | text: "配置文件写入失败`n请重启 InputTip", 21 | }], "InputTip - 错误").Show() 22 | } 23 | return default 24 | } 25 | } 26 | /** 27 | * 写入配置文件 28 | * @param key 配置文件中的键名 29 | * @param value 要写入的值 30 | * @param {"InputMethod" | "Config-v2"} section 配置文件中的分区名 31 | * @param {String} path 配置文件的路径 32 | */ 33 | writeIni(key, value, section := "Config-v2", path := "InputTip.ini") { 34 | try { 35 | IniWrite('"' value '"', path, section, key) 36 | } catch { 37 | createTipGui([{ 38 | opt: "cRed", 39 | text: "配置文件写入失败`n请重启 InputTip", 40 | }], "InputTip - 错误").Show() 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/utils/options.ahk: -------------------------------------------------------------------------------- 1 | ; InputTip 2 | 3 | #Requires AutoHotkey v2.0 4 | ;@AHK2Exe-SetLanguage 0x0804 5 | ;@Ahk2Exe-SetMainIcon img/favicon.ico 6 | ;@Ahk2Exe-SetCopyright Copyright (c) 2023-present abgox 7 | #SingleInstance Force 8 | #Warn All, Off 9 | 10 | Persistent 11 | ListLines 0 12 | KeyHistory 5 13 | DetectHiddenWindows 1 14 | InstallKeybdHook 15 | CoordMode 'Mouse', 'Screen' 16 | SetStoreCapsLockMode 0 17 | 18 | ;@AHK2Exe-SetVersion 2.38.0 19 | currentVersion := "2.38.0" 20 | -------------------------------------------------------------------------------- /src/utils/show.ahk: -------------------------------------------------------------------------------- 1 | ; InputTip 2 | 3 | updateDelay() 4 | 5 | ; 鼠标悬浮在符号上 6 | isOverSymbol := 0 7 | while 1 { 8 | Sleep(delay) 9 | ; 正在使用鼠标或有键盘操作 10 | if (A_TimeIdle < leaveDelay) { 11 | needShow := symbolType 12 | if (symbolType && hoverHide) { 13 | if (isMouseOver("abgox-InputTip-Symbol-Window")) { 14 | hideSymbol() 15 | isOverSymbol := 1 16 | continue 17 | } 18 | } 19 | try { 20 | exe_name := ProcessGetName(WinGetPID("A")) 21 | exe_str := ":" exe_name ":" 22 | } catch { 23 | hideSymbol() 24 | needShow := 0 25 | } 26 | if (symbolType) { 27 | if (needSkip(exe_str)) { 28 | hideSymbol() 29 | lastSymbol := "" 30 | lastCursor := "" 31 | lastWindow := "" 32 | continue 33 | } 34 | if (useWhiteList) { 35 | if (!showCursorPos && !InStr(app_show_state, exe_str) && !WinActive("ahk_class AutoHotkeyGUI")) { 36 | hideSymbol() 37 | needShow := 0 38 | } 39 | } else { 40 | if (InStr(app_hide_state, exe_str)) { 41 | hideSymbol() 42 | needShow := 0 43 | } 44 | } 45 | } 46 | if (needHide) { 47 | hideSymbol() 48 | needShow := 0 49 | } 50 | if (exe_name != lastWindow) { 51 | WinWaitActive("ahk_exe " exe_name) 52 | lastSymbol := "" 53 | lastCursor := "" 54 | lastWindow := exe_name 55 | if (InStr(app_CN, exe_str)) { 56 | switch_CN() 57 | if (isCN()) { 58 | loadCursor("CN", 1) 59 | ShowSymbolEx("CN") 60 | } 61 | } else if (InStr(app_EN, exe_str)) { 62 | switch_EN() 63 | if (!isCN()) { 64 | loadCursor("EN", 1) 65 | ShowSymbolEx("EN") 66 | } 67 | } else if (InStr(app_Caps, exe_str)) { 68 | switch_Caps() 69 | if (GetKeyState("CapsLock", "T")) { 70 | loadCursor("Caps", 1) 71 | ShowSymbolEx("Caps") 72 | } 73 | } 74 | } 75 | if (GetKeyState("CapsLock", "T")) { 76 | loadCursor("Caps") 77 | ShowSymbolEx("Caps") 78 | continue 79 | } 80 | try { 81 | v := isCN() ? "CN" : "EN" 82 | } catch { 83 | hideSymbol() 84 | continue 85 | } 86 | loadCursor(v) 87 | ShowSymbolEx(v) 88 | } 89 | } 90 | 91 | ShowSymbolEx(state) { 92 | global canShowSymbol 93 | if (needShow) { 94 | if (showCursorPos || InStr(showCursorPosList, exe_str)) { 95 | try { 96 | MouseGetPos(&left, &top) 97 | canShowSymbol := 1 98 | loadSymbol(state, left, top, left, top, 1) 99 | } catch { 100 | hideSymbol() 101 | } 102 | return 103 | } 104 | try { 105 | canShowSymbol := returnCanShowSymbol(&left, &top, &right, &bottom) 106 | 107 | WinGetPos(&x, &y, &w, &h, "A") 108 | if (top < y || top > y + h) { 109 | hideSymbol() 110 | return 111 | } 112 | loadSymbol(state, left, top, right, bottom) 113 | } catch { 114 | hideSymbol() 115 | } 116 | } 117 | } 118 | 119 | updateDelay() { 120 | if (hideSymbolDelay) { 121 | SetTimer(updateDelayTimer, 25) 122 | updateDelayTimer() { 123 | global needHide, isWait 124 | if (GetKeyState("LButton", "P")) { 125 | needHide := 0 126 | isWait := 1 127 | SetTimer(_timer, -hideSymbolDelay) 128 | _timer() { 129 | isWait := 0 130 | } 131 | } 132 | if (!isWait) { 133 | if (A_TimeIdleKeyboard >= hideSymbolDelay - delay) { 134 | needHide := 1 135 | hideSymbol() 136 | } else { 137 | needHide := 0 138 | } 139 | } 140 | if (hideSymbolDelay = 0) { 141 | SetTimer(updateDelayTimer, 0) 142 | needHide := 0 143 | isWait := 0 144 | } 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/utils/tools.ahk: -------------------------------------------------------------------------------- 1 | ; InputTip 2 | 3 | /** 4 | * 将数组转换成字符串,并用指定分隔符连接 5 | * @param {Array} arr 数组 6 | * @param {String} separator 分隔符 7 | * @returns {String} 连接后的字符串 8 | */ 9 | arrJoin(arr, separator := ",") { 10 | res := "" 11 | for i, v in arr { 12 | res .= i = arr.Length ? v : v separator 13 | } 14 | return res 15 | } 16 | 17 | /** 18 | * 检查是否存在子目录 19 | * @param {String} path 目录路径 20 | * @returns 是否存在子目录 21 | */ 22 | hasChildDir(path) { 23 | Loop Files path "\*", "D" { 24 | return A_Index 25 | } 26 | } 27 | 28 | /** 29 | * 鼠标是否悬浮在指定窗口上 30 | * @param WinTitle 窗口标题 31 | * @returns 是否悬浮在窗口上 32 | */ 33 | isMouseOver(WinTitle) { 34 | try { 35 | MouseGetPos(, , &Win) 36 | return WinExist(WinTitle " ahk_id " Win) 37 | } 38 | return 0 39 | } 40 | 41 | /** 42 | * 替换环境变量中的变量 43 | * @param {String} str 环境变量 44 | * @returns {String} 替换后的字符串 45 | */ 46 | replaceEnvVariables(str) { 47 | while RegExMatch(str, "%\w+%", &match) { 48 | env := match[] 49 | envValue := EnvGet(StrReplace(env, "%", "")) 50 | str := StrReplace(str, env, envValue) 51 | } 52 | return str 53 | } 54 | 55 | /** 56 | * 获取到屏幕信息 57 | * @returns {Array} 一个数组 [{num:1,left:0,top:0,right:0,bottom:0}] 58 | */ 59 | getScreenInfo() { 60 | list := [] 61 | MonitorCount := MonitorGetCount() 62 | MonitorPrimary := MonitorGetPrimary() 63 | Loop MonitorCount 64 | { 65 | MonitorGet A_Index, &L, &T, &R, &B 66 | MonitorGetWorkArea A_Index, &WL, &WT, &WR, &WB 67 | list.Push({ 68 | main: MonitorPrimary, 69 | count: MonitorCount, 70 | num: A_Index, 71 | left: L, 72 | top: T, 73 | right: R, 74 | bottom: B 75 | }) 76 | } 77 | return list 78 | } 79 | 80 | /** 81 | * 激活的窗口在哪个屏幕 82 | * 83 | * 调用时外层必须使用 try 包裹,因为 MouseGetPos 在极少数情况下,会因为权限问题报错拒绝访问 84 | * @example 85 | * try { 86 | * isWhichScreen() 87 | * ; ... 88 | * } 89 | */ 90 | isWhichScreen(screenList) { 91 | try { 92 | WinGetClientPos(&x, &y, &w, &h, "A") 93 | 94 | ; 窗口的中心坐标 95 | cx := x + w / 2 96 | cy := y + h / 2 97 | } catch { 98 | return "" 99 | } 100 | 101 | for v in screenList { 102 | if (cx >= v.left && cx <= v.right && cy >= v.top && cy <= v.bottom) { 103 | return v 104 | } 105 | } 106 | } 107 | 108 | ; 从字符串中提取出数字,可以带负号 109 | returnNumber(value) { 110 | if (value = "" || !(value ~= "\d")) { 111 | return 0 112 | } 113 | RegExMatch(value, "(-?\d+)", &numbers) 114 | return numbers[1] 115 | } 116 | -------------------------------------------------------------------------------- /src/utils/verify-file.ahk: -------------------------------------------------------------------------------- 1 | ; InputTip 2 | 3 | dirList := ["InputTipSymbol", "InputTipSymbol/default", "InputTipCursor", "InputTipCursor/default", "InputTipCursor/default/CN", "InputTipCursor/default/EN", "InputTipCursor/default/Caps"] 4 | 5 | for d in dirList { 6 | if (!DirExist(d)) { 7 | DirCreate(d) 8 | } 9 | } 10 | 11 | if (A_IsCompiled) { 12 | if (!FileExist("InputTipSymbol/default/CN.png")) { 13 | FileInstall("InputTipSymbol/default/CN.png", "InputTipSymbol/default/CN.png", 1) 14 | } 15 | if (!FileExist("InputTipSymbol/default/EN.png")) { 16 | FileInstall("InputTipSymbol/default/EN.png", "InputTipSymbol/default/EN.png", 1) 17 | } 18 | if (!FileExist("InputTipSymbol/default/Caps.png")) { 19 | FileInstall("InputTipSymbol/default/Caps.png", "InputTipSymbol/default/Caps.png", 1) 20 | } 21 | if (!FileExist("InputTipSymbol/default/offer.png")) { 22 | FileInstall("InputTipSymbol/default/offer.png", "InputTipSymbol/default/offer.png", 1) 23 | } 24 | if (!FileExist("InputTipSymbol/default/favicon.png")) { 25 | FileInstall("InputTipSymbol/default/favicon.png", "InputTipSymbol/default/favicon.png", 1) 26 | } 27 | if (!FileExist("InputTipSymbol/default/favicon-pause.png")) { 28 | FileInstall("InputTipSymbol/default/favicon-pause.png", "InputTipSymbol/default/favicon-pause.png", 1) 29 | } 30 | 31 | if (!FileExist("InputTipCursor/default/CN/AppStarting.ani")) { 32 | FileInstall("InputTipCursor/default/CN/AppStarting.ani", "InputTipCursor/default/CN/AppStarting.ani", 1) 33 | } 34 | if (!FileExist("InputTipCursor/default/CN/Arrow.cur")) { 35 | FileInstall("InputTipCursor/default/CN/Arrow.cur", "InputTipCursor/default/CN/Arrow.cur", 1) 36 | } 37 | if (!FileExist("InputTipCursor/default/CN/Cross.cur")) { 38 | FileInstall("InputTipCursor/default/CN/Cross.cur", "InputTipCursor/default/CN/Cross.cur", 1) 39 | } 40 | if (!FileExist("InputTipCursor/default/CN/Hand.cur")) { 41 | FileInstall("InputTipCursor/default/CN/Hand.cur", "InputTipCursor/default/CN/Hand.cur", 1) 42 | } 43 | if (!FileExist("InputTipCursor/default/CN/Help.cur")) { 44 | FileInstall("InputTipCursor/default/CN/Help.cur", "InputTipCursor/default/CN/Help.cur", 1) 45 | } 46 | if (!FileExist("InputTipCursor/default/CN/IBeam.cur")) { 47 | FileInstall("InputTipCursor/default/CN/IBeam.cur", "InputTipCursor/default/CN/IBeam.cur", 1) 48 | } 49 | if (!FileExist("InputTipCursor/default/CN/No.cur")) { 50 | FileInstall("InputTipCursor/default/CN/No.cur", "InputTipCursor/default/CN/No.cur", 1) 51 | } 52 | if (!FileExist("InputTipCursor/default/CN/Pen.cur")) { 53 | FileInstall("InputTipCursor/default/CN/Pen.cur", "InputTipCursor/default/CN/Pen.cur", 1) 54 | } 55 | if (!FileExist("InputTipCursor/default/CN/SizeAll.cur")) { 56 | FileInstall("InputTipCursor/default/CN/SizeAll.cur", "InputTipCursor/default/CN/SizeAll.cur", 1) 57 | } 58 | if (!FileExist("InputTipCursor/default/CN/SizeNESW.cur")) { 59 | FileInstall("InputTipCursor/default/CN/SizeNESW.cur", "InputTipCursor/default/CN/SizeNESW.cur", 1) 60 | } 61 | if (!FileExist("InputTipCursor/default/CN/SizeNS.cur")) { 62 | FileInstall("InputTipCursor/default/CN/SizeNS.cur", "InputTipCursor/default/CN/SizeNS.cur", 1) 63 | } 64 | if (!FileExist("InputTipCursor/default/CN/SizeNWSE.cur")) { 65 | FileInstall("InputTipCursor/default/CN/SizeNWSE.cur", "InputTipCursor/default/CN/SizeNWSE.cur", 1) 66 | } 67 | if (!FileExist("InputTipCursor/default/CN/SizeWE.cur")) { 68 | FileInstall("InputTipCursor/default/CN/SizeWE.cur", "InputTipCursor/default/CN/SizeWE.cur", 1) 69 | } 70 | if (!FileExist("InputTipCursor/default/CN/UpArrow.cur")) { 71 | FileInstall("InputTipCursor/default/CN/UpArrow.cur", "InputTipCursor/default/CN/UpArrow.cur", 1) 72 | } 73 | if (!FileExist("InputTipCursor/default/CN/Wait.ani")) { 74 | FileInstall("InputTipCursor/default/CN/Wait.ani", "InputTipCursor/default/CN/Wait.ani", 1) 75 | } 76 | 77 | if (!FileExist("InputTipCursor/default/EN/AppStarting.ani")) { 78 | FileInstall("InputTipCursor/default/EN/AppStarting.ani", "InputTipCursor/default/EN/AppStarting.ani", 1) 79 | } 80 | if (!FileExist("InputTipCursor/default/EN/Arrow.cur")) { 81 | FileInstall("InputTipCursor/default/EN/Arrow.cur", "InputTipCursor/default/EN/Arrow.cur", 1) 82 | } 83 | if (!FileExist("InputTipCursor/default/EN/Cross.cur")) { 84 | FileInstall("InputTipCursor/default/EN/Cross.cur", "InputTipCursor/default/EN/Cross.cur", 1) 85 | } 86 | if (!FileExist("InputTipCursor/default/EN/Hand.cur")) { 87 | FileInstall("InputTipCursor/default/EN/Hand.cur", "InputTipCursor/default/EN/Hand.cur", 1) 88 | } 89 | if (!FileExist("InputTipCursor/default/EN/Help.cur")) { 90 | FileInstall("InputTipCursor/default/EN/Help.cur", "InputTipCursor/default/EN/Help.cur", 1) 91 | } 92 | if (!FileExist("InputTipCursor/default/EN/IBeam.cur")) { 93 | FileInstall("InputTipCursor/default/EN/IBeam.cur", "InputTipCursor/default/EN/IBeam.cur", 1) 94 | } 95 | if (!FileExist("InputTipCursor/default/EN/No.cur")) { 96 | FileInstall("InputTipCursor/default/EN/No.cur", "InputTipCursor/default/EN/No.cur", 1) 97 | } 98 | if (!FileExist("InputTipCursor/default/EN/Pen.cur")) { 99 | FileInstall("InputTipCursor/default/EN/Pen.cur", "InputTipCursor/default/EN/Pen.cur", 1) 100 | } 101 | if (!FileExist("InputTipCursor/default/EN/SizeAll.cur")) { 102 | FileInstall("InputTipCursor/default/EN/SizeAll.cur", "InputTipCursor/default/EN/SizeAll.cur", 1) 103 | } 104 | if (!FileExist("InputTipCursor/default/EN/SizeNESW.cur")) { 105 | FileInstall("InputTipCursor/default/EN/SizeNESW.cur", "InputTipCursor/default/EN/SizeNESW.cur", 1) 106 | } 107 | if (!FileExist("InputTipCursor/default/EN/SizeNS.cur")) { 108 | FileInstall("InputTipCursor/default/EN/SizeNS.cur", "InputTipCursor/default/EN/SizeNS.cur", 1) 109 | } 110 | if (!FileExist("InputTipCursor/default/EN/SizeNWSE.cur")) { 111 | FileInstall("InputTipCursor/default/EN/SizeNWSE.cur", "InputTipCursor/default/EN/SizeNWSE.cur", 1) 112 | } 113 | if (!FileExist("InputTipCursor/default/EN/SizeWE.cur")) { 114 | FileInstall("InputTipCursor/default/EN/SizeWE.cur", "InputTipCursor/default/EN/SizeWE.cur", 1) 115 | } 116 | if (!FileExist("InputTipCursor/default/EN/UpArrow.cur")) { 117 | FileInstall("InputTipCursor/default/EN/UpArrow.cur", "InputTipCursor/default/EN/UpArrow.cur", 1) 118 | } 119 | if (!FileExist("InputTipCursor/default/EN/Wait.ani")) { 120 | FileInstall("InputTipCursor/default/EN/Wait.ani", "InputTipCursor/default/EN/Wait.ani", 1) 121 | } 122 | 123 | if (!FileExist("InputTipCursor/default/Caps/AppStarting.ani")) { 124 | FileInstall("InputTipCursor/default/Caps/AppStarting.ani", "InputTipCursor/default/Caps/AppStarting.ani", 1) 125 | } 126 | if (!FileExist("InputTipCursor/default/Caps/Arrow.cur")) { 127 | FileInstall("InputTipCursor/default/Caps/Arrow.cur", "InputTipCursor/default/Caps/Arrow.cur", 1) 128 | } 129 | if (!FileExist("InputTipCursor/default/Caps/Cross.cur")) { 130 | FileInstall("InputTipCursor/default/Caps/Cross.cur", "InputTipCursor/default/Caps/Cross.cur", 1) 131 | } 132 | if (!FileExist("InputTipCursor/default/Caps/Hand.cur")) { 133 | FileInstall("InputTipCursor/default/Caps/Hand.cur", "InputTipCursor/default/Caps/Hand.cur", 1) 134 | } 135 | if (!FileExist("InputTipCursor/default/Caps/Help.cur")) { 136 | FileInstall("InputTipCursor/default/Caps/Help.cur", "InputTipCursor/default/Caps/Help.cur", 1) 137 | } 138 | if (!FileExist("InputTipCursor/default/Caps/IBeam.cur")) { 139 | FileInstall("InputTipCursor/default/Caps/IBeam.cur", "InputTipCursor/default/Caps/IBeam.cur", 1) 140 | } 141 | if (!FileExist("InputTipCursor/default/Caps/No.cur")) { 142 | FileInstall("InputTipCursor/default/Caps/No.cur", "InputTipCursor/default/Caps/No.cur", 1) 143 | } 144 | if (!FileExist("InputTipCursor/default/Caps/Pen.cur")) { 145 | FileInstall("InputTipCursor/default/Caps/Pen.cur", "InputTipCursor/default/Caps/Pen.cur", 1) 146 | } 147 | if (!FileExist("InputTipCursor/default/Caps/SizeAll.cur")) { 148 | FileInstall("InputTipCursor/default/Caps/SizeAll.cur", "InputTipCursor/default/Caps/SizeAll.cur", 1) 149 | } 150 | if (!FileExist("InputTipCursor/default/Caps/SizeNESW.cur")) { 151 | FileInstall("InputTipCursor/default/Caps/SizeNESW.cur", "InputTipCursor/default/Caps/SizeNESW.cur", 1) 152 | } 153 | if (!FileExist("InputTipCursor/default/Caps/SizeNS.cur")) { 154 | FileInstall("InputTipCursor/default/Caps/SizeNS.cur", "InputTipCursor/default/Caps/SizeNS.cur", 1) 155 | } 156 | if (!FileExist("InputTipCursor/default/Caps/SizeNWSE.cur")) { 157 | FileInstall("InputTipCursor/default/Caps/SizeNWSE.cur", "InputTipCursor/default/Caps/SizeNWSE.cur", 1) 158 | } 159 | if (!FileExist("InputTipCursor/default/Caps/SizeWE.cur")) { 160 | FileInstall("InputTipCursor/default/Caps/SizeWE.cur", "InputTipCursor/default/Caps/SizeWE.cur", 1) 161 | } 162 | if (!FileExist("InputTipCursor/default/Caps/UpArrow.cur")) { 163 | FileInstall("InputTipCursor/default/Caps/UpArrow.cur", "InputTipCursor/default/Caps/UpArrow.cur", 1) 164 | } 165 | if (!FileExist("InputTipCursor/default/Caps/Wait.ani")) { 166 | FileInstall("InputTipCursor/default/Caps/Wait.ani", "InputTipCursor/default/Caps/Wait.ani", 1) 167 | } 168 | } else { 169 | if (!FileExist("../InputTip.bat")) { 170 | FileAppend('REM InputTip.bat' "`n" 'start "" /min "%~dp0\src\AutoHotkey\AutoHotkey64.exe" "%~dp0\src\InputTip.ahk"`n', "..\InputTip.bat", "`n UTF-8-Raw") 171 | } 172 | 173 | ; 丢失的文件列表 174 | missFileList := [] 175 | 176 | pngList := [ 177 | "InputTipSymbol/default/CN.png", 178 | "InputTipSymbol/default/EN.png", 179 | "InputTipSymbol/default/Caps.png", 180 | "InputTipSymbol/default/offer.png", 181 | "InputTipSymbol/default/favicon.png", 182 | "InputTipSymbol/default/favicon-pause.png", 183 | "img/favicon.ico" 184 | ] 185 | for v in pngList { 186 | if (!FileExist(v)) { 187 | missFileList.Push(v) 188 | } 189 | } 190 | styleList := [ 191 | "AppStarting.ani", "Arrow.cur", "Cross.cur", "Hand.cur", "Help.cur", "IBeam.cur", "No.cur", "Pen.cur", "SizeAll.cur", "SizeNESW.cur", "SizeNS.cur", "SizeNWSE.cur", "SizeWE.cur", "UpArrow.cur", "Wait.ani" 192 | ] 193 | for v in ["CN", "EN", "Caps"] { 194 | for s in styleList { 195 | p := "InputTipCursor/default/" v "/" s 196 | if (!FileExist(p)) { 197 | missFileList.Push(p) 198 | } 199 | } 200 | } 201 | if (missFileList.Length) { 202 | fontOpt := ["s" readIni("gui_font_size", "12"), "Microsoft YaHei"] 203 | downloading(*) { 204 | 205 | g := createGuiOpt("InputTip - 正在处理文件丢失...") 206 | g.AddText(, "正在下载丢失的文件: ") 207 | g.tip := g.AddText("xs cRed", "------------------------------------------------------------") 208 | 209 | g.AddText("xs", "------------------------------------------------------------") 210 | g.AddText("xs", "官网:") 211 | g.AddLink("yp", 'https://inputtip.abgox.com') 212 | g.AddText("xs", "Github:") 213 | g.AddLink("yp", 'https://github.com/abgox/InputTip') 214 | g.AddText("xs", "Gitee: :") 215 | g.AddLink("yp", 'https://gitee.com/abgox/InputTip') 216 | g.AddLink("xs", '版本更新日志: 官网 Github Gitee') 217 | g.Show() 218 | g.OnEvent("Close", downloading) 219 | return g 220 | } 221 | downloadingGui := downloading() 222 | 223 | done := 1 224 | fileCount := missFileList.Length 225 | for i, f in missFileList { 226 | for u in baseUrl { 227 | downloadingGui.tip.Text := i '/' fileCount " : " f 228 | dir := RegExReplace(f, "/[^/]*$", "") 229 | try { 230 | if (!DirExist(dir)) { 231 | DirCreate(dir) 232 | } 233 | Download(u "src/" f, f) 234 | break 235 | } 236 | } 237 | 238 | if (!FileExist(f)) { 239 | done := 0 240 | break 241 | } 242 | } 243 | downloadingGui.Destroy() 244 | 245 | if (!done) { 246 | createGui(errGui).Show() 247 | errGui(info) { 248 | g := createGuiOpt("InputTip - 正在处理文件丢失...") 249 | g.AddText("cRed", "可能因为网络等其他原因,文件没有正常恢复,请手动处理") 250 | g.AddLink("cGray", '你可以前往 官网 Github Github 手动下载') 251 | if (info.i) { 252 | return g 253 | } 254 | w := info.w 255 | bw := w - g.MarginX * 2 256 | 257 | y := g.AddButton("xs w" bw, "我知道了") 258 | y.Focus() 259 | y.OnEvent("Click", yes) 260 | g.OnEvent("Close", yes) 261 | yes(*) { 262 | g.Destroy() 263 | } 264 | return g 265 | } 266 | } 267 | } 268 | } 269 | 270 | 271 | /** 272 | * 检查文件是否存在,如果不存在,从远程获取 273 | * @param urlPath 基于 baseUrl 的相对路径 274 | * @param filePath 文件路径 275 | */ 276 | ensureFile(urlPath, filePath) { 277 | if (FileExist(filePath)) { 278 | return 279 | } 280 | done := 0 281 | for u in baseUrl { 282 | dir := RegExReplace(filePath, "/[^/]*$", "") 283 | try { 284 | if (!DirExist(dir)) { 285 | DirCreate(dir) 286 | } 287 | Download(u urlPath, filePath) 288 | done := 1 289 | break 290 | } 291 | } 292 | } 293 | 294 | /** 295 | * - 检查配置文件 296 | * - 当配置文件不存在(无法读取 mode 配置项)时,进入初始化引导 297 | */ 298 | checkIni() { 299 | try { 300 | mode := IniRead("InputTip.ini", "InputMethod", "mode") 301 | } catch { 302 | gc.init := 1 303 | 304 | userName := readIni("userName", A_UserName, "UserInfo") 305 | 306 | ; 输入法模式 307 | mode := readIni("mode", 1, "InputMethod") 308 | 309 | ; 是否使用白名单机制,如果是第一次使用,就直接使用白名单机制 310 | useWhiteList := readIni("useWhiteList", 1) 311 | 312 | fz := "s14" 313 | createGui(confirmGui).Show() 314 | confirmGui(info) { 315 | g := Gui("AlwaysOnTop", "InputTip - 初始化引导") 316 | g.SetFont(fz, "Microsoft YaHei") 317 | g.AddText(, "你是否希望 InputTip 修改鼠标样式?") 318 | g.AddText("xs cRed", "InputTip 会根据不同输入法状态同步修改鼠标样式") 319 | g.AddEdit("xs Disabled -VScroll", "更多详情,请点击「托盘菜单」中的「关于」,前往官网或项目中查看") 320 | 321 | if (info.i) { 322 | return g 323 | } 324 | w := info.w 325 | bw := w - g.MarginX * 2 326 | 327 | g.AddButton("xs cRed w" bw, "【是】修改鼠标样式").OnEvent("Click", e_yes) 328 | e_yes(*) { 329 | g.Destroy() 330 | createGui(yesGui).Show() 331 | yesGui(info) { 332 | g := Gui("AlwaysOnTop") 333 | g.SetFont(fz, "Microsoft YaHei") 334 | g.AddText(, "你真的确定要修改鼠标样式吗?") 335 | g.AddText("cRed", "请谨慎选择,如果误点了确定,恢复鼠标样式需要以下步骤: `n 1. 点击「托盘菜单」=>「更改配置」`n 2. 将「1. 是否同步修改鼠标样式」的值更改为【否】") 336 | 337 | if (info.i) { 338 | return g 339 | } 340 | w := info.w 341 | bw := w - g.MarginX * 2 342 | 343 | g.AddButton("xs cRed w" bw, "【是】对,我很确定").OnEvent("Click", e_yes) 344 | e_yes(*) { 345 | g.Destroy() 346 | writeIni("changeCursor", 1) 347 | global changeCursor := 1 348 | initWhiteList() 349 | } 350 | g.AddButton("w" bw, "【否】不,我点错了").OnEvent("Click", e_no) 351 | e_no(*) { 352 | g.Destroy() 353 | writeIni("changeCursor", 0) 354 | global changeCursor := 0 355 | initWhiteList() 356 | } 357 | return g 358 | } 359 | } 360 | g.AddButton("w" bw, "【否】保留现有样式").OnEvent("Click", e_no) 361 | e_no(*) { 362 | g.Destroy() 363 | writeIni("changeCursor", 0) 364 | global changeCursor := 0 365 | initWhiteList() 366 | } 367 | g.OnEvent("Close", e_exit) 368 | e_exit(*) { 369 | try { 370 | IniDelete("InputTip.ini", "InputMethod", "mode") 371 | } 372 | ExitApp() 373 | } 374 | return g 375 | } 376 | initWhiteList() { 377 | createGui(listTipGui).Show() 378 | listTipGui(info) { 379 | g := Gui("AlwaysOnTop", "InputTip - 初始化引导") 380 | g.SetFont(fz, "Microsoft YaHei") 381 | g.AddText("cRed", "对于符号显示,InputTip 现在默认使用白名单机制。") 382 | g.AddLink("cRed", '白名单机制 : 只有在白名单中的应用进程窗口会显示符号。') 383 | g.AddText(, "建议立即添加你常用的应用进程窗口到白名单中。") 384 | 385 | if (info.i) { 386 | return g 387 | } 388 | w := info.w 389 | bw := w - g.MarginX * 2 390 | 391 | _c := g.AddButton("w" bw, "【是】现在去添加") 392 | _c.Focus() 393 | _c.OnEvent("Click", add_white_list) 394 | add_white_list(*) { 395 | close() 396 | fn_white_list() 397 | } 398 | g.AddButton("w" bw, "【否】暂时不添加").OnEvent("Click", close) 399 | close(*) { 400 | g.Destroy() 401 | gc.init := 0 402 | checkUpdate(1, 1) 403 | } 404 | return g 405 | } 406 | } 407 | } 408 | } 409 | -------------------------------------------------------------------------------- /src/version.txt: -------------------------------------------------------------------------------- 1 | 2.38.0 2 | --------------------------------------------------------------------------------