功能描述

原始的右键菜单可能无法满足我的日常需求,比如简单的一点:复制路径。

所以我使用ahk写了一个脚本,可以打开自定义的菜单(使用热键);

仓库地址

截图如下:

image

其中添加了几项有用的功能,相比右键菜单要方便很多。

实现原理

原理是获取到文件管理器窗口,并获取其选中项属性(选中的文件),见下面代码:


#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)()

}
posted on   落寞的雪  阅读(45)  评论(0)    收藏  举报
努力加载评论中...

点击右上角即可分享
微信分享提示