├── README.md
├── LICENSE
└── ALTRun.ahk
/README.md:
--------------------------------------------------------------------------------
1 |
ALTRun
2 |
3 | ALTRun (AHK) 是一款开源免费、简洁高效、功能强大的启动工具
4 |
5 | > 主界面
6 |
7 | 
8 |
9 | > 主界面 (无背景图片+简化+暗黑模式)
10 |
11 | 
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 | }
--------------------------------------------------------------------------------