如果你经常打开固定的一批文件夹、脚本、文档,最直接的方法当然是放桌面快捷方式。但桌面图标一多,很快又会乱。AHK 的 Menu 命令很适合做一个轻量入口:热键一按,常用文件夹和文件直接从菜单里打开。

Jack 博客里有几篇文章围绕 QuickLinks 和文件夹菜单展开,我觉得最值得保留的是这个思路:不要把菜单写死在脚本里,而是让脚本从某个文件夹读取内容,自动生成菜单。以后要增加入口,只需要往文件夹里放快捷方式或文件。

先做一个固定菜单

先看最简单版本。这个版本适合入口很少的情况。

#Requires AutoHotkey v1.1

Menu, QuickLinks, Add, 我的文档, OpenDocs
Menu, QuickLinks, Add, 下载目录, OpenDownloads
Menu, QuickLinks, Add, 脚本目录, OpenScripts

F1::
Menu, QuickLinks, Show
return

OpenDocs:
Run, %A_MyDocuments%
return

OpenDownloads:
Run, %A_UserProfile%\Downloads
return

OpenScripts:
Run, %A_ScriptDir%
return

这个写法很稳,但缺点也明显:每增加一个入口,都要改代码。入口多了以后,脚本和数据混在一起,维护起来不舒服。

从文件夹生成菜单

更适合长期使用的办法,是准备一个 QuickLinks 文件夹。里面放文件、快捷方式、子文件夹,脚本启动时扫描这个文件夹,把内容变成菜单项。

QuickDir := A_ScriptDir "\QuickLinks"
FileCreateDir, %QuickDir%

F1::
Menu, QuickLinks, UseErrorLevel
Menu, QuickLinks, DeleteAll

Loop, Files, %QuickDir%\*.*, F
    Menu, QuickLinks, Add, %A_LoopFileName%, OpenQuickItem

Menu, QuickLinks, Show
return

OpenQuickItem:
Run, % QuickDir "\" A_ThisMenuItem
return

这段代码每次按热键时都会重新生成菜单,所以你往 QuickLinks 里新增文件后,不需要重启脚本。这里用到的 Menu, DeleteAll 很关键,它会先清空旧菜单,避免重复添加。前面加一行 Menu, QuickLinks, UseErrorLevel,是为了避免菜单第一次还不存在时直接报错。

选择一个顶层文件夹

如果你不想把目录写死,可以用 FileSelectFolder 让用户选择一个顶层文件夹。这个命令比 FileSelectFile 更适合此场景,因为它明确要求选择文件夹,不会误选文件。

F1::
FileSelectFolder, TopDir, *%A_ScriptDir%, 3, 选择要生成菜单的文件夹
if ErrorLevel
    return

Menu, FolderMenu, UseErrorLevel
Menu, FolderMenu, DeleteAll
Loop, Files, %TopDir%\*.*, F
    Menu, FolderMenu, Add, %A_LoopFileName%, OpenFolderItem

Menu, FolderMenu, Show
return

OpenFolderItem:
Run, % TopDir "\" A_ThisMenuItem
return

这个版本适合临时查看某个目录里的文件。如果是每天都用的快捷入口,我更建议固定一个 QuickLinks 目录,这样心智负担更低。

子文件夹怎么办

如果目录里有子文件夹,可以把子文件夹做成子菜单。下面这个例子只处理一层子目录,逻辑更容易读;如果要无限层级递归,代码会复杂不少。

QuickDir := A_ScriptDir "\QuickLinks"

F1::
Menu, MainQuick, UseErrorLevel
Menu, MainQuick, DeleteAll

Loop, Files, %QuickDir%\*.*, D
{
    subMenu := "Sub_" A_Index
    Menu, %subMenu%, UseErrorLevel
    Menu, %subMenu%, DeleteAll

    Loop, Files, %A_LoopFileFullPath%\*.*, F
        Menu, %subMenu%, Add, %A_LoopFileName%, OpenSubItem

    Menu, MainQuick, Add, %A_LoopFileName%, :%subMenu%
}

Loop, Files, %QuickDir%\*.*, F
    Menu, MainQuick, Add, %A_LoopFileName%, OpenMainItem

Menu, MainQuick, Show
return

OpenMainItem:
Run, % QuickDir "\" A_ThisMenuItem
return

OpenSubItem:
; 简化示例:实际项目里建议用对象保存菜单项和完整路径的对应关系。
MsgBox, 子菜单项目:%A_ThisMenuItem%
return

子菜单一多,最麻烦的不是显示,而是“点了某个菜单项后,怎么知道它对应哪个完整路径”。严谨一点的写法,可以用对象保存 菜单名 + 菜单项 到完整路径的映射。这样即使不同文件夹里有同名文件,也不会混淆。

用对象保存路径映射

下面是更实用的核心写法:菜单项显示文件名,真正运行时从对象里取完整路径。

QuickDir := A_ScriptDir "\QuickLinks"
ItemPath := {}

F1::
Menu, QuickLinks, UseErrorLevel
Menu, QuickLinks, DeleteAll
ItemPath := {}

Loop, Files, %QuickDir%\*.*, F
{
    key := A_LoopFileName
    ItemPath[key] := A_LoopFileFullPath
    Menu, QuickLinks, Add, %key%, OpenMappedItem
}

Menu, QuickLinks, Show
return

OpenMappedItem:
Run, % ItemPath[A_ThisMenuItem]
return

这个结构清楚很多:菜单只是入口,路径数据放在对象里。后面如果要加图标、排序、过滤扩展名,也更容易扩展。

适合做成什么工具

我觉得这个思路很适合做三个方向:

  • 常用文件夹菜单:快速打开项目、资料、下载、截图目录。
  • 脚本启动菜单:把常用 AHK 脚本放到一个目录里,菜单点击运行。
  • 资料入口菜单:把教程、模板、表格、文档用快捷方式集中管理。

如果菜单项超过几十个,就不要继续硬堆菜单了。可以考虑搜索框、ListView 或模糊搜索。菜单适合“常用入口”,不适合当完整文件管理器。

声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。