Orion9

|
Posted: Thu Feb 27, 2025 00:23 Post subject: |
|
|
Loopback
Теперь работает )
Добавив такую функцию в Autorun, вы, конечно, дали ключ от всех дверей, но проблем хватает Я не имею в виду этот небольшой баг с "ulong_ptr". Чтобы в полной мере пользоваться WIN API, нужно много знать и понимать, как работает Windows. Одним лишь сайтом Microsoft тут не обойтись.
Но кое-что можно уже пробовать и воплощать. Например, я сначала увлёкся иконкой в трее ради интереса, но теперь понимаю, что жить без неё не могу
Многое ещё не доделано, но кое-что продемонстрировать уже можно:
 Hidden text Code: | Pragma IncludeOnce
# 64000-65000
RegisterCommand 64000 TrayIcon
RegisterCommand 64001 ChangeTrayIcon
RegisterCommand 64002 NotifyInfo
# коды клавиш клавиатуры
Const K_SHIFT = 0x10, K_CTRL = 0x11, K_ALT = 0x12, K_ESC = 0x1B, K_WIN = 0x5B
# дополнительные настроки
Global AUTORUN_INI = %COMMANDER_PATH% & "\Ini\Autorun.ini"
# иконки окна уведомлений
Const NIIF_NONE = 0x00000000, _
NIIF_INFO = 0x00000001, _
NIIF_WARNING = 0x00000002, _
NIIF_ERROR = 0x00000003, _
NIIF_USER = 0x00000004
# без звука
Const NIIF_NOSOUND = 0x00000010
# большая иконка
Const NIIF_LARGE_ICON = 0x00000020
# сообщения окна уведомлений
Const NIN_BALLOONSHOW = 0x402, _
NIN_BALLOONHIDE = 0x403, _
NIN_BALLOONTIMEOUT = 0x404, _
NIN_BALLOONUSERCLICK = 0x405, _
NIN_POPUPOPEN = 0x406, _
NIN_POPUPCLOSE = 0x407
# флаги структуры
Const NIF_MESSAGE = 0x00000001, _
NIF_ICON = 0x00000002, _
NIF_TIP = 0x00000004, _
NIF_STATE = 0x00000008, _
NIF_INFO = 0x00000010
# системные сообщения
Const WM_MOUSEMOVE = 0x0200, _
WM_LBUTTONDOWN = 0x0201, _
WM_LBUTTONUP = 0x0202, _
WM_LBUTTONDBLCLK = 0x0203, _
WM_RBUTTONDOWN = 0x0204, _
WM_RBUTTONUP = 0x0205, _
WM_RBUTTONDBLCLK = 0x0206, _
WM_MBUTTONDOWN = 0x0207, _
WM_MBUTTONUP = 0x0208, _
WM_MBUTTONDBLCLK = 0x0209
# функции обратного вызова
SetMessageAction /P 55555 TrayAction
SetMessageAction /P 55565 TrayNotifyInfo
Func TrayAction(hWnd, uMsg, wParam, lParam)
# движение над иконкой
If lParam = WM_MOUSEMOVE Then
If LAST_HINT_WINDOW = 0 Then
If IsPressed(K_CTRL) Then ShowHint(GetState("threads"), "", "", 2000, 1)
#If IsPressed(K_CTRL) Then ShowDarkHint(GetState("threads"), 2000, 1)
EndIf
EndIf
# левый клик
If lParam = WM_LBUTTONDOWN Then
If IsPressed(K_CTRL) Then
ShowDarkHint(GetState("threads"))
Return
EndIf
AutorunMenu(0)
# правый клик
Elseif lParam = WM_RBUTTONDOWN Then
ShowDarkHint(GetState("libs"))
# клик по сообщению
Elseif lParam = NIN_BALLOONUSERCLICK Then
MsgBox("Baloon click")
#WinSetState(23)
# клик "закрыть сообщение"
ElseIf lParam = NIN_BALLOONTIMEOUT Then
MsgBox("Time-out")
EndIf
EndFunc
Func TrayNotifyInfo(hWnd, uMsg, wParam, lParam)
NotifyIcon("delete", 1010)
EndFunc
Global TrayShow = 0, TrayIcon = 0
TrayIcon(0)
Func TrayIcon(lParam)
Local ico, idx = 0
IniRead TrayShow %AUTORUN_INI% "TrayIcon" "Show" 1
If Not TrayShow Then
Return
EndIf
IniRead ico %AUTORUN_INI% "TrayIcon" "Icon"
IniRead idx %AUTORUN_INI% "TrayIcon" "Index"
If ico = "" Or Not FileExist(ico) Then
idx = 0
ico = %COMMANDER_PATH% & "\TOTALCMD.EXE"
EndIf
Local hint = "Autorun " & FileGetVersion(AUTORUN_PATH & "\Autorun.wdx", "FileVersion")
Local hIco = DllCall("shell32\ExtractIconW", "ptr", AUTORUN_TCHANDLE, "wstr", ico, "uint", idx, "ptr")
#NotifyIcon("add", 1001, 55555, hIco, hint, "Tray icon added", "Autorun", 1)
TrayIcon = NotifyIcon("add", 1001, 55555, hIco, hint)
If hIco > 0 Then DllCall("DestroyIcon", "ptr", hIco, "bool")
EndFunc
Func ChangeTrayIcon(lParam)
Static f = GetKnownFolderPath("System") & "\shell32.dll", i = 10
i += 1
Local hIco = DllCall("shell32\ExtractIconW", "ptr", AUTORUN_TCHANDLE, "wstr", f, "uint", i, "ptr")
If IsPressed(0x11) Then
NotifyIcon("delete", 1001)
ElseIf IsPressed(0x10) Then
NotifyIcon("add", 1001, 55555, hIco, "Autorun")
Else
If IsPressed(0x12) Then hIco = 0
NotifyIcon("set", 1001, 55555, hIco, "", "Icon changed to shell32.dll, " & i, "", 2)
Sleep(2000)
NotifyIcon("set", 1001,, hIco,, "Icon changed to shell32.dll, " & i,, 2)
EndIf
If hIco > 0 Then DllCall("DestroyIcon", "ptr", hIco, "bool")
EndFunc
Func DeleteTrayIcon(lParam)
If NotifyIcon("delete", 1001) Then TrayIcon = 0
EndFunc
Func NotifyInfo(lParam)
Local idx = 15
Local file = GetKnownFolderPath("System") & "\shell32.dll"
Local hIco = DllCall("shell32\ExtractIconW", "ptr", AUTORUN_TCHANDLE, "wstr", file, "uint", idx, "ptr")
NotifyInfoMessage(hIco, "Test message", "", NIIF_INFO)
If hIco > 0 Then DllCall("DestroyIcon", "ptr", hIco, "bool")
EndFunc
Func NotifyInfoMessage(hIcon, InfoText, InfoTitle = "Autorun", InfoType = 0)
Local buf = Buffer((auPtrSize = 4 ? 956 : 976))
Local dwFlags = 27 # NIF_MESSAGE|NIF_STATE|NIF_INFO
buf.Zero()
If auX64 Then
buf.SetNum(0, "dword", buf.size)
buf.SetNum(8, "hwnd", AUTORUN_TCHANDLE)
buf.SetNum(16, "uint", 1010, _
"uint", dwFlags, _
"uint", 55565)
buf.SetNum(32, "ptr", hIcon)
buf.SetNum(296, "dword", 1, _
"dword", 1)
Else
buf.SetNum(0, "dword", buf.size, _
"hwnd", AUTORUN_TCHANDLE, _
"uint", 1010, _
"uint", dwFlags, _
"uint", 55565, _
"ptr", hIcon) )
buf.SetNum(280, "dword", 1, _
"dword", 1)
EndIf
buf.SetStr(StrLeft(InfoText, 263) & Chr(0), (auX64 ? 40 : 24) + 256 + 4 + 4)
If StrLen(InfoTitle) > 0 Then
buf.SetStr(StrLeft(InfoTitle, 63) & Chr(0), (auX64 ? 40 : 24) + 256 + 4 + 4 + 512 + 4)
EndIf
If InfoType > 0 Then
buf.SetNum((auX64 ? 40 : 24) + 256 + 4 + 4 + 512 + 4 + 128, "dword", InfoType)
EndIf
Local Result = DllCall("Shell32.dll\Shell_NotifyIconW", "uint", 0, "ptr", buf.ptr, "bool")
Free(buf)
Return Result
EndFunc
Func NotifyIcon(Action, ID, CallbackMessage = 0, hIcon = 0, Tip = "", InfoText = "", InfoTitle = "", InfoType = 0)
Local Message, Result
Local TIP_MAXCHAR = 127, INFO_MAXCHAR = 199, TITLE_MAXCHAR = 63
Local buf = Buffer((auPtrSize = 4 ? 956 : 976))
buf.Zero()
Local FLAGS = BitOR((CallbackMessage = 0 ? 0 : NIF_MESSAGE), _
(hIcon = 0 ? 0 : NIF_ICON), _
(StrLen(Tip) = 0 ? 0 : NIF_TIP), _
(StrLen(InfoText) = 0 ? 0 : NIF_INFO))
Switch Action
Case "add"
Message = 0
Case "set"
Message = 1
Case "delete"
Message = 2
Else
Return
EndSwitch
If auX64 Then
buf.SetNum(0, "dword", buf.size)
buf.SetNum(8, "hwnd", AUTORUN_TCHANDLE)
buf.SetNum(16, "uint", ID, _
"uint", FLAGS, _
"uint", CallbackMessage)
buf.SetNum(32, "ptr", hIcon)
Else
buf.SetNum(0, "dword", buf.size, _
"hwnd", AUTORUN_TCHANDLE, _
"uint", ID, _
"uint", FLAGS, _
"uint", CallbackMessage, _
"ptr", hIcon)
EndIf
If StrLen(Tip) > 0 Then
buf.SetStr(StrLeft(Tip, TIP_MAXCHAR) & Chr(0), (auX64 ? 40 : 24)) # auPtrSize*2 + 4*4 + padding for X64
EndIf
If StrLen(InfoText) > 0 Then
buf.SetStr(StrLeft(InfoText, INFO_MAXCHAR) & Chr(0), (auX64 ? 40 : 24) + 264) # 256 + 4 + 4
If StrLen(InfoTitle) > 0 Then
buf.SetStr(StrLeft(InfoTitle, TITLE_MAXCHAR) & Chr(0), (auX64 ? 40 : 24) + 780) # 512 + 4
EndIf
If InfoType > 0 Then
buf.SetNum((auX64 ? 40 : 24) + 780 + 128, "dword", InfoType)
EndIf
EndIf
Result = DllCall("Shell32.dll\Shell_NotifyIconW", "uint", Message, "ptr", buf.ptr, "bool")
Free(buf)
Return Result
EndFunc |
Вверху коды кнопок. Можно запустить два потока, чтобы иконка сама менялась в фоне с интервалом:
 Hidden text Code: | RunThread ThreadWatchLangFunc
Func ThreadWatchLangFunc
Local file = GetKnownFolderPath("System") & "\shell32.dll"
Local lng = AUTORUN_TCLANG, idx
While 1
OutputDebugString("lang=" & AUTORUN_TCLANG & " lng=" & lng)
If Not (lng = AUTORUN_TCLANG) Then
Switch AUTORUN_TCLANG
Case 'ENG'
# ChangeLangEN 0
idx = 13
Case 'RUS'
# ChangeLangRU 0
idx = 15
EndSwitch
lng = AUTORUN_TCLANG
Local hIco = DllCall("shell32\ExtractIconW", "ptr", AUTORUN_TCHANDLE, "wstr", file, "uint", idx, "ptr")
NotifyIcon("set", 1001, 55555, hIco)
#NotifyIcon("set", 1001, 55555, hIco, "", "Language changed to " & lng, "", 1)
If hIco > 0 Then DllCall("DestroyIcon", "ptr", hIco, "bool")
Endif
Sleep(1000)
Wend
EndFunc
RunThread ThreadFunction
# пример из справки
Func ThreadFunction
Local sPath, sName
Local ru = true
While 1
sPath = RequestCopyDataInfo("SP")
sName = RequestCopyDataInfo("SN")
sPath = sPath & sName
# выводим путь, просматривать можно с DebugView
# выполнение цикла при этом не блокируется
OutputDebugString("Autorun: Path = " & sPath)
Sleep(5000)
ru = Not ru
If ru Then
CommandExec("em_change_lang_ru")
Else
CommandExec("em_change_lang_en")
EndIf
Wend
EndFunc
|
Одмн поток меняет язык раз в 5 секунд, другой следит за сменой языка. Как только язык меняется, меняется и иконка. |
|