Orion9

|
Posted: Fri Nov 28, 2025 14:08 Post subject: |
|
|
Autorun большая плюшка
Раз, два, три и есть менюшка )
 Drives.aucfg | Code: | Pragma IncludeOnce
Global hDiskWnd, gDiskWndProc, gBindDiskWnd = true
Global gDriveList = List()
ControlSetMouseAction /R 15 DrivesMenu
ControlSetMouseAction /K:S /R 15 DrivesMenu
ControlSetMouseAction /K:C /R 15 DrivesMenu
If gBindDiskWnd Then
Global gDiskWP = Callback("DiskWndProc", "hwnd;uint;wparam;lparam")
hDiskWnd = WinFind(AUTORUN_TCHANDLE, _
AUTORUN_TCARCH = 32 ? "TMyPanel" : "Window", AUTORUN_TCARCH = 32 ? 6 : 10)
If hDiskWnd > 0 Then
gDiskWndProc = DllCall("SetWindowLong" & (auX64 ? "PtrW" : "W"), _
"hwnd", hDiskWnd, "int", -4, "long_ptr", gDiskWP.Ptr, "ptr")
EndIf
EndIf
Func DiskWndProc(hWnd, uMsg, wParam, lParam)
Static WM_LBUTTONDOWN = 0x0201, _
WM_RBUTTONDOWN = 0x0204
Switch uMsg
Case WM_RBUTTONDOWN
DrivesMenu
EndSwitch
Return DllCall("CallWindowProcW", _
"ptr", gDiskWndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
EndFunc
Func DrivesMenu()
ShowPopupMenu /D /F "CreateDrivesMenu"
#ShowPopupMenu /D /F /I:24 "CreateDrivesMenu"
EndFunc
Func CreateDrivesMenu()
Local txt, bBuffer, bLine, bExtra
Local bRecInfo = IsPressed(0x10) ? false : true
If IsPressed(0x11) Then
bBuffer = true
bLine = true
bExtra = true
EndIf
Static buf = Buffer(256)
buf.Zero()
Local nSymb = DllCall("GetLogicalDriveStringsW", "dword", buf.size, "ptr", buf.ptr)
If Not nSymb Then
MsgBox("Не удалось получить список дисков" & auCRLF "SYSERROR: " & SYSERROR, "Autorun")
Return
EndIf
Local i = 0, sz, sDrive
gDriveList.Count = 0
While 1
sDrive = buf.GetStr(i)
sz = StrLen(sDrive)
If sz = 0 Then break
gDriveList.add(sDrive)
i = i + sz*2 + 2
Wend
Local sVolume, nCluster, nSector, nFree, nTotal, sName, sFS
txt = 'MENUITEM "Этот компьютер", em_aucmd Shell32.dll,15 CommandExec cm_OpenDesktop' & auCRLF
txt &= 'MENUITEM SEPARATOR' & auCRLF
For i = 0 To gDriveList.Count - 1
sDrive = gDriveList[i]
Local nDriveIco
Local nDriveType = DllCall("GetDriveType", "wstr", sDrive, "uint")
Switch nDriveType
Case 0 To 1
nDriveIco = 53 # DRIVE_UNKNOWN
Case 2
nDriveIco = 6 # DRIVE_REMOVABLE
Case 3
nDriveIco = 8 # DRIVE_FIXED
Case 4
nDriveIco = 9 # DRIVE_REMOTE
Case 5
nDriveIco = 11 # DRIVE_CDROM
Case 6
nDriveIco = 12 # DRIVE_RAMDISK
Else
nDriveIco = 7 # DEFAULT
EndSwitch
If sDrive = SystemDrive & "\" Then
sDriveIco = "imageres.dll,31"
Else
sDriveIco = "shell32.dll," & nDriveIco
EndIf
nFree = 0
nTotal = 0
DllCall("GetDiskFreeSpaceW", "wstr", sDrive, _
"dword*", @nCluster, "dword*", @nSector, _
"dword*", @nFree, "dword*", @nTotal)
If nTotal = 0 Then
IF nDriveIco = 11 Then sDrive = "CD-ROM (" & StrReplace(sDrive, "\", "") & ")"
txt &= 'MENUITEM "' & sDrive & '\t' & '", em_aucmd /D ' & sDriveIco & " DrivesMenuGoto " & i & auCRLF
If bLine Then
txt &= 'MENUITEM "' & Chr(9620) & '\t' & "" & '"'& auCRLF
EndIf
Continue
EndIf
Local nLine = 25 - Ceil(nFree/nTotal*25)
Local sLine = StrRepeat(Chr(9620), nLine)
Local nBytes = nCluster*nSector
Local nPrc = Round(100 - nFree/nTotal*100,0) & "%"
Local nSize = SizeFormat(nFree*nBytes, 1, "T", 1, 3) & " / " & SizeFormat(nTotal*nBytes, 1, "T", 1, 3) & " "
DllCall("GetVolumeInformationW", _
"wstr", sDrive, "wstr:256", @sName, "dword", 512, "ptr", 0, "ptr", 0, "ptr", 0, "wstr:256", @sFS, "dword", 512)
If bBuffer Then
Static nam = Buffer(512), fs = Buffer(512)
nam.Zero()
fs.Zero()
DllCall("GetVolumeInformationW", _
"wstr", sDrive, "ptr", nam.ptr, "dword", 512, "ptr", 0, "ptr", 0, "ptr", 0, "ptr", fs.ptr, "dword", 512)
sName = nam.GetStr()
sFS = fs.GetStr()
EndIf
nSize = SizeFormat(nFree*nBytes, 1, "T", 1, 3) & " из " & SizeFormat(nTotal*nBytes, 1, "T", 1, 3) & " свободно"
sDrive = sName & " (" & StrReplace(gDriveList[i], "\", "") & ")"
txt &= 'MENUITEM "' & sDrive & " " & nSize & '\t' & nPrc & '", em_aucmd ' & sDriveIco & " DrivesMenuGoto " & i & auCRLF
If bLine Then
txt &= 'MENUITEM "' & sLine & '\t' & "" & '", em_aucmd ' & "-1" & " DrivesMenuGoto " & i & auCRLF
EndIf
Next
Local rbSize, rbNumber, sRecInfo
If bRecInfo Then
RecycleBinInfo(rbSize, rbNumber)
sRecInfo = SizeFormat(rbSize, 1, "T", 1, 3) & ", " & rbNumber & " элементов"
EndIf
txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'MENUITEM "Корзина: ' & sRecInfo &'" , cm_OpenRecycled' & auCRLF
If bExtra Then
txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'MENUITEM "Сеть", cm_OpenNetwork' & auCRLF
txt &= 'MENUITEM "Панель управления", cm_OpenControls' & auCRLF
EndIf
Return txt
EndFunc
Func DrivesMenuGoto(nItem)
If IsPressed(0x11) Then
SendCommand("cm_OpenDriveByIndex", nItem+1)
Return
EndIf
Local Target = gDriveList[nItem]
If RequestInfo(1000) = 1 Then
CommandExec /CD %'Target'
Else
CommandExec /CD '' %'Target'
Endif
EndFunc
Func RecycleBinInfo(ByRef nSize, ByRef nNumber)
Static buf = Buffer(auX64 ? 24 : 20)
buf.Zero()
buf.SetNum(0, "dword", buf.size)
DllCall("Shell32.dll\SHQueryRecycleBinW", "ptr", 0, "ptr", buf.ptr)
If auX64 Then
nSize = buf.GetNum(8, "int64")
nNumber = buf.GetNum(16, "int64")
Else
nSize = buf.GetNum(4, "int64")
nNumber = buf.GetNum(12, "int64")
EndIf
EndFunc |
Функция перечисления дисков была реализована еще в модуле Torrents.aucfg, но не пропадать же добру напрасно? Решил, что можно развить эту тему и придать функции вторую жизнь.
Меню отображает логические диски с расширенной информацией о размере и занятом пространстве. Вызов с CTRL добавляет полосу для графического представления, но полоса не является графическим объектом (обычный юникодный символ), поэтому смотрится так себе.
Меня больше привлекла возможность использовать это меню в полноэкранном режиме, вызывая его, например, кликом рядом с вкладками или горячей клавишей, но можно использовать и по-другому. Выбор пункта открывает корень диска. Удержание CTRL - текущий каталог на диске.
Есть у меня террабайтный диск, которому больше 10 лет. Большую часть времени он просто спит. Но в последнее время стал просыпаться медленно, и если вызвать меню в этот момент, то оно может не сразу появиться.
Похоже, это происходит из-за подсчета места в корзине, пришлось добавить еще один модификатор Shift. Вызов меню с Shift не вызывает функцию RecycleBinInfo, которая получает сведения о корзине.
В общем, меню пока очень и очень эксперементальное. Над новыми пунктами и функционалом еще можно подумать.
Loopback
Пока я оставил оба варианта в коде, как вы можете видеть. Вопрос больше связан с примером в справке:
| Code: | Local sysdir
DllCall("GetSystemDirectoryW", "wstr:256", @sysdir, "int", 255) |
Почему используется int 255 и какой размер буфера создает wstr:256?
Еще вопрос. ControlSetMouseAction /R 15 DrivesMenu, получается, кликает по кнопкам [\] и [..], можно сделать, чтобы эти кнопки не попадали в индекс 15?
P.S.
Лень все-таки была побеждена, и сводка по зарегистрированным командам родилась.
 Hidden text | Code: | # Alt + "\"
SetHotkeyAction /K:A /V:220 ModuleRegInfo
Global aModuleName = List()
Func ModuleRegInfo()
AutorunModules()
Global gRegCmdCount = 0, gRegCmdName
ShowPopupMenu /D /F /I:0 "ModuleRegInfoMenu"
EndFunc
Func AutorunModules()
Local j = 1, s = ""
Static p = GetState("paths")
aModuleName.Count = 0
While 1
s = StrPart(p, auCRLF, j)
If ERROR = 1 then break
If StrPos(s , '#') And StrRight(s, 3) ="cfg" Then
s = StrPart(StrTrim(s), ": ", 2)
aModuleName.Add(s)
Endif
j += 1
Wend
EndFunc
Func ModuleRegInfoMenu()
Local mnu, txt, text, rex, reg, nRegs, name, i, cmd
Static lst = List("RegisterCommand", "SetHotkeyAction", "ControlSetMouseAction")
Static c = 0
c += 1
If c > lst.Count Then c = 1
cmd = lst[c-1]
For i = 0 To aModuleName.Count - 1
text = FileRead(aModuleName[i])
rex = RegExp("(.)(" & cmd & ".*?)\r\n", text)
txt = ""
reg = 0
If rex.Exec() Then
Do
reg += 1
mark = rex.Match[1] = Chr(10) ? "" : "/D"
txt &= 'MENUITEM "' & StrReplace(rex.Match[2],'"',"") & '", em_aucmd ' & mark & auCRLF
Until not rex.ExecNext()
gRegCmdCount += reg
name = FileGetBaseName(aModuleName[i])
mnu &= 'POPUP "' & name & ' (' & reg & ')"' & auCRLF
mnu &= txt & auCRLF
mnu &= 'END_POPUP' & auCRLF
EndIf
Free(rex)
Next
gRegCmdName = cmd
mnu = 'MENUITEM "' & cmd & '", em_aucmd -1 ClipPut %"gRegCmdName"' & auCRLF & _
'MENUITEM SEPARATOR' & auCRLF & mnu & auCRLF & _
'MENUITEM SEPARATOR' & auCRLF & _
'MENUITEM "Total commands: ' & gRegCmdCount & '", em_aucmd'
Return mnu
EndFunc |
Регулярные выражения, конечно, значительно упростили задачу, спасибо за функционал. Само меню выглядит так:
 Hidden text
Неактивные пункты значит команда находится не в начале строки и скорее всего закомментирована или ее имя просто упоминается где-то в переменных или функциях. |
|