FileSelectFolder, path, , , 选择一个文件夹 if !path ExitApp FileMenu(path) Menu, % MD5(path), show ExitApp ;文件夹路径创建Menu函数 FileMenu(folder){ static FileMD5 := [] ;文件夹 folders := cmd("dir /AD /b /s """ folder "*""") folders .= "`n" folder ;首先建立所有menu Loop, Parse, folders, `n, `r { md5 := MD5(A_LoopField) FileMD5[md5] := A_LoopField Menu, % md5, add, Menu, % md5, DeleteAll } ;关联上级菜单 Loop, Parse, folders, `n, `r { StringGetPos, pos, A_LoopField, , R if !Errorlevel { SplitPath, A_LoopField, path2, path1 path1md5 := MD5(path1) If !IsEmptyFolder(A_LoopField) Menu, % path1md5, add, % path2, % ":" MD5(A_LoopField) else Menu, % path1md5, add, % path2, FileHandle Menu, % path1md5, Icon, % path2, shell32.dll, 4 } } ;文件 files := cmd("dir /A-D /b /s """ folder "*""") Loop, Parse, files, `n, `r { StringGetPos, pos, A_LoopField, , R if !Errorlevel { SplitPath, A_LoopField, path2, path1 path1md5 := MD5(path1) Menu, % path1md5, add, % path2, FileHandle SplitPath, A_LoopField, , , ext if !ext { Menu, % path1md5, Icon, % path2, shell32.dll, 1 continue } if (ext="exe") { try Menu, % path1md5, Icon, % path2, % A_LoopField catch e Menu, % path1md5, Icon, % path2, shell32.dll, 3 continue } if (StrLen(icon :=GetFileAssocIcon(ext))>2) { Icon := StrSplit(icon,",") try Menu, % path1md5, Icon, % path2, % Icon[1], % Icon[2] ? Icon[2] : "" catch e Menu, % path1md5, Icon, % path2, shell32.dll, 1 continue } Menu, % path1md5, Icon, % path2, shell32.dll, 1 } } ;解析句柄 修改此处决定如何处理文件 FileHandle: if A_ThisMenuItem MsgBox % FileMD5[A_ThisMenu] "" A_ThisMenuItem return } MD5(string, encoding = "UTF-8") { return CalcStringHash(string, 0x8003, encoding) } ; CalcAddrHash ====================================================================== CalcAddrHash(addr, length, algid, byref hash = 0, byref hashlength = 0) { static h := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f"] static b := h.MinIndex() hProv := hHash := o := "" if (DllCall("advapi32CryptAcquireContext", "Ptr*", hProv, "Ptr", 0, "Ptr", 0, "UInt", 24, "UInt", 0xf0000000)) { if (DllCall("advapi32CryptCreateHash", "Ptr", hProv, "UInt", algid, "UInt", 0, "UInt", 0, "Ptr*", hHash)) { if (DllCall("advapi32CryptHashData", "Ptr", hHash, "Ptr", addr, "UInt", length, "UInt", 0)) { if (DllCall("advapi32CryptGetHashParam", "Ptr", hHash, "UInt", 2, "Ptr", 0, "UInt*", hashlength, "UInt", 0)) { VarSetCapacity(hash, hashlength, 0) if (DllCall("advapi32CryptGetHashParam", "Ptr", hHash, "UInt", 2, "Ptr", &hash, "UInt*", hashlength, "UInt", 0)) { Loop % hashlength { v := NumGet(hash, A_Index - 1, "UChar") o .= h[(v >> 4) + b] h[(v & 0xf) + b] } } } } DllCall("advapi32CryptDestroyHash", "Ptr", hHash) } DllCall("advapi32CryptReleaseContext", "Ptr", hProv, "UInt", 0) } return o } ; CalcStringHash ==================================================================== CalcStringHash(string, algid, encoding = "UTF-8", byref hash = 0, byref hashlength = 0) { chrlength := (encoding = "CP1200" || encoding = "UTF-16") ? 2 : 1 length := (StrPut(string, encoding) - 1) * chrlength VarSetCapacity(data, length, 0) StrPut(string, &data, Floor(length / chrlength), encoding) return CalcAddrHash(&data, length, algid, hash, hashlength) } cmd(command){ static i i++ RunWait, %ComSpec% /c %command% >%A_Temp%cmd%i%.tmp, , Hide FileRead, content, %A_Temp%cmd%i%.tmp StringReplace, content, content, `r, , All return content } IsEmptyFolder(path){ loop, %path%* return return 1 } GetFileAssocIcon(ext){ ;txt ;缓存设置 static Icons := [] ;是否缓存 if Icons[ext] return Icons[ext] else { RegRead, Name, HKCR, .%ext%, if ErrorLevel return RegRead, DefaultIcon, HKCR, %Name%DefaultIcon, if ErrorLevel return a := StrSplit(DefaultIcon,",") DefaultIcon := a[1] "," a[2]+1 Icons[ext] := DefaultIcon return DefaultIcon } }