1

Тема: AHK: Загрузка разных иконок для программы

Нужно чтобы при нажатии шортката в области систим трей появлялась иконка1, а при другом шорткате она менялась на иконку 2, а при третьем вообще изчезала.
Пока создал 2 скрипта:
1)

#persistent
Menu, Tray, Icon, favicon.ico
return

2)

#persistent
Menu, Tray, Icon, favicon1.ico
return

И код который их соответственно запускает и закрывает.

DetectHiddenWindows, On 
WinClose, C:\Users\Malcev\Desktop\favicon.ahk
RunWait, C:\Users\Malcev\Desktop\favicon1.ahk

Может как-то можно упростить?
А то получается куча файлов для такого несложного действия.
Спасибо!

2

Re: AHK: Загрузка разных иконок для программы

В одном скрипте Menu, Tray, Icon с разными файлами по горячим клавишам.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

3

Re: AHK: Загрузка разных иконок для программы

Точно!
А возможно что бы скрипт не себе менял иконку, а добавлял еще одну?

4

Re: AHK: Загрузка разных иконок для программы

Нет, так нельзя.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

5

Re: AHK: Загрузка разных иконок для программы

А можно главным скриптом послать комманду в исполняемые скрипты о смене иконки?

6

Re: AHK: Загрузка разных иконок для программы

А вот это можно .

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

7

Re: AHK: Загрузка разных иконок для программы

Malcev пишет:

Точно!
А возможно что бы скрипт не себе менял иконку, а добавлял еще одну?

teadrinker пишет:

Нет, так нельзя.

Решение от teadrinker: AHK: Двойная иконка в трее.

8

Re: AHK: Загрузка разных иконок для программы

Если нельзя, но очень хочется, то можно.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

9

Re: AHK: Загрузка разных иконок для программы

А как в этом коде загрузить иконки не из dll или exe, а просто указать путь к ico?

if hIcon := ExtractIcon(A_AhkPath, 2, 16)
   hAssociatedGui1 := AddTrayIcon(hIcon)  ; первая дополнительная иконка

if hIcon := ExtractIcon("Shell32.dll", 44, 16)
   hAssociatedGui2 := AddTrayIcon(hIcon)  ; вторая дополнительная иконка
OnExit, Exit

; если нужно меню для иконок
OnMessage(0x404, "AHK_NOTIFYICON")
Menu, MyTrayMenu, Add, Завершение работы, CloseApp
Return

CloseApp:
   ExitApp

Exit:
   RemoveTrayIcon(hAssociatedGui1), RemoveTrayIcon(hAssociatedGui2)
   ExitApp

ExtractIcon(sFile, IconNumber, IconSize)
{
   coding := A_IsUnicode ? "W" : "A"

   SplitPath, sFile,,, ext
   (ext = "ico" && IconNumber := 0)

   if PrivateExtractIcons := DllCall("GetProcAddress"
                              , Ptr, DllCall("LoadLibrary", Str, "User32", Ptr)
                              , AStr, "PrivateExtractIcons" . coding, Ptr)
   {
      Result := DllCall(PrivateExtractIcons, Str, sFile, Int, IconNumber-1
                  , Int, IconSize, Int, IconSize, PtrP, hIcon, UIntP, 0, UInt, 1, UInt, 0)
      if !Result
         MsgBox, 16,, % "Не удалось извлечь иконку.`nОшибка " A_LastError
      else if (Result = 0xFFFFFFFF || Result = -1)
         MsgBox, 16,, Файл "%sFile%" не найден!
   }

   else
   {
      if !DllCall("Shell32\ExtractIconEx" . coding, Str, sFile, Int, IconNumber-1, PtrP, hIconLarge, PtrP, hIconSmall, UInt, 1)
      {
         MsgBox, 16,, % "Не удалось извлечь иконку.`nОшибка " A_LastError
         return
      }
      SysGet, SmallIconSize, % SM_CXSMICON := 49
      if (IconSize <= SmallIconSize)
         DllCall("DestroyIcon", Ptr, hIconLarge), hIcon := hIconSmall
      else
         DllCall("DestroyIcon", Ptr, hIconSmall), hIcon := hIconLarge

      hIcon := DllCall("CopyImage", Ptr, hIcon, UInt, IMAGE_ICON := 1
         , Int, IconSize, Int, IconSize, UInt, LR_COPYRETURNORG := 0x4|LR_COPYDELETEORG := 0x8, Ptr)
   }

   Return hIcon
}

AddTrayIcon(hIcon)
{
   static NIF_MESSAGE := 1, NIF_ICON := 2, GuiNumber := 99
   
   VarSetCapacity(NOTIFYICONDATA, size := A_PtrSize = 8 ? 848 : A_IsUnicode? 828 : 444, 0)
   NumPut(size, NOTIFYICONDATA, "UInt")
   Gui, % GuiNumber-- ": +hwndhGui"
   NumPut(hGui, NOTIFYICONDATA, A_PtrSize)
   NumPut(uID := 0x404, NOTIFYICONDATA, 2*A_PtrSize, "UInt")
   NumPut(NIF_MESSAGE|NIF_ICON, NOTIFYICONDATA, 2*A_PtrSize + 4, "UInt")
   NumPut(nMsg := 0x404, NOTIFYICONDATA, 2*A_PtrSize + 8, "UInt")
   NumPut(hIcon, NOTIFYICONDATA, 3*A_PtrSize+8)
   
   DllCall("shell32\Shell_NotifyIcon", UInt, NIM_ADD := 0, Ptr, &NOTIFYICONDATA)
   DllCall("DestroyIcon", Ptr, hIcon)
   Return hGui
}

RemoveTrayIcon(hWnd, uID=0x404)
{
   VarSetCapacity(NOTIFYICONDATA, size := A_PtrSize = 8 ? 848 : A_IsUnicode? 828 : 444, 0)
   NumPut(size, NOTIFYICONDATA, "UInt")
   NumPut(hWnd, NOTIFYICONDATA, A_PtrSize)
   NumPut(uID, NOTIFYICONDATA, 2*A_PtrSize, "UInt")
   DllCall("shell32\Shell_NotifyIcon", "UInt", NIM_DELETE := 2, Ptr, &NOTIFYICONDATA)
   Return
}

AHK_NOTIFYICON(wp, lp, msg, hwnd)   ; wp — uID, lp — Message
{
   global hAssociatedGui1, hAssociatedGui2
   static WM_RBUTTONUP := 0x205
   if (lp = WM_RBUTTONUP && (hwnd = hAssociatedGui1 || hwnd = hAssociatedGui2))
      Menu, MyTrayMenu, Show
}

10

Re: AHK: Загрузка разных иконок для программы

Так же.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

11 (изменено: Malcev, 2014-11-13 03:08:25)

Re: AHK: Загрузка разных иконок для программы

Правильно ли я понимаю, что для того, чтобы менять иконки шорткатами нужно делать так:

OnExit, Exit

1::
hIcon := ExtractIcon(A_AhkPath, 2, 16)
RemoveTrayIcon(hAssociatedGui1)
hAssociatedGui1 := AddTrayIcon(hIcon)  ; первая дополнительная иконка
return

2::
hIcon := ExtractIcon("Shell32.dll", 44, 16)
RemoveTrayIcon(hAssociatedGui1)
hAssociatedGui1 := AddTrayIcon(hIcon)  ; первая дополнительная иконка
return


CloseApp:
   ExitApp

Exit:
   RemoveTrayIcon(hAssociatedGui1)
   ExitApp

ExtractIcon(sFile, IconNumber, IconSize)
{
   coding := A_IsUnicode ? "W" : "A"

   SplitPath, sFile,,, ext
   (ext = "ico" && IconNumber := 0)

   if PrivateExtractIcons := DllCall("GetProcAddress"
                              , Ptr, DllCall("LoadLibrary", Str, "User32", Ptr)
                              , AStr, "PrivateExtractIcons" . coding, Ptr)
   {
      Result := DllCall(PrivateExtractIcons, Str, sFile, Int, IconNumber-1
                  , Int, IconSize, Int, IconSize, PtrP, hIcon, UIntP, 0, UInt, 1, UInt, 0)
      if !Result
         MsgBox, 16,, % "Не удалось извлечь иконку.`nОшибка " A_LastError
      else if (Result = 0xFFFFFFFF || Result = -1)
         MsgBox, 16,, Файл "%sFile%" не найден!
   }

   else
   {
      if !DllCall("Shell32\ExtractIconEx" . coding, Str, sFile, Int, IconNumber-1, PtrP, hIconLarge, PtrP, hIconSmall, UInt, 1)
      {
         MsgBox, 16,, % "Не удалось извлечь иконку.`nОшибка " A_LastError
         return
      }
      SysGet, SmallIconSize, % SM_CXSMICON := 49
      if (IconSize <= SmallIconSize)
         DllCall("DestroyIcon", Ptr, hIconLarge), hIcon := hIconSmall
      else
         DllCall("DestroyIcon", Ptr, hIconSmall), hIcon := hIconLarge

      hIcon := DllCall("CopyImage", Ptr, hIcon, UInt, IMAGE_ICON := 1
         , Int, IconSize, Int, IconSize, UInt, LR_COPYRETURNORG := 0x4|LR_COPYDELETEORG := 0x8, Ptr)
   }

   Return hIcon
}

AddTrayIcon(hIcon)
{
   static NIF_MESSAGE := 1, NIF_ICON := 2, GuiNumber := 99
   
   VarSetCapacity(NOTIFYICONDATA, size := A_PtrSize = 8 ? 848 : A_IsUnicode? 828 : 444, 0)
   NumPut(size, NOTIFYICONDATA, "UInt")
   Gui, % GuiNumber-- ": +hwndhGui"
   NumPut(hGui, NOTIFYICONDATA, A_PtrSize)
   NumPut(uID := 0x404, NOTIFYICONDATA, 2*A_PtrSize, "UInt")
   NumPut(NIF_MESSAGE|NIF_ICON, NOTIFYICONDATA, 2*A_PtrSize + 4, "UInt")
   NumPut(nMsg := 0x404, NOTIFYICONDATA, 2*A_PtrSize + 8, "UInt")
   NumPut(hIcon, NOTIFYICONDATA, 3*A_PtrSize+8)
   
   DllCall("shell32\Shell_NotifyIcon", UInt, NIM_ADD := 0, Ptr, &NOTIFYICONDATA)
   DllCall("DestroyIcon", Ptr, hIcon)
   Return hGui
}

RemoveTrayIcon(hWnd, uID=0x404)
{
   VarSetCapacity(NOTIFYICONDATA, size := A_PtrSize = 8 ? 848 : A_IsUnicode? 828 : 444, 0)
   NumPut(size, NOTIFYICONDATA, "UInt")
   NumPut(hWnd, NOTIFYICONDATA, A_PtrSize)
   NumPut(uID, NOTIFYICONDATA, 2*A_PtrSize, "UInt")
   DllCall("shell32\Shell_NotifyIcon", "UInt", NIM_DELETE := 2, Ptr, &NOTIFYICONDATA)
   Return
}

12

Re: AHK: Загрузка разных иконок для программы

Нет, не так, а что именно ты хочешь сделать?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

13

Re: AHK: Загрузка разных иконок для программы

Я хочу чтобы при нажатии "1" появлялась в трее первая иконка, а при нажатии "2" она менялась на вторую.

14

Re: AHK: Загрузка разных иконок для программы

В смысле, «первая иконка» — это в дополнение к уже имеющейся иконке скрипта, или как?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

15

Re: AHK: Загрузка разных иконок для программы

Да. Изначально скрипт загружает только свою иконку.
Потом при нажатии 1, добавляет еще одну.
При нажатии 2 -  меняет добавленную на вторую.

16

Re: AHK: Загрузка разных иконок для программы

Тогда так:

Menu, Tray, Icon, % A_AhkPath, 2
OnExit, RemoveIcon
Return

1:: (!hIcon1 && (hIcon1 := ExtractIcon("imageres.dll", 77, 16))
    && hAssociatedGui := AddTrayIcon(hIcon1))

2:: (!hIcon2 && (hIcon2 := ExtractIcon("imageres.dll", 2, 16))
    && ModifyTrayIcon(hIcon2, hAssociatedGui))
    
Esc:: ExitApp

RemoveIcon:
   RemoveTrayIcon(hAssociatedGui)
   ExitApp

ExtractIcon(sFile, IconNumber, IconSize)
{
   coding := A_IsUnicode ? "W" : "A"

   SplitPath, sFile,,, ext
   (ext = "ico" && IconNumber := 0)

   if PrivateExtractIcons := DllCall("GetProcAddress"
                              , Ptr, DllCall("LoadLibrary", Str, "User32", Ptr)
                              , AStr, "PrivateExtractIcons" . coding, Ptr)
   {
      Result := DllCall(PrivateExtractIcons, Str, sFile, Int, IconNumber-1
                  , Int, IconSize, Int, IconSize, PtrP, hIcon, UIntP, 0, UInt, 1, UInt, 0)
      if !Result
         MsgBox, 16,, % "Не удалось извлечь иконку.`nОшибка " A_LastError
      else if (Result = 0xFFFFFFFF || Result = -1)
         MsgBox, 16,, Файл "%sFile%" не найден!
   }

   else
   {
      if !DllCall("Shell32\ExtractIconEx" . coding, Str, sFile, Int, IconNumber-1, PtrP, hIconLarge, PtrP, hIconSmall, UInt, 1)
      {
         MsgBox, 16,, % "Не удалось извлечь иконку.`nОшибка " A_LastError
         return
      }
      SysGet, SmallIconSize, % SM_CXSMICON := 49
      if (IconSize <= SmallIconSize)
         DllCall("DestroyIcon", Ptr, hIconLarge), hIcon := hIconSmall
      else
         DllCall("DestroyIcon", Ptr, hIconSmall), hIcon := hIconLarge

      hIcon := DllCall("CopyImage", Ptr, hIcon, UInt, IMAGE_ICON := 1
         , Int, IconSize, Int, IconSize, UInt, LR_COPYRETURNORG := 0x4|LR_COPYDELETEORG := 0x8, Ptr)
   }

   Return hIcon
}

AddTrayIcon(hIcon)
{
   static NIF_MESSAGE := 1, NIF_ICON := 2, GuiNumber := 99, NIM_ADD := 0, uID := 0x404
   
   VarSetCapacity(NOTIFYICONDATA, size := A_PtrSize = 8 ? 848 : A_IsUnicode? 828 : 444, 0)
   NumPut(size, NOTIFYICONDATA, "UInt")
   Gui, % GuiNumber-- ": +hwndhGui"
   NumPut(hGui, NOTIFYICONDATA, A_PtrSize)
   NumPut(uID, NOTIFYICONDATA, 2*A_PtrSize, "UInt")
   NumPut(NIF_MESSAGE|NIF_ICON, NOTIFYICONDATA, 2*A_PtrSize + 4, "UInt")
   NumPut(nMsg := 0x404, NOTIFYICONDATA, 2*A_PtrSize + 8, "UInt")
   NumPut(hIcon, NOTIFYICONDATA, 3*A_PtrSize+8)
   
   DllCall("shell32\Shell_NotifyIcon", UInt, NIM_ADD, Ptr, &NOTIFYICONDATA)
   DllCall("DestroyIcon", Ptr, hIcon)
   Return hGui
}

ModifyTrayIcon(hIcon, hGui, uID = 0x404)
{
   static NIM_MODIFY := 1, NIF_ICON := 2
   
   VarSetCapacity(NOTIFYICONDATA, size := A_PtrSize = 8 ? 848 : A_IsUnicode? 828 : 444, 0)
   NumPut(size, NOTIFYICONDATA, "UInt")
   NumPut(hGui, NOTIFYICONDATA, A_PtrSize)
   NumPut(uID, NOTIFYICONDATA, 2*A_PtrSize, "UInt")
   NumPut(NIF_ICON, NOTIFYICONDATA, 2*A_PtrSize + 4, "UInt")
   NumPut(hIcon, NOTIFYICONDATA, 3*A_PtrSize+8)
   
   res := DllCall("shell32\Shell_NotifyIcon", UInt, NIM_MODIFY, Ptr, &NOTIFYICONDATA)
   DllCall("DestroyIcon", Ptr, hIcon)
   Return res
}

RemoveTrayIcon(hWnd, uID=0x404)
{
   VarSetCapacity(NOTIFYICONDATA, size := A_PtrSize = 8 ? 848 : A_IsUnicode? 828 : 444, 0)
   NumPut(size, NOTIFYICONDATA, "UInt")
   NumPut(hWnd, NOTIFYICONDATA, A_PtrSize)
   NumPut(uID, NOTIFYICONDATA, 2*A_PtrSize, "UInt")
   Return DllCall("shell32\Shell_NotifyIcon", "UInt", NIM_DELETE := 2, Ptr, &NOTIFYICONDATA)
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

17 (изменено: Malcev, 2014-11-13 19:39:04)

Re: AHK: Загрузка разных иконок для программы

Если нажимаю сразу "2", то иконка не появляется.
Если нажимаю 1, потом 2 и потом опять 1, то иконка остается 2.
А к каким последствиям может привести моя модификация скрипта?

18

Re: AHK: Загрузка разных иконок для программы

Malcev пишет:

Если нажимаю сразу "2", то иконка не появляется.
Если нажимаю 1, потом 2 и потом опять 1, то иконка остается 2.

Так задача была:

Malcev пишет:

Потом при нажатии 1, добавляет еще одну.
При нажатии 2 -  меняет добавленную на вторую.

Malcev пишет:

А к каким последствиям может привести моя модификация скрипта?

Работать не будет правильно, с каждым нажатием память отъедать. Нужно понимать, как работают эти функции, там при каждом вызове AddTrayIcon() создаётся новое скрытое окно. Чтобы менялось туда-обратно, лучше так:

Menu, Tray, Icon, % A_AhkPath, 2
OnExit, RemoveIcon
Return

1::
2::
    hIcon:= ExtractIcon("imageres.dll", A_ThisHotkey = 1 ? 77 : 2, 16)
    hAssociatedGui ? ModifyTrayIcon(hIcon, hAssociatedGui) : hAssociatedGui := AddTrayIcon(hIcon)
    Return
   
Esc:: ExitApp

RemoveIcon:
   RemoveTrayIcon(hAssociatedGui)
   ExitApp

ExtractIcon(sFile, IconNumber, IconSize)
{
   coding := A_IsUnicode ? "W" : "A"

   SplitPath, sFile,,, ext
   (ext = "ico" && IconNumber := 0)

   if PrivateExtractIcons := DllCall("GetProcAddress"
                              , Ptr, DllCall("LoadLibrary", Str, "User32", Ptr)
                              , AStr, "PrivateExtractIcons" . coding, Ptr)
   {
      Result := DllCall(PrivateExtractIcons, Str, sFile, Int, IconNumber-1
                  , Int, IconSize, Int, IconSize, PtrP, hIcon, UIntP, 0, UInt, 1, UInt, 0)
      if !Result
         MsgBox, 16,, % "Не удалось извлечь иконку.`nОшибка " A_LastError
      else if (Result = 0xFFFFFFFF || Result = -1)
         MsgBox, 16,, Файл "%sFile%" не найден!
   }

   else
   {
      if !DllCall("Shell32\ExtractIconEx" . coding, Str, sFile, Int, IconNumber-1, PtrP, hIconLarge, PtrP, hIconSmall, UInt, 1)
      {
         MsgBox, 16,, % "Не удалось извлечь иконку.`nОшибка " A_LastError
         return
      }
      SysGet, SmallIconSize, % SM_CXSMICON := 49
      if (IconSize <= SmallIconSize)
         DllCall("DestroyIcon", Ptr, hIconLarge), hIcon := hIconSmall
      else
         DllCall("DestroyIcon", Ptr, hIconSmall), hIcon := hIconLarge

      hIcon := DllCall("CopyImage", Ptr, hIcon, UInt, IMAGE_ICON := 1
         , Int, IconSize, Int, IconSize, UInt, LR_COPYRETURNORG := 0x4|LR_COPYDELETEORG := 0x8, Ptr)
   }

   Return hIcon
}

AddTrayIcon(hIcon)
{
   static NIF_MESSAGE := 1, NIF_ICON := 2, GuiNumber := 99, NIM_ADD := 0, uID := 0x404
   
   VarSetCapacity(NOTIFYICONDATA, size := A_PtrSize = 8 ? 848 : A_IsUnicode? 828 : 444, 0)
   NumPut(size, NOTIFYICONDATA, "UInt")
   Gui, % GuiNumber-- ": +hwndhGui"
   NumPut(hGui, NOTIFYICONDATA, A_PtrSize)
   NumPut(uID, NOTIFYICONDATA, 2*A_PtrSize, "UInt")
   NumPut(NIF_MESSAGE|NIF_ICON, NOTIFYICONDATA, 2*A_PtrSize + 4, "UInt")
   NumPut(nMsg := 0x404, NOTIFYICONDATA, 2*A_PtrSize + 8, "UInt")
   NumPut(hIcon, NOTIFYICONDATA, 3*A_PtrSize+8)
   
   DllCall("shell32\Shell_NotifyIcon", UInt, NIM_ADD, Ptr, &NOTIFYICONDATA)
   DllCall("DestroyIcon", Ptr, hIcon)
   Return hGui
}

ModifyTrayIcon(hIcon, hGui, uID = 0x404)
{
   static NIM_MODIFY := 1, NIF_ICON := 2
   
   VarSetCapacity(NOTIFYICONDATA, size := A_PtrSize = 8 ? 848 : A_IsUnicode? 828 : 444, 0)
   NumPut(size, NOTIFYICONDATA, "UInt")
   NumPut(hGui, NOTIFYICONDATA, A_PtrSize)
   NumPut(uID, NOTIFYICONDATA, 2*A_PtrSize, "UInt")
   NumPut(NIF_ICON, NOTIFYICONDATA, 2*A_PtrSize + 4, "UInt")
   NumPut(hIcon, NOTIFYICONDATA, 3*A_PtrSize+8)
   
   res := DllCall("shell32\Shell_NotifyIcon", UInt, NIM_MODIFY, Ptr, &NOTIFYICONDATA)
   DllCall("DestroyIcon", Ptr, hIcon)
   Return res
}

RemoveTrayIcon(hWnd, uID=0x404)
{
   VarSetCapacity(NOTIFYICONDATA, size := A_PtrSize = 8 ? 848 : A_IsUnicode? 828 : 444, 0)
   NumPut(size, NOTIFYICONDATA, "UInt")
   NumPut(hWnd, NOTIFYICONDATA, A_PtrSize)
   NumPut(uID, NOTIFYICONDATA, 2*A_PtrSize, "UInt")
   Return DllCall("shell32\Shell_NotifyIcon", "UInt", NIM_DELETE := 2, Ptr, &NOTIFYICONDATA)
}

Нажимать можно в любом порядке.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

19

Re: AHK: Загрузка разных иконок для программы

А такой код не будет есть память?

OnExit, RemoveIcon
Return

1::
hIcon:= ExtractIcon("imageres.dll", 77, 16)
if hAssociatedGui1
   ModifyTrayIcon(hIcon, hAssociatedGui1)
else
   hAssociatedGui1 := AddTrayIcon(hIcon)
return

2::
hIcon:= ExtractIcon("imageres.dll", 2, 16)
if hAssociatedGui1
   ModifyTrayIcon(hIcon, hAssociatedGui1)
else
   hAssociatedGui1 := AddTrayIcon(hIcon)
return

3::
hIcon:= ExtractIcon("imageres.dll", 4, 16)
if !hAssociatedGui2
   hAssociatedGui2 := AddTrayIcon(hIcon)
return

4::
hIcon:= ExtractIcon("imageres.dll", 8, 16)
if !hAssociatedGui3
   hAssociatedGui3 := AddTrayIcon(hIcon)
return
   
Esc:: ExitApp

RemoveIcon:
   RemoveTrayIcon(hAssociatedGui1), RemoveTrayIcon(hAssociatedGui2), RemoveTrayIcon(hAssociatedGui3)
   ExitApp

ExtractIcon(sFile, IconNumber, IconSize)
{
   coding := A_IsUnicode ? "W" : "A"

   SplitPath, sFile,,, ext
   (ext = "ico" && IconNumber := 0)

   if PrivateExtractIcons := DllCall("GetProcAddress"
                              , Ptr, DllCall("LoadLibrary", Str, "User32", Ptr)
                              , AStr, "PrivateExtractIcons" . coding, Ptr)
   {
      Result := DllCall(PrivateExtractIcons, Str, sFile, Int, IconNumber-1
                  , Int, IconSize, Int, IconSize, PtrP, hIcon, UIntP, 0, UInt, 1, UInt, 0)
      if !Result
         MsgBox, 16,, % "Не удалось извлечь иконку.`nОшибка " A_LastError
      else if (Result = 0xFFFFFFFF || Result = -1)
         MsgBox, 16,, Файл "%sFile%" не найден!
   }

   else
   {
      if !DllCall("Shell32\ExtractIconEx" . coding, Str, sFile, Int, IconNumber-1, PtrP, hIconLarge, PtrP, hIconSmall, UInt, 1)
      {
         MsgBox, 16,, % "Не удалось извлечь иконку.`nОшибка " A_LastError
         return
      }
      SysGet, SmallIconSize, % SM_CXSMICON := 49
      if (IconSize <= SmallIconSize)
         DllCall("DestroyIcon", Ptr, hIconLarge), hIcon := hIconSmall
      else
         DllCall("DestroyIcon", Ptr, hIconSmall), hIcon := hIconLarge

      hIcon := DllCall("CopyImage", Ptr, hIcon, UInt, IMAGE_ICON := 1
         , Int, IconSize, Int, IconSize, UInt, LR_COPYRETURNORG := 0x4|LR_COPYDELETEORG := 0x8, Ptr)
   }

   Return hIcon
}

AddTrayIcon(hIcon)
{
   static NIF_MESSAGE := 1, NIF_ICON := 2, GuiNumber := 99, NIM_ADD := 0, uID := 0x404
   
   VarSetCapacity(NOTIFYICONDATA, size := A_PtrSize = 8 ? 848 : A_IsUnicode? 828 : 444, 0)
   NumPut(size, NOTIFYICONDATA, "UInt")
   Gui, % GuiNumber-- ": +hwndhGui"
   NumPut(hGui, NOTIFYICONDATA, A_PtrSize)
   NumPut(uID, NOTIFYICONDATA, 2*A_PtrSize, "UInt")
   NumPut(NIF_MESSAGE|NIF_ICON, NOTIFYICONDATA, 2*A_PtrSize + 4, "UInt")
   NumPut(nMsg := 0x404, NOTIFYICONDATA, 2*A_PtrSize + 8, "UInt")
   NumPut(hIcon, NOTIFYICONDATA, 3*A_PtrSize+8)
   
   DllCall("shell32\Shell_NotifyIcon", UInt, NIM_ADD, Ptr, &NOTIFYICONDATA)
   DllCall("DestroyIcon", Ptr, hIcon)
   Return hGui
}

ModifyTrayIcon(hIcon, hGui, uID = 0x404)
{
   static NIM_MODIFY := 1, NIF_ICON := 2
   
   VarSetCapacity(NOTIFYICONDATA, size := A_PtrSize = 8 ? 848 : A_IsUnicode? 828 : 444, 0)
   NumPut(size, NOTIFYICONDATA, "UInt")
   NumPut(hGui, NOTIFYICONDATA, A_PtrSize)
   NumPut(uID, NOTIFYICONDATA, 2*A_PtrSize, "UInt")
   NumPut(NIF_ICON, NOTIFYICONDATA, 2*A_PtrSize + 4, "UInt")
   NumPut(hIcon, NOTIFYICONDATA, 3*A_PtrSize+8)
   
   res := DllCall("shell32\Shell_NotifyIcon", UInt, NIM_MODIFY, Ptr, &NOTIFYICONDATA)
   DllCall("DestroyIcon", Ptr, hIcon)
   Return res
}

RemoveTrayIcon(hWnd, uID=0x404)
{
   VarSetCapacity(NOTIFYICONDATA, size := A_PtrSize = 8 ? 848 : A_IsUnicode? 828 : 444, 0)
   NumPut(size, NOTIFYICONDATA, "UInt")
   NumPut(hWnd, NOTIFYICONDATA, A_PtrSize)
   NumPut(uID, NOTIFYICONDATA, 2*A_PtrSize, "UInt")
   Return DllCall("shell32\Shell_NotifyIcon", "UInt", NIM_DELETE := 2, Ptr, &NOTIFYICONDATA)
}

20

Re: AHK: Загрузка разных иконок для программы

Память, вроде, не ест, судя по диспетчеру задач, но в коде есть ошибка: при повторном нажатии 3 и 4 будут получены новые дескрипторы иконок, которые нигде не удаляются, это тоже как-то расходует ресурсы системы. Тут я подробно не знаю, но знаю, что такие хендлы должны удаляться с помощью DllCall("DestroyIcon", Ptr, hIcon).

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

21

Re: AHK: Загрузка разных иконок для программы

А если сделать так, то наверное не будут получены новые дескрипторы иконок при повторном нажатии?

3::
if !hAssociatedGui2
{
   hIcon:= ExtractIcon("imageres.dll", 4, 16)
   hAssociatedGui2 := AddTrayIcon(hIcon)
}
return

4::
if !hAssociatedGui3
{
   hIcon:= ExtractIcon("imageres.dll", 8, 16)
   hAssociatedGui3 := AddTrayIcon(hIcon)
}
return

22

Re: AHK: Загрузка разных иконок для программы

Так можно.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder