未修改前为默认的文件夹图标,只能依靠名字检索
根据目录内主程序图标修改后,一目了然
留问:除了手动修改,有没有更优雅的方式呢
我用ahk写过给图库各个文件夹生成图标的,改一改就能用来给软件文件夹生成图标了。
自动提取文件夹内部exe图标,不过要是有多个exe怎么办?
,看起来不错,等会看看。
至于文件夹内检索出有多个exe,弹窗手动选择
我待会贴一下代码,你改一改试试,我觉得不难,会ahk基础的话
推荐2个软件:
这个软件可以自定义文件夹图标, 并给这些文件夹贴上徽章. 所以比起同类软件来说, 自定义程度和图标的丰富程度会高很多. 徽章的位置大小也是可以自由调节的.
而且我已经做了官方中文版, 官网直接下载即可.
题外话,平时启动开始菜单搜索/各种启动器启动已经很方便了。另外开始菜单中的快捷方式够用了,快捷方式右键可以随时打开原文件位置
目前在用Claunch,有时候手动进入program files目录添加软件,看到文件夹都是一样的图标不舒服
强迫症懂的,不过这种东西可能重装系统,或者是引用的图片位置更改了,就全空了…就容易没有耐心去搞了。
关于 Windows 的文件夹图标和名称都是 desktop.ini 决定的这个我是知道的,不过这个 A: 盘是什么我就不清楚了。是上述的软件的效果吗?
A盘是我软件安装目录
原来如此,这种指向确实没有什么问题
印象中是 Windows 10 还是 11 某个版本开始可以把盘修改为 A 盘
我改了一个用来给软件文件夹做图标的版本,不过没有添加多个exe选择的功能,而且还有bug。
有空我可能改一改?(不过我八成不会动弹了,因为已经够我用了,多个exe选择还挺烦)
代码ahk v1.几
#SingleInstance
FileselectFolder, path, , , 请选择根目录
FilesetAttrib +S,%path%\*, 2 ,1
loop Files, %path%\* , D R ;递归子文件夹
{
loop, Files, %A_LoopFileLongPath%\* , F
{
if (A_LoopFileExt = "exe")
{
exe_path := A_LoopFileLongPath
break ,1
}
}
ini=%A_LoopFileLongPath%\desktop.ini
icofullpath=%A_LoopFileLongPath%\folder.ico
Png2Icon(exe_path, icofullpath)
IniWrite folder.ico, %ini%, .ShellClassInfo, IconFile
IniWrite 0 , %ini%, .ShellClassInfo, IconIndex
IniWrite 0 , %ini%, .ShellClassInfo, ConfirmFileOp
}
MsgBox everything is Ok
return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;以下是png转ico库
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Png2Icon(sourcePng, destIco) {
hBitmap := LoadPicture(sourcePng, "GDI+")
hIcon := HIconFromHBitmap(hBitmap)
HiconToFile(hIcon, destIco)
DllCall("DestroyIcon", "Ptr", hIcon), DllCall("DeleteObject", hBitmap)
}
HIconFromHBitmap(hBitmap) {
VarSetCapacity(BITMAP, size := 4*4 + A_PtrSize*2, 0)
DllCall("GetObject", "Ptr", hBitmap, "Int", size, "Ptr", &BITMAP)
width := NumGet(BITMAP, 4, "UInt"), height := NumGet(BITMAP, 8, "UInt")
hDC := DllCall("GetDC", "Ptr", 0, "Ptr")
hCBM := DllCall("CreateCompatibleBitmap", "Ptr", hDC, "Int", width, "Int", height, "Ptr")
VarSetCapacity(ICONINFO, 4*2 + A_PtrSize*3, 0)
NumPut(1, ICONINFO)
NumPut(hCBM, ICONINFO, 4*2 + A_PtrSize)
NumPut(hBitmap, ICONINFO, 4*2 + A_PtrSize*2)
hIcon := DllCall("CreateIconIndirect", "Ptr", &ICONINFO, "Ptr")
DllCall("DeleteObject", "Ptr", hCBM), DllCall("ReleaseDC", "Ptr", 0, "Ptr", hDC)
Return hIcon
}
HiconToFile(hIcon, destFile) {
static szICONHEADER := 6, szICONDIRENTRY := 16, szBITMAP := 16 + A_PtrSize*2, szBITMAPINFOHEADER := 40
, IMAGE_BITMAP := 0, flags := (LR_COPYDELETEORG := 0x8) | (LR_CREATEDIBSECTION := 0x2000)
, szDIBSECTION := szBITMAP + szBITMAPINFOHEADER + 8 + A_PtrSize*3
, copyImageParams := ["UInt", IMAGE_BITMAP, "Int", 0, "Int", 0, "UInt", flags, "Ptr"]
VarSetCapacity(ICONINFO, 8 + A_PtrSize*3, 0)
DllCall("GetIconInfo", "Ptr", hIcon, "Ptr", &ICONINFO)
if !hbmMask := DllCall("CopyImage", "Ptr", NumGet(ICONINFO, 8 + A_PtrSize), copyImageParams*) {
MsgBox, % "CopyImage failed. LastError: " . A_LastError
Return
}
hbmColor := DllCall("CopyImage", "Ptr", NumGet(ICONINFO, 8 + A_PtrSize*2), copyImageParams*)
VarSetCapacity(mskDIBSECTION, szDIBSECTION, 0)
VarSetCapacity(clrDIBSECTION, szDIBSECTION, 0)
DllCall("GetObject", "Ptr", hbmMask , "Int", szDIBSECTION, "Ptr", &mskDIBSECTION)
DllCall("GetObject", "Ptr", hbmColor, "Int", szDIBSECTION, "Ptr", &clrDIBSECTION)
clrWidth := NumGet(clrDIBSECTION, 4, "UInt")
clrHeight := NumGet(clrDIBSECTION, 8, "UInt")
clrBmWidthBytes := NumGet(clrDIBSECTION, 12, "UInt")
clrBmPlanes := NumGet(clrDIBSECTION, 16, "UShort")
clrBmBitsPixel := NumGet(clrDIBSECTION, 18, "UShort")
clrBits := NumGet(clrDIBSECTION, 16 + A_PtrSize)
colorCount := clrBmBitsPixel >= 8 ? 0 : 1 << (clrBmBitsPixel * clrBmPlanes)
clrDataSize := clrBmWidthBytes * clrHeight
mskHeight := NumGet(mskDIBSECTION, 8, "UInt")
mskBmWidthBytes := NumGet(mskDIBSECTION, 12, "UInt")
mskBits := NumGet(mskDIBSECTION, 16 + A_PtrSize)
mskDataSize := mskBmWidthBytes * mskHeight
iconDataSize := clrDataSize + mskDataSize
dwBytesInRes := szBITMAPINFOHEADER + iconDataSize
dwImageOffset := szICONHEADER + szICONDIRENTRY
VarSetCapacity(ICONHEADER, szICONHEADER, 0)
NumPut(1, ICONHEADER, 2, "UShort")
NumPut(1, ICONHEADER, 4, "UShort")
VarSetCapacity(ICONDIRENTRY, szICONDIRENTRY, 0)
NumPut(clrWidth , ICONDIRENTRY, 0, "UChar")
NumPut(clrHeight , ICONDIRENTRY, 1, "UChar")
NumPut(colorCount , ICONDIRENTRY, 2, "UChar")
NumPut(clrBmPlanes , ICONDIRENTRY, 4, "UShort")
NumPut(clrBmBitsPixel, ICONDIRENTRY, 6, "UShort")
NumPut(dwBytesInRes , ICONDIRENTRY, 8, "UInt")
NumPut(dwImageOffset , ICONDIRENTRY, 12, "UInt")
NumPut(clrHeight*2 , clrDIBSECTION, szBITMAP + 8, "UInt")
NumPut(iconDataSize, clrDIBSECTION, szBITMAP + 20, "UInt")
File := FileOpen(destFile, "w", "cp0")
File.RawWrite(ICONHEADER, szICONHEADER)
File.RawWrite(ICONDIRENTRY, szICONDIRENTRY)
File.RawWrite(&clrDIBSECTION + szBITMAP, szBITMAPINFOHEADER)
File.RawWrite(clrBits + 0, clrDataSize)
File.RawWrite(mskBits + 0, mskDataSize)
File.Close()
DllCall("DeleteObject", "Ptr", hbmColor)
DllCall("DeleteObject", "Ptr", hbmMask)
}
所以为什么会有人想把盘符改成A开始……我觉得好不习惯诶(((
请教一下,我自己研究写了一个AHK脚本,按下快捷键时捕获选中文件的路径,再生成desktop.ini,但遇到了一个小问题,就是不起作用。通过右键属性来更改,查看desktop.ini,里面内容与我用AHK生成的一模一样,但是用AHK生成的ini没能改掉图标是什么情况?
通过AHK生成的desktop.ini文件:
[.ShellClassInfo]
IconResource=A:\Program Files\AutoOff\AutoOff_4.21.exe,0
AHK代码:
F3::
sel := Explorer_GetSelected()
str1 := sel ",0"
inipath := Explorer_GetPath() "\desktop.ini"
IniWrite, %str1%, %inipath%, .ShellClassInfo, IconResource
FileSetAttrib, +HS-A, %inipath%
return
;以下内容为获取选中文件路径
Explorer_GetPath(hwnd="")
{
if !(window := Explorer_GetWindow(hwnd))
return ErrorLevel := "ERROR"
if (window="desktop")
return A_Desktop
path := window.LocationURL
path := RegExReplace(path, "ftp://.*@","ftp://")
path := RegExReplace(path, "%20"," ") ;替换空格,否则显示%20
StringReplace, path, path, file:///
StringReplace, path, path, /, \, All
; thanks to polyethene
Loop
If RegExMatch(path, "i)(?<=%)[da-f]{1,2}", hex)
StringReplace, path, path, `%%hex%, % Chr("0x" . hex), All
Else Break
return path
}
Explorer_GetAll(hwnd="")
{
return Explorer_Get(hwnd)
}
Explorer_GetSelected(hwnd="")
{
return Explorer_Get(hwnd,true)
}
Explorer_GetWindow(hwnd="")
{
; thanks to jethrow for some pointers here
WinGet, process, processName, % "ahk_id" hwnd := hwnd? hwnd:WinExist("A")
WinGetClass class, ahk_id %hwnd%
if (process!="explorer.exe")
return
if (class ~= "(Cabinet|Explore)WClass")
{
for window in ComObjCreate("Shell.Application").Windows
if (window.hwnd==hwnd)
return window
}
else if (class ~= "Progman|WorkerW")
return "desktop" ; desktop found
}
Explorer_Get(hwnd="",selection=false)
{
if !(window := Explorer_GetWindow(hwnd))
return ErrorLevel := "ERROR"
if (window="desktop")
{
ControlGet, hwWindow, HWND,, SysListView321, ahk_class Progman
if !hwWindow ; #D mode
ControlGet, hwWindow, HWND,, SysListView321, A
ControlGet, files, List, % ( selection ? "Selected":"") "Col1",,ahk_id %hwWindow%
base := SubStr(A_Desktop,0,1)=="" ? SubStr(A_Desktop,1,-1) : A_Desktop
Loop, Parse, files, `n, `r
{
path := base "" A_LoopField
IfExist %path% ; ignore special icons like Computer (at least for now)
ret .= path "`n"
}
}
else
{
if selection
collection := window.document.SelectedItems
else
collection := window.document.Folder.Items
for item in collection
ret .= item.path "`n"
}
return Trim(ret,"`n")
}
[quote=“dog, post:14, topic:35094”]
FilesetAttrib +S,%path%\*, 2 ,1
[/quote]
是需要设置attrib的,你查一下这个函数有说明
我看看哈
可以用啊,刷新一下图标就出来了,你这个方法好,不用转ico图标出来了。
刷新图标缓存的代码,可能有用,可能没用你试试
RefreshExplorer() { ; by teadrinker on D437 @ tiny.cc/refreshexplorer
local Windows := ComObjCreate("Shell.Application").Windows
Windows.Item(ComObject(0x13, 8)).Refresh()
for Window in Windows
if (Window.Name != "Internet Explorer")
Window.Refresh()
}
实测有效,把这段代码加上就好了,然后每次执行后加一句RefreshExplorer() 就好了。
如果不是历史遗留问题,A 盘本来应该就是系统盘的,除非是某些软件是把路径相关的写死了,不然手动改成 A 盘问题不大。尊重个性化需求(虽然我不改
我当年大概是windows vista 的时候改过,然后windows不能索引