Total Commander Forum Index Total Commander
Форум поддержки пользователей Total Commander
Сайты: Все о Total Commander | Totalcmd.net | Ghisler.com | RU.TCKB
 
 RulesRules   SearchSearch   FAQFAQ   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Single Post  Topic: Autorun 
Author Message
Orion9



PostPosted: Wed Feb 11, 2026 20:35    Post subject: Reply with quote

FallenAngel
Если вкратце.

Функция NotifyIcon принимает следующие параметры:
Code:
  sAction - тип действия ("add", "set", "delete")
      uID - внутренний уникальный идентификатор иконки
nCallback - код зарегистрированного сообщения для функции обратного вызова
    hIcon - дескриптор иконки (только для "add")
     sTip - текст подсказки в трее
    sText - текст уведомления (только для "add" и "set")
   sTitle - текст заголовка уведомления
    nType - флаги NIIF_* (изменение вида и поведения окна уведомлений)
   
Func NotifyIcon(sAction, uID, nCallback = 0, hIcon = 0, sTip = "", sText = "", sTitle = "", nType = 0)

Чтобы добавить иконку в трей, нужен режим "add" и еще 3 параметра. Четвертый параметр sTip тоже желателен, т.к. он отвечает за текст подсказки в трее, но его в принципе можно не указывать.

Все сводится к одному вызову, например:
Code:
NotifyIcon("add", 1005, gCode, hIco, "Иконка Autorun")

Первый и последний параметры нам уже понятны. Осталось разобраться за что именно отвечают uID = 1005, nCallback = gCode, hIcon = hIco.

uID - это просто внутренний код иконки, взятый буквально от балды. Приложение может держать в трее несколько иконок, оболочке Windows и нам самим нужно как-то их отличать. Код может быть любым числом. Здесь он 1005.

nCallback - это код, который использует оболочка, когда она посылает сообщения о событиях в трее назад приложению. И снова этот код мы должны сами придумать, но только в определенном диапазоне. Чтобы не забивать этим голову, мы просим систему выделить нам уникальный незанятый код. Каким именно будет этот код, нам не важно, мы просто запоминаем его в переменной gCode:
Code:
Global gCode = DllCall("RegisterWindowMessageW", "wstr", "TrayNotify1005", "uint")

Теперь получив нужный код, мы должны внутри приложения привязать его к реальной функции, которая будет запускаться каждый раз, когда оболочка шлет нам сообщения с этим кодом.
Code:
SetMessageAction /P %"gCode" "TestrayAction"

Внутри функции мы должны обрабатывать те сообщения, события которых нам интересны. Это прежде всего события левого и правого клика, но можно обрабатывать и другие события.
Code:
Func TestrayAction(hWnd, uMsg, wParam, lParam)
    If lParam = WM_LBUTTONDOWN Then
       MsgBox("Клик по иконке")
    ElseIf lParam = WM_RBUTTONDOWN Then
       ShowPopupMenu("~/D", COMMANDER_PATH & "\Bars\Vertical.bar")
    EndIf
EndFunc

Левый клик по иконке выводит MsgBox, правый отображает меню из Vertical.bar. Можно использать и другие команды, em_команды, mnu и bar файлы — здесь есть, где фантазии развернуться.

Остается только иконка. Дескриптор иконки hIcon можно получать по-разному. Самый простой способ — послать сообщение окну ТС с кодом 0x7f, тогда тотал вернет дескриптор своей иконки:
Code:
hIcon = SendMessage(AUTORUN_TCHANDLE, 0x7f, 2, 0)

Можно также получить дескриптор функцией ExtractIcon, вызывать которую нужно через DllCall
Code:
sIco = GetKnownFolderPath("System") & "\shell32.dll"
hIco = DllCall("shell32\ExtractIconW", _
               "ptr", AUTORUN_TCHANDLE, _
               "wstr", sIco, "uint", 15, "ptr")

В вызовах DllCall нет ничего страшного. По сути, это просто запрос к Windows, чтобы она выполнила за нас определенные действия. В данном случае таким действием является извлечение иконки с индексом 15 из shell32.dll и передача нам дескриптора.

Нам, в свою очередь, остается передать этот дескриптор функции NotifyIcon вместе с другими параметрами. Итого, полученный код будет выглядеть так:
Code:
# регистрация кода для функции обратного вызова
Global gCode = DllCall("RegisterWindowMessageW", "wstr", "TrayNotify1005", "uint")
# привязка функции обратного вызова к полученному коду
SetMessageAction /P %"gCode" "TestrayAction"

# функция обратного вызова
Func TestrayAction(hWnd, uMsg, wParam, lParam)
    If lParam = WM_LBUTTONDOWN Then
       #MsgBox("Клик по иконке")
       NotifyIcon("set", 1005, gCode, hIco, "", "Test message", "", NIIF_WARNING)
    ElseIf lParam = WM_RBUTTONDOWN Then
       ShowPopupMenu("~/D", COMMANDER_PATH & "\Bars\Vertical.bar")
    EndIf
EndFunc

# путь к иконке
sIco = GetKnownFolderPath("System") & "\shell32.dll"
# получение дескриптора иконки с индексом 15
hIco = DllCall("shell32\ExtractIconW", _
               "ptr", AUTORUN_TCHANDLE, _
               "wstr", sIco, "uint", 15, "ptr")
               
# установка в трей с идентификатором 1005   
NotifyIcon("add", 1005, gCode, hIco, "Иконка Autorun")

Вот так. Несколько строк и дело в шляпе иконка в трее Smile

Однако, чтобы этот фрагмент кода заработал самостоятельно, без привязки к модулю Icons.aucfg, необходимо перенести из него все константы и, собственно, саму функцию NotifyIcon:
 Hidden text

Работает у вас?

В этот код я добавил обработку CTRL:
Code:
If IsPressed(0x11) Then
   NotifyIcon("set", 1005, gCode, hIco, "", "Test message", "", NIIF_WARNING)
   Return
EndIf

Теперь клик по иконке с Ctrl отображает системное уведомление. Функция NotifyIcon может не только добавлять или менять иконку в трее, но также показывать системные уведомления. Единственное условие — иконка в трее должна существовать. Именно поэтому, чтобы была возможность вызвать системные уведомления без привязки к конкретной иконке, реализована функция NotifyInfoMessage.
Code:
#{
     Вызов системных уведомлений:
     
           InfoText - текст уведомления (255 символов)
          InfoTitle - текст заголовка уведомления (63 символов)
           InfoType - флаги NIIF_* меняющие вид и поведение окна уведомлений
           
     Функция использует идентификатор "1010"
#}
Func NotifyInfoMessage(InfoText, InfoTitle = "Autorun", InfoType = 0)

Функция заранее резервирует идентификатор иконки и не требует указания дескриптора — дескриптор берется из файла, указанного в gNotifyIcon. Если файл не существует, будет использоваться иконка тотала. Для обратного вызова также получается код и сохраняется в переменную Code1010. Функция обратного вызова определена как TrayNotifyInfo. Данная функция обрабатывает левый клик по иконке в трее, где отображается меню лога уведомлений. Это еще одна особенность NotifyInfoMessage — она сохраняет лог уведомлений в текущей сессии. Т.о. даже если уведомление было пропущено (закрыто по таймауту) в трее можно будет увидеть его след:
 Hidden text

Это только сами функции и их вызов. В реальности код разрастается из-за различных условий и проверок. Например, вряд ли есть необходимость всегда держать иконку в трее, а значит надо как-то учитывать это при запуске — считывать ключ из ини-файла, смотреть его значение, загружать или не загружать иконку в зависимости от этого значения и т.д. Именно поэтому модуль получился больше, чем эти две функции, ведь это мой рабочий модуль, т.е. модуль, который я использую у себя в ТС. Кое-что там лишнее и переплетается с другими модулями, поэтому сам модуль не универсальный, универсальны только эти две функции.

Как-то так Smile
View user's profile Send private message


Powered by phpBB © 2001, 2005 phpBB Group