1.[AHK] 桌面图标显隐2.[AHK2] 轻松拖拽窗口3.[AHK2] 虚拟键盘4.[AHK2] 音量控制5.[AHK2] 常用的Tooltip(封装常用方法)6.[AHK2] 亮度控制7.[AHK2] 媒体管理8.[AHK] 区分^ScrollLock 和 ^Pause9.[AHK2] 窗口置顶管理10.[AHK2] 切换鼠标锁定11.[AHK2] 更改脚本初始代码12.[AHK2] 让终止符决定热字串13.[AHK2] 屏幕放大镜14.[AHK2] 实现简单的贴图工具15.[AHK2] 向对象原型添加属性和方法16.[AHK2] 合并使用#include的脚本17.[AHK2] 截图工具18.[AHK2] wt调用命令19.[AHK2] 不用结束符的热字串20.[AHK2] 获取文件资源管理器中的选中文件21.仓库在哪?22.[AHK2] 借助vlc设置桌面动态背景23.[AHK2] 取色与颜色表示转换24.[AHK2] 取色工具25.[AHK2] 如何解析ahk命令行26.[AHK2] 杂谈——抽象的ahk代码风格是怎么来的?27.[AHK2] 脚本间通信28.[AHK2] 将绝对路径导入转化为相对路径导入
29.[AHK2] 实现自定义文件管理器右键菜单
30.[AHK2] 控制窗口透明度功能描述
原始的右键菜单可能无法满足我的日常需求,比如简单的一点:复制路径。
所以我使用ahk写了一个脚本,可以打开自定义的菜单(使用热键);
截图如下:
其中添加了几项有用的功能,相比右键菜单要方便很多。
实现原理
原理是获取到文件管理器窗口,并获取其选中项属性(选中的文件),见下面代码:
#Include ..\Extend.ahk #Include ..\Path.ahk class Explorer { __New(hwnd) { window := this._GetWindow(hwnd) if !window { throw Error('invalid window') } this.hwnd := hwnd this.isDesktop := window = 'desktop' this.window := window } static IsValidHwnd(hwnd) => WinGetProcessName('ahk_id' hwnd) = 'explorer.exe' static IsWinExist(hwnd) => WinExist('ahk_id' hwnd) _GetWindow(hwnd) { if !Explorer.IsValidHwnd(hwnd) { return } className := WinGetClass('ahk_id ' hwnd) if className ~= '(Cabinet|Explore)WClass' { for win in ComObject('Shell.Application').Windows if win.Hwnd = hwnd { return win } } else if className ~= 'Progman|WorkerW' { return 'desktop' } } _GetListViewContent(selection, options) { if !Explorer.IsWinExist(this.hwnd) return arr := [] if this.isDesktop { List := ListViewGetContent(options, "SysListView321", 'ahk_class WorkerW') Loop Parse, List, "`n" { loop parse A_LoopField, A_Tab arr.Push(Path.Join(A_Desktop, A_LoopField)) } } else { if selection collection := this.window.document.Selecteditems else collection := this.window.document.Folder.Items for item in collection { arr.push(item.path) } } return arr } GetListViewSelected() => this._GetListViewContent(true, "Selected Col1") GetListViewAll() => this._GetListViewContent(false, 'Col1') GetLocationURL() => (Explorer.IsWinExist(this.hwnd) && !this.isDesktop) ? this.window.LocationURL : '' GetURL() => SubStr(this.GetLocationURL(), 9) }
源脚本来自网上
通过此脚本,就可以获取到选中文件、URL等信息了。
实现ui
上面的脚本可以获取到数据,还需要界面来展示,下面的代码使用ListView
来实现一个简单菜单:
#Include G:\AHK\git-ahk-lib\Tip.ahk #Include G:\AHK\git-ahk-lib\Theme.ahk #Include G:\AHK\git-ahk-lib\Extend.ahk #Include G:\AHK\git-ahk-lib\util\Explorer.ahk #Include G:\AHK\git-ahk-lib\util\Animation.ahk CoordMode 'Mouse', 'Screen' !#0:: ShowContextMenu() imgList := IL_Create(10) , IL_Add(imgList, './resource/icon/vscode.ico') , IL_Add(imgList, './resource/icon/markdown.ico') , IL_Add(imgList, './resource/icon/text.png') ExplorerContextActions := [ ['Icon' 0, '复制路径', _copyPath], ['Icon' 0, '复制文本', _copyText], ['Icon' 1, '以vscode打开', _openWithVsCode], ['Icon' 2, '以typora打开', _openWithTypora], ['Icon' 3, '以记事本打开', _openWithNotepad], ] selected := [] ShowContextMenu() { try id := WinGetID('A') catch { Tip.ShowTip('Error on get id') return } if !Explorer.IsValidHwnd(id) return window := Explorer(WinGetID('A')) global selected := window.GetListViewSelected() if !selected.Length return ExplorerContext.Show(imgList, ExplorerContextActions) } _openWithVsCode() { if selected.Length Run(A_ComSpec ' /c code ' selected[1]) } _openWithTypora() { if selected.Length Run(A_ComSpec Format(' /c F:\Typore\Typora\Typora.exe "{}"', selected[1]), , 'Hide') } _openWithNotepad() { if selected.Length Run('notepad ' selected.join(A_Space)) } _copyPath() { if selected.Length A_Clipboard := '', A_Clipboard := selected[1], Tip.ShowTip('Copied!') } _copyText() { if selected.Length { _p := selected[1] _t := FileRead(_p, 'utf-8') A_Clipboard := '', A_Clipboard := _t, Tip.ShowTip('Copied!') } } class ExplorerContext extends Gui { static Width := 150 cbs := Map() __New(imageList := '', actions := []) { super.__New('+AlwaysOnTop +ToolWindow -Caption') this.SetFont('s14', 'consolas') lv := this.AddListView('w' ExplorerContext.Width ' Grid -Multi -Hdr Lv0x2000 LV0x8000', ['items']) lv.OnEvent('Click', (p*) => this.OnLvClick(p*)) this.lv := lv, lv.SetImageList(imageList) for v in actions this.LvAdd(v[1], v[2], v[3]) Theme.Light(this) } static Show(imgList, actions) { static ins := ExplorerContext(imgList, actions) Animation.FadeIn(ins, (*) => ins.Modify(), , 8) Hotkey '~LButton Up', (*) => ins._Hide(), 'On' } Modify() => (lv := this.lv, this.GetPos(&x, &y, &w, &h), lv.Move(3, 3, w - 6, h - 6), lv.ModifyCol(1, w - 10)) LvAdd(opts, col, callback) => (this.lv.Add(opts, col), this.cbs.Set(col, callback)) _Hide() => (Animation.FadeOut(this, true), HotKey('~LButton Up', 'Off')) OnLvClick(lv, row, *) => this.cbs.Get(lv.GetText(row, 1), Noop)() }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 百万级群聊的设计实践
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期