├── README.md ├── LICENSE └── ALTRun.ahk /README.md: -------------------------------------------------------------------------------- 1 |

ALTRun ALTRun

2 | 3 | ALTRun (AHK) 是一款开源免费、简洁高效、功能强大的启动工具 4 | 5 | > 主界面 6 | 7 | ![GUI](https://github.com/user-attachments/assets/a9da445b-4386-4118-bfb7-5bd2c5972efa) 8 | 9 | > 主界面 (无背景图片+简化+暗黑模式) 10 | 11 | ![Dark](https://github.com/user-attachments/assets/5bd76455-4eda-42e5-9934-c915b48994df) 12 | 13 | 14 | ## 特性 15 | - 绿色便携和轻量化, 不修改系统注册表 16 | - 低资源占用, 单程序文件 < 1MB,内存占用 < 10MB 17 | - 支持模糊搜索, 智能匹配 18 | - 支持搜索时匹配中文拼音首字母 19 | - 支持自定义命令、批量管理、命令分组 20 | - 支持优先级智能排序, 根据使用频率自动调整命令 21 | - 支持历史记录 22 | - 支持通过"发送到"菜单,快速创建命令 23 | - 支持 Everything 搜索集成 24 | - 支持 Total Commander 文件管理集成 25 | - 支持多种热键自定义, 多快捷键支持 26 | - 支持数学表达式计算, 结构计算表达式 27 | - 支持中英文界面自动切换 28 | - 支持深度自定义, 托盘菜单、右键菜单、主窗口自定义 29 | - 暗黑模式支持,可按照需求深度自定义 30 | - 提供右键菜单和命令管理器,操作更便捷 31 | - 支持自动添加日期到文件名/备注 32 | - 支持类似 Listary 快速切换目录功能 33 | 34 | 35 | ## 快速开始 36 | 1. [下载程序](https://github.com/zhugecaomao/ALTRun/releases) 37 | 2. 双击运行 `ALTRun.exe` 38 | 3. 使用 `Alt+Space` 或自定义热键呼出主界面 39 | 4. 输入关键词搜索和运行命令 40 | 41 | 42 | ## 常用热键 43 | - `Alt+Space` / `Alt+R`:显示/隐藏主窗口 44 | - `Esc` / `失去焦点`:隐藏主窗口 45 | - `上下箭头`: 选择上一个或下一个命令 46 | - `回车`: 运行命令 47 | - `F1`:帮助关于 48 | - `F2`:配置选项 49 | - `F3`:编辑当前命令 50 | - `F4`:直接修改设置文件 51 | - `Ctrl+D`:用文件管理器定位命令所在目录 52 | - `Ctrl+D`:重命名文件(夹) (在重命名框时自动激活) 53 | - `Ctrl+G`:打开/保存对话框路径快速跳转到 Total Commander 目录 54 | - `Ctrl+E`:打开/保存对话框路径快速跳转到 资源管理器 目录 55 | - `Ctrl+I`:重建索引数据库 56 | - `Ctrl+Q`:重载脚本 57 | - `上下箭头`:切换命令 58 | - `鼠标滚轮`:切换命令 59 | - `Alt+序号`:运行对应序号命令 60 | - `Ctrl+序号`:定位到对应序号命令 61 | - `鼠标中键`:运行命令 62 | 63 | 64 | 65 | ## 配置说明 66 | 所有配置、命令、历史记录均保存在程序目录下的 `ALTRun.ini` 文件中 67 | 68 | 可通过主界面或托盘菜单进入“配置选项”进行详细设置 69 | 70 | 71 | ## 贡献 72 | 欢迎提交 Issue 和 PR,或在 [Discussions](https://github.com/zhugecaomao/ALTRun/discussions) 交流建议 73 | 74 | 如果你喜欢这个项目,请给它一个星标 ⭐ 75 | 76 | 77 | ## 其他说明 78 | 更多详细用法、FAQ、进阶技巧请见 [Wiki](https://github.com/zhugecaomao/ALTRun/wiki) 79 | 80 | 特别感谢 [ALTRun by etworker](https://github.com/etworker/ALTRun) (Delphi) 和 [RunZ by goreliu](https://github.com/goreliu/runz) (AutoHotkey) 81 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /ALTRun.ahk: -------------------------------------------------------------------------------- 1 | ;=================================================== 2 | ; ALTRun - An effective launcher for Windows 3 | ; https://github.com/zhugecaomao/ALTRun 4 | ;=================================================== 5 | #Requires AutoHotkey v2.0 6 | #SingleInstance Force 7 | #NoTrayIcon 8 | #Warn All, OutputDebug 9 | SetWorkingDir(A_ScriptDir) 10 | FileEncoding("UTF-8") 11 | 12 | ;@Ahk2Exe-SetName ALTRun 13 | ;@Ahk2Exe-SetDescription ALTRun - An effective launcher for Windows 14 | ;@Ahk2Exe-SetVersion 2025.12.01 15 | ;@Ahk2Exe-SetCopyright Copyright (c) since 2013 16 | ;@Ahk2Exe-SetOrigFilename ALTRun.ahk 17 | 18 | 19 | ;=================================================== 20 | ; 声明全局变量, 默认情况下, 函数是假定-局部的 21 | ; 在函数内访问或创建的变量默认为局部的, 但以下情况除外: 22 | ; - 全局变量只能被函数读取, 不能被赋值或使用引用运算符(&). 23 | ; - 嵌套函数可以引用由闭合它的函数创建的局部或静态变量. 24 | ; 内置类, 如 Object; 它们被预定义为全局变量 25 | ;=================================================== 26 | Global g_LOG := Logger(A_Temp . "\ALTRun.log") 27 | Global g_INI := A_ScriptDir . "\ALTRun.ini" 28 | Global g_TITLE := "ALTRun - v2025.12.01" 29 | 30 | Global g_COMMANDS := Array() ; All commands 31 | Global g_CMDINDEX := Array() ; Searchable text for All commands 32 | Global g_FALLBACK := Array() ; Fallback commands 33 | Global g_HISTORYS := Array() ; Execution history 34 | Global g_MATCHED := Array() ; Matched commands 35 | Global g_SECTION := Map( 36 | "CONFIG" , "Config", 37 | "GUI" , "Gui", 38 | "DFTCMD" , "DefaultCommand", 39 | "USERCMD" , "UserCommand", 40 | "FALLBACK" , "FallbackCommand", 41 | "HOTKEY" , "Hotkey", 42 | "HISTORY" , "History", 43 | "INDEX" , "Index", 44 | "USAGE" , "Usage" 45 | ) 46 | 47 | Global g_CONFIG := Map( 48 | "AutoStartup" , 1, 49 | "EnableSendTo" , 1, 50 | "InStartMenu" , 1, 51 | "ShowTrayIcon" , 1, 52 | "HideOnLostFocus", 1, 53 | "AlwaysOnTop" , 1, 54 | "ShowCaption" , 0, 55 | "XPthemeBg" , 1, 56 | "EscClearInput" , 1, 57 | "KeepInput" , 1, 58 | "ShowIcon" , 1, 59 | "LargeIcons" , 1, 60 | "SendToGetLnk" , 1, 61 | "SaveHistory" , 1, 62 | "SaveLog" , 1, 63 | "MatchPath" , 0, 64 | "ShowGrid" , 0, 65 | "ShowHdr" , 0, 66 | "ShowSN" , 1, 67 | "ShowBorder" , 1, 68 | "SmartRank" , 1, 69 | "SmartMatch" , 1, 70 | "MatchBeginning" , 0, 71 | "ShowHint" , 1, 72 | "ShowRunCount" , 1, 73 | "ShowStatusBar" , 1, 74 | "ShowBtnRun" , 1, 75 | "ShowBtnOpt" , 1, 76 | "DoubleBuffer" , 1, 77 | "StruCalc" , 0, 78 | "ShortenPath" , 1, 79 | "Chinese" , 0, ; InStr("7804,0004,0804,1004", A_Language) cause IME problem? 80 | "MatchPinyin" , 1, 81 | "MidScrollSwitch", 0, 82 | "MidClickRun" , 0, 83 | "AutoUpdateCheck", 1, 84 | "HistoryLen" , 10, 85 | "RunCount" , 0, 86 | "AutoSwitchDir" , 0, 87 | "FileMgr" , "Explorer.exe", 88 | "IndexDir" , "A_ProgramsCommon,A_StartMenu,C:\Other\Index\Location", 89 | "IndexType" , "*.lnk,*.exe", 90 | "IndexDepth" , 2, 91 | "IndexExclude" , "Uninstall *", 92 | "Everything" , "C:\Apps\Everything.exe", 93 | "DialogWin" , "ahk_class #32770", 94 | "FileMgrID" , "ahk_class CabinetWClass, ahk_class TTOTAL_CMD", 95 | "ExcludeWin" , "ahk_class SysListView32, ahk_exe Explorer.exe" 96 | ) 97 | 98 | g_LOG.Debug("///// ALTRun is starting... /////`n") 99 | SetLanguage() 100 | 101 | Global g_CONFIG_P1 := Map( 102 | "AutoStartup" , g_LNG[101], 103 | "EnableSendTo" , g_LNG[102], 104 | "InStartMenu" , g_LNG[103], 105 | "ShowTrayIcon" , g_LNG[104], 106 | "HideOnLostFocus", g_LNG[105], 107 | "AlwaysOnTop" , g_LNG[106], 108 | "ShowCaption" , g_LNG[107], 109 | "XPthemeBg" , g_LNG[108], 110 | "EscClearInput" , g_LNG[109], 111 | "KeepInput" , g_LNG[110], 112 | "ShowIcon" , g_LNG[111], 113 | "SendToGetLnk" , g_LNG[112], 114 | "SaveHistory" , g_LNG[113], 115 | "SaveLog" , g_LNG[114], 116 | "MatchPath" , g_LNG[115], 117 | "ShowGrid" , g_LNG[116], 118 | "ShowHdr" , g_LNG[117], 119 | "ShowSN" , g_LNG[118], 120 | "ShowBorder" , g_LNG[119], 121 | "SmartRank" , g_LNG[120], 122 | "SmartMatch" , g_LNG[121], 123 | "MatchBeginning" , g_LNG[122], 124 | "ShowHint" , g_LNG[123], 125 | "ShowRunCount" , g_LNG[124], 126 | "ShowStatusBar" , g_LNG[125], 127 | "ShowBtnRun" , g_LNG[126], 128 | "ShowBtnOpt" , g_LNG[127], 129 | "DoubleBuffer" , g_LNG[128], 130 | "StruCalc" , g_LNG[129], 131 | "ShortenPath" , g_LNG[130], 132 | "Chinese" , g_LNG[131], 133 | "MatchPinyin" , g_LNG[132], 134 | "MidScrollSwitch", g_LNG[133], 135 | "MidClickRun" , g_LNG[134], 136 | "AutoUpdateCheck", g_LNG[135], 137 | "LargeIcons" , g_LNG[136] 138 | ) 139 | 140 | Global g_HOTKEY := Map( 141 | "Hotkey1" , "F1", 142 | "Trigger1" , "About", 143 | "Hotkey2" , "F2", 144 | "Trigger2" , "Options", 145 | "Hotkey3" , "F3", 146 | "Trigger3" , "EditCommand", 147 | "Hotkey4" , "F4", 148 | "Trigger4" , "UserCommand", 149 | "Hotkey5" , "^n", 150 | "Trigger5" , "NewCommand", 151 | "Hotkey6" , "None", 152 | "Trigger6" , "Unset", 153 | "Hotkey7" , "None", 154 | "Trigger7" , "Unset", 155 | "CondTitle" , "ahk_exe RAPTW.exe", 156 | "CondHotkey" , "~Mbutton", 157 | "CondAction" , "PTTools", 158 | "GlobalHotkey1" , "!Space", 159 | "GlobalHotkey2" , "!r", 160 | "TotalCMDDir" , "^g", 161 | "ExplorerDir" , "^e", 162 | "AutoDateAtEnd" , "ahk_class TCmtEditForm,ahk_exe Notepad4.exe", 163 | "AutoDateAEHKey", "^d", 164 | "AutoDateBefExt", "ahk_class CabinetWClass,ahk_class Progman,ahk_class WorkerW,ahk_class #32770", 165 | "AutoDateBEHKey", "^d" 166 | ) 167 | 168 | Global g_GUI := Map( ; GUI related variables 169 | "ListRows" , 9, 170 | "ColWidth" , "36,0,300,AutoHdr", 171 | "MainGUIFont" , "Microsoft YaHei, norm s10.0", 172 | "OptGUIFont" , "Microsoft YaHei, norm s9.0", 173 | "MainSBFont" , "Microsoft YaHei, norm s9.0", 174 | "WinX" , 600, 175 | "WinY" , 400, 176 | "MainGUIColor" , "0xFFFFFF", 177 | "CMDListColor" , "0xFFFFFF", 178 | "Background" , "Default", 179 | "Transparency" , 255 180 | ) 181 | 182 | Global g_RUNTIME := Map( ; Runtime variables, not saved to ini 183 | "CurrentCommand", "", 184 | "UseDisplay" , 0, 185 | "UseFallback" , 0, 186 | "Arg" , "", 187 | "OneDrive" , EnvGet("OneDrive"), 188 | "RegEx" , "imS)", 189 | "Max" , 1 190 | ) 191 | 192 | Global g_USAGE := Map(A_YYYY . A_MM . A_DD, 1) 193 | 194 | LoadConfig("initialize") ; iniWrite create ini whenever not exist 195 | 196 | ; Global variables which are only read by the function, not assigned or used with the reference operator (&). 197 | Global MainGUI 198 | Global myListView 199 | Global myInputBox 200 | Global OptGUI 201 | Global OptListView 202 | Global CmdMgrGUI 203 | Global myImageList := IL_Create(10, 5, g_CONFIG["LargeIcons"]) ; Create an ImageList so that the ListView can display some icons, 3rd param is 1: large icons, 0: small icons 204 | Global myIconMap := Map("DIR", IL_Add(myImageList,"imageres.dll",-3) ; Icon cache index, IconIndex=1/2/3/4 for type dir/func/url/eval/cmd 205 | ,"FUNC", IL_Add(myImageList,"imageres.dll",-100) 206 | ,"URL" , IL_Add(myImageList,"imageres.dll",-144) 207 | ,"EVAL", IL_Add(myImageList,"imageres.dll",-182) 208 | ,"CMD" , IL_Add(myImageList,"imageres.dll",-100)) ; "imageres.dll",-5323 is cmd.exe icon 209 | 210 | LoadCommands() 211 | LoadHistory() 212 | UpdateSendTo() 213 | UpdateStartup() 214 | UpdateStartMenu() 215 | SetTrayMenu() ; SetTrayMenu before SetMainGUI, GUI window uses the tray icon that was in effect at the time the window was created 216 | SetMainGUI() ; Create and set main GUI 217 | RegisterHotkey() 218 | Listary() 219 | Plugins() 220 | AutoCheckUpdate() 221 | return 222 | ;;==================== Autorun until here ========================= 223 | 224 | SetMainGUI() { 225 | Global MainGUI, myInputBox, myListView, myStatus, myImageList 226 | 227 | Run_W := g_CONFIG["ShowBtnRun"] * 80 228 | Run_X := g_CONFIG["ShowBtnRun"] * 10 229 | Run_H := !g_CONFIG["ShowBtnRun"] 230 | Opt_W := g_CONFIG["ShowBtnOpt"] * 80 231 | Opt_X := g_CONFIG["ShowBtnOpt"] * 10 232 | Opt_H := !g_CONFIG["ShowBtnOpt"] 233 | List_W := g_GUI["WinX"] - 24 234 | List_H := g_GUI["WinY"] - 95 235 | Input_W := List_W - Run_X - Run_W - Opt_X - Opt_W 236 | TopMost := g_CONFIG["AlwaysOnTop"] ? "AlwaysOnTop" : "" 237 | Caption := g_CONFIG["ShowCaption"] ? "" : " -Caption" 238 | Theme := g_CONFIG["XPthemeBg"] ? "" : " -Theme" 239 | DBuffer := g_CONFIG["DoubleBuffer"] ? " +LV0x10000" : "" 240 | Header := g_CONFIG["ShowHdr"] ? "" : " -Hdr" 241 | Grid := g_CONFIG["ShowGrid"] ? " Grid" : "" 242 | Border := g_CONFIG["ShowBorder"] ? "" : " -E0x200" 243 | 244 | MainGUI := Gui(TopMost Caption Theme " +MinSize300x160", g_TITLE) 245 | MainGUI.OnEvent("Close" , MainGUI_Close) 246 | MainGUI.OnEvent("Escape", MainGUI_Escape) 247 | MainGUI.OnEvent("Size" , MainGUI_Size) 248 | MainGUI.OnEvent("ContextMenu", MainGUI_ContextMenu) 249 | MainGUI.BackColor := g_GUI["MainGUIColor"] 250 | MainGUI.SetFont(StrSplit(g_GUI["MainGUIFont"], ",")[2], StrSplit(g_GUI["MainGUIFont"], ",")[1]) 251 | myInputBox := MainGUI.AddEdit("x12 y10 r1 -WantReturn border -E0x200 W" Input_W, g_LNG[13]) 252 | myInputBox.Opt("Background" g_GUI["CMDListColor"]) 253 | myInputBox.OnEvent("Change", Input_Change) 254 | myRunBtn := MainGUI.AddButton("x+" Run_X " yp W" Run_W " hp Default Hidden" Run_H, g_LNG[11]) 255 | myRunBtn.OnEvent("Click", RunCurrentCommand) 256 | myOptBtn := MainGUI.AddButton("x+" Opt_X " yp W" Opt_W " hp Hidden" Opt_H, g_LNG[12]) 257 | myOptBtn.OnEvent("Click", (*) => Options()) 258 | myListView := MainGUI.AddListView("x12 yp+36 W" List_W " H" List_H " -Multi", g_LNG[10]) 259 | myListView.Opt(DBuffer Header Grid Border " Background" g_GUI["CMDListColor"] " +Report") ; ListView View Modes: Report, Icon, Tile, IconSmall, List 260 | myListView.OnEvent("Click", LV_Click) 261 | myListView.OnEvent("ContextMenu", LV_ContextMenu) 262 | myListView.OnEvent("DoubleClick", LVRunCommand) 263 | if (g_CONFIG["LargeIcons"]) { 264 | myListView.SetImageList(myImageList, 1) ; Attach the ImageList to the ListView, 2nd param is 1: large icons, 0: small icons, 2: state icons (AHK Doc incorrect) 265 | } else { 266 | myListView.SetImageList(myImageList) 267 | } 268 | 269 | Loop 4 { 270 | if (StrSplit(g_GUI["ColWidth"], ",").Length >= A_Index) { 271 | if (StrSplit(g_GUI["ColWidth"], ",")[A_Index] != "") 272 | myListView.ModifyCol(A_Index, StrSplit(g_GUI["ColWidth"], ",")[A_Index]) 273 | } 274 | } 275 | 276 | myStatus := MainGUI.AddEdit("x12 y+10 r1 -WantReturn ReadOnly -E0x200 border W" List_W " Hidden" (!g_CONFIG["ShowStatusBar"]), ) 277 | myStatus.Opt("Background" g_GUI["CMDListColor"]) 278 | myStatus.SetFont(StrSplit(g_GUI["MainSBFont"], ",")[2], StrSplit(g_GUI["MainSBFont"], ",")[1]) 279 | 280 | if FileExist(AbsPath(g_GUI["Background"])) { 281 | try MainGUI.AddPic("x0 y0 0x4000000", AbsPath(g_GUI["Background"])) 282 | } else if (g_GUI["Background"] = "Default") { 283 | try MainGUI.AddPic("x0 y0 0x4000000", ExtractRes()) 284 | } 285 | 286 | ListResult(g_LNG[50]) 287 | 288 | ;=================================================== 289 | ; Resolve command line arguments, A_Args[1] A_Args[2] 290 | ;=================================================== 291 | local HideWin := "" 292 | for value in A_Args{ 293 | g_LOG.Debug("Resolving command line args" A_Index " = " value) 294 | if (A_Index = 1) { 295 | if (value = "-Startup" || value = "-StartMenu") 296 | HideWin := "Hide " 297 | 298 | if (value = "-SendTo" && A_Args.Length >= 2) { 299 | HideWin := "Hide " 300 | Path := A_Args[2] 301 | 302 | SplitPath(Path, &Desc, , &fileExt) ; Extra name from _Path (if _Type is dir and has "." in path, nameNoExt will not get full folder name) 303 | 304 | fileType := InStr(FileExist(Path), "D") ? "Dir" : "File" ; Default Type is File, Set Type is Dir only if the file exists and is a directory 305 | 306 | if (fileExt = "lnk" && g_CONFIG["SendToGetLnk"]) { 307 | FileGetShortcut(Path, Path, , &fileArg, &Desc) 308 | Path .= " " fileArg 309 | } 310 | CmdMgr(g_SECTION["USERCMD"], fileType, Path, Desc, 1, "") ; Add new command to database 311 | } 312 | } 313 | } 314 | 315 | if (g_GUI["Transparency"] < 250){ 316 | WinSetTransparent(g_GUI["Transparency"], MainGUI.Hwnd) ; By default, hidden windows are not detected. however, when using pure HWNDs, hidden windows are always detected regardless of DetectHiddenWindows. 317 | } 318 | 319 | WinSetRegion("0-0" " w" g_GUI["WinX"] " h" g_GUI["WinY"] " R20-20", MainGUI.Hwnd) ; Set rounded corners 320 | 321 | MainGUI.Show(HideWin "w" g_GUI["WinX"] " h" g_GUI["WinY"] " Center") 322 | 323 | if g_CONFIG["HideOnLostFocus"] { 324 | ; 方案 1 - OnMessage(0x0006, WM_ACTIVATE) 325 | ; 事件驱动, 高效无延迟, 无资源占用 326 | ; 某些情况有窗口闪烁和托盘菜单右键点击"显示"窗口闪退问题 327 | ; 方案 2 - SetTimer(MonitorFocus, 30) 328 | ; Ahk原生方式, 代码简单可靠, 但有轻微性能开销, 有稍许延迟 30ms 329 | ; 方案 3 - Control.OnEvent("LoseFocus", MonitorFocus) 330 | ; Ahk原生方式, 事件驱动, 高效无延迟, 无资源占用 331 | ; 因 Gui 本身没有 LoseFocus 事件, 需要注册主界面所有控件的 LoseFocus 事件 332 | ; 修复托盘菜单右键点击"显示"窗口闪退问题 333 | myInputBox.OnEvent("LoseFocus", MonitorFocus) 334 | myListView.OnEvent("LoseFocus", MonitorFocus) 335 | myRunBtn.OnEvent("LoseFocus", MonitorFocus) 336 | myOptBtn.OnEvent("LoseFocus", MonitorFocus) 337 | myStatus.OnEvent("LoseFocus", MonitorFocus) 338 | } 339 | return 340 | } 341 | 342 | MoveWindow(*) { ; Allow moving a captionless window by mouse-drag 343 | DllCall("ReleaseCapture") 344 | SendMessage(0xA1, 2, 0, MainGUI.Hwnd) ; WM_NCLBUTTONDOWN, HTCAPTION 345 | } 346 | 347 | ; 创建任务栏托盘程序图标 348 | SetTrayMenu() { 349 | if !g_CONFIG["ShowTrayIcon"] { 350 | A_IconHidden := 1 351 | return 352 | } 353 | 354 | static myTrayMenu := "" ; 只在第一次调用时创建 355 | 356 | if !IsObject(myTrayMenu) { 357 | myTrayMenu := A_TrayMenu 358 | try { 359 | TraySetIcon("imageres.dll", -100) 360 | 361 | myTrayMenu.Delete() ; 删除默认项 362 | myTrayMenu.Add(g_LNG[300], ToggleWindow) 363 | myTrayMenu.Add(g_LNG[301], (*) => Options()) 364 | myTrayMenu.Add(g_LNG[310], UserCommand) 365 | myTrayMenu.Add() ; 分隔线 366 | myTrayMenu.Add(g_LNG[302], Reindex) 367 | myTrayMenu.Add(g_LNG[303], Usage) 368 | myTrayMenu.Add(g_LNG[305], (*) => ListLines()) 369 | myTrayMenu.Add() ; 分隔线 370 | myTrayMenu.Add(g_LNG[309], Update) 371 | myTrayMenu.Add(g_LNG[304], About) 372 | myTrayMenu.Add() 373 | myTrayMenu.Add(g_LNG[307], ReStart) 374 | myTrayMenu.Add(g_LNG[308], Exit) 375 | 376 | myTrayMenu.SetIcon(g_LNG[300], "imageres.dll", -100) 377 | myTrayMenu.SetIcon(g_LNG[301], "imageres.dll", -114) 378 | myTrayMenu.SetIcon(g_LNG[310], "imageres.dll", -88) 379 | myTrayMenu.SetIcon(g_LNG[302], "imageres.dll", -8) 380 | myTrayMenu.SetIcon(g_LNG[303], "imageres.dll", -150) 381 | myTrayMenu.SetIcon(g_LNG[305], "imageres.dll", -165) 382 | myTrayMenu.SetIcon(g_LNG[309], "imageres.dll", -5338) 383 | myTrayMenu.SetIcon(g_LNG[304], "imageres.dll", -81) 384 | myTrayMenu.SetIcon(g_LNG[307], "imageres.dll", -5311) 385 | myTrayMenu.SetIcon(g_LNG[308], "imageres.dll", -98) 386 | 387 | myTrayMenu.Default := g_LNG[300] 388 | myTrayMenu.ClickCount := 1 389 | A_IconTip := g_TITLE 390 | A_IconHidden := 0 391 | 392 | g_LOG.Debug("SetTrayMenu: Create myTrayMenu...OK") 393 | } catch as e { 394 | g_LOG.Debug("SetTrayMenu: Error creating myTrayMenu: " . e.Message) 395 | } 396 | } 397 | return 398 | } 399 | 400 | RegisterHotkey() { 401 | ; 注册全局热键 402 | HotIfWinActive 403 | try { 404 | Hotkey(g_HOTKEY["GlobalHotkey1"], ToggleWindow) 405 | Hotkey(g_HOTKEY["GlobalHotkey2"], ToggleWindow) 406 | 407 | g_LOG.Debug("RegisterHotkey: Set global activate hotkeys...OK") 408 | } catch as e { 409 | g_LOG.Debug("RegisterHotkey: Failed to set global activate hotkeys..." e.Message) 410 | } 411 | 412 | ; 注册主窗口热键, 使用 ahk_id Hwnd 增强可靠性 413 | HotIfWinActive("ahk_id " MainGUI.Hwnd) 414 | try { 415 | Hotkey("!F4" , Exit) 416 | Hotkey("Tab" , TabFunc) 417 | Hotkey("F1" , About) 418 | Hotkey("F2" , Options) 419 | Hotkey("F3" , EditCommand) 420 | Hotkey("F4" , UserCommand) 421 | Hotkey("^q" , ReStart) 422 | Hotkey("^d" , OpenContainer) 423 | Hotkey("^c" , CopyCommand) 424 | Hotkey("^n" , NewCommand) 425 | Hotkey("^Del" , DelCommand) 426 | Hotkey("^i" , Reindex) 427 | Hotkey("Down" , NextCommand) 428 | Hotkey("Up" , PrevCommand) 429 | Hotkey("^NumpadAdd" , RankUp) 430 | Hotkey("^NumpadSub" , RankDown) 431 | 432 | if (g_CONFIG["MidScrollSwitch"]) { 433 | Hotkey("WheelDown" , NextCommand) 434 | Hotkey("WheelUp" , PrevCommand) 435 | } 436 | 437 | if (g_CONFIG["MidClickRun"]) { 438 | Hotkey("MButton" , RunCurrentCommand) 439 | } 440 | 441 | g_LOG.Debug("RegisterHotkey: Set local hotkeys (F1-F4)...OK") 442 | } catch as e { 443 | g_LOG.Debug("RegisterHotkey: Failed to set local hotkeys (F1-F4)..." e.Message) 444 | } 445 | 446 | Loop g_GUI["ListRows"] { 447 | try { 448 | Hotkey("!" . A_Index, RunSelectedCommand) ; 通过热键选择并运行指定命令 = Alt + index (1-9) 449 | Hotkey("^" . A_Index, GotoCommand) ; 通过热键选择指定命令 = Ctrl + index (1-9) 450 | 451 | g_LOG.Debug("RegisterHotkey: Set command list local hotkey " A_Index "...OK") 452 | } catch as e { 453 | g_LOG.Debug("RegisterHotkey: Failed to set command list local hotkey " A_Index . e.Message) 454 | } 455 | } 456 | 457 | Loop 7 { 458 | KeyName := "Hotkey" . A_Index 459 | Trigger := "Trigger" . A_Index 460 | if (g_HOTKEY.Has(KeyName) && g_HOTKEY[KeyName] != "" && g_HOTKEY[Trigger] != "") { ; 自定义热键执行指定功能 = Hotkey + Trigger 461 | try { 462 | Hotkey(g_HOTKEY[KeyName], ExecuteFunc.Bind(, g_HOTKEY[Trigger], A_Index)) 463 | g_LOG.Debug("RegisterHotkey: Set customized function list local hotkey " A_Index " " g_HOTKEY[KeyName] " <-> " g_HOTKEY[Trigger] "...OK") 464 | } catch as e { 465 | g_LOG.Debug("RegisterHotkey: Failed to set customized function list local hotkey..." e.Message) 466 | } 467 | } 468 | } 469 | 470 | ; 注册条件热键, 执行指定功能 471 | HotIfWinActive(g_HOTKEY["CondTitle"]) 472 | if g_HOTKEY.Has("CondTitle") && g_HOTKEY.Has("CondHotkey") && g_HOTKEY.Has("CondAction") { 473 | try { 474 | Hotkey(g_HOTKEY["CondHotkey"], ExecuteFunc.Bind(, g_HOTKEY["CondAction"], 1)) 475 | g_LOG.Debug("RegisterHotkey: Set conditional hotkey " g_HOTKEY["CondHotkey"] " <-> " g_HOTKEY["CondAction"] " for " g_HOTKEY["CondTitle"] "...OK") 476 | } catch as e { 477 | g_LOG.Debug("RegisterHotkey: Failed to set conditional hotkey..." e.Message) 478 | } 479 | } 480 | HotIfWinActive ; Turn off context, make subsequent hotkeys global again 481 | return 482 | } 483 | 484 | ExecuteFunc(HotkeyName, FuncName, Index) { 485 | RunCommand("FUNC | " FuncName) 486 | g_LOG.Debug("ExecutFunc: Execute function...=" FuncName) 487 | } 488 | 489 | Activate() { 490 | MainGUI.Show() 491 | 492 | if (WinWaitActive("ahk_id " MainGUI.Hwnd, , 3)) { ; Wait for the window to be active, ahk_id is more reliable than g_TITLE 493 | myInputBox.Focus() 494 | SendMessage(0xB1, 0, -1, myInputBox.Hwnd) ; EM_SETSEL (0xB1) 495 | } 496 | } 497 | 498 | ToggleWindow(*) { 499 | WinActive("ahk_id " MainGUI.Hwnd) ? MainGUI_Close() : Activate() 500 | } 501 | 502 | Input_Change(*) { 503 | SearchCommand(myInputBox.Value) 504 | } 505 | 506 | SearchCommand(command := "") { 507 | Global g_MATCHED, g_RUNTIME, g_FALLBACK, g_COMMANDS, g_CMDINDEX 508 | 509 | g_MATCHED := Array() 510 | Prefix := SubStr(command, 1, 1) 511 | 512 | ; Handle fallback commands 513 | if (Prefix = "+" or Prefix = " " or Prefix = ">") { 514 | idx := (Prefix = "+") ? 1 : (Prefix = " ") ? 2 : 3 515 | g_RUNTIME["CurrentCommand"] := g_FALLBACK[idx] 516 | g_MATCHED.Push(g_RUNTIME["CurrentCommand"]) 517 | return ListResult(g_MATCHED) 518 | } 519 | 520 | ; Search commands using precomputed searchable text 521 | for index, strToSearch in g_CMDINDEX { 522 | if FuzzyMatch(strToSearch, command) { 523 | g_MATCHED.Push(g_COMMANDS[index]) 524 | g_RUNTIME["CurrentCommand"] := g_MATCHED[1] 525 | 526 | if g_MATCHED.Length >= g_GUI["ListRows"] 527 | break 528 | } 529 | } 530 | 531 | ; If no matches found, evaluate as expression if enabled 532 | if (g_MATCHED.Length = 0) { 533 | evalResult := Eval(command) 534 | if (IsNumber(evalResult) && evalResult != 0) { 535 | g_MATCHED := StruCalc(Round(evalResult, 6)) ; Round is to fix 5+0.3 = 5.300000000000001 issue 536 | return ListResult(g_MATCHED, True) 537 | } 538 | 539 | g_RUNTIME["UseFallback"] := True 540 | g_MATCHED := g_FALLBACK 541 | g_RUNTIME["CurrentCommand"] := g_FALLBACK[1] 542 | } Else { 543 | g_RUNTIME["UseFallback"] := False 544 | } 545 | return ListResult(g_MATCHED) 546 | } 547 | 548 | ListResult(arrayToShow := [], UseDisplay := false) { 549 | myListView.Opt("-Redraw") ; Improve performance by disabling redrawing during load. 550 | myListView.Delete() 551 | g_RUNTIME["UseDisplay"] := UseDisplay 552 | 553 | for index, command in arrayToShow { 554 | parts := StrSplit(command, " | ") 555 | type := parts.Length >= 1 ? parts[1] : "" ; Ensure type has default 556 | path := parts.Length >= 2 ? parts[2] : "" ; Ensure path has default 557 | desc := parts.Length >= 3 ? parts[3] : "" ; Ensure desc has default (fix for missing 3rd element) 558 | index := g_CONFIG["ShowSN"] ? index : "" 559 | iconx := GetIconIndex(path, type) 560 | 561 | if (type != "URL" && g_CONFIG["ShortenPath"]) { ; Show Full path / Shorten path, except for URL 562 | SplitPath(path, &path) ; Extra name from path (if type is Dir and has "." in path, fileName will not get full folder name) 563 | } 564 | 565 | myListView.Add("Icon" iconx, index, type, path, desc) 566 | } 567 | 568 | ; rowsShown := Min(g_GUI["ListRows"], myListView.GetCount()) 569 | ; RowH := g_CONFIG["LargeIcons"] ? 36 : 22 570 | ; HdrH := g_CONFIG["ShowHdr"] ? 20 : 0 571 | ; List_H := rowsShown * RowH + HdrH + 8 ; 8 = padding for margins 572 | ; ; Compute overall window height to contain input/status/buttons 573 | ; g_GUI["WinY"] := (List_H + 95) ; keep a sensible minimum height 574 | ; Try { 575 | ; myListView.Move( , , , List_H) 576 | ; WinMove( , , , g_GUI["WinY"], "ahk_id " MainGUI.Hwnd) ; Resize window without changing position 577 | ; } catch { 578 | ; ; If WinMove fails for any reason, continue without hard failure 579 | ; } 580 | 581 | if (g_RUNTIME["CurrentCommand"] != "") { 582 | statusBarText := StrSplit(g_RUNTIME["CurrentCommand"], " | ")[2] 583 | } else { 584 | statusBarText := (myListView.GetCount() > 0) ? myListView.GetText(1, 3) : "" 585 | } 586 | 587 | myListView.Modify(1, "Select Focus Vis") ; Select 1st row 588 | myListView.Opt("+Redraw") ; Re-enable redrawing. 589 | SetStatusBar(statusBarText) 590 | } 591 | 592 | GetIconIndex(path, type) { ; Get file's icon index (TO-DO: Prepare to omit the file type) 593 | Global myIconMap 594 | if not g_CONFIG["ShowIcon"] ; ShowIcon disabled, return 0 595 | Return 0 596 | 597 | if (type = "") { 598 | return 0 599 | } else if (type = "DIR") { 600 | return 1 601 | } else if InStr("FUNC,TIP,提示,CMD", type, 0) { 602 | return 2 603 | } else if (type = "URL") { 604 | return 3 605 | } else if (type = "EVAL") { 606 | return 4 607 | } else if (type = "FILE") { 608 | path := AbsPath(path) ; Must store in var for afterward use, trim space (in AbsPath) 609 | SplitPath(path, , , &fileExt) ; Get the file's extension. 610 | if (fileExt ~= "^(?i:EXE|ICO|ANI|CUR|LNK)$") { ; File types that have their own icon 611 | IconIndex := myIconMap.Has(path) ? myIconMap[path] : GetIcon(path, path) ; File path exist in ImageList, get the index, several calls can be avoided and performance is greatly improved 612 | } else { ; Some other extension/file-type like pdf or xlsx 613 | IconIndex := myIconMap.Has(fileExt) ? myIconMap[fileExt] : GetIcon(path, fileExt) 614 | } 615 | Return IconIndex 616 | } 617 | } 618 | 619 | GetIcon(path, ExtOrPath) { ; Get file's icon 620 | Global myImageList, myIconMap 621 | sfi_size := A_PtrSize + 688 622 | sfi := Buffer(sfi_size) ; Calculate buffer size required for SHFILEINFO structure. VarSetStrCapacity change to Buffer 623 | iconSize := g_CONFIG["LargeIcons"] ? 0x100 : 0x101 ; 0x100 is SHGFI_ICON+SHGFI_LARGEICON, 0x101 is SHGFI_ICON+SHGFI_SMALLICON 624 | 625 | if not DllCall("Shell32\SHGetFileInfoW", "Str", path, "UInt", 0, "Ptr", sfi, "UInt", sfi_size, "UInt", iconSize) 626 | IconIndex := 9999999 ; Set it out of bounds to display a blank icon. 627 | else { ; Icon successfully loaded. Extract the hIcon member from the structure 628 | hIcon := NumGet(sfi, 0, "Ptr") ; Add the HICON directly to the small-icon lists. 629 | IconIndex := DllCall("ImageList_ReplaceIcon", "ptr", myImageList, "int", -1, "ptr", hIcon) + 1 ; Uses +1 to convert the returned index from zero-based to one-based: 630 | DllCall("DestroyIcon", "Ptr", hIcon) ; Now that it's been copied into the ImageLists, the original should be destroyed 631 | myIconMap[ExtOrPath] := IconIndex ; Cache the icon based on file type (xlsx, pdf) or path (exe, lnk) to save memory and improve loading performance 632 | } 633 | Return IconIndex 634 | } 635 | 636 | AbsPath(Path, KeepRunAs := False) { ; Convert path to absolute path 637 | Path := Trim(Path) 638 | 639 | if (!KeepRunAs) 640 | Path := StrReplace(Path, "*RunAs ", "") ; Remove *RunAs (Admin Run) to get absolute path 641 | 642 | if (InStr(Path, "A_") = 1 && InStr(Path, "\")) { ; Resolve path like A_ScriptDir, some server path has "Plot A_IGLS" in it, so InStr must be 1 643 | SubParts := StrSplit(Path, " ", " `t") 644 | if (SubParts.Length > 1 && InStr(SubParts[1], "A_") = 1) { 645 | VarName := SubParts[1] 646 | VarValue := %VarName% 647 | Path := VarValue . StrReplace(SubParts[2], "`"", "") 648 | } 649 | } else if (InStr(Path, "A_") = 1) { 650 | Path := %Path% 651 | } 652 | 653 | ; 如果只是可执行名(如 notepad.exe)且本地不存在,尝试在 PATH 中用 SearchPathW 查找完整路径 654 | if (!FileExist(Path) && InStr(Path, "\") = 0) { 655 | ; 准备缓冲区用于 SearchPathW 返回宽字符路径 656 | buf := Buffer(260 * 2) 657 | res := DllCall("kernel32\SearchPathW", "Ptr", 0, "WStr", Path, "WStr", "", "UInt", buf.Size // 2, "Ptr", buf, "Ptr", 0) 658 | if (res && res > 0) { 659 | Path := StrGet(buf, "UTF-16") 660 | } 661 | } 662 | 663 | Path := StrReplace(Path, "%Temp%", A_Temp) 664 | Path := StrReplace(Path, "%OneDrive%", g_RUNTIME["OneDrive"]) 665 | Return Path 666 | } 667 | 668 | RelativePath(Path) { ; Convert path to relative path 669 | Path := StrReplace(Path, A_Temp, "%Temp%") 670 | Path := StrReplace(Path, g_RUNTIME["OneDrive"], "%OneDrive%") 671 | Return Path 672 | } 673 | 674 | RunCommand(originCmd) { 675 | UpdateRunCount() 676 | MainGUI_Close() 677 | ParseArg() 678 | g_RUNTIME["UseDisplay"] := false 679 | g_LOG.Debug("RunCommand: Execute " g_CONFIG["RunCount"] "=" originCmd) 680 | 681 | split := StrSplit(originCmd, " | ") 682 | type := split.Length >= 1 ? split[1] : "" ; Ensure type has default 683 | path := split.Length >= 2 ? AbsPath(split[2], True) : "" ; Ensure path has default 684 | 685 | if (type = "") { 686 | return 687 | } else if (type = "DIR") { 688 | OpenDir(path) 689 | } else if (type = "FUNC") { 690 | try { 691 | %path%() 692 | } catch as e { 693 | MsgBox("Could not find function: " path "`n`nError message: " e.Message, g_TITLE, 48) 694 | } 695 | } else { ; For type "FILE","URL","CMD" and other Unknown type 696 | try { 697 | Run(path) 698 | } catch as e { 699 | MsgBox("Could not run command: " path "`n`nError message: " e.Message, g_TITLE, 48) 700 | } 701 | } 702 | 703 | if (g_CONFIG["SaveHistory"]) { 704 | g_HISTORYS.InsertAt(1, originCmd " Arg=" g_RUNTIME["Arg"]) ; Adjust command history 705 | 706 | if (g_HISTORYS.Length > g_CONFIG["HistoryLen"]) { 707 | g_HISTORYS.Pop() 708 | } 709 | 710 | IniDelete(g_INI, g_SECTION["HISTORY"]) 711 | for index, element in g_HISTORYS 712 | IniWrite(element, g_INI, g_SECTION["HISTORY"], index) ; Save command history 713 | } 714 | 715 | g_CONFIG["SmartRank"] ? UpdateRank(originCmd) : "" 716 | return 717 | } 718 | 719 | TabFunc(*) { ; Limit tab to switch focused control between myInputBox & ListView only 720 | if (MainGUI.FocusedCtrl.ClassNN = "Edit1") { ; MainGUI.FocusedCtrl.ClassNN: Edit1 or SysListView321 721 | myListView.Focus() 722 | } else { 723 | myInputBox.Focus() 724 | } 725 | } 726 | 727 | PrevCommand(*) { 728 | ChangeCommand(-1, False) 729 | } 730 | 731 | NextCommand(*) { 732 | ChangeCommand(1, False) 733 | } 734 | 735 | GotoCommand(*) { 736 | index := SubStr(A_ThisHotkey, 2, 1) ; Get index from hotkey (select specific command = Shift + index) 737 | 738 | if (index <= g_MATCHED.Length) { 739 | ChangeCommand(index, True) 740 | g_RUNTIME["CurrentCommand"] := g_MATCHED[index] 741 | } 742 | } 743 | 744 | RunSelectedCommand(*) { 745 | GotoCommand() 746 | RunCommand(g_RUNTIME["CurrentCommand"]) 747 | } 748 | 749 | ChangeCommand(Step := 1, ResetSelRow := False) { 750 | selectedRow := ResetSelRow ? Step : myListView.GetNext() + Step ; Get target row no. to be selected 751 | selectedRow := selectedRow > myListView.GetCount() ? 1 : selectedRow ; Listview cycle selection (Mod has bug on upward cycle) 752 | selectedRow := selectedRow < 1 ? myListView.GetCount() : selectedRow 753 | 754 | if (g_MATCHED.Length >= selectedRow) { 755 | g_RUNTIME["CurrentCommand"] := g_MATCHED[selectedRow] ; Get current command from selected row 756 | SetStatusBar(StrSplit(g_RUNTIME["CurrentCommand"], " | ")[2]) 757 | } else { 758 | SetStatusBar(myListView.GetText(selectedRow, 3)) 759 | } 760 | 761 | myListView.Modify(selectedRow, "Select Focus Vis") ; make new index row selected, Focused, and Visible 762 | } 763 | 764 | LV_Click(myListView, rowNumber) { 765 | if (!rowNumber) ; 如果用户左键点击了列表行以外的地方 766 | Return 767 | 768 | if (g_MATCHED.Length >= rowNumber) { 769 | g_RUNTIME["CurrentCommand"] := g_MATCHED[rowNumber] ; Get current command from focused row 770 | SetStatusBar(StrSplit(g_RUNTIME["CurrentCommand"], " | ")[2]) 771 | } else { 772 | SetStatusBar(myListView.GetText(rowNumber, 3)) 773 | } 774 | } 775 | 776 | LV_ContextMenu(GuiCtrlObj, rowNumber, IsRightClick, X, Y) { ; On ListView ContextMenu 777 | Global myListView, g_MATCHED, g_RUNTIME 778 | 779 | if (rowNumber = 0) { ; 如果用户右键点击了列表行以外的地方 780 | SetMainGUIContextMenu("", GuiCtrlObj, rowNumber, IsRightClick, X, Y) 781 | return 782 | } 783 | 784 | if (g_MATCHED.Length >= rowNumber) { 785 | g_RUNTIME["CurrentCommand"] := g_MATCHED[rowNumber] 786 | SetListViewContextMenu(X, Y) 787 | } else { ; For cases like first hint page 788 | SetStatusBar(myListView.GetText(rowNumber, 3)) 789 | SetMainGUIContextMenu("", GuiCtrlObj, rowNumber, IsRightClick, X, Y) 790 | } 791 | } 792 | 793 | SetListViewContextMenu(X, Y) { 794 | static myListViewContextMenu := "" ; 只在第一次调用右键菜单时创建 795 | 796 | if !IsObject(myListViewContextMenu) { 797 | myListViewContextMenu := Menu() 798 | 799 | try { 800 | myListViewContextMenu.Add(g_LNG[400], LVRunCommand) 801 | myListViewContextMenu.Add(g_LNG[401], OpenContainer) 802 | myListViewContextMenu.Add(g_LNG[402], CopyCommand) 803 | myListViewContextMenu.Add() 804 | myListViewContextMenu.Add(g_LNG[403], NewCommand) 805 | myListViewContextMenu.Add(g_LNG[404], EditCommand) 806 | myListViewContextMenu.Add(g_LNG[405], DelCommand) 807 | 808 | myListViewContextMenu.SetIcon(g_LNG[400], "imageres.dll", -100) 809 | myListViewContextMenu.SetIcon(g_LNG[401], "imageres.dll", -3) 810 | myListViewContextMenu.SetIcon(g_LNG[402], "imageres.dll", -5314) 811 | myListViewContextMenu.SetIcon(g_LNG[403], "imageres.dll", -2) 812 | myListViewContextMenu.SetIcon(g_LNG[404], "imageres.dll", -5306) 813 | myListViewContextMenu.SetIcon(g_LNG[405], "imageres.dll", -5305) 814 | 815 | g_LOG.Debug("SetListViewContextMenu: Create myListViewContextMenu...OK") 816 | } catch as e { 817 | g_LOG.Debug("SetListViewContextMenu: Error creating myListViewContextMenu: " . e.Message) 818 | } 819 | } 820 | myListViewContextMenu.Show(X, Y) 821 | return 822 | } 823 | 824 | LVRunCommand(*) { ; On ListView double click action 825 | focusedRow := myListView.GetNext(0, "Focused") ; Check focused row, only operate focusd row instead of all selected rows 826 | if (!focusedRow) ; Return if no focused row is found 827 | Return 828 | 829 | if (g_MATCHED.Length >= focusedRow) { 830 | g_RUNTIME["CurrentCommand"] := g_MATCHED[focusedRow] ; Get current command from focused row 831 | RunCommand(g_RUNTIME["CurrentCommand"]) ; Execute the command if the user selected "Run Enter" 832 | } 833 | } 834 | 835 | CopyCommand(*) { ; ListView ContextMenu 836 | focusedRow := myListView.GetNext(0, "Focused") ; Check focused row, only operate focusd row instead of all selected rows 837 | if (!focusedRow) ; Return if no focused row is found 838 | Return 839 | 840 | if (g_MATCHED.Length >= focusedRow) { 841 | g_RUNTIME["CurrentCommand"] := g_MATCHED[focusedRow] ; Get current command from focused row 842 | } 843 | 844 | if (MainGUI.FocusedCtrl.ClassNN = "SysListView321") { 845 | A_Clipboard := myListView.GetText(focusedRow, 3) ; Get the text from the focusedRow's 3rd field. 846 | } else { 847 | SendInput("^c") ; If input box or status box is focused 848 | } 849 | } 850 | 851 | ; Get text from 1st part of StatusBar 852 | CopyStatusBarText(*) { 853 | A_Clipboard := StatusBarGetText(1, "ahk_id " MainGUI.Hwnd) 854 | ToolTip(g_LNG[408] A_Clipboard) 855 | SetTimer(() => ToolTip(""), -2000) ; Hide tooltip after 2 seconds 856 | } 857 | 858 | MainGUI_Escape(*) { 859 | (g_CONFIG["EscClearInput"] && myInputBox.Value) ? ClearInput() : MainGUI_Close() 860 | } 861 | 862 | MainGUI_Close(*) { 863 | if (!g_CONFIG["KeepInput"]) { 864 | ClearInput() 865 | } 866 | 867 | ; Animate hide if possible 868 | ;try DllCall("AnimateWindow", "Ptr", MainGUI.Hwnd, "Int", 90, "UInt", 0x90000) 869 | 870 | MainGUI.Hide() 871 | UpdateUsage() 872 | SetStatusBar("TIP") ; Update StatusBar tip information after GUI hide 873 | } 874 | 875 | MainGUI_Size(GuiObj, MinMax, Width, Height) { 876 | ; g_GUI["WinX"] := Width 877 | ; g_GUI["WinY"] := Height 878 | 879 | ; g_GUI.ListX := g_GUI.WinX - 24 880 | ; g_GUI.ListY := g_GUI.WinY - 76 881 | ; g_GUI.Input_W := g_GUI.ListX - g_CONFIG.ShowBtnRun * 90 - g_CONFIG.ShowBtnOpt * 90 882 | ; GuiControl, Main:Move, MyListView, % "W" g_GUI.ListX " H" g_GUI.ListY ; Resize ListView to fit new window size 883 | ; GuiControl, Main:Move, MyInput, % "W" g_GUI.Input_W ; Resize Input to fit new window size 884 | ; LV_ModifyCol(4, "AutoHdr") ; Auto adjust column width to fit new window size 885 | ; SB_SetParts(g_GUI.WinX - 90 * g_CONFIG.ShowRunCount) 886 | ; SetStatusBar("窗口大小已经改变, 如需保留窗口尺寸, 请进入选项设置页面进行保存") 887 | ; OutputDebug("MainGUI_Size - " MinMax "-" Width "-" Height) 888 | } 889 | 890 | ; 主界面右键菜 891 | MainGUI_ContextMenu(GuiObj, GuiCtrlObj, Item, IsRightClick, X, Y) { 892 | 893 | GuiCtrlType := IsObject(GuiCtrlObj) ? GuiCtrlObj.Type : "" 894 | 895 | if (GuiCtrlType = "ListView" || GuiCtrlType = "StatusBar") 896 | return 897 | 898 | SetMainGUIContextMenu(GuiObj, GuiCtrlObj, Item, IsRightClick, X, Y) 899 | return 900 | } 901 | 902 | SetMainGUIContextMenu(GuiObj, GuiCtrlObj, Item, IsRightClick, X, Y) { 903 | static myContextMenu := "" ; 只在第一次调用时创建 904 | 905 | if !IsObject(myContextMenu) { 906 | myContextMenu := Menu() 907 | try { 908 | myContextMenu.Add(g_LNG[301], (*) => Options()) 909 | myContextMenu.Add(g_LNG[310], UserCommand) 910 | myContextMenu.Add() ; 分隔线 911 | myContextMenu.Add(g_LNG[302], Reindex) 912 | myContextMenu.Add(g_LNG[303], Usage) 913 | myContextMenu.Add(g_LNG[305], (*) => ListLines()) 914 | myContextMenu.Add() ; 分隔线 915 | myContextMenu.Add(g_LNG[309], Update) 916 | myContextMenu.Add(g_LNG[304], About) 917 | myContextMenu.Add() 918 | myContextMenu.Add(g_LNG[307], ReStart) 919 | myContextMenu.Add(g_LNG[308], Exit) 920 | 921 | myContextMenu.SetIcon(g_LNG[301], "imageres.dll", -114) 922 | myContextMenu.SetIcon(g_LNG[310], "imageres.dll", -88) 923 | myContextMenu.SetIcon(g_LNG[302], "imageres.dll", -8) 924 | myContextMenu.SetIcon(g_LNG[303], "imageres.dll", -150) 925 | myContextMenu.SetIcon(g_LNG[305], "imageres.dll", -165) 926 | myContextMenu.SetIcon(g_LNG[309], "imageres.dll", -5338) 927 | myContextMenu.SetIcon(g_LNG[304], "imageres.dll", -81) 928 | myContextMenu.SetIcon(g_LNG[307], "imageres.dll", -5311) 929 | myContextMenu.SetIcon(g_LNG[308], "imageres.dll", -98) 930 | 931 | g_LOG.Debug("SetMainGUIContextMenu: Create myContextMenu...OK") 932 | } catch as e { 933 | g_LOG.Debug("SetMainGUIContextMenu: Error creating myContextMenu: " . e.Message) 934 | } 935 | } 936 | myContextMenu.Show(X, Y) 937 | return 938 | } 939 | 940 | ClearInput() { 941 | myInputBox.Focus() 942 | myInputBox.Value := "" 943 | Input_Change() ; v1 no need, v2 需要手动调用绑定的事件处理函数 944 | } 945 | 946 | Exit(*) { 947 | ExitApp() 948 | } 949 | 950 | ReStart(*) { 951 | Reload() 952 | } 953 | 954 | SetStatusBar(strToShow) { ; Set StatusBar text, Mode 1: Current command (default), 2: Hint, 3: Any text 955 | if (strToShow = "TIP") { 956 | strToShow := g_LNG[51] g_LNG[Random(52, 71)] ; Randomly select a tip from hint list g_LNG 52~71 957 | } else { 958 | strToShow := strToShow 959 | } 960 | 961 | myStatus.value := strToShow 962 | } 963 | 964 | RunCurrentCommand(*) { 965 | RunCommand(g_RUNTIME["CurrentCommand"]) 966 | } 967 | 968 | ParseArg() { 969 | commandPrefix := SubStr(myInputBox.Value, 1, 1) 970 | 971 | if (commandPrefix = "+" || commandPrefix = " " || commandPrefix = ">") { 972 | Return g_RUNTIME["Arg"] := SubStr(myInputBox.Value, 2) ; 直接取命令为参数 973 | } 974 | 975 | if (InStr(myInputBox.Value, " ") && !g_RUNTIME["UseFallback"]) { ; 用空格来判断参数 976 | g_RUNTIME["Arg"] := SubStr(myInputBox.Value, InStr(myInputBox.Value, " ") + 1) 977 | } 978 | else if (g_RUNTIME["UseFallback"]) { 979 | g_RUNTIME["Arg"] := myInputBox.Value 980 | } 981 | else { 982 | g_RUNTIME["Arg"] := "" 983 | } 984 | } 985 | 986 | ; 模糊匹配函数 987 | ; Haystack: 待搜索字符串 (命令的可搜索文本) 988 | ; Needle : 搜索关键词 (输入框内容) 989 | FuzzyMatch(Haystack, Needle) { 990 | ; 如果 Needle 为空,直接返回 按照命令优先级排序显示所有命令 991 | if (!Needle) 992 | return true 993 | 994 | ; 如果是数学表达式 (包含数字和运算符的字符串),跳过模糊匹配 995 | ; 例如: 25+5 或 6*5 会显示 Eval 结果而不是匹配文件中的 "30" 996 | if RegExMatch(Needle, "^[\d+\-*/^(). ]+$") && RegExMatch(Needle, "[+\-*/^]") 997 | return false 998 | 999 | Needle := StrReplace(Needle, "\", ".*") 1000 | Needle := StrReplace(Needle, " ", ".*") ; 空格直接替换为匹配任意字符 1001 | return RegExMatch(Haystack, g_RUNTIME["RegEx"] . Needle) 1002 | } 1003 | 1004 | ; 更新命令权重函数 1005 | UpdateRank(originCmd, showRank := false, inc := 1) { 1006 | Sections := Array(g_SECTION["DFTCMD"],g_SECTION["USERCMD"],g_SECTION["INDEX"]) 1007 | 1008 | for index, section in Sections { 1009 | Rank := IniRead(g_INI, section, originCmd, "KeyNotFound") 1010 | 1011 | if (Rank = "KeyNotFound" or Rank = "ERROR" or originCmd = "") ; If originCmd not exist in this section, then check next section 1012 | continue ; Skips the rest of a loop and begins a new one 1013 | 1014 | Rank := IsInteger(Rank) ? Rank + inc : inc ; 如果成功定位到命令, 计算命令新权重 1015 | Rank := (Rank < 0) ? -1 : Rank ; 如果权重降到负数, 统一设置为 -1, 然后屏蔽/排除 1016 | 1017 | IniWrite(Rank, g_INI, section, originCmd) ; 更新命令权重 1018 | if (showRank) 1019 | SetStatusBar("UpdateRank: Rank for current command : " Rank) 1020 | 1021 | g_LOG.Debug("UpdateRank: Rank updated for command..." originCmd "=" Rank) 1022 | break 1023 | } 1024 | LoadCommands() ; New rank will take effect in real-time by LoadCommands again 1025 | } 1026 | 1027 | UpdateUsage() { 1028 | currDate := A_YYYY . A_MM . A_DD 1029 | 1030 | if (!g_USAGE.Has(currDate)) { 1031 | g_USAGE[currDate] := 1 1032 | } else { 1033 | g_USAGE[currDate] += 1 1034 | } 1035 | 1036 | g_RUNTIME["Max"] := Max(g_RUNTIME["Max"], g_USAGE[currDate]) 1037 | IniWrite(g_USAGE[currDate], g_INI, g_SECTION["USAGE"], currDate) 1038 | } 1039 | 1040 | UpdateRunCount() { 1041 | g_CONFIG["RunCount"]++ 1042 | IniWrite(g_CONFIG["RunCount"], g_INI, g_SECTION["CONFIG"], "RunCount") 1043 | g_LOG.Debug("UpdateRunCount: RunCount update to..." g_CONFIG["RunCount"]) 1044 | } 1045 | 1046 | RankUp(*) { 1047 | UpdateRank(g_RUNTIME["CurrentCommand"], true) 1048 | } 1049 | 1050 | RankDown(*) { 1051 | UpdateRank(g_RUNTIME["CurrentCommand"], true, -1) 1052 | } 1053 | 1054 | LoadCommands() { 1055 | Global g_COMMANDS := Array() ; Clear g_COMMANDS, g_FALLBACK, g_CMDINDEX (searchable text for all commands) 1056 | Global g_CMDINDEX := Array() 1057 | Global g_FALLBACK := Array() 1058 | Local RankString := "" 1059 | 1060 | for index, line in StrSplit(LoadConfig("commands"), "`n", "`r") ; Read commands sections (built-in, user & index), read each line, separate key and value 1061 | { 1062 | if (!Trim(line) || SubStr(line, 1, 1) = ";") ; Skip empty line or comment line 1063 | continue 1064 | 1065 | command := StrSplit(line, "=")[1] 1066 | rank := StrSplit(line, "=")[2] 1067 | 1068 | if (command != "" and rank > 0) { 1069 | splitResult := StrSplit(command, " | ") 1070 | type := splitResult[1] 1071 | path := splitResult[2] 1072 | desc := splitResult.Has(3) ? splitResult[3] : "" 1073 | SplitPath(path, &filename) 1074 | 1075 | strToSearch := g_CONFIG["MatchPath"] ? path " " desc : filename " " desc ; search file name include extension, and desc (For MatchBeginning option, exclude "type") 1076 | strToSearch := g_CONFIG["MatchPinyin"] ? GetFirstChar(strToSearch) : strToSearch ; 中文转为拼音首字母 1077 | 1078 | RankString .= rank "`t" command "`t" strToSearch "`n" 1079 | } 1080 | } 1081 | 1082 | ; Sort commands by rank (reverse numerical) 1083 | RankString := Sort(RankString, "R N") 1084 | for index, line in StrSplit(RankString, "`n", "`r") 1085 | { 1086 | if !Trim(line) 1087 | continue ; 跳过空行 1088 | 1089 | split := StrSplit(line, "`t") ; line format is "rank `t Command `t strToSearch" 1090 | g_COMMANDS.Push(split[2]) 1091 | g_CMDINDEX.Push(split[3]) 1092 | } 1093 | 1094 | ; Read FALLBACK section 1095 | FALLBACKCMDSEC := "" 1096 | Try FALLBACKCMDSEC := IniRead(g_INI, g_SECTION["FALLBACK"]) 1097 | if (FALLBACKCMDSEC = "") { 1098 | IniWrite(" 1099 | ( 1100 | ; Fallback Commands show when search result is empty 1101 | ; Commands in order, modify as desired 1102 | ; Format: Command Type | Command | Description 1103 | ; Command Type: File, Dir, CMD, URL 1104 | ; 1105 | Func | NewCommand | New Command 1106 | Func | Everything | Search by Everything 1107 | Func | Google | Search Clipboard or Input by Google 1108 | Func | AhkRun | Run Command use AutoHotkey Run 1109 | Func | Bing | Search Clipboard or Input by Bing 1110 | CMD | Calc.exe | Calculator 1111 | )", g_INI, g_SECTION["FALLBACK"]) 1112 | FALLBACKCMDSEC := IniRead(g_INI, g_SECTION["FALLBACK"]) 1113 | } 1114 | for line in StrSplit(FALLBACKCMDSEC, "`n") { 1115 | if (line != "") 1116 | g_FALLBACK.Push(line) 1117 | } 1118 | 1119 | g_LOG.Debug("LoadCommands: Loaded COMMANDS=" g_COMMANDS.Length ", FALLBACK=" g_FALLBACK.Length) 1120 | return 1121 | } 1122 | 1123 | LoadHistory() { 1124 | if (g_CONFIG["SaveHistory"]) { 1125 | Loop g_CONFIG["HistoryLen"] { 1126 | Try history := IniRead(g_INI, g_SECTION["HISTORY"], A_Index, "") 1127 | g_HISTORYS.Push(history) 1128 | } 1129 | g_LOG.Debug("LoadHistory: Loaded history..." g_HISTORYS.Length) 1130 | } else { 1131 | Try IniDelete(g_INI, g_SECTION["HISTORY"]) 1132 | g_LOG.Debug("LoadHistory: History section cleaned up...") 1133 | } 1134 | } 1135 | 1136 | GetCmdOutput(command) { 1137 | TempFile := A_Temp . "\ALTRun.stdout" 1138 | FullCommand := A_ComSpec " /C " command " > " TempFile 1139 | 1140 | RunWait(FullCommand, A_Temp, "Hide") 1141 | Result := FileRead(TempFile) 1142 | try FileDelete(TempFile) 1143 | Return RTrim(Result, "`r`n") ; Remove result rightmost/last "`r`n" 1144 | } 1145 | 1146 | GetRunResult(command) { ; 运行CMD并取返回结果方式2 1147 | shell := ComObject("WScript.Shell") ; WshShell object: https://msdn.microsoft.com/en-us/library/aew9yb99 1148 | exec := shell.Exec(A_ComSpec " /C " command) ; Execute a single command via cmd.exe 1149 | Return exec.StdOut.ReadAll() ; Read and Return the command's output 1150 | } 1151 | 1152 | OpenDir(Path) { 1153 | Path := AbsPath(Path) 1154 | 1155 | Try{ 1156 | Run(g_CONFIG["FileMgr"] ' `"' Path '`"') 1157 | g_LOG.Debug("OpenDir: Using=" g_CONFIG["FileMgr"] " to open dir=" Path "...OK") 1158 | } catch as e { 1159 | g_LOG.Debug("OpenDir: Failed to open dir=" Path " Error=" e.Message) 1160 | MsgBox("Could not open dir: " Path "`n`nError message: " e.Message, g_TITLE, 48) 1161 | } 1162 | } 1163 | 1164 | OpenContainer(*) { 1165 | if (StrSplit(g_RUNTIME["CurrentCommand"], " | ").Length < 2) { 1166 | return MsgBox("No valid file to open container folder.", g_TITLE, 48) 1167 | } 1168 | Path := AbsPath(StrSplit(g_RUNTIME["CurrentCommand"], " | ")[2]) 1169 | 1170 | try { 1171 | if (g_CONFIG["FileMgr"] = "Explorer.exe") 1172 | Run(g_CONFIG["FileMgr"] ' /Select, `"' Path '`"') 1173 | else 1174 | Run(g_CONFIG["FileMgr"] ' /P `"' Path '`"') ; /P Parent folder 1175 | 1176 | g_LOG.Debug("OpenContainer: Using=" g_CONFIG["FileMgr"] " to open container dir for file=" Path "...OK") 1177 | } catch as e { 1178 | g_LOG.Debug("OpenContainer: Failed to open container dir for file=" Path " Error=" e.Message) 1179 | MsgBox("Failed to open container dir for file: " . Path "`n`nError message: " . e.Message, g_TITLE, 48) 1180 | } 1181 | } 1182 | 1183 | ; 监听窗口失去焦点时自动关闭 1184 | MonitorFocus(*) { 1185 | if (!WinExist("ahk_id " MainGUI.Hwnd) || g_RUNTIME["UseDisplay"]) 1186 | return 1187 | 1188 | if (!WinActive("ahk_id " MainGUI.Hwnd)) { 1189 | MainGUI_Close() 1190 | g_LOG.Debug("MonitorFocus: ALTRun lose focus, auto closing...") 1191 | } 1192 | } 1193 | 1194 | ; WM_ACTIVATE(wParam, lParam, msg, hwnd){ ; Close on lose focus, OnMessage is far more efficient than SetTimer + WinActive check 1195 | ; if (hwnd != MainGUI.Hwnd) { ; Ignore messages from other windows 1196 | ; g_LOG.Debug("WM_ACTIVATE: Ignored message from hwnd (" hwnd ") != MainGUI.Hwnd (" MainGUI.Hwnd ")") 1197 | ; return 0 1198 | ; } 1199 | 1200 | ; if (!WinExist("ahk_id " MainGUI.Hwnd)) { ; Ignore when MainGUI does not exist, to avoid flahshing issue 1201 | ; g_LOG.Debug("WM_ACTIVATE: Ignored message, MainGUI does not exist...") 1202 | ; return 0 1203 | ; } 1204 | 1205 | ; isActivated := (wParam > 0) ; wParam > 0 means the window is being activated 1206 | ; g_LOG.Debug("WM_ACTIVATE: Window is " (isActivated ? "activated..." : "de-activated...")) 1207 | 1208 | ; if (!isActivated && WinExist("ahk_id " MainGUI.Hwnd) && !g_RUNTIME["UseDisplay"]) { 1209 | ; MainGUI_Close() 1210 | ; g_LOG.Debug("WM_ACTIVATE: Window lose focus, auto closing...") 1211 | ; } 1212 | ; return 0 1213 | ; } 1214 | 1215 | UpdateSendTo() { ; the lnk in SendTo must point to a exe 1216 | lnkPath := StrReplace(A_StartMenu, "\Start Menu", "\SendTo\") "ALTRun.lnk" 1217 | if (!g_CONFIG["EnableSendTo"]) { 1218 | try FileDelete(lnkPath) 1219 | g_LOG.Debug("UpdateSendTo: Update SendTo shortcut...Disabled") 1220 | return 1221 | } 1222 | 1223 | if (A_IsCompiled) 1224 | FileCreateShortcut(A_ScriptFullPath, lnkPath, ,"-SendTo", "Send command to ALTRun User Command list") 1225 | else 1226 | FileCreateShortcut(A_AhkPath, lnkPath, , A_ScriptFullPath " -SendTo", "Send command to ALTRun User Command list") 1227 | 1228 | g_LOG.Debug("UpdateSendTo: Update SendTo shortcut...OK") 1229 | return 1230 | } 1231 | 1232 | UpdateStartup() { 1233 | lnkPath := A_Startup "\ALTRun.lnk" 1234 | 1235 | if (!g_CONFIG["AutoStartup"]) { 1236 | try FileDelete(lnkPath) 1237 | g_LOG.Debug("UpdateStartup: Update Startup shortcut...Disabled") 1238 | return 1239 | } 1240 | 1241 | FileCreateShortcut(A_ScriptFullPath, lnkPath, A_ScriptDir, "-startup", "ALTRun - An effective launcher") 1242 | 1243 | g_LOG.Debug("UpdateStartup: Update Startup shortcut...OK") 1244 | return 1245 | } 1246 | 1247 | UpdateStartMenu() { 1248 | lnkPath := A_Programs "\ALTRun.lnk" 1249 | 1250 | if (!g_CONFIG["InStartMenu"]) { 1251 | try FileDelete(lnkPath) 1252 | g_LOG.Debug("UpdateStartMenu: Update StartMenu shortcut...Disabled") 1253 | return 1254 | } 1255 | 1256 | FileCreateShortcut(A_ScriptFullPath, lnkPath, A_ScriptDir, "-StartMenu", "ALTRun - An effective launcher") 1257 | g_LOG.Debug("UpdateStartMenu: Update StartMenu shortcut...OK") 1258 | return 1259 | } 1260 | 1261 | Reindex(*) { ; Re-create Index section 1262 | IniDelete(g_INI, g_SECTION["INDEX"]) ; Clear old index section 1263 | for dirIndex, dir in StrSplit(g_CONFIG["IndexDir"], ",") { 1264 | searchPath := RegExReplace(AbsPath(dir), "\\+$") ; Remove trailing backslashes 1265 | 1266 | for extIndex, ext in StrSplit(g_CONFIG["IndexType"], ",") { 1267 | Loop Files, searchPath "\" ext, "R" { ; Calculate path relative to searchPath and count subdir levels 1268 | rel := SubStr(A_LoopFileFullPath, StrLen(searchPath) + 2) ; +2 to skip the backslash 1269 | seps := (rel = "") ? 0 : StrLen(rel) - StrLen(StrReplace(rel, "\", "")) ; Count backslashes to determine depth 1270 | 1271 | if (seps >= g_CONFIG["IndexDepth"]) ; If file is deeper than allowed depth, skip it. 1272 | continue 1273 | 1274 | if (g_CONFIG["IndexExclude"] != "" && RegExMatch(A_LoopFileFullPath, g_CONFIG["IndexExclude"])) 1275 | continue ; Skip this file and move on to the next loop. 1276 | 1277 | IniWrite("1", g_INI, g_SECTION["INDEX"], "File | " A_LoopFileFullPath) ; Store file type for later use 1278 | 1279 | static ProgressGui := "" ; Static to persist GUI across loop iterations 1280 | if (!ProgressGui) { ; Create GUI only once 1281 | ProgressGui := Gui("-MinimizeBox +AlwaysOnTop", "Reindex") 1282 | ProgressGui.Add("Text", , "ReIndexing...") 1283 | ProgressGui.Add("Progress", "vMyProgress w200", A_Index) 1284 | ProgressGui.Add("Text", "vMyFileName w200", A_LoopFileName) 1285 | ProgressGui.Show() 1286 | } else { ; Update existing GUI 1287 | ProgressGui["MyProgress"].Value := A_Index 1288 | ProgressGui["MyFileName"].Text := A_LoopFileName 1289 | Sleep 30 1290 | } 1291 | } 1292 | } 1293 | if (ProgressGui) { ; Destroy GUI after loop 1294 | ProgressGui.Destroy() 1295 | ProgressGui := "" 1296 | } 1297 | } 1298 | 1299 | g_LOG.Debug("Reindex: Indexing search database...OK") 1300 | TrayTip("ReIndex database finish successfully.", g_TITLE, 8) 1301 | LoadCommands() 1302 | } 1303 | 1304 | About(*) { 1305 | Options(8) 1306 | } 1307 | 1308 | Usage(*) { 1309 | Options(7) 1310 | } 1311 | 1312 | AutoCheckUpdate(*) { 1313 | if (!g_CONFIG["AutoUpdateCheck"]) 1314 | return 1315 | 1316 | ; One-time timer to check for updates 1317 | SetTimer(CheckUpdate, -1000) 1318 | } 1319 | 1320 | Update(*) { 1321 | ; Manual update check, show message box 1322 | CheckUpdate(False) 1323 | } 1324 | 1325 | ; Main update check function, called from tray menu (*) or with silent flag 1326 | CheckUpdate(Silent := True) { 1327 | RepoAPI := "https://api.github.com/repos/zhugecaomao/ALTRun/releases/latest" 1328 | ReleasePage := "https://github.com/zhugecaomao/ALTRun/releases" 1329 | 1330 | try { 1331 | tmpFile := A_Temp "\ALTRun_latest.json" 1332 | Download(RepoAPI, tmpFile) 1333 | json := FileRead(tmpFile, "UTF-8") 1334 | 1335 | ; Extract latest version from tag_name 1336 | if !RegExMatch(json, '"tag_name"\s*:\s*"([^"]+)"', &verMatch) 1337 | throw Error("Cannot find 'tag_name' in GitHub API response.") 1338 | 1339 | latestVersion := Trim(verMatch[1], "vV ") 1340 | currentVersion := Trim(g_TITLE, "ALTRun - v ") 1341 | 1342 | ; Compare versions 1343 | if (CompareVersion(latestVersion, currentVersion) > 0) { 1344 | MsgBox(g_LNG[805] latestVersion g_LNG[806], g_Title, 64) 1345 | Run ReleasePage 1346 | } else if (!Silent) { 1347 | ; Only show "up-to-date" message for manual checks 1348 | MsgBox(g_LNG[807] currentVersion g_LNG[808], g_Title, 64) 1349 | } 1350 | 1351 | } catch as e { 1352 | if (!Silent) 1353 | MsgBox(g_LNG[809] e.Message, g_Title, 48) 1354 | else 1355 | g_LOG.Debug("CheckUpdate: Update check failed: " e.Message) 1356 | } 1357 | } 1358 | 1359 | CompareVersion(v1, v2) { 1360 | v1Parts := StrSplit(v1, ".") 1361 | v2Parts := StrSplit(v2, ".") 1362 | Loop Max(v1Parts.Length, v2Parts.Length) { 1363 | diff := (v1Parts[A_Index] + 0) - (v2Parts[A_Index] + 0) 1364 | if diff 1365 | return diff 1366 | } 1367 | return 0 1368 | } 1369 | 1370 | Listary() { ; Listary 快速更换保存/打开对话框路径 1371 | Loop Parse, g_CONFIG["FileMgrID"], "," ; File Manager Class, default is Windows Explorer & Total Commander 1372 | GroupAdd("FileMgrID", A_LoopField) 1373 | 1374 | Loop Parse, g_CONFIG["DialogWin"], "," ; 需要QuickSwith的窗口, 包括打开/保存对话框等 1375 | GroupAdd("DialogBox", A_LoopField) 1376 | 1377 | Loop Parse, g_CONFIG["ExcludeWin"], "," ; 排除特定窗口,避免被 Auto-QuickSwitch 影响 1378 | GroupAdd("ExcludeWin", A_LoopField) 1379 | 1380 | if (g_CONFIG["AutoSwitchDir"]) { 1381 | g_LOG.Debug("Listary: Auto-QuickSwitch enabled, monitoring thread...") 1382 | Loop { 1383 | TcHwnd := WinWaitActive("ahk_class TTOTAL_CMD") 1384 | WinWaitNotActive() 1385 | 1386 | ; 检测当前窗口是否符合打开保存对话框条件 1387 | If(WinActive("ahk_group DialogBox") && !WinActive("ahk_group ExcludeWin")) { 1388 | Title := WinGetTitle("A") 1389 | ProcessName := WinGetProcessName("A") 1390 | g_LOG.Debug("Listary: Dialog detected, active window ahk_title=" Title ", ahk_exe=" ProcessName) 1391 | SyncTCPath() ; NO Return, as will terimate loop (AutoSwitchDir) 1392 | } 1393 | Sleep 100 ; Reduce CPU usage 1394 | } 1395 | } 1396 | 1397 | HotIfWinActive("ahk_group DialogBox") ; 设置对话框路径定位热键,为了不影响其他程序热键,设置只对打开/保存对话框生效 1398 | try { 1399 | Hotkey(g_HOTKEY["ExplorerDir"], SyncExplorerPath) ; Ctrl+E 把打开/保存对话框的路径定位到资源管理器当前浏览的目录 1400 | Hotkey(g_HOTKEY["TotalCMDDir"], SyncTCPath) ; Ctrl+G 把打开/保存对话框的路径定位到TC当前浏览的目录 1401 | g_LOG.Debug("Listary: Set quickswitch hotkey " g_HOTKEY["ExplorerDir"] " for Explorer, " g_HOTKEY["TotalCMDDir"] " for Total Commander...OK") 1402 | } catch as e { 1403 | g_LOG.Debug("Listary: Failed to set quickswitch hotkey..." e.Message) 1404 | } 1405 | HotIfWinActive ; Turn off context, make subsequent hotkeys global again 1406 | return 1407 | } 1408 | 1409 | ; Sync dialog box to Total Commander path (TC 7.x ~ 10.x) 1410 | SyncTCPath(*) { 1411 | ClipSaved := ClipboardAll() 1412 | A_Clipboard := "" 1413 | ; Get the HWND of TC (WinGetID may occur error if TC not found) 1414 | hwnd := WinExist("ahk_class TTOTAL_CMD") 1415 | if (!hwnd) { 1416 | MsgBox(g_LNG[219], g_TITLE, 48) 1417 | g_LOG.Debug("SyncTCPath: No Total Commander window found") 1418 | return 1419 | } 1420 | try { 1421 | SendMessage(1075, 2029, 0, , "ahk_class TTOTAL_CMD") ; TC: WM_USER + 75, TC_GETCURRENTPATH = 2029 1422 | } catch as e { 1423 | g_LOG.Debug("SyncTCPath: SendMessage failed, exception - " . e.Message) 1424 | A_Clipboard := ClipSaved 1425 | return 1426 | } 1427 | ; Wait up to 0.1 seconds for the clipboard to contain data 1428 | if (ClipWait(0.1) = 0) { 1429 | A_Clipboard := ClipSaved 1430 | g_LOG.Debug("SyncTCPath: Clipboard wait timed out") 1431 | return 1432 | } 1433 | ; 确保路径以反斜杠结尾, 解决AutoCAD不识别路径问题 1434 | OutDir := RTrim(A_Clipboard, "\") . "\" 1435 | A_Clipboard := ClipSaved 1436 | SetDialogPath(OutDir) 1437 | } 1438 | 1439 | ; Sync dialog box to Explorer path (Win7 ~ Win11) 1440 | SyncExplorerPath(*) { 1441 | ; Get the HWND of Explorer (WinGetID may occur error if Explorer not found) 1442 | hwnd := WinExist("ahk_class CabinetWClass") 1443 | if (!hwnd) { 1444 | MsgBox(g_LNG[220], g_TITLE, 48) 1445 | g_LOG.Debug("SyncExplorerPath: No Explorer window found") 1446 | return 1447 | } 1448 | try { 1449 | for window in ComObject("Shell.Application").Windows 1450 | if (window.HWND = hwnd) { 1451 | Dir := window.Document.Folder.Self.Path 1452 | SetDialogPath(Dir) 1453 | return 1454 | } 1455 | g_LOG.Debug("SyncExplorerPath: No matching Explorer window") 1456 | } catch as e { 1457 | g_LOG.Debug("SyncExplorerPath: COM error - " e.Message) 1458 | } 1459 | } 1460 | 1461 | ; Set dialog box path to specified directory 1462 | SetDialogPath(Dir) { 1463 | if (!Dir || !FileExist(Dir)) { 1464 | g_LOG.Debug("SetDialogPath: Invalid directory :" Dir) 1465 | return 1466 | } 1467 | ActiveClass := WinGetClass("A") 1468 | if (ActiveClass = "Qt5QWindowIcon") { 1469 | ; WPS dialog: Its Edit control has no valid id, try simulate keyboard input (not fully reliable) 1470 | SendInput "{Dir}" 1471 | SendInput "{Enter}" 1472 | g_LOG.Debug("SetDialogPath: Set path to " Dir " (WPS dialog)") 1473 | } else { 1474 | ; Windows Standard dialog: Edit1 is the path input box 1475 | dialogControl := ControlGetHwnd("Edit1", "A") 1476 | if (dialogControl) { 1477 | ControlFocus("Edit1", "A") 1478 | ControlSetText(Dir, "Edit1", "A") 1479 | ControlSend("{Enter}", "Edit1", "A") 1480 | g_LOG.Debug("SetDialogPath: Set dialog path to=" Dir) 1481 | } else { 1482 | g_LOG.Debug("SetDialogPath: No Edit1 control found in dialog") 1483 | } 1484 | } 1485 | } 1486 | 1487 | UserCommand(*) { 1488 | Run("Notepad.exe " . g_INI) 1489 | } 1490 | 1491 | ; From command "New Command" or GUI context menu "New Command" 1492 | NewCommand(*) { 1493 | CmdMgr(g_SECTION["USERCMD"], , , g_RUNTIME["Arg"], 1, "") 1494 | } 1495 | 1496 | EditCommand(*) { 1497 | Global g_RUNTIME, g_SECTION, g_INI ; 明确声明全局变量 1498 | 1499 | currentCmd := g_RUNTIME["CurrentCommand"] 1500 | if !currentCmd 1501 | return 1502 | 1503 | for index, section in StrSplit(g_SECTION["DFTCMD"] "," g_SECTION["USERCMD"] "," g_SECTION["INDEX"], ",") { 1504 | rank := IniRead(g_INI, section, currentCmd, "KeyNotFound") 1505 | 1506 | ; If currentCmd not exist in this section, skips the rest of a loop and begin to check next section 1507 | if (rank = "KeyNotFound" || rank = "ERROR") 1508 | continue 1509 | 1510 | if IsInteger(rank) { 1511 | parts := StrSplit(currentCmd, " | ") 1512 | type := parts.Length >= 1 ? parts[1] : "" 1513 | path := parts.Length >= 2 ? parts[2] : "" 1514 | desc := parts.Length >= 3 ? parts[3] : "" 1515 | 1516 | g_Log.Debug("EditCommand: Editing command=" currentCmd) 1517 | CmdMgr(section, type, path, desc, rank, currentCmd) 1518 | break 1519 | } 1520 | } 1521 | } 1522 | 1523 | DelCommand(*) { 1524 | currentCmd := g_RUNTIME["CurrentCommand"] 1525 | if !currentCmd 1526 | return 1527 | 1528 | for index, section in StrSplit(g_SECTION["DFTCMD"] "," g_SECTION["USERCMD"] "," g_SECTION["INDEX"], ",") { 1529 | rank := IniRead(g_INI, section, currentCmd, "KeyNotFound") 1530 | if (rank = "KeyNotFound" || rank = "ERROR") 1531 | continue 1532 | 1533 | result := MsgBox(g_LNG[800] section "]`n`n" currentCmd, g_LNG[801], 52) ; 52 = Yes/No + Question icon 1534 | 1535 | if result = "YES" { 1536 | try { 1537 | IniDelete(g_INI, section, currentCmd) 1538 | MsgBox(g_LNG[802] "`n`n" currentCmd, g_TITLE, 64) ; 64 = Info icon 1539 | } catch as e { 1540 | MsgBox(g_LNG[803] "`n`n" currentCmd, g_TITLE, 48) ; 48 = Error icon 1541 | } 1542 | break 1543 | } 1544 | } 1545 | LoadCommands() 1546 | } 1547 | 1548 | 1549 | CmdMgr(Section := "UserCommand", Type := "File", Path := "", Desc := "", Rank := 1, OriginCmd := "") { ; 命令管理窗口 1550 | Global CmdMgrGUI 1551 | Local typeList := Array("File", "Dir", "CMD", "URL", "Func") 1552 | 1553 | g_LOG.Debug("Starting Command Manager... Args=" Section "|" Type "|" Path "|" Desc "|" Rank) 1554 | 1555 | CmdMgrGUI := Gui(, g_LNG[700]) 1556 | CmdMgrGUI.SetFont("S9 Norm", "Microsoft Yahei") 1557 | CmdMgrGUI.AddGroupBox("w600 h260", g_LNG[701]) 1558 | CmdMgrGUI.Add("Text", "x25 yp+30", g_LNG[702]) 1559 | CmdMgrGUI.AddDropDownList("x160 yp-5 w130 vType Choose" GetArrayIndex(Type, typeList), typeList) 1560 | CmdMgrGUI.Add("Text", "x315 yp+5", g_LNG[705]) 1561 | CmdMgrGUI.Add("Edit", "x435 yp-5 w130 Disabled vSection", Section) 1562 | CmdMgrGUI.Add("Text", "x25 yp+60", g_LNG[703]) 1563 | CmdMgrGUI.Add("Edit", "x160 yp-5 w405 -WantReturn vPath", Path).Focus() 1564 | CmdMgrGUI.AddButton("x575 yp w30 hp", "...").OnEvent("Click", (*) => SelectCmdPath(CmdMgrGUI["Type"].Text)) 1565 | CmdMgrGUI.Add("Text", "x25 yp+80", g_LNG[704]) 1566 | CmdMgrGUI.AddEdit("x160 yp-5 w405 -WantReturn vDesc", Desc) 1567 | CmdMgrGUI.AddText("x25 yp+60", g_LNG[706]) 1568 | CmdMgrGUI.AddEdit("x160 yp-5 w405 +Number vRank", Rank) 1569 | CmdMgrGUI.AddButton("Default x420 w90", g_LNG[7]).OnEvent("Click", (*) => CmdMgrButtonOK(Section, CmdMgrGUI["Type"].Text, CmdMgrGUI["Path"].Text, CmdMgrGUI["Desc"].Text, CmdMgrGUI["Rank"].Text, OriginCmd)) 1570 | CmdMgrGUI.AddButton("x521 yp w90", g_LNG[8]).OnEvent("Click", CmdMgrGuiClose) 1571 | CmdMgrGUI.OnEvent("Close", CmdMgrGUIClose) 1572 | CmdMgrGUI.OnEvent("Escape", CmdMgrGUIClose) 1573 | CmdMgrGUI.Show("Center") 1574 | } 1575 | 1576 | SelectCmdPath(Type) { 1577 | CmdMgrGUI.Opt("+OwnDialogs") ; Make open dialog Modal 1578 | 1579 | if (Type = "Dir") 1580 | Path := DirSelect(, 3, 'Please select directory') 1581 | else 1582 | Path := FileSelect(3, , , 'All Files (*.*)') 1583 | 1584 | if (Path != "") 1585 | CmdMgrGUI["Path"].Value := Path 1586 | } 1587 | 1588 | CmdMgrButtonOK(Section, Type, Path, Desc, Rank, OriginCmd) { 1589 | CmdMgrGUI.Submit() 1590 | Desc := Desc ? " | " Desc : Desc 1591 | 1592 | if (Path = "") { 1593 | return MsgBox(g_LNG[821], g_LNG[820], 64) 1594 | } else { 1595 | try { 1596 | IniDelete(g_INI, Section, OriginCmd) ; Delete old command if path or desc changed 1597 | IniWrite(Rank, g_INI, Section, Type " | " Path Desc) 1598 | } catch as e { 1599 | MsgBox(g_LNG[822] e.Message, g_LNG[820], 64) 1600 | return 1601 | } 1602 | MsgBox(g_LNG[823] Section " ]`n`n" Type " | " Path " " Desc " = " Rank, g_LNG[820], 64) 1603 | } 1604 | LoadCommands() 1605 | } 1606 | 1607 | CmdMgrGuiClose(*) { 1608 | CmdMgrGUI.Destroy() 1609 | } 1610 | 1611 | Plugins() { ; Plugins (Ctrl+D 自动添加日期) 1612 | Loop Parse, g_HOTKEY["AutoDateBefExt"], "," 1613 | GroupAdd("FileListMangr", A_LoopField) 1614 | 1615 | Loop Parse, g_HOTKEY["AutoDateAtEnd"], "," 1616 | GroupAdd("TextBox", A_LoopField) 1617 | 1618 | HotIfWinActive("ahk_group FileListMangr") ; 针对所有设定好的程序 按Ctrl+D自动在文件(夹)名之后添加日期 1619 | Hotkey(g_HOTKEY["AutoDateBEHKey"], RenameWithDate) 1620 | 1621 | 1622 | HotIfWinActive("ahk_group TextBox") 1623 | Hotkey(g_HOTKEY["AutoDateAEHKey"], LineEndAddDate) 1624 | HotIfWinActive 1625 | 1626 | g_LOG.Debug("Plugins: Load AutoDate plugins...OK") 1627 | return 1628 | } 1629 | 1630 | RenameWithDate(*) { ; 针对所有设定好的程序 按Ctrl+D自动在文件(夹)名之后添加日期 1631 | FocusedHwnd := ControlGetFocus("A") ; 获取当前激活的窗口中的聚焦的控件名称 1632 | FocusedClassNN := ControlGetClassNN(FocusedHwnd) 1633 | 1634 | if (InStr(FocusedClassNN, "Edit") or InStr(FocusedClassNN, "Scintilla")) ; 如果当前激活的控件为Edit类或者Scintilla1(Notepad2),则Ctrl+D功能生效 1635 | NameAddDate("FileListMangr", FocusedClassNN) 1636 | Else 1637 | SendInput "^D" ; 如果不是,则发送原始的Ctrl+D 1638 | 1639 | g_LOG.Debug("RenameWithDate: Current control=" FocusedClassNN) 1640 | Return 1641 | } 1642 | 1643 | LineEndAddDate(*) { ; 针对TC File Comment对话框 按Ctrl+D自动在备注文字之后添加日期 1644 | CurrentDate := FormatTime(, "dd.MM.yyyy") 1645 | SendInput "{End}" 1646 | Sleep 10 1647 | SendInput "{Blind}{Text} - " CurrentDate 1648 | g_LOG.Debug("LineEndAddDate: Add date at end= - " CurrentDate) 1649 | } 1650 | 1651 | NameAddDate(WinName, CurrCtrl) { ; 在文件(夹)名编辑框中添加日期,CurrCtrl为当前控件(名称编辑框Edit) 1652 | EditCtrlText := ControlGetText(CurrCtrl, "A") 1653 | SplitPath(EditCtrlText, &fileName, &fileDir, &fileExt, &nameNoExt) 1654 | CurrentDate := FormatTime(, "dd.MM.yyyy") 1655 | 1656 | ; 仅当扩展名不是空 & 最后是点后直接跟 1~4 个字母/数字时 & 字符 <5 & 不是纯数字, 才把后缀视为真实扩展名(避免像 "1. DWG" 这种点后有空格被误判), 才加日期在后缀名之前 1657 | if (fileExt != "" && RegExMatch(EditCtrlText, "\.[A-Za-z0-9]{1,4}$") && StrLen(fileExt) < 5 && !RegExMatch(fileExt,"^\d+$")) { 1658 | if RegExMatch(nameNoExt, " - \d{2}\.\d{2}\.\d{4}$") { 1659 | baseName := RegExReplace(nameNoExt, " - \d{2}\.\d{2}\.\d{4}$", "") 1660 | } 1661 | else if RegExMatch(nameNoExt, "-\d{2}\.\d{2}\.\d{4}$") { 1662 | baseName := RegExReplace(nameNoExt, "-\d{2}\.\d{2}\.\d{4}$", "") 1663 | } else { 1664 | baseName := nameNoExt 1665 | } 1666 | NameWithDate := baseName " - " CurrentDate "." fileExt 1667 | } else if (RegExMatch(fileName, " - \d{2}\.\d{2}\.\d{4}$")) { ; 如果无后缀, 文件(夹)名最后有日期,则更新为当前日期 1668 | NameWithDate := RegExReplace(fileName, " - \d{2}\.\d{2}\.\d{4}$", " - " CurrentDate) 1669 | } else if (RegExMatch(nameNoExt, "-\d{2}\.\d{2}\.\d{4}$")) { 1670 | NameWithDate := RegExReplace(fileName, "-\d{2}\.\d{2}\.\d{4}$", " - " CurrentDate) 1671 | } else { 1672 | NameWithDate := EditCtrlText " - " CurrentDate 1673 | } 1674 | ControlFocus(CurrCtrl, "A") 1675 | ControlSetText(NameWithDate, CurrCtrl, "A") 1676 | SendInput "{Blind}{End}" 1677 | g_LOG.Debug("NameAddDate: Add date to filename= " NameWithDate) 1678 | } 1679 | 1680 | GetArrayIndex(searchValue, Array){ 1681 | for index, element in Array 1682 | { 1683 | if (element = searchValue) 1684 | return index 1685 | } 1686 | } 1687 | 1688 | PTTools() { 1689 | if not WinExist("PT Tools"){ 1690 | try { 1691 | Run(A_ScriptDir "\PTTools.ahk") 1692 | } catch as e { 1693 | MsgBox(e.Message, ,48) 1694 | return 1695 | } 1696 | } else { 1697 | WinActivate("PT Tools") 1698 | } 1699 | return 1700 | } 1701 | 1702 | StruCalc(evalResult) { 1703 | result := [] 1704 | formatVal := RegExReplace(evalResult, "\G\d+?(?=(\d{3})+(?:\D|$))", "$0" ",") ; To add thousand separator 1705 | result.Push("Eval | " formatVal) 1706 | 1707 | if !g_CONFIG["StruCalc"] 1708 | return result 1709 | 1710 | result.Push(" | ") ; 空行分隔 1711 | ; 主筋计算 1712 | rebarNum := Ceil((evalResult - 80) / 300 + 1) 1713 | spacing := Max(Round((evalResult - 80) / (rebarNum - 0.999)), 0) ; Use 0.999 to avoid division by zero error 1714 | result.Push("Eval | With beam width = " formatVal " mm") 1715 | result.Push(" | Main bar number = " rebarNum " (" spacing " C/C)") 1716 | result.Push(" | ") ; 空行分隔 1717 | ; 配筋面积计算 1718 | result.Push("Eval | With As = " formatVal " mm2") 1719 | result.Push(" | Rebar = " Ceil(evalResult / 132.7) "H13 / " 1720 | . Ceil(evalResult / 201.1) "H16 / " 1721 | . Ceil(evalResult / 314.2) "H20 / " 1722 | . Ceil(evalResult / 490.9) "H25 / " 1723 | . Ceil(evalResult / 804.2) "H32") 1724 | 1725 | return result 1726 | } 1727 | 1728 | Options(ActTab := 1) { 1729 | Global OptGUI, OptListView 1730 | Local FuncList := ["Unset", "Active", "ToggleWindow", "Google", "Bing" 1731 | , "Everything", "TabFunc", "PrevCommand", "NextCommand", "CopyCommand" 1732 | , "ClearInput", "RunCurrentCommand", "RankUp", "RankDown", "Reindex" 1733 | , "About", "Usage", "Update", "UserCommand", "NewCommand", "EditCommand" 1734 | , "DelCommand", "CmdMgr", "Options", "TurnMonitorOff", "EmptyRecycle" 1735 | , "MuteVolume", "ReStart", "Exit", "PTTools"] 1736 | 1737 | g_LOG.Debug("Options: Opening Options window... Tab=" ActTab) 1738 | MainGUI_Close() 1739 | if WinExist(g_LNG[2]) { 1740 | return WinActivate(g_LNG[2]) 1741 | } 1742 | 1743 | t := A_TickCount 1744 | ActTab := IsNumber(ActTab) ? ActTab : 1 ; Convert ActTab to number, default is 1 (for case like [Option`tF2]) 1745 | OptGUI := Gui("+Owner" MainGUI.hwnd, g_LNG[2]) ; +Owner MainGUI.hwnd fix GUI flicking issue 1746 | OptGUI.SetFont(StrSplit(g_GUI["OptGUIFont"], ",")[2], StrSplit(g_GUI["OptGUIFont"], ",")[1]) 1747 | OptTab := OptGUI.AddTab3("Choose" ActTab, g_LNG[100]) 1748 | 1749 | OptTab.UseTab(1) ; CONFIG Tab 1750 | OptListView := OptGUI.AddListView("w500 h300 Checked -Hdr", ["Settings"]) 1751 | for key, description in g_CONFIG_P1 { 1752 | OptListView.Add("Check" g_CONFIG[key], description) 1753 | } 1754 | OptListView.ModifyCol(1, "AutoHdr") 1755 | 1756 | OptGUI.AddText("x24 yp+320", g_LNG[150]) 1757 | OptGUI.AddComboBox("x130 yp-5 w394 vFileMgr Choose1", [g_CONFIG["FileMgr"], "Explorer.exe", "C:\Apps\TotalCMD.exe /O /T /S"]) 1758 | OptGUI.AddText("x24 yp+40", g_LNG[151]) 1759 | OptGUI.AddComboBox("x130 yp-5 w394 vEverything Choose1", [g_CONFIG["Everything"], "C:\Apps\Everything.exe"]) 1760 | OptGUI.AddText("x24 yp+40", g_LNG[152]) 1761 | OptGUI.AddDDL("x130 yp-5 w394 Sort vHistoryLen Choose" g_CONFIG["HistoryLen"]*0.1, [10,20,30,40,50,60]) 1762 | 1763 | OptTab.UseTab(2) ; GUI Tab 1764 | OptGUI.AddGroupBox("w500 h420", g_LNG[170]) 1765 | OptGUI.AddText("x33 yp+25", g_LNG[171]) 1766 | OptGUI.AddDDL("x183 yp-5 w330 vListRows Choose" g_GUI["ListRows"], [1,2,3,4,5,6,7,8,9]) ; ListRows limit <= 9 1767 | OptGUI.AddText("x33 yp+45", g_LNG[172]) 1768 | OptGUI.AddComboBox("x183 yp-5 w330 vColWidth Choose1", [g_GUI["ColWidth"], "20,0,460,AutoHdr", "30,46,460,AutoHdr"]) 1769 | OptGUI.AddText("x33 yp+45", g_LNG[176]) 1770 | OptGUI.AddEdit("x183 yp-5 w120 +Number vWinX", g_GUI["WinX"]) 1771 | OptGUI.AddText("x345 yp", "x") 1772 | OptGUI.AddEdit("x393 yp w120 +Number vWinY", g_GUI["WinY"]) 1773 | 1774 | OptGUI.AddText("x33 yp+45", g_LNG[173]) 1775 | OptGUI.AddEdit("x183 yp w240 r1 -E0x200 +ReadOnly vMainGUIFont", g_GUI["MainGUIFont"]).SetFont(StrSplit(g_GUI["MainGUIFont"], ",")[2], StrSplit(g_GUI["MainGUIFont"], ",")[1]) 1776 | OptGUI.AddButton("x433 yp-5 w80", g_LNG[182]).OnEvent("Click", (*) => SelectFont("MainGUIFont")) 1777 | OptGUI.AddText("x33 yp+45", g_LNG[174]) 1778 | OptGUI.AddEdit("x183 yp w240 r1 -E0x200 +ReadOnly vOptGUIFont", g_GUI["OptGUIFont"]) 1779 | OptGUI.AddButton("x433 yp-5 w80", g_LNG[182]).OnEvent("Click", (*) => SelectFont("OptGUIFont")) 1780 | OptGUI.AddText("x33 yp+45", g_LNG[175]) 1781 | OptGUI.AddEdit("x183 yp w240 r1 -E0x200 +ReadOnly vMainSBFont", g_GUI["MainSBFont"]).SetFont(StrSplit(g_GUI["MainSBFont"], ",")[2], StrSplit(g_GUI["MainSBFont"], ",")[1]) 1782 | OptGUI.AddButton("x433 yp-5 w80", g_LNG[182]).OnEvent("Click", (*) => SelectFont("MainSBFont")) 1783 | 1784 | OptGUI.AddText("x33 yp+45", g_LNG[179]) 1785 | OptGUI.AddEdit("x183 yp w240 r1 -E0x200 +ReadOnly vMainGUIColor", g_GUI["MainGUIColor"]) 1786 | OptGUI.AddButton("x433 yp-5 w80", g_LNG[183]).OnEvent("Click", PickMainGUIColor) 1787 | OptGUI.AddText("x33 yp+45", g_LNG[178]) 1788 | OptGUI.AddEdit("x183 yp w240 r1 -E0x200 +ReadOnly vCMDListColor", g_GUI["CMDListColor"]) 1789 | OptGUI.AddButton("x433 yp-5 w80", g_LNG[183]).OnEvent("Click", PickCMDListColor) 1790 | 1791 | OptGUI.AddText("x33 yp+45", g_LNG[180]) 1792 | OptGUI.AddComboBox("x183 yp-5 w240 vBackground Choose1", [g_GUI["Background"], "Default", "None", "ALTRun.jpg", "C:\Path\Picture.jpg"]) 1793 | OptGUI.AddButton("x433 yp-2 w80 vSelectBackground", g_LNG[184]).OnEvent("Click", SelectBackground) 1794 | OptGUI.AddText("x33 yp+45", g_LNG[181]) 1795 | OptGUI.AddSlider("x183 yp-5 w330 Range50-255 TickInterval5 Tooltip vTransparency", g_GUI["Transparency"]) 1796 | 1797 | OptTab.UseTab(3) ; Hotkey Tab 1798 | OptGUI.AddGroupBox("w500 h115", g_LNG[191]) 1799 | OptGUI.AddText("x33 yp+25", g_LNG[192]) 1800 | OptGUI.AddHotkey("x285 yp-4 w230 vGlobalHotkey1", g_HOTKEY["GlobalHotkey1"]) 1801 | OptGUI.AddText("x33 yp+35", g_LNG[193]) 1802 | OptGUI.AddHotkey("x285 yp-4 w230 vGlobalHotkey2", g_HOTKEY["GlobalHotkey2"]) 1803 | OptGUI.AddText("x33 yp+35", g_LNG[194]) 1804 | OptGUI.AddLink("x285 yp w230", "" g_LNG[195] "").OnEvent("Click", ResetHotkey) 1805 | 1806 | OptGUI.Add("GroupBox", "x24 yp+38 w500 h290", g_LNG[200]) 1807 | Loop 7 { 1808 | OptGUI.AddText("x33 yp+40", g_LNG[201]) 1809 | OptGUI.AddHotkey("x143 yp-5 w120 vHotkey" A_Index, g_HOTKEY["Hotkey" A_Index]) 1810 | OptGUI.AddText("x285 yp+5", g_LNG[202]) 1811 | OptGUI.AddDDL("x395 yp-5 w120 vTrigger" A_Index " Choose" GetArrayIndex(g_HOTKEY["Trigger" A_Index], FuncList), FuncList) 1812 | } 1813 | 1814 | HotIfWinActive ; Turn off global hotkey when options() called by hotif hotkey F2 1815 | if (g_HOTKEY["GlobalHotkey1"] != "") { 1816 | Hotkey(g_HOTKEY["GlobalHotkey1"], ToggleWindow, "Off") 1817 | g_LOG.Debug("Options: Turn Off GlobalHotkey1...OK") 1818 | } 1819 | if (g_HOTKEY["GlobalHotkey2"] != "") { 1820 | Hotkey(g_HOTKEY["GlobalHotkey2"], ToggleWindow, "Off") 1821 | g_LOG.Debug("Options: Turn Off GlobalHotkey2...OK") 1822 | } 1823 | 1824 | OptTab.UseTab(4) ; INDEX Tab 1825 | OptGUI.AddGroupBox("w500 h190", g_LNG[160]) 1826 | OptGUI.AddText("x33 yp+25", g_LNG[161]) 1827 | OptGUI.AddComboBox("x183 yp-5 w330 vIndexDir Choose1", [g_CONFIG["IndexDir"], "A_ProgramsCommon,A_StartMenu"]) 1828 | OptGUI.AddText("x33 yp+45", g_LNG[162]) 1829 | OptGUI.AddComboBox("x183 yp-5 w330 vIndexType Choose1", [g_CONFIG["IndexType"], "*.lnk,*.exe"]) 1830 | OptGUI.AddText("x33 yp+45", g_LNG[164]) 1831 | OptGUI.AddDropDownList("x183 yp-5 w330 vIndexDepth Choose" g_CONFIG["IndexDepth"], [1,2,3,4,5,6,7,8,9]) 1832 | OptGUI.AddText("x33 yp+45", g_LNG[163]) 1833 | OptGUI.AddComboBox("x183 yp-5 w330 vIndexExclude Choose1", [g_CONFIG["IndexExclude"], "Uninstall *"]) 1834 | 1835 | OptTab.UseTab(5) ; LISTARY Tab 1836 | OptGUI.AddGroupBox("w500 h145", g_LNG[211]) 1837 | OptGUI.AddText("x33 yp+30", g_LNG[212]) 1838 | OptGUI.AddComboBox("x183 yp-5 w330 vFileMgrID Choose1", [g_CONFIG["FileMgrID"], "ahk_class CabinetWClass", "ahk_class CabinetWClass, ahk_class TTOTAL_CMD"]) 1839 | OptGUI.AddText("x33 yp+45", g_LNG[213]) 1840 | OptGUI.AddComboBox("x183 yp-5 w330 vDialogWin Choose1", [g_CONFIG["DialogWin"], "ahk_class #32770"]) 1841 | OptGUI.AddText("x33 yp+45", g_LNG[214]) 1842 | OptGUI.AddComboBox("x183 yp-5 w330 vExcludeWin Choose1", [g_CONFIG["ExcludeWin"], "ahk_class SysListView32, ahk_exe Explorer.exe"]) 1843 | OptGUI.AddGroupBox("x24 yp+50 w500 h145", g_LNG[215]) 1844 | OptGUI.AddText("x33 yp+30", g_LNG[216]) 1845 | OptGUI.AddHotkey("x183 yp-5 w330 vTotalCMDDir", g_HOTKEY["TotalCMDDir"]) 1846 | OptGUI.AddText("x33 yp+45", g_LNG[217]) 1847 | OptGUI.AddHotkey("x183 yp-5 w330 vExplorerDir", g_HOTKEY["ExplorerDir"]) 1848 | OptGUI.AddCheckBox("x33 yp+45 vAutoSwitchDir Checked" g_CONFIG["AutoSwitchDir"], g_LNG[218]) 1849 | 1850 | OptTab.UseTab(6) ; PLUGINS Tab 1851 | OptGUI.AddGroupBox("w500 h110", g_LNG[251]) 1852 | OptGUI.AddText("x33 yp+30", g_LNG[252]) 1853 | OptGUI.AddComboBox("x183 yp-5 w330 vAutoDateAtEnd Choose1", [g_HOTKEY["AutoDateAtEnd"], "ahk_class TCmtEditForm,ahk_exe Notepad4.exe"]) 1854 | OptGUI.AddText("x33 yp+45", g_LNG[253]) 1855 | OptGUI.AddHotkey("x183 yp-5 w80 vAutoDateAEHKey", g_HOTKEY["AutoDateAEHKey"]) 1856 | OptGUI.AddText("x300 yp+5", g_LNG[254]) 1857 | OptGUI.AddDDL("x395 yp-5 w120 vAutoDateAEFormat Choose1", ["- dd.MM.yyyy"]) 1858 | 1859 | OptGUI.AddGroupBox("x24 y+30 w500 h110", g_LNG[255]) 1860 | OptGUI.AddText("x33 yp+30", g_LNG[252]) 1861 | OptGUI.AddComboBox("x183 yp-5 w330 vAutoDateBefExt Choose1", [g_HOTKEY["AutoDateBefExt"], "ahk_class CabinetWClass,ahk_class Progman,ahk_class WorkerW,ahk_class #32770"]) 1862 | OptGUI.AddText("x33 yp+45", g_LNG[253]) 1863 | OptGUI.AddHotkey("x183 yp-5 w80 vAutoDateBEHKey", g_HOTKEY["AutoDateBEHKey"]) 1864 | OptGUI.AddText("x300 yp+5", g_LNG[254]) 1865 | OptGUI.AddDDL("x395 yp-5 w120 vAutoDateBEFormat Choose1", ["- dd.MM.yyyy"]) 1866 | 1867 | OptGUI.AddGroupBox("x24 y+30 w500 h110", g_LNG[259]) 1868 | OptGUI.AddText("x33 yp+30", g_LNG[260]) 1869 | OptGUI.AddComboBox("x183 yp-5 w330 vCondTitle Choose1", [g_HOTKEY["CondTitle"]]) 1870 | OptGUI.AddText("x33 yp+45", g_LNG[261]) 1871 | OptGUI.AddComboBox("x183 yp-5 w80 vCondHotkey Choose1", [g_HOTKEY["CondHotkey"]]) 1872 | OptGUI.AddText("x300 yp+5", g_LNG[262]) 1873 | OptGUI.AddDDL("x395 yp-5 w120 vCondAction Choose" GetArrayIndex(g_HOTKEY["CondAction"], FuncList), FuncList) 1874 | 1875 | OptTab.UseTab(7) ; USAGE Tab 1876 | OptGUI.AddGroupBox("x66 y80 w445 h300", ) 1877 | 1878 | g_USAGE[A_YYYY . A_MM . A_DD] := g_USAGE.Has(A_YYYY . A_MM . A_DD) ? g_USAGE[A_YYYY . A_MM . A_DD] : 1 1879 | for date, count in g_USAGE { ; Draw usage graph 1880 | OptGUI.AddProgress("c94DD88 Vertical y96 w14 h280 xm+" 50+A_Index*14 " Range0-" g_RUNTIME["Max"]+10, count) 1881 | } 1882 | 1883 | OptGUI.AddText("x24 yp-5 cGray",g_RUNTIME["Max"]) 1884 | OptGUI.AddText("x24 yp+140 cGray", Round(g_RUNTIME["Max"]/2)) 1885 | OptGUI.AddText("x24 yp+140 cGray", 0) 1886 | OptGUI.AddText("x66 yp+15 cGray", g_LNG[500]) 1887 | OptGUI.AddText("x476 yp cGray", g_LNG[501]) 1888 | OptGUI.AddText("x66 yp+33", g_LNG[502]) 1889 | OptGUI.AddEdit("x400 yp-5 w100 r1 -E0x200 +ReadOnly Right vRunCount", g_CONFIG["RunCount"]) 1890 | OptGUI.AddText("x66 yp+35", g_LNG[503]) 1891 | OptGUI.AddEdit("x400 yp-5 w100 r1 -E0x200 +ReadOnly Right", g_USAGE[A_YYYY . A_MM . A_DD]) 1892 | 1893 | OptTab.UseTab(8) ; ABOUT Tab 1894 | OptGUI.AddPic("x33 y+20 w48 h-1 Icon-100", "imageres.dll") 1895 | OptGUI.AddText("x96 yp+5 w400", g_TITLE).SetFont("S11") 1896 | OptGUI.AddLink("xp yp+45 w400", g_LNG[601]) 1897 | 1898 | OptTab.UseTab() ; 后续添加的控件将不属于前面的选项卡控件 1899 | OptGUI.AddButton("Default x278 w80", g_LNG[7]).OnEvent("Click", OPTButtonOK) 1900 | OptGUI.AddButton("x368 yp w80", g_LNG[8]).OnEvent("Click", OPTGuiClose) 1901 | OptGUI.AddButton("x458 yp w80", g_LNG[9]).OnEvent("Click", (*) => Run("https://github.com/zhugecaomao/ALTRun/wiki")) 1902 | OptGUI.OnEvent("Close", OPTGuiClose) 1903 | OptGUI.OnEvent("Escape", OPTGuiClose) 1904 | 1905 | g_LOG.Debug("Options: Load options window...OK, elapsed time=" A_TickCount - t "ms") 1906 | OutputDebug("Options: Load options window...OK, elapsed time=" A_TickCount - t "ms") 1907 | OptGUI.Show("Center") 1908 | return 1909 | } 1910 | 1911 | ResetHotkey(*) { 1912 | OptGUI["GlobalHotkey1"].Value := "!Space" 1913 | OptGUI["GlobalHotkey2"].Value := "!r" 1914 | return 1915 | } 1916 | 1917 | SelectFont(TargetVar := "MainGUIFont") { 1918 | ; Set the fontObj (optional) - only set the ones you want to pre-select 1919 | ; fontObj := Map("name","Terminal","size",14,"color",0xFF0000,"strike",1,"underline",1,"italic",1,"bold",1) 1920 | initFont := StrSplit(g_GUI[TargetVar], ",")[1] 1921 | fontObj := Map("name", initFont) 1922 | fontObj := FontSelect(fontObj, OptGUI.hwnd) 1923 | If (!fontObj) 1924 | return 1925 | 1926 | OptGUI[TargetVar].Text := fontObj["name"] ", " fontObj["str"] ; 更新控件字体并设置显示文本 1927 | OptGUI[TargetVar].SetFont(fontObj["str"], fontObj["name"]) 1928 | g_LOG.Debug("SelectFont: OptGUI[" TargetVar "] font set to=" fontObj["str"] ", " fontObj["name"]) 1929 | } 1930 | 1931 | PickCMDListColor(*) { 1932 | color := ColorSelect(g_GUI["CMDListColor"], OptGUI.hwnd, , "full") ; hwnd and custColorObj are optional 1933 | If (color = -1) 1934 | return 1935 | 1936 | ;g_GUI["CMDListColor"] := color 1937 | OptGUI["CMDListColor"].Value := color ; 更新选项窗口控件并设置控件颜色 1938 | ;OptGUI["CMDListColor"].Opt("c" color) 1939 | } 1940 | 1941 | PickMainGUIColor(*) { 1942 | color := ColorSelect(g_GUI["MainGUIColor"], OptGUI.hwnd, , "full") 1943 | If (color = -1) 1944 | return 1945 | 1946 | ;g_GUI["MainGUIColor"] := color 1947 | OptGUI["MainGUIColor"].Value := color 1948 | ;OptGUI["MainGUIColor"].Opt("c" color) 1949 | } 1950 | 1951 | SelectBackground(*) { 1952 | OptGUI.Opt("+OwnDialogs") ; Make open dialog Modal 1953 | 1954 | file := FileSelect(3, , , 'Image Files (*.jpg; *.png; *.bmp; *.gif)') 1955 | If (file = "") 1956 | return 1957 | 1958 | OptGUI["Background"].Text := file 1959 | g_LOG.Debug("SelectBackground: Background image selected=" file) 1960 | } 1961 | 1962 | OPTButtonOK(*) { 1963 | SaveConfig() 1964 | Reload 1965 | } 1966 | 1967 | OPTGuiClose(*) { 1968 | g_LOG.Debug("OPTGuiClose: Closing Options window...") 1969 | 1970 | HotIfWinActive ; Turn on global hotkey 1971 | if (g_HOTKEY["GlobalHotkey1"] != "") { 1972 | Hotkey(g_HOTKEY["GlobalHotkey1"], ToggleWindow, "On") 1973 | g_LOG.Debug("OPTGuiClose: Turn On GlobalHotkey1...OK") 1974 | } 1975 | if (g_HOTKEY["GlobalHotkey2"] != "") { 1976 | Hotkey(g_HOTKEY["GlobalHotkey2"], ToggleWindow, "On") 1977 | g_LOG.Debug("OPTGuiClose: Turn On GlobalHotkey2...OK") 1978 | } 1979 | 1980 | OptGUI.Hide() 1981 | g_LOG.Debug("OPTGuiClose: OptGUI.Hide...OK") 1982 | return 1983 | } 1984 | 1985 | LoadConfig(Arg) { 1986 | g_LOG.Debug("LoadConfig: Loading configuration (" Arg ")...OK") 1987 | 1988 | if (Arg = "config" || Arg = "initialize" || Arg = "all") { 1989 | for key, value in g_CONFIG { ; Read [Config] to Map 1990 | g_CONFIG[key] := IniRead(g_INI, g_SECTION["CONFIG"], key, value) 1991 | } 1992 | 1993 | for key, value in g_HOTKEY { ; Read [Hotkey] section 1994 | g_HOTKEY[key] := IniRead(g_INI, g_SECTION["HOTKEY"], key, value) 1995 | } 1996 | 1997 | for key, value in g_GUI { ; Read [GUI] section 1998 | g_GUI[key] := IniRead(g_INI, g_SECTION["GUI"], key, value) 1999 | } 2000 | 2001 | g_RUNTIME["RegEx"] := g_CONFIG["MatchBeginning"] ? "imS)^" : "imS)" 2002 | 2003 | OffsetDate := DateAdd(A_Now, -30, "Days") 2004 | USAGESEC := "" 2005 | Try USAGESEC := IniRead(g_INI, g_SECTION["USAGE"]) 2006 | if (USAGESEC != "") { 2007 | for line in StrSplit(USAGESEC, "`n") { 2008 | if (!line) ; Skip empty lines 2009 | continue 2010 | split := StrSplit(line, "=") 2011 | Date := split[1] 2012 | Count := split[2] 2013 | 2014 | if (Date <= SubStr(OffsetDate, 1, 8)) { ; Clean up usage record before 30 days 2015 | IniDelete(g_INI, g_SECTION["USAGE"], Date) 2016 | continue 2017 | } 2018 | 2019 | g_USAGE[Date] := Count 2020 | g_RUNTIME["Max"] := Max(g_RUNTIME["Max"], Count) 2021 | } 2022 | } 2023 | 2024 | Loop 30 { 2025 | OffsetDate := DateAdd(OffsetDate, 1, "Days") 2026 | Date := SubStr(OffsetDate, 1, 8) 2027 | g_USAGE[Date] := g_USAGE.Has(Date) ? g_USAGE[Date] : 0 2028 | } 2029 | } 2030 | 2031 | if (Arg = "commands" || Arg = "initialize" || Arg = "all") { ; Built-in command initialize 2032 | DFTCMDSEC := "" 2033 | Try DFTCMDSEC := IniRead(g_INI, g_SECTION["DFTCMD"]) 2034 | if (DFTCMDSEC = "") { 2035 | IniWrite(" 2036 | ( 2037 | ; This section is Built-In commands with high priority 2038 | ; App will auto generate this section while it is empty 2039 | ; Please make sure App is not running before modifying. 2040 | ; 2041 | Func | About | Help & About (F1)=99 2042 | Func | Options | Setting Options (F2)=99 2043 | Func | Reload | Reload ALTRun=99 2044 | Func | EditCommand | Edit current command (F3)=99 2045 | Func | UserCommand | Change setting file directly (F4)=99 2046 | Func | NewCommand | New Command=99 2047 | Func | OpenContainer | Locate cmd's dir with File Manager=99 2048 | Func | Usage | ALTRun Usage Status=99 2049 | Func | Reindex | Reindex search database=99 2050 | Func | Everything | Search by Everything=99 2051 | Func | PTTools | PT Tools (AHK)=99 2052 | Func | AhkRun | Run Command use AutoHotkey Run=99 2053 | Func | Google | Search Clipboard or Input by Google=99 2054 | Func | Bing | Search Clipboard or Input by Bing=99 2055 | Func | EmptyRecycle | Empty Recycle Bin=99 2056 | Func | TurnMonitorOff | Turn off Monitor, Close Monitor=99 2057 | Func | MuteVolume | Mute Volume=99 2058 | File | %Temp%\ALTRun.log | ALTRun Log File=99 2059 | Dir | A_ScriptDir | ALTRun Program Dir=99 2060 | Dir | A_Startup | Current User Startup Dir=99 2061 | Dir | A_StartupCommon | All User Startup Dir=99 2062 | Dir | A_ProgramsCommon | Windows Search.Index.Cortana Dir=99 2063 | CMD | explorer.exe | Windows File Explorer=99 2064 | CMD | cmd.exe | Windows Command Processor=99 2065 | CMD | Shell:AppsFolder | AppsFolder Applications=66 2066 | CMD | ::{645FF040-5081-101B-9F08-00AA002F954E} | Recycle Bin=66 2067 | CMD | Notepad.exe | Notepad=66 2068 | CMD | WF.msc | Windows Defender Firewall with Advanced Security=66 2069 | CMD | TaskSchd.msc | Task Scheduler=66 2070 | CMD | DevMgmt.msc | Device Manager=66 2071 | CMD | EventVwr.msc | Event Viewer=66 2072 | CMD | CompMgmt.msc | Computer Manager=66 2073 | CMD | TaskMgr.exe | Task Manager=66 2074 | CMD | Calc.exe | Calculator=66 2075 | CMD | MsPaint.exe | Paint=66 2076 | CMD | Regedit.exe | Registry Editor=66 2077 | CMD | CleanMgr.exe | Disk Space Clean-up Manager=66 2078 | CMD | GpEdit.msc | Group Policy=66 2079 | CMD | DiskMgmt.msc | Disk Management=66 2080 | CMD | DxDiag.exe | Directx Diagnostic Tool=66 2081 | CMD | LusrMgr.msc | Local Users and Groups=66 2082 | CMD | MsConfig.exe | System Configuration=66 2083 | CMD | PerfMon.exe /Res | Resources Monitor=66 2084 | CMD | PerfMon.exe | Performance Monitor=66 2085 | CMD | WinVer.exe | About Windows=66 2086 | CMD | Services.msc | Services=66 2087 | CMD | NetPlWiz | User Accounts=66 2088 | CMD | Control | Control Panel=66 2089 | CMD | Control Intl.cpl | Region and Language Options=66 2090 | CMD | Control Firewall.cpl | Windows Defender Firewall=66 2091 | CMD | Control AppWiz.cpl | Programs and Features=66 2092 | CMD | Control Sysdm.cpl | System Properties=66 2093 | CMD | Control AdminTools | Windows Tools=66 2094 | CMD | Control Inetcpl.cpl,,4 | Internet Properties=66 2095 | CMD | Control UserPasswords | User Accounts=66 2096 | )", g_INI, g_SECTION["DFTCMD"]) 2097 | DFTCMDSEC := IniRead(g_INI, g_SECTION["DFTCMD"]) 2098 | } 2099 | 2100 | USERCMDSEC := "" 2101 | Try USERCMDSEC := IniRead(g_INI, g_SECTION["USERCMD"]) 2102 | if (USERCMDSEC = "") { 2103 | IniWrite(" 2104 | ( 2105 | ; This section is User-Defined commands, modify as desired 2106 | ; Format: Command Type | Command | Description=Rank 2107 | ; Command type: File, Dir, CMD, URL, some sample below 2108 | ; Please make sure App is not running before modifying 2109 | ; 2110 | File | C:\Windows\Notepad.exe=9 2111 | Dir | %AppData%\Microsoft\Windows\SendTo | Windows SendTo Dir=9 2112 | Dir | %OneDrive% | OneDrive=9 2113 | Dir | A_Desktop | Desktop=99 2114 | CMD | cmd.exe /k ipconfig | Check IP Address=9 2115 | CMD | explorer /Select,C:\Program Files | Open and select C:\Program Files=9 2116 | CMD | Control Printers | Devices and Printers=66 2117 | CMD | ::{20D04FE0-3AEA-1069-A2D8-08002B30309D} | This PC=9 2118 | URL | www.google.com | Google=9 2119 | )", g_INI, g_SECTION["USERCMD"]) 2120 | USERCMDSEC := IniRead(g_INI, g_SECTION["USERCMD"]) 2121 | } 2122 | 2123 | INDEXSEC := "" 2124 | Try INDEXSEC := IniRead(g_INI, g_SECTION["INDEX"]) 2125 | if (INDEXSEC = "") { 2126 | if (MsgBox(g_LNG[804], g_TITLE, 4161) = "Cancel") { 2127 | ExitApp() 2128 | } 2129 | Reindex() 2130 | } 2131 | 2132 | return DFTCMDSEC . "`n" . USERCMDSEC . "`n" . INDEXSEC 2133 | } 2134 | return 2135 | } 2136 | 2137 | SaveConfig() { 2138 | Global OptListView 2139 | 2140 | OptGUI.Submit() 2141 | for key, description in g_CONFIG_P1 { 2142 | g_CONFIG[key] := (A_Index = OptListView.GetNext(A_Index-1, "C")) ? 1 : 0 ; for Options - General page - Check Listview 2143 | IniWrite(g_CONFIG[key], g_INI, g_SECTION["CONFIG"], key) 2144 | } 2145 | 2146 | CONFIG_P2 := Array("FileMgr","Everything","HistoryLen","RunCount" 2147 | ,"AutoSwitchDir","IndexDir" ,"IndexType","IndexDepth" 2148 | ,"IndexExclude" ,"DialogWin","FileMgrID","ExcludeWin") 2149 | 2150 | for index, key in CONFIG_P2 { 2151 | if (OptGUI[key].Type = "CheckBox") { 2152 | g_CONFIG[key] := OptGUI[key].Value 2153 | } else { 2154 | g_CONFIG[key] := OptGUI[key].Text 2155 | } 2156 | IniWrite(g_CONFIG[key], g_INI, g_SECTION["CONFIG"], key) 2157 | } 2158 | 2159 | for key, value in g_GUI { 2160 | if (OptGUI[key].Type = "Slider") { 2161 | g_GUI[key] := OptGUI[key].Value 2162 | } else { 2163 | g_GUI[key] := OptGUI[key].Text 2164 | } 2165 | IniWrite(g_GUI[key], g_INI, g_SECTION["GUI"], key) 2166 | } 2167 | 2168 | for key, value in g_HOTKEY { 2169 | if (OptGUI[key].Type = "Hotkey") { 2170 | g_HOTKEY[key] := OptGUI[key].Value 2171 | } else { 2172 | g_HOTKEY[key] := OptGUI[key].Text 2173 | } 2174 | IniWrite(g_HOTKEY[key], g_INI, g_SECTION["HOTKEY"], key) 2175 | } 2176 | 2177 | g_LOG.Debug("SaveConfig: Save config...OK") 2178 | return 2179 | } 2180 | 2181 | ; ==================== Built-in Functions ========================= 2182 | AhkRun() { 2183 | try { 2184 | Run(g_RUNTIME["Arg"]) 2185 | } catch as e { 2186 | g_LOG.Debug("AhkRun: Error occur=" . e.Message) 2187 | } 2188 | return 2189 | } 2190 | 2191 | TurnMonitorOff() { ; 关闭显示器: 2192 | SendMessage(0x112, 0xF170, 2, , "Program Manager") ; 0x112 is WM_SYSCOMMAND, 0xF170 is SC_MONITORPOWER, 使用 -1 代替 2 来打开显示器, 使用 1 代替 2 来激活显示器的节能模式. 2193 | } 2194 | 2195 | EmptyRecycle() { 2196 | local Result := MsgBox("Do you really want to empty the Recycle Bin?", , "YesNo") 2197 | if (Result = "Yes") 2198 | { 2199 | FileRecycleEmpty 2200 | } 2201 | return 2202 | } 2203 | 2204 | MuteVolume() { 2205 | SoundSetMute(true) 2206 | } 2207 | 2208 | Google() { 2209 | word := g_RUNTIME["Arg"] = "" ? A_Clipboard : g_RUNTIME["Arg"] 2210 | Run("https://www.google.com/search?q=" word "&newwindow=1") 2211 | } 2212 | 2213 | Bing() { 2214 | word := g_RUNTIME["Arg"] = "" ? A_Clipboard : g_RUNTIME["Arg"] 2215 | Run("https://cn.bing.com/search?q=" word) 2216 | } 2217 | 2218 | Everything() { 2219 | try { 2220 | Run(g_CONFIG["Everything"] . ' -s `"' g_RUNTIME["Arg"] '`"') 2221 | } catch as e { 2222 | MsgBox("Everything software not found.`n`nPlease check ALTRun setting and Everything program file.`n`nError message=" . e.Message) 2223 | } 2224 | return 2225 | } 2226 | 2227 | ; ==================== Language Setting ========================= 2228 | SetLanguage() { 2229 | ENG := Map() 2230 | CHN := Map() 2231 | 2232 | ENG[1] := "English" ; 1~9 Reserved 2233 | ENG[2] := "Options" 2234 | ENG[7] := "OK" 2235 | ENG[8] := "Cancel" 2236 | ENG[9] := "Help" 2237 | ENG[10] := ["No.", "Type", "Command", "Description"] ; 10~49 Main GUI 2238 | ENG[11] := "Run" 2239 | ENG[12] := "Options" 2240 | ENG[13] := "Type anything here to search..." 2241 | ENG[50] := ["Tip | F1 | Help & About", "Tip | F2 | Options and settings", "Tip | F3 | Edit current command", "Tip | F4 | Change setting file directly", "Tip | Alt+Space / Alt+R | Activate ALTRun", "Tip | Alt+Space / Esc / Lose Focus | Deactivate ALTRun", "Tip | Enter / Alt+No. | Run selected command", "Tip | Arrow Up or Down | Previous / next command", "Tip | Ctrl+D | Locate cmd's dir with File Manager"] 2242 | ENG[51] := "Tip: " 2243 | ENG[52] := "It's better to activate ALTRun by hotkey (ALT + Space)" ; 50~99 Tips 2244 | ENG[53] := "Smart Rank - Auto adjusts command priority (rank) based on frequency of use." 2245 | ENG[54] := "Arrow Up / Down = Move to previous / next command" 2246 | ENG[55] := "Esc = Clear input / close window" 2247 | ENG[56] := "Enter = Run current command" 2248 | ENG[57] := "Alt + No. = Run specific command" 2249 | ENG[58] := "Start with + = New Command" 2250 | ENG[59] := "F3 = Edit current command" 2251 | ENG[60] := "F2 = Options setting" 2252 | ENG[61] := "Ctrl+I = Reindex file search database" 2253 | ENG[62] := "F1 = ALTRun Help & About" 2254 | ENG[63] := "ALT + Space = Show / Hide Window" 2255 | ENG[64] := "Ctrl+Q = Reload ALTRun" 2256 | ENG[65] := "Ctrl + No. = Select specific command" 2257 | ENG[66] := "Alt + F4 = Exit" 2258 | ENG[67] := "Ctrl+D = Open current command's dir with File Manager" 2259 | ENG[68] := "F4 = Change setting file directly (.ini)" 2260 | ENG[69] := "Start with space = Search file by Everything" 2261 | ENG[70] := "Ctrl+'+' = Increase rank of current command" 2262 | ENG[71] := "Ctrl+'-' = Decrease rank of current command" 2263 | ENG[100] := ["General", "GUI", "Hotkey", "Index", "Listary", "Plugins", "Usage", "About"] ; 100~149 Options window (General - Check Listview) 2264 | ENG[101] := "Launch on Windows startup" 2265 | ENG[102] := "Enable SendTo - Create commands conveniently using Windows SendTo" 2266 | ENG[103] := "Enable ALTRun shortcut in the Windows Start menu" 2267 | ENG[104] := "Show tray icon in the system taskbar" 2268 | ENG[105] := "Close window on losing focus" 2269 | ENG[106] := "Always stay on top" 2270 | ENG[107] := "Show Main Window's Caption" 2271 | ENG[108] := "Use Windows Theme instead of Classic Theme" 2272 | ENG[109] := "Press [ESC] to clear input, press again to close window (Untick: Close directly)" 2273 | ENG[110] := "Keep last input and matching result on close" 2274 | ENG[111] := "Show command icon in the result list" 2275 | ENG[112] := "SendToGetLnk - Retrieve .lnk target on SendTo" 2276 | ENG[113] := "Save commands execution history" 2277 | ENG[114] := "Save application log" 2278 | ENG[115] := "Match full path on search" 2279 | ENG[116] := "Show Command List Grid Lines" 2280 | ENG[117] := "Show Command List Header" 2281 | ENG[118] := "Show Command List Serial Number" 2282 | ENG[119] := "Show Command List Border Line" 2283 | ENG[120] := "Smart Sorting (Auto-adjust command priority based on usage habits)" 2284 | ENG[121] := "Smart Matching" 2285 | ENG[122] := "Match beginning of the string (Untick: Match from any position)" 2286 | ENG[123] := "Show Status Bar Hints/Tips" 2287 | ENG[124] := "Show Command Executed RunCount in the Status Bar" 2288 | ENG[125] := "Show Status Bar" 2289 | ENG[126] := "Show [Run] Button on Main Window" 2290 | ENG[127] := "Show [Options] Button on Main Window" 2291 | ENG[128] := "Double-Buffering to reduce flicker (WinXP+)" 2292 | ENG[129] := "Enable express structure calculation" 2293 | ENG[130] := "Show Shorten Path (Show file/folder/app name only instead of full path)" 2294 | ENG[131] := "Set language to Chinese Simplified (简体中文)" 2295 | ENG[132] := "Match Chinese Pinyin first characters" 2296 | ENG[133] := "Use the mouse wheel scroll to select the command" 2297 | ENG[134] := "Click mouse middle button to run the selected command" 2298 | ENG[135] := "Auto check for updates" 2299 | ENG[136] := "Show large icons" 2300 | 2301 | ENG[150] := "File Manager" ; 150~159 Options window (Other than Check Listview) 2302 | ENG[151] := "Everything" 2303 | ENG[152] := "History length" 2304 | ENG[160] := "Index" ; 160~169 Index 2305 | ENG[161] := "Index location" 2306 | ENG[162] := "Index file type" 2307 | ENG[163] := "Index exclude" 2308 | ENG[164] := "Index depth" 2309 | ENG[170] := "GUI" ; 170~189 GUI 2310 | ENG[171] := "Search result number" 2311 | ENG[172] := "Width of each column" 2312 | ENG[173] := "Font (Main GUI)" 2313 | ENG[174] := "Font (Options)" 2314 | ENG[175] := "Font (Status Bar)" 2315 | ENG[176] := "Window size (W x H)" 2316 | ENG[177] := "Cmd list size (W x H)" 2317 | ENG[178] := "Color (Command List)" 2318 | ENG[179] := "Color (Main GUI)" 2319 | ENG[180] := "Background picture" 2320 | ENG[181] := "Transparency" 2321 | ENG[182] := "Select font" 2322 | ENG[183] := "Select color" 2323 | ENG[184] := "Select image" 2324 | ENG[190] := "Hotkey" ; 190~209 Hotkey 2325 | ENG[191] := "Activate Hotkey (Global)" 2326 | ENG[192] := "Primary Hotkey" 2327 | ENG[193] := "Secondary Hotkey" 2328 | ENG[194] := "Two hotkeys can be set simultaneously" 2329 | ENG[195] := "Reset hotkey" 2330 | ENG[200] := "Actions and Hotkeys (Non-Global)" 2331 | ENG[201] := "Hotkey" 2332 | ENG[202] := "Trigger action" 2333 | ENG[203] := "Hotkey" 2334 | ENG[204] := "Hotkey 2" 2335 | ENG[206] := "Hotkey 3" 2336 | ENG[210] := "Listary" ; 210~249 Listary 2337 | ENG[211] := "Dir Quick-Switch" 2338 | ENG[212] := "File Manager ID" 2339 | ENG[213] := "Open/Save Dialog ID" 2340 | ENG[214] := "Exclude Windows ID" 2341 | ENG[215] := "Hotkey" 2342 | ENG[216] := "QuickSwitch to TC's dir" 2343 | ENG[217] := "QuickSwitch to Explorer" 2344 | ENG[218] := "Auto switch dir on open/save dialog" 2345 | ENG[219] := "No Total Commander window found, please open Total Commander first!" 2346 | ENG[220] := "No Explorer window found, please open Explorer first!" 2347 | 2348 | ENG[250] := "Plugins" ; 250~299 Plugins 2349 | ENG[251] := "Auto-date at end of text" 2350 | ENG[252] := "Apply to window id" 2351 | ENG[253] := "Hotkey" 2352 | ENG[254] := "Date format" 2353 | ENG[255] := "Auto-date before file extension" 2354 | ENG[259] := "Conditional action" 2355 | ENG[260] := "If window id/class contains" 2356 | ENG[261] := "Hotkey (Editable)" 2357 | ENG[262] := "Trigger action" 2358 | ENG[300] := "Show" ; 300+ TrayMenu 2359 | ENG[301] := "Options`tF2" 2360 | ENG[302] := "ReIndex`tCtrl+I" 2361 | ENG[303] := "Usage" 2362 | ENG[304] := "About`tF1" 2363 | ENG[305] := "Script Info" 2364 | ENG[307] := "Reload`tCtrl+Q" 2365 | ENG[308] := "Exit`tAlt+F4" 2366 | ENG[309] := "Update" 2367 | ENG[310] := "Settings File`tF4" 2368 | 2369 | ENG[400] := "Run`tEnter" ; 400+ LV_ContextMenu (Right-click) 2370 | ENG[401] := "Locate`tCtrl+D" 2371 | ENG[402] := "Copy`tCtrl+C" 2372 | ENG[403] := "New`tCtrl+N" 2373 | ENG[404] := "Edit`tF3" 2374 | ENG[405] := "Delete`tCtrl+Del" 2375 | ENG[406] := "" 2376 | ENG[407] := "Copy statusbar text" 2377 | ENG[408] := "Copied : " 2378 | ENG[410] := "Show usage status" 2379 | ENG[500] := "30 days ago" ; 500+ Usage Status 2380 | ENG[501] := "Now" 2381 | ENG[502] := "Total number of times the command was executed" 2382 | ENG[503] := "Number of times the program was activated today" 2383 | ENG[600] := "About" ; 600+ About 2384 | ENG[601] := "An open-source, lightweight, efficient and powerful launcher" 2385 | . "`nIt provides a streamlined and efficient way to find anything on your system and launch any application in your way" 2386 | . "`n`nSetting file:`n" g_INI "`n`nProgram file:`n" A_ScriptFullPath 2387 | . "`n`nCheck for Updates" 2388 | . "`nhttps://github.com/zhugecaomao/ALTRun/releases" 2389 | . "`n`nSource code at GitHub" 2390 | . "`nhttps://github.com/zhugecaomao/ALTRun" 2391 | . "`n`nSee Help and Wiki page for more details" 2392 | . "`nhttps://github.com/zhugecaomao/ALTRun/wiki" 2393 | ENG[700] := "Commander Manager" ; 700+ Command Manager 2394 | ENG[701] := "Command" 2395 | ENG[702] := "Command type" 2396 | ENG[703] := "Command line" 2397 | ENG[704] := "ShortCut/Description" 2398 | ENG[705] := "Command Section" 2399 | ENG[706] := "Command Rank" 2400 | ENG[800] := "Do you really want to delete the following command?`n`n[" ; 800+ Message Info 2401 | ENG[801] := "Confirm Want to Delete?" 2402 | ENG[802] := "Command has been deleted successfully!" 2403 | ENG[803] := "Error occur when delete the command!" 2404 | ENG[804] := "Index database is empty, please click`n`n'OK' to rebuild the index`n`n'Cancel' to exit the program`n`n(Please ensure the program directory is writable)" 2405 | ENG[805] := "A new version (" 2406 | ENG[806] := ") is available!`n`nClick OK to open the download page..." 2407 | ENG[807] := "You are already using the latest version (" 2408 | ENG[808] := ") !" 2409 | ENG[809] := "Failed to check for updates! Please check your network connection.`n`nError message: " 2410 | ENG[820] := "Command Manager" 2411 | ENG[821] := "Command Path is empty, please input correct command path!" 2412 | ENG[822] := "Error occur when add command, error message: " 2413 | ENG[823] := "The following command added / modified successfully!`n`n[ " 2414 | 2415 | CHN[1] := "简体中文" ; 1~9 Reserved 2416 | CHN[2] := "配置" 2417 | CHN[7] := "确定" 2418 | CHN[8] := "取消" 2419 | CHN[9] := "帮助" 2420 | CHN[10] := ["序号", "类型", "命令", "描述"] ; 10~49 Main GUI 2421 | CHN[11] := "运行" 2422 | CHN[12] := "配置" 2423 | CHN[13] := "在此输入搜索内容..." 2424 | CHN[50] := ["提示 | F1 | 帮助关于", "提示 | F2 | 配置选项", "提示 | F3 | 编辑当前命令", "提示 | F4 | 直接修改设置文件", "提示 | Alt+空格 / Alt+R | 激活 ALTRun", "提示 | 失去焦点 / Esc / 快捷键 | 关闭 ALTRun", "提示 | 回车 / Alt+序号 | 运行命令", "提示 | 上下箭头键 | 选择上一个或下一个命令", "提示 | Ctrl+D | 使用文件管理器定位命令所在目录"] 2425 | CHN[51] := "提示: " ; 50~99 Tips 2426 | CHN[52] := "推荐使用热键激活 (ALT + 空格)" 2427 | CHN[53] := "智能排序 - 根据使用频率自动调整命令优先级 (排序)" 2428 | CHN[54] := "上/下箭头 = 上/下一个命令" 2429 | CHN[55] := "Esc = 清除输入 / 关闭窗口" 2430 | CHN[56] := "回车 = 运行当前命令" 2431 | CHN[57] := "Alt + 序号 = 运行指定的命令" 2432 | CHN[58] := "以 + 开头 = 新建命令" 2433 | CHN[59] := "F3 = 编辑当前命令" 2434 | CHN[60] := "F2 = 配置选项设置" 2435 | CHN[61] := "Ctrl+I = 重建文件搜索数据库" 2436 | CHN[62] := "F1 = ALTRun 帮助&关于" 2437 | CHN[63] := "ALT + 空格 = 显示 / 隐藏窗口" 2438 | CHN[64] := "Ctrl+Q = 重新加载 ALTRun" 2439 | CHN[65] := "Ctrl + 序号 = 选择指定的命令" 2440 | CHN[66] := "Alt + F4 = 退出" 2441 | CHN[67] := "Ctrl+D = 使用文件管理器定位当前命令所在目录" 2442 | CHN[68] := "F4 = 直接修改设置文件 (.ini)" 2443 | CHN[69] := "以空格开头 = 使用 Everything 搜索文件" 2444 | CHN[70] := "Ctrl+'+' = 增加当前命令的优先级" 2445 | CHN[71] := "Ctrl+'-' = 减少当前命令的优先级" 2446 | CHN[100] := ["常规", "界面", "热键", "索引", "Listary", "插件", "状态统计", "关于"] ; 100~149 Options window (Listview) 2447 | CHN[101] := "随系统自动启动" 2448 | CHN[102] := "添加到“发送到”菜单" 2449 | CHN[103] := "添加到“开始”菜单" 2450 | CHN[104] := "显示托盘图标 (系统任务栏中)" 2451 | CHN[105] := "失去焦点时关闭窗口" 2452 | CHN[106] := "窗口置顶" 2453 | CHN[107] := "显示主窗口标题栏" 2454 | CHN[108] := "使用当前系统主题 (取消勾选: 使用经典主题)" 2455 | CHN[109] := "按下 [ESC] 清除输入, 再次按下关闭窗口 (取消勾选: 直接关闭窗口)" 2456 | CHN[110] := "保留最近一次输入和匹配结果" 2457 | CHN[111] := "显示命令图标" 2458 | CHN[112] := "使用“发送到”时, 追溯 .lnk 目标文件" 2459 | CHN[113] := "保存历史记录" 2460 | CHN[114] := "保存运行日志" 2461 | CHN[115] := "搜索时匹配完整路径" 2462 | CHN[116] := "显示命令列表网格线" 2463 | CHN[117] := "显示命令列表标题栏" 2464 | CHN[118] := "显示命令列表序号" 2465 | CHN[119] := "显示命令列表边框线" 2466 | CHN[120] := "智能排序 (根据使用习惯自动调整命令优先级)" 2467 | CHN[121] := "智能匹配" 2468 | CHN[122] := "搜索时匹配字符串开头 (取消勾选: 匹配任意位置)" 2469 | CHN[123] := "显示状态栏提示信息" 2470 | CHN[124] := "显示命令执行次数 (状态栏)" 2471 | CHN[125] := "显示状态栏" 2472 | CHN[126] := "显示主窗口 [运行] 按钮" 2473 | CHN[127] := "显示主窗口 [选项] 按钮" 2474 | CHN[128] := "双缓冲绘图, 改善窗口闪烁" 2475 | CHN[129] := "启用快速结构计算" 2476 | CHN[130] := "显示简化路径 (仅显示文件/文件夹/应用程序名称, 而非完整路径)" 2477 | CHN[131] := "设置语言为简体中文 (Simplified Chinese)" 2478 | CHN[132] := "搜索时匹配拼音首字母" 2479 | CHN[133] := "使用鼠标滚轮滚动选择命令" 2480 | CHN[134] := "单击鼠标中键运行选定命令" 2481 | CHN[135] := "自动检查更新" 2482 | CHN[136] := "显示大图标" 2483 | 2484 | CHN[150] := "文件管理器" ; 150~159 Options window (Other than Check Listview) 2485 | CHN[151] := "Everything" 2486 | CHN[152] := "历史命令数量" 2487 | CHN[160] := "索引" ; 160~169 Index 2488 | CHN[161] := "索引位置" 2489 | CHN[162] := "索引文件类型" 2490 | CHN[163] := "索引排除项" 2491 | CHN[164] := "索引目录深度" 2492 | CHN[170] := "界面" ; 170~189 GUI 2493 | CHN[171] := "搜索结果数量" 2494 | CHN[172] := "每列宽度" 2495 | CHN[173] := "字体 (主界面)" 2496 | CHN[174] := "字体 (选项页)" 2497 | CHN[175] := "字体 (状态栏)" 2498 | CHN[176] := "主窗口尺寸 (宽 x 高)" 2499 | CHN[177] := "命令列表尺寸 (宽 x 高)" 2500 | CHN[178] := "颜色 (命令列表)" 2501 | CHN[179] := "颜色 (主界面)" 2502 | CHN[180] := "背景图片" 2503 | CHN[181] := "透明度" 2504 | CHN[182] := "选择字体" 2505 | CHN[183] := "选择颜色" 2506 | CHN[184] := "选择图片" 2507 | CHN[190] := "热键" ; 190~209 Hotkey 2508 | CHN[191] := "激活热键 (全局)" 2509 | CHN[192] := "主热键" 2510 | CHN[193] := "辅热键" 2511 | CHN[194] := "可以同时设置两个热键" 2512 | CHN[195] := "重置激活热键" 2513 | CHN[200] := "快捷操作和热键 (非全局)" 2514 | CHN[201] := "快捷键" 2515 | CHN[202] := "触发操作" 2516 | CHN[203] := "热键 1" 2517 | CHN[204] := "热键 2" 2518 | CHN[206] := "热键 3" 2519 | CHN[210] := "Listary" ; 210~249 Listary 2520 | CHN[211] := "目录快速切换" 2521 | CHN[212] := "文件管理器 ID" 2522 | CHN[213] := "打开/保存对话框 ID" 2523 | CHN[214] := "排除窗口 ID" 2524 | CHN[215] := "热键" 2525 | CHN[216] := "快速切换到 TC 目录" 2526 | CHN[217] := "快速切换到 资源管理器" 2527 | CHN[218] := "自动切换路径" 2528 | CHN[219] := "没有找到Total Commander窗口,请先打开Total Commander!" 2529 | CHN[220] := "没有找到资源管理器窗口,请先打开资源管理器!" 2530 | 2531 | CHN[250] := "插件" ; 250~299 Plugins 2532 | CHN[251] := "文本末尾自动添加日期" 2533 | CHN[252] := "应用到窗口 ID" 2534 | CHN[253] := "热键" 2535 | CHN[254] := "日期格式" 2536 | CHN[255] := "扩展名前自动添加日期" 2537 | CHN[259] := "条件触发快捷操作" 2538 | CHN[260] := "如果窗口特征包含" 2539 | CHN[261] := "热键 (自由定制)" 2540 | CHN[262] := "触发操作" 2541 | CHN[300] := "显示" ; 300+ 托盘菜单 2542 | CHN[301] := "配置选项`tF2" 2543 | CHN[302] := "重建索引`tCtrl+I" 2544 | CHN[303] := "状态统计" 2545 | CHN[304] := "关于`tF1" 2546 | CHN[305] := "脚本信息" 2547 | CHN[307] := "重新加载`tCtrl+Q" 2548 | CHN[308] := "退出`tAlt+F4" 2549 | CHN[309] := "检查更新" 2550 | CHN[310] := "配置文件`tF4" 2551 | 2552 | CHN[400] := "运行命令`tEnter" ; 400+ 列表右键菜单 2553 | CHN[401] := "定位命令`tCtrl+D" 2554 | CHN[402] := "复制命令`tCtrl+C" 2555 | CHN[403] := "新建命令`tCtrl+N" 2556 | CHN[404] := "编辑命令`tF3" 2557 | CHN[405] := "删除命令`tCtrl+Del" 2558 | CHN[406] := "" 2559 | CHN[407] := "复制状态栏信息" 2560 | CHN[408] := "已复制 : " 2561 | CHN[410] := "显示状态统计" 2562 | CHN[500] := "30天前" 2563 | CHN[501] := "当前" ; 500+ 状态统计 2564 | CHN[502] := "运行过的命令总次数" 2565 | CHN[503] := "今天激活程序的次数" 2566 | CHN[600] := "关于" ; 600+ 关于 2567 | CHN[601] := "一款开源、轻量、高效、功能强大的启动工具" 2568 | . "`n能够快速查找系统中的内容或者启动应用程序" 2569 | . "`n`n配置文件`n" g_INI "`n`n程序文件`n" A_ScriptFullPath 2570 | . "`n`n版本更新" 2571 | . "`nhttps://github.com/zhugecaomao/ALTRun/releases" 2572 | . "`n`n源代码开源在 GitHub" 2573 | . "`nhttps://github.com/zhugecaomao/ALTRun" 2574 | . "`n`n有关更多详细信息,请参阅帮助和 Wiki 页面" 2575 | . "`nhttps://github.com/zhugecaomao/ALTRun/wiki" 2576 | CHN[700] := "命令管理器" ; 700+ 命令管理器 2577 | CHN[701] := "命令" 2578 | CHN[702] := "命令类型" 2579 | CHN[703] := "命令行" 2580 | CHN[704] := "快捷项/描述 (可搜索)" 2581 | CHN[705] := "储存节段" 2582 | CHN[706] := "命令权重" 2583 | CHN[800] := "您确定要删除以下命令吗?`n`n[" ; 800+ 提示消息 2584 | CHN[801] := "确认删除?" 2585 | CHN[802] := "命令已成功删除!" 2586 | CHN[803] := "删除命令时发生错误!" 2587 | CHN[804] := "检测到当前的索引数据库为空, 请点击:`n`n'确定' 重新建立索引`n`n'取消' 退出程序`n`n(请确保程序目录有写入权限)" 2588 | CHN[805] := "有新版本可用 (" 2589 | CHN[806] := ") !`n`n点击确定打开下载页面..." 2590 | CHN[807] := "您已经在使用最新版本 (" 2591 | CHN[808] := ") 了!" 2592 | CHN[809] := "检查更新失败! 请检查您的网络连接.`n`n错误信息: " 2593 | CHN[820] := "命令管理器" 2594 | CHN[821] := "命令路径为空, 请输入正确的命令路径!" 2595 | CHN[822] := "添加命令时发生错误, 错误信息: " 2596 | CHN[823] := "以下命令添加/修改成功!`n`n[ " 2597 | 2598 | Global g_LNG := IniRead(g_INI, "Config", "Chinese", 0) ? CHN : ENG 2599 | g_LOG.Debug("SetLanguage: Set language to " g_LNG[1] "...OK") 2600 | return 2601 | } 2602 | 2603 | ;;==================== Expression Eval ========================= 2604 | Eval(expression) { 2605 | ; 移除所有空格 2606 | expression := StrReplace(expression, " ") 2607 | 2608 | ; 检查非法字符(只允许数字、运算符、括号、小数点) 2609 | if (!RegExMatch(expression, "^[\d+\-*/^().]*$")) 2610 | return 0 2611 | 2612 | ; 递归处理括号 2613 | while RegExMatch(expression, "\(([^()]*)\)", &match) { 2614 | result := EvalSimple(match[1]) ; 计算括号内的内容 2615 | expression := StrReplace(expression, (match&&match[0]), result) 2616 | } 2617 | 2618 | ; 计算最终无括号表达式 2619 | Return EvalSimple(expression) 2620 | } 2621 | 2622 | EvalSimple(expression) { ; 计算不含括号的简单数学表达式 2623 | ; 处理幂运算符 ^ 2624 | while RegExMatch(expression, "(-?\d+(\.\d+)?)([\^])(-?\d+(\.\d+)?)", &match) { 2625 | base := match[1], exponent := match[4] 2626 | result := base ** exponent ; 执行幂运算 2627 | expression := StrReplace(expression, (match&&match[0]), result) 2628 | } 2629 | 2630 | ; 支持 ** 作为幂运算符替代 2631 | while RegExMatch(expression, "(-?\d+(\.\d+)?)(\*\*)(-?\d+(\.\d+)?)", &match) { 2632 | base := match[1], exponent := match[4] 2633 | result := base ** exponent 2634 | expression := StrReplace(expression, (match&&match[0]), result) 2635 | } 2636 | 2637 | ; 处理乘除法运算(已加入除以零保护) 2638 | while RegExMatch(expression, "(-?\d+(\.\d+)?)([*/])(-?\d+(\.\d+)?)", &match) { 2639 | operand1 := match[1], operator := match[3], operand2 := match[4] 2640 | if (operator = "*") 2641 | result := operand1 * operand2 2642 | else { 2643 | ; 防止除以零,operand2 可能为 "0" 或 "0.0" 等 2644 | if (Abs(operand2) < 1e-12) { 2645 | ; 这里选择将除以零的子表达式替换为 0,避免抛出异常 2646 | result := 0 2647 | } else { 2648 | result := operand1 / operand2 2649 | } 2650 | } 2651 | expression := StrReplace(expression, (match&&match[0]), result) 2652 | } 2653 | 2654 | ; 处理加减法运算 2655 | while RegExMatch(expression, "(-?\d+(\.\d+)?)([+\-])(-?\d+(\.\d+)?)", &match) { 2656 | operand1 := match[1], operator := match[3], operand2 := match[4] 2657 | result := (operator = "+") ? operand1 + operand2 : operand1 - operand2 2658 | expression := StrReplace(expression, (match&&match[0]), result) 2659 | } 2660 | 2661 | ; 返回最终结果 2662 | Return expression 2663 | } 2664 | 2665 | ;;==================== Performance Test Only ========================= 2666 | 2667 | Test() { 2668 | t := A_TickCount 2669 | Loop 50 { 2670 | chr1 := Random(Ord("a"),Ord("z")) 2671 | chr2 := Random(Ord("A"),Ord("Z")) ;65,90 2672 | chr3 := Random(Ord("a"),Ord("z")) ;97,122 2673 | 2674 | Activate() 2675 | myInputBox.Value := chr(chr1) 2676 | Input_Change() 2677 | Sleep 10 2678 | myInputBox.Value := chr(chr1) " " chr(chr2) 2679 | Input_Change() 2680 | Sleep 10 2681 | myInputBox.Value := chr(chr1) " " chr(chr2) " " chr(chr3) 2682 | Input_Change() 2683 | } 2684 | t := A_TickCount - t 2685 | g_LOG.Debug("mock test search ' " chr(chr1) " " chr(chr2) " " chr(chr3) " ' 50 times, elapsed time=" t) 2686 | MsgBox "Search '" chr(chr1) " " chr(chr2) " " chr(chr3) "' elapsed time=" t 2687 | } 2688 | 2689 | ;;==================== Logger Class ========================= 2690 | 2691 | class Logger { 2692 | __New(filename) { 2693 | this.filename := filename 2694 | } 2695 | 2696 | Debug(Msg) { 2697 | if (g_CONFIG["SaveLog"]) 2698 | FileAppend("[" . A_Now . "] " . Msg . "`n", this.filename) 2699 | } 2700 | } 2701 | 2702 | ;;==================== Font Select Dialog ========================= 2703 | ; FontSelect() - Display the standard Windows font selection dialog 2704 | 2705 | ; AHK v2 2706 | ; originally posted by maestrith 2707 | ; https://autohotkey.com/board/topic/94083-ahk-11-font-and-color-dialogs/ 2708 | 2709 | ; ====================================================================== 2710 | ; Example 2711 | ; ====================================================================== 2712 | 2713 | ; Global fontObj 2714 | 2715 | ; oGui := Gui.New("","Change Font Example") 2716 | ; oGui.OnEvent("close","gui_exit") 2717 | ; ctl := oGui.AddEdit("w500 h200 vMyEdit1","Sample Text") 2718 | ; ctl.SetFont("bold underline italic strike c0xFF0000") 2719 | ; oGui.AddEdit("w500 h200 vMyEdit2","Sample Text") 2720 | ; oGui.AddButton("Default","Change Font").OnEvent("click","button_click") 2721 | ; oGui.Show() 2722 | 2723 | ; button_click(ctl,info) { 2724 | ; If (!isSet(fontObj)) 2725 | ; fontObj := "" 2726 | ; fontObj := Map("name","Terminal","size",14,"color",0xFF0000,"strike",1,"underline",1,"italic",1,"bold",1) ; init font obj (optional) 2727 | 2728 | ; fontObj := FontSelect(fontObj,ctl.gui.hwnd) ; shows the user the font selection dialog 2729 | 2730 | ; If (!fontObj) 2731 | ; return ; to get info from fontObj use ... bold := fontObj["bold"], fontObj["name"], etc. 2732 | 2733 | ; ctl.gui["MyEdit1"].SetFont(fontObj["str"],fontObj["name"]) ; apply font+style in one line, or... 2734 | ; ctl.gui["MyEdit2"].SetFont(fontObj["str"],fontObj["name"]) 2735 | ; } 2736 | 2737 | ; gui_exit(oGui) { 2738 | ; ExitApp 2739 | ; } 2740 | 2741 | ; ====================================================================== 2742 | ; END Example 2743 | ; ====================================================================== 2744 | 2745 | ; to initialize fontObj (not required): 2746 | ; ============================================ 2747 | ; fontObj := Map("name","Tahoma","size",14,"color",0xFF0000,"strike",1,"underline",1,"italic",1,"bold",1) 2748 | 2749 | ; ================================================================== 2750 | ; fntName = name of var to store selected font 2751 | ; fontObj = name of var to store fontObj object 2752 | ; hwnd = parent gui hwnd for modal, leave blank for not modal 2753 | ; effects = allow selection of underline / strike out / italic 2754 | ; ================================================================== 2755 | ; fontObj output: 2756 | ; 2757 | ; fontObj["str"] = string to use with AutoHotkey to set GUI values - see examples 2758 | ; fontObj["hwnd"] = handle of the font object to use with SendMessage - see examples 2759 | ; ================================================================== 2760 | FontSelect(fontObject:="",hwnd:=0,Effects:=1) { 2761 | fontObject := (fontObject="") ? Map() : fontObject 2762 | logfont := Buffer((A_PtrSize = 4) ? 60 : 92, 0) 2763 | uintVal := DllCall("GetDC","uint",0) 2764 | LogPixels := DllCall("GetDeviceCaps","uint",uintVal,"uint",90) 2765 | Effects := 0x041 + (Effects ? 0x100 : 0) 2766 | 2767 | fntName := fontObject.Has("name") ? fontObject["name"] : "" 2768 | fontBold := fontObject.Has("bold") ? fontObject["bold"] : 0 2769 | fontBold := fontBold ? 700 : 400 2770 | fontItalic := fontObject.Has("italic") ? fontObject["italic"] : 0 2771 | fontUnderline := fontObject.Has("underline") ? fontObject["underline"] : 0 2772 | fontStrikeout := fontObject.Has("strike") ? fontObject["strike"] : 0 2773 | fontSize := fontObject.Has("size") ? fontObject["size"] : 10 2774 | fontSize := fontSize ? Floor(fontSize*LogPixels/72) : 16 2775 | c := fontObject.Has("color") ? fontObject["color"] : 0 2776 | 2777 | c1 := Format("0x{:02X}",(c&255)<<16) ; convert RGB colors to BGR for input 2778 | c2 := Format("0x{:02X}",c&65280) 2779 | c3 := Format("0x{:02X}",c>>16) 2780 | fontColor := Format("0x{:06X}",c1|c2|c3) 2781 | 2782 | NumPut "uint", fontSize, logfont 2783 | NumPut "uint", fontBold, "char", fontItalic, "char", fontUnderline, "char", fontStrikeout, logfont, 16 2784 | 2785 | choosefont := Buffer(A_PtrSize=8?104:60,0), cap := choosefont.size 2786 | NumPut "UPtr", hwnd, choosefont, A_PtrSize 2787 | offset1 := (A_PtrSize = 8) ? 24 : 12 2788 | offset2 := (A_PtrSize = 8) ? 36 : 20 2789 | offset3 := (A_PtrSize = 4) ? 6 * A_PtrSize : 5 * A_PtrSize 2790 | 2791 | fontArray := Array([cap,0,"Uint"],[logfont.ptr,offset1,"UPtr"],[effects,offset2,"Uint"],[fontColor,offset3,"Uint"]) 2792 | 2793 | for index,value in fontArray 2794 | NumPut value[3], value[1], choosefont, value[2] 2795 | 2796 | if (A_PtrSize=8) { 2797 | strput(fntName,logfont.ptr+28,"UTF-16") 2798 | r := DllCall("comdlg32\ChooseFont","UPtr",CHOOSEFONT.ptr) ; cdecl 2799 | fntName := strget(logfont.ptr+28,"UTF-16") 2800 | } else { 2801 | strput(fntName,logfont.ptr+28,32,"UTF-8") 2802 | r := DllCall("comdlg32\ChooseFontA","UPtr",CHOOSEFONT.ptr) ; cdecl 2803 | fntName := strget(logfont.ptr+28,32,"UTF-8") 2804 | } 2805 | 2806 | if !r 2807 | return false 2808 | 2809 | fontObj := Map("bold",16,"italic",20,"underline",21,"strike",22) 2810 | for a,b in fontObj 2811 | fontObject[a] := NumGet(logfont,b,"UChar") 2812 | 2813 | fontObject["bold"] := (fontObject["bold"] < 188) ? 0 : 1 2814 | 2815 | c := NumGet(choosefont,(A_PtrSize=4)?6*A_PtrSize:5*A_PtrSize,"UInt") ; convert from BGR to RBG for output 2816 | c1 := Format("0x{:02X}",(c&255)<<16), c2 := Format("0x{:02X}",c&65280), c3 := Format("0x{:02X}",c>>16) 2817 | c := Format("0x{:06X}",c1|c2|c3) 2818 | fontObject["color"] := c 2819 | 2820 | fontSize := NumGet(choosefont,A_PtrSize=8?32:16,"UInt") / 10 ; 32:16 2821 | fontObject["size"] := fontSize 2822 | fontHwnd := DllCall("CreateFontIndirect","uptr",logfont.ptr) ; last param "cdecl" 2823 | fontObject["name"] := fntName 2824 | 2825 | logfont := "", choosefont := "" 2826 | 2827 | If (!fontHwnd) { 2828 | fontObject := "" 2829 | return 0 2830 | } Else { 2831 | fontObject["hwnd"] := fontHwnd 2832 | b := fontObject["bold"] ? "bold" : "" 2833 | i := fontObject["italic"] ? "italic" : "" 2834 | s := fontObject["strike"] ? "strike" : "" 2835 | c := fontObject["color"] ? "c" fontObject["color"] : "" 2836 | z := fontObject["size"] ? "s" fontObject["size"] : "" 2837 | u := fontObject["underline"] ? "underline" : "" 2838 | fullStr := b "|" i "|" s "|" c "|" z "|" u 2839 | str := "" 2840 | Loop Parse fullStr, "|" 2841 | If (A_LoopField) 2842 | str .= A_LoopField " " 2843 | fontObject["str"] := "norm " Trim(str) 2844 | 2845 | return fontObject 2846 | } 2847 | } 2848 | 2849 | ; typedef struct tagLOGFONTW { 2850 | ; LONG lfHeight; |4 / 0 2851 | ; LONG lfWidth; |4 / 4 2852 | ; LONG lfEscapement; |4 / 8 2853 | ; LONG lfOrientation; |4 / 12 2854 | ; LONG lfWeight; |4 / 16 2855 | ; BYTE lfItalic; |1 / 20 2856 | ; BYTE lfUnderline; |1 / 21 2857 | ; BYTE lfStrikeOut; |1 / 22 2858 | ; BYTE lfCharSet; |1 / 23 2859 | ; BYTE lfOutPrecision; |1 / 24 2860 | ; BYTE lfClipPrecision; |1 / 25 2861 | ; BYTE lfQuality; |1 / 26 2862 | ; BYTE lfPitchAndFamily; |1 / 27 2863 | ; WCHAR lfFaceName[LF_FACESIZE]; |[32|64] / 28 ---> size [60|92] -- 32 TCHARs [UTF-8|UTF-16] 2864 | ; } LOGFONTW, *PLOGFONTW, *NPLOGFONTW, *LPLOGFONTW; 2865 | 2866 | 2867 | ; typedef struct tagCHOOSEFONTW { 2868 | ; DWORD lStructSize; |4 / 0 2869 | ; HWND hwndOwner; |[4|8] / [ 4| 8] A_PtrSize * 1 2870 | ; HDC hDC; |[4|8] / [ 8|16] A_PtrSize * 2 2871 | ; LPLOGFONTW lpLogFont; |[4|8] / [12|24] A_PtrSize * 3 2872 | ; INT iPointSize; |4 / [16|32] A_PtrSize * 4 2873 | ; DWORD Flags; |4 / [20|36] 2874 | ; COLORREF rgbColors; |4 / [24|40] 2875 | ; LPARAM lCustData; |[4|8] / [28|48] 2876 | ; LPCFHOOKPROC lpfnHook; |[4|8] / [32|56] 2877 | ; LPCWSTR lpTemplateName; |[4|8] / [36|64] 2878 | ; HINSTANCE hInstance; |[4|8] / [40|72] 2879 | ; LPWSTR lpszStyle; |[4|8] / [44|80] 2880 | ; WORD nFontType; |2 / [48|88] 2881 | ; WORD ___MISSING_ALIGNMENT__; |2 / [50|92] 2882 | ; INT nSizeMin; |4 / [52|96] 2883 | ; INT nSizeMax; |4 / [56|100] -- len: 60 / 104 2884 | ; } CHOOSEFONTW; 2885 | 2886 | ;;==================== Color Select Dialog ========================= 2887 | ; ColorSelect() - Display the standard Windows color selection dialog 2888 | 2889 | ; AHK v2 2890 | ; originally posted by maestrith 2891 | ; https://autohotkey.com/board/topic/94083-ahk-11-font-and-color-dialogs/ 2892 | 2893 | ; #SingleInstance,Force 2894 | 2895 | ; Global defColor 2896 | 2897 | ; === optional input color object, max 16 indexes number 1-16 === 2898 | ; === can be Array(), [], or Map() 2899 | ; defColor := Array(0xFF0000,0,0x00FF00,0,0x0000FF) 2900 | ; =============================================================== 2901 | ; Example 2902 | ; =============================================================== 2903 | 2904 | ; global cc, defColor 2905 | ; cc := 0x00FF00 ; green 2906 | ; defColor := [0xAA0000,0x00AA00,0x0000AA] 2907 | 2908 | ; oGui := Gui.New("-MinimizeBox -MaximizeBox","Choose Color") 2909 | ; oGui.OnEvent("close","close_event") 2910 | ; oGui.OnEvent("escape","close_event") 2911 | ; oGui.AddButton("w150","Choose Color").OnEvent("click","choose_event") 2912 | ; oGui.BackColor := cc 2913 | ; oGui.Show("") 2914 | ; return 2915 | 2916 | 2917 | ; choose_event(ctl,info) { 2918 | ; hwnd := ctl.gui.hwnd ; grab hwnd 2919 | ; cc := "0x" ctl.gui.BackColor ; pre-select color from gui background (optional) 2920 | 2921 | ; cc := ColorSelect(cc,hwnd,defColor,0) ; hwnd and defColor are optional 2922 | 2923 | ; If (cc = -1) 2924 | ; return 2925 | 2926 | ; colorList := "" 2927 | ; For k, v in defColor { 2928 | ; If v { 2929 | ; colorList .= "Index: " k " / Color: " v "`r`n" 2930 | ; } 2931 | ; } 2932 | 2933 | ; If cc 2934 | ; msgbox "Output color: " cc "`r`n`r`nCustom colors saved:`r`n`r`n" Trim(colorList,"`r`n") 2935 | 2936 | ; ctl.gui.BackColor := cc ; set gui background color 2937 | ; } 2938 | 2939 | ; close_event(guiObj) { 2940 | ; ExitApp 2941 | ; } 2942 | 2943 | ; =============================================================== 2944 | ; END Example 2945 | ; =============================================================== 2946 | 2947 | ; ============================================================================================= 2948 | ; Color = Start color 2949 | ; hwnd = Parent window 2950 | ; custColorObj = Use for input to init custom colors, or output to save custom colors, or both. 2951 | ; ... custColorObj can be Array() or Map(). 2952 | ; disp = full / basic ... full displays custom colors panel, basic does not 2953 | ; ============================================================================================= 2954 | ; All params are optional. With no hwnd dialog will show at top left of screen. User must 2955 | ; parse output custColorObj and decide how to save custom colors... no more automatic ini file. 2956 | ; ============================================================================================= 2957 | 2958 | ColorSelect(Color := 0, hwnd := 0, &custColorObj := "",disp:=1) { 2959 | Color := (Color = "") ? 0 : Color ; fix silly user "oops" 2960 | disp := disp ? 0x3 : 0x1 ; init disp / 0x3 = full panel / 0x1 = basic panel 2961 | 2962 | c1 := Format("0x{:02X}",(Color&255)<<16) ; convert RGB colors to BGR for input 2963 | c2 := Format("0x{:02X}",Color&65280) ; init start Color 2964 | c3 := Format("0x{:02X}",Color>>16) 2965 | Color := Format("0x{:06X}",c1|c2|c3) 2966 | 2967 | CUSTOM := Buffer(16 * A_PtrSize,0) ; init custom colors obj 2968 | 2969 | CHOOSECOLOR := Buffer(9 * A_PtrSize,0) ; init dialog 2970 | size := CHOOSECOLOR.size 2971 | 2972 | If (IsObject(custColorObj)) { 2973 | Loop 16 { 2974 | If (custColorObj.Has(A_Index)) { 2975 | col := custColorObj[A_Index] = "" ? 0 : custColorObj[A_Index] ; init "" to 0 (black) 2976 | 2977 | c4 := Format("0x{:02X}",(col&255)<<16) ; convert RGB colors to BGR for input 2978 | c5 := Format("0x{:02X}",col&65280) ; 2979 | c6 := Format("0x{:02X}",col>>16) 2980 | custCol := Format("0x{:06X}",c4|c5|c6) 2981 | NumPut "UInt", custCol, CUSTOM, ((A_Index-1) * 4) ; type, number, target, offset 2982 | } 2983 | } 2984 | } 2985 | 2986 | NumPut "UInt", size, CHOOSECOLOR, 0 2987 | NumPut "UPtr", hwnd, CHOOSECOLOR, A_PtrSize 2988 | NumPut "UInt", Color, CHOOSECOLOR, 3 * A_PtrSize 2989 | NumPut "UInt", disp, CHOOSECOLOR, 5 * A_PtrSize 2990 | NumPut "UPtr", CUSTOM.ptr, CHOOSECOLOR, 4 * A_PtrSize 2991 | 2992 | ret := DllCall("comdlg32\ChooseColor", "UPtr", CHOOSECOLOR.ptr, "UInt") 2993 | 2994 | if !ret 2995 | return -1 2996 | 2997 | custColorObj := Array() 2998 | Loop 16 { 2999 | newCustCol := NumGet(CUSTOM, (A_Index-1) * 4, "UInt") 3000 | c7 := Format("0x{:02X}",(newCustCol&255)<<16) ; convert RGB colors to BGR for input 3001 | c8 := Format("0x{:02X}",newCustCol&65280) 3002 | c9 := Format("0x{:02X}",newCustCol>>16) 3003 | newCustCol := Format("0x{:06X}",c7|c8|c9) 3004 | custColorObj.InsertAt(A_Index, newCustCol) 3005 | } 3006 | 3007 | Color := NumGet(CHOOSECOLOR, 3 * A_PtrSize, "UInt") 3008 | 3009 | c1 := Format("0x{:02X}",(Color&255)<<16) ; convert RGB colors to BGR for input 3010 | c2 := Format("0x{:02X}",Color&65280) 3011 | c3 := Format("0x{:02X}",Color>>16) 3012 | Color := Format("0x{:06X}",c1|c2|c3) 3013 | 3014 | CUSTOM := "", CHOOSECOLOR := "" 3015 | 3016 | return Color 3017 | } 3018 | 3019 | ;; 获取拼音首字母 3020 | GetFirstChar(str) { 3021 | ; GBK编码区间对应的拼音首字母 3022 | static array := [ [-20319,-20284,"A"], [-20283,-19776,"B"], [-19775,-19219,"C"] 3023 | , [-19218,-18711,"D"], [-18710,-18527,"E"], [-18526,-18240,"F"], [-18239,-17923,"G"] 3024 | , [-17922,-17418,"H"], [-17417,-16475,"J"], [-16474,-16213,"K"], [-16212,-15641,"L"] 3025 | , [-15640,-15166,"M"], [-15165,-14923,"N"], [-14922,-14915,"O"], [-14914,-14631,"P"] 3026 | , [-14630,-14150,"Q"], [-14149,-14091,"R"], [-14090,-13319,"S"], [-13318,-12839,"T"] 3027 | , [-12838,-12557,"W"], [-12556,-11848,"X"], [-11847,-11056,"Y"], [-11055,-10247,"Z"] ] 3028 | 3029 | ; 如果不包含中文字符,则直接返回原字符 3030 | if !RegExMatch(str, "[^\x{00}-\x{ff}]") 3031 | Return str 3032 | 3033 | out := "" 3034 | for char in StrSplit(str) { 3035 | code := Ord(char) 3036 | if (code >= 0x2E80 && code <= 0x9FFF) { 3037 | buf := Buffer(4) 3038 | StrPut(char, buf, "CP936") 3039 | nGBKCode := (NumGet(buf, 0, "UChar") << 8) + NumGet(buf, 1, "UChar") - 65536 3040 | for i, a in array { 3041 | if (nGBKCode >= a[1] && nGBKCode <= a[2]) { 3042 | out .= a[3] 3043 | break 3044 | } 3045 | } 3046 | } else { 3047 | out .= char 3048 | } 3049 | } 3050 | return out 3051 | } 3052 | 3053 | ExtractRes() { 3054 | base64 := " 3055 | ( 3056 | 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" 3138 | )" 3139 | file := A_Temp "\ALTRun.jpg" 3140 | bin := Buffer(StrLen(base64) * 3 // 4) 3141 | 3142 | DllCall("Crypt32.dll\CryptStringToBinary", "Str", base64, "UInt", 0, "UInt", 1, "Ptr", bin, "UIntP", size := bin.Size, "Ptr", 0, "Ptr", 0) 3143 | f := FileOpen(file, "w", "CP0") 3144 | f.RawWrite(bin) 3145 | f.Close() 3146 | return file 3147 | } --------------------------------------------------------------------------------