如何从Windows资源管理器获取鼠标悬停热项的文件名与完整路径
资源管理器DirectUIHWND控件下获取鼠标悬停热项路径实现方案
已验证可落地的跨版本方案(兼容Vista~Win11全版本,无需回退控件)
- 基于Shell公开COM接口实现(推荐,稳定性最高)
不需要修改注册表回退SysListView32控件,直接调用系统对外暴露的Shell视图接口即可,不受底层控件类型变更影响:- 先通过
IShellWindows枚举定位到当前鼠标所在的资源管理器窗口,获取当前文件夹视图对应的IFolderView接口指针 - 拦截到tooltip通知或者需要取热项时,直接调用
GetCursorPos拿到当前鼠标屏幕坐标,转成视图客户区坐标后,调用IFolderView::GetItemAtPoint传入坐标做命中测试,拿到对应项的PIDL,再通过SHCreateItemFromIDList生成IShellItem指针 - 调用
IShellItem::GetDisplayName,传SIGDN_NORMALDISPLAY参数获取显示文件名,传SIGDN_FILESYSPATH参数获取文件完整磁盘路径
该逻辑和资源管理器内部取热项的逻辑一致,不存在版本兼容问题,也不需要等待视图重建,实时生效。
- 先通过
- 基于已子类化的Tooltip控件快速取数(适配已有的实现)
已经完成tooltip父窗口子类化、能拦截tooltip通知的前提下,不需要额外做命中测试:- 拦截到
TTN_SHOW通知时,直接向tooltip控件发送TTM_GETTEXT消息,即可直接取出当前tooltip绑定的文件项显示名称 - 拿到文件名后,结合当前资源管理器文件夹的
IShellFolder接口枚举当前视图内所有项,匹配显示名即可拿到对应项的PIDL,进而生成IShellItem获取完整路径。该方案代码量最小,不需要额外处理坐标转换和命中测试逻辑。
- 拦截到
旧方案局限性说明
网上流传的修改注册表回退SysListView32控件的方案,本质是修改资源管理器视图初始化时的加载配置,已经创建完成的DirectUI视图不会实时响应配置变更,必须切换文件夹触发视图销毁重建才能生效,属于全局修改,会破坏系统原生资源管理器的视觉效果和交互逻辑,不建议使用。
避坑提示
不要尝试逆向DirectUIHWND的内部窗口消息、内存结构来取热项:不同Windows大版本(Win7/Win10/Win11各迭代版本)的DirectUI内部实现、数据结构偏移差异极大,每次系统更新都可能导致代码崩溃,维护成本极高。系统公开的Shell COM接口是官方对外承诺兼容的接口,不会随版本更新失效。
内容的提问来源于stack exchange,提问作者khalfan
相关产品推荐
相关产品推荐

