Orion9

|
Posted: Fri Jan 16, 2026 20:46 Post subject: |
|
|
FallenAngel
Я там фигню сморозил. Вместо:
| Code: | txt &= "Файл от " & Date('', gWttrFile) & ' ' & Time('', gWttrFile) & " "
txt &= gWttrFile & auCRLF
txt &= "Файл от " & Date('', file) & ' ' & Time('', file) & " "
txt &= file & auCRLF |
Должно быть:
| Code: | txt &= "Временные файлы:" & auCRLF
txt &= "Файл от " & Date('', FileGetTime(gWttrFile)) & ' ' & Time('', FileGetTime(gWttrFile)) & " "
txt &= gWttrFile & auCRLF
txt &= "Файл от " & Date('', FileGetTime(file)) & ' ' & Time('', FileGetTime(file)) & " "
txt &= file & auCRLF |
На автомате просто делал и не проверил толком, но теперь корректно показывает дату изменения файлов по Alt, так что сразу видно, когда было последнее обновление.
Также добавил сведения об обновлении в саму подсказку. По идее надо было сразу это сделать, но не думал, что проблемы с сервером окажутся настолько серьезными, да и времени не было.
Сейчас лучше видно, что происходит в фоне. Информация в заголовке обновляется хоть и медленно, но стабильно (все-таки файл очень маленький приходит от сервера). А вот с Wttr.html могут быть проблемы. Мало того, что он скачивается медленно, так еще и не докачивается иногда, хотя у него размер всего 25-30 Кб. В общем, добавил некоторых проверок. Сейчас недокаченный файл будет отображаться в подсказке примерно так:
 Hidden text | Code: | Файл поврежден
<pre>
Weather report: 47.37,8.55
\ / Sunny
.-. 4 °C
― ( ) ― ↓ 4 km/h
`-’ 10 km
/ \ 0.0 mm
┌─────────────┐
┌──────────────────────────────┬───────────────────────┤ Fri 16 Jan ├───────────────────────┬──────────────────────────────┐
│ Morning │ Noon └──────┬──────┘ Evening │ Night │
├──────────────────────────────┼──────────────────────────────┼──────────────────────────────┼──────────────────────────────┤
│ \ / Partly Cloudy │ \ / Sunny │ Freezing fog │ Mist │
│ _ /"".-. -2 °C │ .-. +4(3) °C │ _ - _ - _ - -2(-3) °C │ _ - _ - _ - -3(-4) °C │
│ \_( ). ← 2-4 km/h │ ― ( ) ― ↓ 4-5 km/h │ _ - _ - _ ← 4-8 km/h │ _ - _ - _ ↖ 4-8 km/h │
│ /(___(__) 10 km │ `-’ 10 km │ _ - _ - _ - 0 km │ _ - _ - _ - 2 km │
│ 0.0 mm | 0% │ / \ 0.0 mm | 0% │ 0.0 mm | 0% │ 0.0 mm | 0% │
└──────────────────────────────┴──────────────────────────────┴──────────────────────────────┴────────────────�[/ |
Это лучше, чем сообщение, что файл не содержит данных.
Еще изменил имена у некоторых функций для лучшей унификации имён в модуле.
Что касается Листера, если задача стоит добиться, чтобы его окно при открытии имело тот же размер и положение, что и окно тотала, то можно привязать функцию к сообщению об изменении позиции окна ТС, в модуле это выглядит так:
| Code: | Func InfoHeaderSet()
WinSetText(gShowTitle ? gInfoHeader : gTitle)
SyncListerPosition()
EndFunc
Func SyncListerPosition()
Static c = 0
If IniRead("~/R", COMMANDER_INI, "Lister", "Maximized", 0) = 0 Then
WinGetPos("x", "y", "w", "h")
IniWrite("~/R", COMMANDER_INI, "Lister", "x", x)
IniWrite("~/R", COMMANDER_INI, "Lister", "y", y)
IniWrite("~/R", COMMANDER_INI, "Lister", "dx", w)
IniWrite("~/R", COMMANDER_INI, "Lister", "dy", h)
c += 4
#ShowHint("Запись ключей: " & c, SYSINFO_DESKTOPWIDTH/2-50, SYSINFO_DESKTOPHEIGHT/2, 1000, 1)
EndIf
EndFunc |
Раскомментируйте ShowHint, чтобы увидеть количество записей в ini-файл, если интересно. Если фича не нужна, просто закомментируйте или уберите SyncListerPosition() из функции InfoHeaderSet().
Теоретически функции SyncListerPosition можно присвоить код через RegisterCommand, например 60050, а далее сделать em_команду с указанным кодом (об этом было 2-3 страницы назад). Полученную em_команду можно использовать в свзяке с командами cm_List*, чтобы перед запуском листера записывались параметры его окна в файл конфигурации.
Shift+клик, как вы хотите, самый сложный вариант. Нужно перехватывать клик, смотреть под каким окном находится указатель мыши, проверять клиентская ли это часть окна или не клиентская, и только потом запускать действие. Тут без Loopback, наверное, не обойтись.
Последний модуль:
 Hidden text | Code: | Sleep(200)
# наведение на заголовок
ControlSetHint /F /D:350 /H:2 0 "InfoHeaderHint"
# правый клик
ControlSetMouseAction /R /H:2 0 "InfoHeaderMenu"
# Shift + клик по заголовку
ControlSetMouseAction /L /K:S /H:2 0 "InfoHeaderSwitch"
Global gTitle = WinGetText(), gInfoHeader = gTitle, gShowTitle = 1, gTitleThread = 0, gTitleRound = 2
Global gWttr = 1, gWttrUrl, gWttrHint, gWttrName, gWttrInterval = 3600
Global gWttrSec = 0, gWttrData, gWttrTip = "", gWttrFile = TEMP & "\wttr.txt", gWttrDataUpdate = 0
Global gWttrIni = COMMANDER_PATH & "\Ini\Header.ini"
Global gWttrIniApp = GetKnownFolderPath("LocalAppData") & "\GHISLER\Wttr.ini"
# запуск
InfoHeaderLaunch()
# WM_WINDOWPOSCHANGING
# реагирование заголовка на изменение позиции окна
SetMessageAction 70 "InfoHeaderSet"
Func InfoHeaderSwitch()
# переключение переменной
gShowTitle = Not gShowTitle
# запись нового значения в Header.ini
IniWrite %gWttrIni% "Title" "ShowTitle" %"gShowTitle"
Sleep(100)
InfoHeaderLaunch()
EndFunc
Func InfoHeaderSet()
WinSetText(gShowTitle ? gInfoHeader : gTitle)
SyncListerPosition()
EndFunc
Func SyncListerPosition()
Static c = 0
If IniRead("~/R", COMMANDER_INI, "Lister", "Maximized", 0) = 0 Then
WinGetPos("x", "y", "w", "h")
IniWrite("~/R", COMMANDER_INI, "Lister", "x", x)
IniWrite("~/R", COMMANDER_INI, "Lister", "y", y)
IniWrite("~/R", COMMANDER_INI, "Lister", "dx", w)
IniWrite("~/R", COMMANDER_INI, "Lister", "dy", h)
c += 4
#ShowHint("Запись ключей: " & c, SYSINFO_DESKTOPWIDTH/2-50, SYSINFO_DESKTOPHEIGHT/2, 1000, 1)
EndIf
EndFunc
Func InfoHeaderLaunch()
# чтение ключа
IniRead gShowTitle %gWttrIni% "Title" "ShowTitle" 1
# запуск заголовка, если он еще не запущен
If gShowTitle And Not gTitleThread Then
gInfoHeader = gTitle & ' ' & "Booting..."
WinSetText(gInfoHeader)
# подготовка конфигурации
InfoHeaderReadIni()
Sleep(200)
RunThread InfoHeader
EndIf
EndFunc
Func InfoHeaderReadIni()
Local sWttrIni = gWttrIni, sUrl
# чтение из Header.ini
IniRead gWttr %gWttrIni% "Title" "Wttr" 1
IniRead sUrl %sWttrIni% "Wttr" "Url" ""
# чтение из AppData\Wttr.ini
If FileExist(gWttrIniApp) Then
sWttrIni = gWttrIniApp
EndIf
IniRead gWttrUrl %sWttrIni% "Wttr" "Url" ""
IniRead gWttrHint %sWttrIni% "Wttr" "Hint" ""
IniRead gWttrName %sWttrIni% "Wttr" "Name" ""
IniRead gWttrInterval %sWttrIni% "Wttr" "Interval" 3600
# нет данных в AppData
# откат к значению из Header.ini
If gWttrUrl = "" Then gWttrUrl = sUrl
# проверка корректности значения интервала
If Not IsInt(gWttrInterval) Then gWttrInterval = 0
if gWttrInterval < 900 Then gWttrInterval = 900
# по умолчанию интервал считается законченным
gWttrSec = gWttrInterval
# проверка существования локального файла
If FileExist(gWttrFile) Then
# количество секунд с последнего обновления
gWttrSec = Round((Now() - FileGetTime(gWttrFile)) / 10000000)
# прошло меньше секунд, чем отведенный интервал
If gWttrSec < gWttrInterval Then gWttrData = StrTrim(FileRead(gWttrFile))
If gWttrName <> "" Then gWttrData = gWttrName & " " & gWttrData
EndIf
EndFunc
Func InfoHeader
Local nRecvSpeed, nSendSpeed, T1, lst = List(" | "," / ","—"," \ ")
Static c = 0
# поток запущен
gTitleThread = 1
# выполнять пока gShowTitle = true
While gShowTitle
T1 = GetUptime()
# погода включена и требуется обновление
If gWttr And gWttrSec >= gWttrInterval Then
# сброс счетчика
gWttrSec = 0
# запуск обновления в отдельном потоке
RunThread "GetWttrData"
EndIf
GetNetSpeed(nRecvSpeed, nSendSpeed)
# идет процесс обновления
If gWttrDataUpdate Then
c += 1
If c > lst.Count Then c = 1
#gWttrData = Weather updating: " & lst[c-1]
gWttrData = "Weather updating: " & gWttrSec & ' sec.'
EndIf
gInfoHeader = gTitle & ' ' & (gWttr ? gWttrData & ' ' : '') & Date("d MMMM, ddd") & '. CPU: ' & StrFormat("%02d", GetCPUUsage()) & '% RAM: ' & GetMemStats() & '% NET: ↓ ' & Round(nRecvSpeed / 1000, gTitleRound) & ' ↑ ' & Round(nSendSpeed / 1000, gTitleRound) & ' mb/s'
WinSetText(gInfoHeader)
# разбитие секунды на более мелкие интервалы
# для лучшего отклика при изменении переменной
While GetUptime() < T1 + 1000
If Not gShowTitle Then Break
Sleep(50)
Wend
# увеличение счетчика до следующего обновления погоды
gWttrSec += 1
Wend
Free(lst)
# поток остановлен
gTitleThread = 0
# обновление заголовка
InfoHeaderSet()
EndFunc
Func GetWttrData()
Local msg, sData, sTip
# флаг операции
gWttrDataUpdate = true
gWttrTip = "Соединение..."
# загрузка файла в тихом режиме
Local code = WinInetDownloadFile(gWttrUrl, gWttrFile, 1)
# снятие флага операции для заголовка
gWttrDataUpdate = false
If code = -1 Then
msg = "WinInet Error: " & code
ElseIf code > 0 Then
msg = "WinInet Error: " & code
gWttrTip = msg & auCRLF & GetWinInetError(code)
EndIf
If code = 0 Then
gWttrTip = "Обновлено в " & Time("", Now())
msg = FileRead(gWttrFile)
If ERROR = 1 Then msg = "FileRead Error: "
EndIf
sData = StrTrim(msg)
gWttrData = sData
# добавление имени местоположения если указано
If code = 0 And gWttrName <> "" Then gWttrData = gWttrName & " " & sData
If code = 0 Then
gWttrSec = 0
Else
# повтор через 30 секунд
gWttrSec = gWttrInterval - 30
EndIf
sTip = gWttrTip
# загрузка данных для подсказки в тихом режиме
gWttrTip = sTip & auCRLF & "Подсказка: Соединение..."
code = WinInetDownloadFile(gWttrHint, TEMP & "\wttr.html", 1)
If code <> 0 Then
msg = "WinInet Error: " & code
gWttrTip = sTip & auCRLF & "Подсказка: " & msg & auCRLF
If code = -1 Then
gWttrTip &= "Download failed or ended with an error."
Else
gWttrTip &= GetWinInetError(code)
EndIf
Else
gWttrTip = sTip & auCRLF & "Подсказка: Обновлено в " & Time("", Now())
EndIf
EndFunc
Func InfoHeaderHint()
Local txt, file = TEMP & "\wttr.html"
If Not IsPressed (0x11) Then
If Not gShowTitle Then Return "Заголовок выключен"
txt &= "Работает" & auCRLF
txt &= "Погода " & (gWttr? "включена" : "отключена") & auCRLF
If gWttr Then
txt &= "Интервал: " & gWttrInterval & " сек." & auCRLF
txt &= "Обновление через: " & gWttrInterval - gWttrSec & " сек." & auCRLF
If gWttrTip <> "" Then txt &= "Статус: " & gWttrTip & auCRLF
EndIf
If IsPressed (0x12) Then
txt &= "Файлы конфигурации:" & auCRLF
txt &= gWttrIni & auCRLF
txt &= gWttrIniApp & auCRLF
txt &= "Временные файлы:" & auCRLF
txt &= "Файл от " & Date('', FileGetTime(gWttrFile)) & ' ' & Time('', FileGetTime(gWttrFile)) & " "
txt &= gWttrFile & auCRLF
txt &= "Файл от " & Date('', FileGetTime(file)) & ' ' & Time('', FileGetTime(file)) & " "
txt &= file & auCRLF
EndIf
Return StrTrim(txt)
Endif
txt = FileRead(file)
If ERROR = 1 Then Return "Ошибка чтения " & file
If txt = "" Then Return "Пустой файл " & file
Local nPrePos = StrPos(txt, "<pre>")
If nPrePos = 0 Then Return "Файл не содержит данных " & file
# стиль подсказки
SetHintParam("csh", "Font", 10, "Consolas")
SetHintParam("csh", "BackColor", 0x001C1C1C)
SetHintParam("csh", "Text", 0xF9F9F9)
# извлечение текста из html
txt = StrReplace(txt, '"', '"')
Static lst = List()
lst.Count = 0
lst.Text = StrTrim(RegExpGet(txt, '<pre>(.*?)</pre>', "$1"))
For i = 0 To lst.Count - 1
If StrLen(lst[i]) > 125 Then lst[i] = StrLeft(lst[i], 122) & ".."
Next
# вернуть предыдущий стиль через 1 сек.
RunThread InfoHeaderHintReload
If lst.Count = 0 Then
Return "Файл поврежден " & auCRLF & StrMid(txt, nPrePos)
EndIf
Return lst.Text
EndFunc
Func InfoHeaderHintReload()
Sleep(1000)
SetHintParam("sh", "Reload")
SetHintParam("csh", "Reload")
EndFunc
Func InfoHeaderMenu()
ShowPopupMenu /D /F "InfoHeaderCreateMenu"
EndFunc
Func InfoHeaderCreateMenu()
Local txt
txt &= 'MENUITEM "Включить", em_aucmd "%COMMANDER_EXE%,37" InfoHeaderStart' & auCRLF
txt &= 'MENUITEM "Выключить", em_aucmd "%COMMANDER_EXE%,36" InfoHeaderStop' & auCRLF
txt &= 'MENUITEM "Обновить погоду", em_aucmd "shell32.dll,13" InfoHeaderUpdate' & auCRLF
txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'POPUP "Заголовок"' & auCRLF
txt &= 'MENUITEM "Отображать погоду", em_aucmd -1 InfoHeaderWttr 1' & auCRLF
txt &= 'MENUITEM "Не отображать погоду", em_aucmd -1 InfoHeaderWttr 0' & auCRLF
txt &= 'END_POPUP' & auCRLF
txt &= 'MENUITEM "Настройки...", em_aucmd "imageres.dll,62" InfoHeaderEditIni' & auCRLF
txt &= 'MENUITEM "Пользователь...", em_aucmd -1 InfoHeaderEditIniApp' & auCRLF
txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'POPUP "Перейти"' & auCRLF
txt &= 'MENUITEM "Перейти к Wttr.ini", em_aucmd "imageres.dll,62" InfoHeaderGotoIniApp' & auCRLF
txt &= 'MENUITEM "Перейти к Wttr.txt", em_aucmd -1 InfoHeaderGotoTemp "Wttr.txt"' & auCRLF
txt &= 'MENUITEM "Перейти к Wttr.html", em_aucmd -1 InfoHeaderGotoTemp "Wttr.html"' & auCRLF
txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'MENUITEM "Перейти к Header.ini", em_aucmd "imageres.dll,62" InfoHeaderGotoIni' & auCRLF
txt &= 'END_POPUP' & auCRLF
txt &= 'MENUITEM "Даты и время", em_aucmd "timedate.cpl" ShellExec rundll32.exe "shell32.dll,Control_RunDLL timedate.cpl"' & auCRLF
Return txt
EndFunc
Func InfoHeaderStart()
# запись значения в Header.ini
IniWrite %gWttrIni% "Title" "ShowTitle" 1
Sleep(100)
InfoHeaderLaunch()
EndFunc
Func InfoHeaderStop()
IniWrite %gWttrIni% "Title" "ShowTitle" 0
Sleep(100)
InfoHeaderLaunch()
EndFunc
Func InfoHeaderUpdate()
If Not gWttr Then
ShowHint("Погода выключена")
Return
EndIf
# обновление через 1 сек.
gWttrSec = gWttrInterval - 1
EndFunc
Func InfoHeaderWttr(Value)
IniWrite %gWttrIni% "Title" "Wttr" %"Value"
gWttr = Value
EndFunc
Func InfoHeaderEditIni()
If FileExist(gWttrIni) Then
ShellExec(gWttrIni)
Else
MsgBox("Файл не существует " & gWttrIni, "Autorun", 16)
EndIf
EndFunc
Func InfoHeaderGotoIni()
CommandExec("~/CD:S", gWttrIni)
EndFunc
Func InfoHeaderEditIniApp()
If FileExist(gWttrIniApp) Then
ShellExec(gWttrIniApp)
Else
MsgBox("Файл пользователя не существует " & gWttrIniApp & auCRLF & auCRLF & _
"Создать новый?", "Autorun", 3+0+32)
If EXTENDED <> 6 Then Return
Local txt = "[Wttr]" & auCRLF & _
"Name=Погода:" & auCRLF & _
"Interval=1800" & auCRLF & _
"Url=https://wttr.in/47.37,8.55?format=%t" & auCRLF & _
"Hint=https://wttr.in/47.37,8.55?T"
FileWrite(gWttrIniApp, txt, "ANSI")
Sleep(100)
If FileExist(gWttrIniApp) Then ShellExec(gWttrIniApp)
EndIf
EndFunc
Func InfoHeaderGotoIniApp()
CommandExec("~/CD:S", gWttrIniApp)
EndFunc
Func InfoHeaderGotoTemp(Filename)
Local sFile = TEMP & "\" & Filename
If FileExist(sFile) Then
CommandExec("~/CD:S", sFile)
Else
MsgBox("Файл не существует " & sFile, "Autorun", 16)
EndIf
EndFunc
Func GetNetSpeed(ByRef nRecvSpeed, ByRef nSendSpeed)
Static nIntfIdx = GetNetInterface()
If nIntfIdx = -1 Then Return
Static nPrevRecv = GetNetInterfaceInfo(nIntfIdx, 'Recv')
Static nPrevSend = GetNetInterfaceInfo(nIntfIdx, 'Sent')
Static nPrevTime = GetUptime()
Local nRecv = GetNetInterfaceInfo(nIntfIdx, 'Recv')
Local nSend = GetNetInterfaceInfo(nIntfIdx, 'Sent')
Local nTime = GetUptime()
Local nTimeDiff = nTime - nPrevTime
nRecvSpeed = Round(Abs(nRecv - nPrevRecv) / nTimeDiff)
nSendSpeed = Round(Abs(nSend - nPrevSend) / nTimeDiff)
nPrevRecv = nRecv
nPrevSend = nSend
nPrevTime = nTime
EndFunc |
P.s.
Обещал пересмотреть другие модули после праздников, но пока не получается. Теперь только в феврале, наверное, попробую еще раз взяться. |
|