QuickLook 的第一印象是「文件资源管理器里的空格键」。但它的取项逻辑并不绑定在资源管理器上:按下空格时,它先看当前前台窗口是谁,再从那个窗口里把「你选中的文件」取出来。所以真正的问题不是「支持不支持资源管理器之外的工具」,而是它认识哪些窗口。
这件事值得单独写一篇,是因为中文资料里几乎没人讲清它,而实际用起来踩坑的概率不低——尤其是 Everything,不同大版本的取项通道完全不同,副作用也完全不同。
一、官方文档写了什么,源码里又有什么
先看官方口径。QuickLook 的 README 里有一栏叫「Works Everywhere」,其中第三方文件管理器两项只列了两个名字:
3rd Party Managers:Total Commander, xplorer²
Cloud Storage:OneDrive, Dropbox ready
只看这一行,结论会是「除了资源管理器,支持面很窄」。但打开官方仓库的源码目录 QuickLook.Native/QuickLook.Native32/,会看到一组名字非常直白的适配文件——每一个都对应一个宿主程序:
| 源码文件 | 对应的宿主程序 | 官方 README 是否列出 |
|---|---|---|
Shell32.cpp | Windows 文件资源管理器 / 原生 Shell | 是(作为主场景) |
DialogHook.cpp | 打开 / 保存文件对话框 | 是 |
Everything.cpp / .h | Everything(文件搜索工具) | 否 |
DOpus.cpp | Directory Opus | 否 |
MultiCommander.cpp | Multi Commander | 否 |
FilePilot.cpp | File Pilot | 否 |
IDMan.cpp | Internet Download Manager | 否 |
DeskBox.cpp | DeskBox | 否 |
这是本文所有结论的来源:官方 README 的清单是残缺的,实际适配面比它写出来的宽。不过要立刻补一句纪律——源码里存在实现,不等于官方承诺「全面支持某个管理器」。所以下面讲的是「源码里是怎么做的」,能不能在你的机器上跑通,仍以本机实测为准。
二、Everything:两条通道,副作用完全不同
Everything 是最容易踩坑的一个,原因在于 QuickLook 为它准备了两套取项方案,优先走哪套取决于你的 Everything 版本。两套方案的效果差异很大。
通道一:Everything 1.5 的隐藏窗口 IPC(无副作用)
源码里的第一步是找窗口。QuickLook 会先取当前前台窗口,然后以它为父窗口去查找一个隐藏子窗口,使用的窗口类是 EVERYTHING_IPC_HIDDEN_WIN_CLASS。找到之后,直接用 GetWindowText 从这个隐藏窗口读走完整路径。
源码里那句注释把意图写得很清楚:Everything v1.5 IPC via hidden window. 这条路径的优点是完全不碰系统剪贴板——你之前在复制的东西不会被动。
通道二:Everything 1.4 的剪贴板回退(会覆盖剪贴板)
如果上一步没找到隐藏窗口,QuickLook 会退回到老办法:按窗口类 EVERYTHING_IPC_WINDOW_CLASS 找 Everything 主窗口,然后给它发一条命令让它「把选中项的完整路径复制到剪贴板」。
接着是这段实现里最需要注意的地方:QuickLook 等大约 100 毫秒,然后打开剪贴板、读取其中的文本、按第一个换行符截断,拿到路径。
它会向你系统剪贴板里写入文件路径,从而覆盖你原本复制的内容。更关键的是:源码里负责备份与恢复剪贴板的两个函数 backupClipboard() 和 restoreClipboard(),目前仍是 // TODO 状态——也就是说,它不会帮你把原来的剪贴板内容还回来。
如果你经常一边复制文本一边用空格翻文件,这一点会实实在在地影响你。
为什么 Everything 1.5 有时「认不到」
把上面两条通道放在一起,就能解释一个流传很广的问题:Everything 1.5 装了之后 QuickLook 取不到选中项。
原因是回退通道需要按窗口类名找到一个唯一的 Everything 主窗口。而 Everything 1.5 如果你开了多实例,窗口就存在歧义,按类名查找可能落空,两条通道就都走不通了。
voidtools 官方论坛给出的解法是把 Everything 配置文件 Everything-1.5a.ini 里的 alpha_instance 改为 0。改完之后,按类名查找能命中唯一窗口,问题随之消失。这类「配置项名 + 具体值」的细节,官方 README 里是不会写的。
三、Directory Opus:只取第一个选中项
Directory Opus 走的是另一套机制,它不依赖剪贴板,但要经过一次跨进程消息往返。
-
定位窗口。按窗口类名
DOpus.ParentWindow与窗口标题Directory Opus组合查找,这两项在源码里都是写死的常量。 -
注册一个隐藏消息窗口。QuickLook 会先创建一个自己的隐藏窗口(类名
QuickLook.Native.DOpus.MsgWindow)专门用来接收回传结果。 -
发送请求。通过
WM_COPYDATA消息把请求发给 Directory Opus,请求里的数据标识为0x15,附带的内容是字符串listsel——语义就是「把当前选中的列表给我」。 -
接收并解析 XML。Directory Opus 会把选中项以 XML 形式回传,结构形如
<results command="listsel"><items><item name="1.jpg" path="C:\folder\1.jpg" /></items></results>。QuickLook 用rapidxml解析它。
源码在遍历 <item> 节点时,取到第一个就返回了,注释原文是 we now cares only the first result。所以你一次框选十个文件,按空格预览的仍然只是排序最靠前的那个。这不是 bug,是当前实现的行为边界。
另外这条往返有 2 秒超时。如果 Directory Opus 正忙或未响应,预览会直接放弃取项。
四、其余适配实现与通用前提
除上面两个,源码里还有 Multi Commander、File Pilot、DeskBox 以及 Internet Download Manager 的适配文件。它们的思路大同小异:找到那个程序的主窗口,用该程序自己的进程间通信方式索要「当前选中项」,再拼出文件路径。
值得一提的是 Internet Download Manager 那一项。IDM 的下载队列列表本身不是文件管理器,但它列出的每一行都对应磁盘上的真实文件,所以适配之后你可以在下载队列里直接按空格确认「下下来的到底是什么」——这个用法在下载完压缩包、又懒得解压确认的时候很实用。
所有联动共用的一个前提:前台焦点
不管宿主是哪个程序,取项的第一步都是「看当前前台窗口是谁」。这带来一条铁律:你要预览的那个工具,必须是当前的活动窗口,而且你要先在里面选中文件。
如果空格没反应,先别怀疑支持性,先确认这两件事。更完整的按键链路排查(托盘进程、输入法、热键冲突、权限一致性等九种原因)写在 空格键没反应的排查清单 里。
五、取不到选中项时,按这个顺序查
第一步:确认 QuickLook 自己在跑
看托盘里有没有 QuickLook 图标。没有就是进程没启动,跟宿主程序无关——这是最常见的误判。
第二步:确认前台焦点在宿主程序上
点是点了文件,但如果焦点被别的窗口抢走(比如 Everything 的搜索框),取项就会落空。特别提醒:在 Everything 里如果光标停在搜索框里,此时按空格是在输入空格,不是在触发预览。
第三步:按宿主程序分别处理
- Everything:检查是否开了多实例。开了就按上文把
alpha_instance改为0。同时注意剪贴板会被占用的情况。 - Directory Opus:确认你是在文件列表里选的项,而不是在树形目录或工具栏上。另外记住它只取第一个选中项。
- Total Commander / xplorer²:这两个是官方 README 明确列出的,属于支持度最高的第三方场景,出问题优先查权限与焦点。
第四步:检查权限是否一致
如果宿主程序是「以管理员身份运行」启动的,而 QuickLook 是普通权限,两者之间存在权限落差,进程间取项就可能失败。反过来也一样。让两者权限保持一致通常能解决问题,这条在 预览异常排查 里也有对应条目。
第五步:回到原生环境交叉验证
在 Windows 自带的文件资源管理器里按空格,如果正常,说明 QuickLook 本体没问题,问题出在与宿主的联动环节;如果也不正常,那属于基础故障,先修基础链路再谈联动。
六、常见问题
官方 README 里没写的文件管理器,是不是就不支持?
不能这样推。README 的第三方管理器一栏只列了 Total Commander 与 xplorer²,但官方仓库源码里另有 Everything、Directory Opus、Multi Commander、File Pilot 等对应实现文件。README 的清单可以理解为「官方愿意背书的典型例子」,而不是完整支持列表。最终能否在你的机器上生效,以本机实测为准。
在 Everything 里按空格,我复制的文本被清掉了,能避免吗?
这是 Everything 回退通道的已知副作用:它会向剪贴板写入文件路径,而源码里备份与恢复剪贴板的函数尚未实现,所以不会帮你还原。可以优先确认自己用的是 Everything 1.5(走隐藏窗口通道,不碰剪贴板)。如果确实在用老通道,建议在按空格预览前先把重要内容粘贴到安全的地方。
Everything 1.5 装了却完全取不到选中项,怎么办?
优先检查是否启用了多实例。取项需要按窗口类名定位到唯一的 Everything 主窗口,多实例会让这个查找落空。voidtools 论坛给出的做法是把配置文件中 alpha_instance 的值改为 0,改完通常即可恢复。注意这个文件的位置随安装方式不同,需在 Everything 自己的安装或配置目录里找。
在 Directory Opus 里框选多个文件,为什么只预览了其中一个?
因为源码在解析 Directory Opus 回传的 XML 时,取到第一个 <item> 节点就返回了,注释里写明只关心第一个结果。这是当前的实现边界,不是配置问题,也无法通过设置改变。
第三方管理器里的预览和资源管理器里的预览,功能一样吗?
预览窗口本身是同一套。差别只在「取到的是哪个文件」这一步——不同宿主的取项实现不同,因此行为边界也不同(例如 Directory Opus 只取第一个选中项)。一旦路径取到,之后的渲染、快捷键、方向键连续切换都是共用的。