1 (изменено: Henior, 2011-08-15 13:58:01)

Тема: AHK: Как работать с областью System Tray

Всем привет! Работает ли AutoHotKey с областью System Tray?

2

Re: AHK: Как работать с областью System Tray

По большому счёту работает, но нужно конкретизировать.

3

Re: AHK: Как работать с областью System Tray

Нужно правой кнопкой мыши нажимать на иконку в tray.

4

Re: AHK: Как работать с областью System Tray

Henior, отредактируй название темы. Слова "Trey" не существует. И, если хочешь, чтоб ответили, опиши поподробнее задачу: по какой иконке, почему нельзя вручную.

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

5 (изменено: Henior, 2011-08-15 14:01:35)

Re: AHK: Как работать с областью System Tray

Как отредактировать название темы?
Нужно автоматизировать скрипт, для этого нужно, чтобы при запуске скрипта, в области системного трея, скрипт нажимал правой кнопкой на иконку и выбирал, в раскрывшемся меню, пункт. Например настройки.
http://s1.ipicture.ru/uploads/20110815/0lcpZpyM.jpg

6

Re: AHK: Как работать с областью System Tray

Название темы можно изменить, отредактировав первое сообщение.

7

Re: AHK: Как работать с областью System Tray

На какую конкретно иконку? На свою, или на первую попавшуюся?

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

8

Re: AHK: Как работать с областью System Tray

Воспользуйтесь командой MouseClick. Если местоположение иконки изменяется, его можно определить при помощи команды ImageSearch.

9

Re: AHK: Как работать с областью System Tray

На свою!
Приведите пожалуйста пример использования ImageSearch.

10

Re: AHK: Как работать с областью System Tray

Общение » AutoHotkey » AutoHotkey: проект перевода, ветка 2  #159

11 (изменено: Henior, 2011-08-15 17:06:29)

Re: AHK: Как работать с областью System Tray

Написал небольшой скриптик, но при запуске выдает ошибку

CoordMode Pixel, Screen
ImageSerch, FoundX, FoundY, 0, 0, A_ScreenWidth, A_ScreenHeight, *75 D:\img_test\icon.jpg
if ErrorLevel = 0
{
	MsgBox %FoundX%, FoundY
	Sleep, 100
}
else
{
	MsgBox find not icon
}

Ошибка
http://s1.ipicture.ru/uploads/20110815/T2hdzWZh.bmp
icon.jpg
http://s1.ipicture.ru/uploads/20110815/aclE4h4I.jpg

Подскажите, что не так?

12

Re: AHK: Как работать с областью System Tray

Подскажите, что не так?

ImageSerch

13 (изменено: WUT, 2011-08-15 23:24:43)

Re: AHK: Как работать с областью System Tray

Эта тема поближе будет: http://www.forum.script-coding.com/view … 847#p47847
Если не принципиально AHK, то здесь готовый пример на Autoit http://www.forum.script-coding.com/view … 847#p47847 (№5, "left" в предпоследней строке заменить на "right")

14

Re: AHK: Как работать с областью System Tray

WUT пишет:

Эта тема поближе будет: http://www.forum.script-coding.com/view … 847#p47847

Сообразно ей, эмуляция клика правой кнопкой по иконке указанного приложения в трее (в данном случае по иконке ICQ):

#NoTrayIcon
SetBatchLines, -1

App = ICQ

PROCESS_VM_OPERATION := (0x8)
PROCESS_VM_READ := (0x10)
PROCESS_QUERY_INFORMATION := (0x400)
SizeOfTBBUTTON := 20, SizeOfTRAYDATA := 24
MEM_COMMIT := 0x1000
MEM_RELEASE := 0x8000
PAGE_READWRITE := 0x4
WM_USER := 0x400
TB_BUTTONCOUNT := (WM_USER + 24)
TB_GETBUTTON := (WM_USER + 23)
WM_RBUTTONDOWN := 0x204
WM_RBUTTONUP := 0x205

hShell_TrayWnd := WinExist("ahk_class Shell_TrayWnd")
ChildClasses = TrayNotifyWnd|SysPager|ToolbarWindow32  ; классы окон в порядке вложенности
Loop, parse, ChildClasses, |
   hChild := DllCall("FindWindowEx", UInt, A_Index = 1 ? hShell_TrayWnd : hChild
                                   , UInt, 0, Str, A_LoopField, UInt, 0)
; последнее вложенное — искомое окно — ToolbarWindow32 делаем последним найденным
WinWait, ahk_id %hChild%
WinGet, PID, PID
hProcess := DllCall("OpenProcess", UInt, PROCESS_VM_OPERATION|PROCESS_VM_READ, UInt, 0, UInt, PID)
lpData := DllCall("VirtualAllocEx", UInt, hProcess, UInt, 0
                                  , UInt, SizeOfTBBUTTON
                                  , UInt, MEM_COMMIT
                                  , UInt, PAGE_READWRITE)
DetectHiddenWindows, On
VarSetCapacity(TBBUTTON, SizeOfTBBUTTON)
VarSetCapacity(TRAYDATA, SizeOfTRAYDATA)

SendMessage, TB_BUTTONCOUNT
Loop % IconCount := ErrorLevel
{
   SendMessage, TB_GETBUTTON, A_Index - 1, lpData
   DllCall("ReadProcessMemory", UInt, hProcess, UInt, lpData
                              , UInt, &TBBUTTON
                              , UInt, SizeOfTBBUTTON, UInt, 0)

   DllCall("ReadProcessMemory", UInt, hProcess, UInt, NumGet(TBBUTTON, 12)
                              , UInt, &TRAYDATA
                              , UInt, SizeOfTRAYDATA, UInt, 0)
   
   hWnd := NumGet(TRAYDATA)
   WinGet, ProcessName, ProcessName, ahk_id %hWnd%
   if ProcessName not contains %App%
      Continue
      
   uID := NumGet(TRAYDATA, 4)
   nMsg := NumGet(TRAYDATA, 8)
   Break
}

DllCall("VirtualFreeEx", UInt, hProcess , UInt, lpData, UInt, 0, UInt, MEM_RELEASE)
DllCall("CloseHandle", UInt, hProcess)

if (uID = "")
   MsgBox, Иконки указанного приложения не найдено!
else
{
   PostMessage, nMsg, uID, WM_RBUTTONDOWN,, ahk_id %hWnd%
   PostMessage, nMsg, uID, WM_RBUTTONUP,, ahk_id %hWnd%
}

Меню появится вблизи курсора.

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

15

Re: AHK: Как работать с областью System Tray

Отредактировал, исправил ошибку: отсчёт иконок начинался с индекса 1 (нужно было с 0), и первая иконка не учитывалась.

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

16 (изменено: Malcev, 2012-11-21 04:25:30)

Re: AHK: Как работать с областью System Tray

А можно сей замечательный скрипт переделать под Win x64?

Можно, конечно, сделать поиск по цвету пикселя, а потом посылать правый клик.
Но хоть убейте не могу понять почему такой код на икспи иногда посылает двойной клик,
а на семерке вообще ничего не посылает?

ControlClick,  ToolBarWindow321, ahk_class Shell_TrayWnd, , right

17

Re: AHK: Как работать с областью System Tray

Malcev пишет:

А можно сей замечательный скрипт переделать под Win x64?

Можно, посмотрю вечером.

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

18

Re: AHK: Как работать с областью System Tray

Отлично!
И хотелось бы получить ответ на второй вопрос.

19

Re: AHK: Как работать с областью System Tray

Malcev пишет:

Но хоть убейте не могу понять почему такой код на икспи иногда посылает двойной клик,
а на семерке вообще ничего не посылает?

ControlClick,  ToolBarWindow321, ahk_class Shell_TrayWnd, , right

Не знаю, а что должно происходить? Куда конкретно посылается клик, ведь не указано.

Malcev пишет:

А можно сей замечательный скрипт переделать под Win x64?

Вот под любую битность (протестировано на скайпе, аська на семёрке у меня пока не установлена):

#NoTrayIcon
WM_RBUTTONDOWN := 0x204, WM_RBUTTONUP := 0x205

PostMessageToTrayIcon("Skype.exe", WM_RBUTTONDOWN, WM_RBUTTONUP)

PostMessageToTrayIcon(ExeFileName, Messages*)
{
/*
Секретная структура TRAYDATA :)
typedef TRAYDATA
{
IntPtr hwnd;
uint uID;
uint uCallbackMessage;
uint Reserved;
uint Reserved2;
IntPtr hIcon;
}
*/
   PROCESS_VM_OPERATION := 0x8
   PROCESS_VM_READ := 0x10
   PROCESS_QUERY_INFORMATION := 0x400
   SizeOfTBBUTTON := 8 + A_PtrSize*3
   SizeOfTRAYDATA := 16 + A_PtrSize*2
   MEM_COMMIT := 0x1000
   MEM_RELEASE := 0x8000
   PAGE_READWRITE := 0x4
   WM_USER := 0x400
   TB_BUTTONCOUNT := WM_USER + 24
   TB_GETBUTTON := WM_USER + 23
    
   hShell_TrayWnd := WinExist("ahk_class Shell_TrayWnd")
   ChildClasses = TrayNotifyWnd|SysPager|ToolbarWindow32  ; классы окон в порядке вложенности
   Loop, parse, ChildClasses, |
      hChild := DllCall("FindWindowEx", Ptr, A_Index = 1 ? hShell_TrayWnd : hChild
                                      , UInt, 0, Str, A_LoopField, UInt, 0, Ptr)
   ; последнее вложенное — искомое окно — ToolbarWindow32 делаем последним найденным
   WinWait, ahk_id %hChild%
   WinGet, PID, PID
   hProcess := DllCall("OpenProcess", UInt, PROCESS_VM_OPERATION|PROCESS_VM_READ, UInt, 0, UInt, PID, Ptr)
   lpData := DllCall("VirtualAllocEx", Ptr, hProcess, UInt, 0
                                     , UInt, SizeOfTBBUTTON
                                     , UInt, MEM_COMMIT
                                     , UInt, PAGE_READWRITE, Ptr)
   DetectHiddenWindows, On
   VarSetCapacity(TBBUTTON, SizeOfTBBUTTON)
   VarSetCapacity(TRAYDATA, SizeOfTRAYDATA)
    
   SendMessage, TB_BUTTONCOUNT
   Loop % IconCount := ErrorLevel
   {
      SendMessage, TB_GETBUTTON, A_Index - 1, lpData
      DllCall("ReadProcessMemory", Ptr, hProcess, Ptr, lpData
                                 , Ptr, &TBBUTTON
                                 , UInt, SizeOfTBBUTTON, UInt, 0)
    
      DllCall("ReadProcessMemory", Ptr, hProcess, Ptr, NumGet(TBBUTTON, 8 + A_PtrSize)
                                 , Ptr, &TRAYDATA
                                 , UInt, SizeOfTRAYDATA, UInt, 0)
    
      hWnd := NumGet(TRAYDATA)
      WinGet, ProcessName, ProcessName, ahk_id %hWnd%
      if (ProcessName != ExeFileName)
         Continue
    
      uID := NumGet(TRAYDATA, A_PtrSize)
      nMsg := NumGet(TRAYDATA, A_PtrSize + 4)
      Break
   }
    
   DllCall("VirtualFreeEx", Ptr, hProcess, Ptr, lpData, UInt, 0, UInt, MEM_RELEASE)
   DllCall("CloseHandle", Ptr, hProcess)
    
   if (uID = "")
      MsgBox, Иконки указанного приложения не найдено!
   else
      for key, value in Messages
      {
         PostMessage, nMsg, uID, value,, ahk_id %hWnd%
         Sleep, 50
      }
}

Для посыла кликов иконкам ahk-скриптов такой вариант не годится, exe-файл у них один и тот же, здесь нужно на хэндл главного окна скрипта ориентироваться.

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

20

Re: AHK: Как работать с областью System Tray

О, спасибо!

Не знаю, а что должно происходить? Куда конкретно посылается клик, ведь не указано.

Как это не указывается?
Клик посылается в середину контрола ToolBarWindow321 окна ahk_class Shell_TrayWnd

21

Re: AHK: Как работать с областью System Tray

А где сказано, что именно в середину? Я не нашёл.

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

22 (изменено: Malcev, 2012-11-21 23:40:36)

Re: AHK: Как работать с областью System Tray

В Options.

Xn: Specify for n the X position to click at, relative to the control's upper left corner. If unspecified, the click will occur at the horizontal-center of the control.
Yn: Specify for n the Y position to click at, relative to the control's upper left corner. If unspecified, the click will occur at the vertical-center of the control.

http://www.autohotkey.com/docs/commands … lClick.htm

А скрипт не работает.
Ни одну иконку не может найти.

23

Re: AHK: Как работать с областью System Tray

Странно что у Вас это работает на x64, т.к. у
ReadProcessMemory типы параметров следующие: Ptr, Ptr, Ptr, Ptr, Ptr
FindWindowEx: Ptr, Ptr, String(Ptr), String(Ptr)
VirtualAllocEx: Ptr, Ptr, Ptr, Int, Int
VirtualFreeEx: Ptr, Ptr, Ptr, Int

24

Re: AHK: Как работать с областью System Tray

Someone, если в функции указатель на переменную со строкой, можно вместо Ptr, &Var указать Str, Var. Если вместо хэндла используется 0, вполне подойдет и UInt.

Malcev пишет:

А скрипт не работает.

Malcev, приведи код, как он выглядит у тебя.

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

25

Re: AHK: Как работать с областью System Tray

А скрипт не работает.

Скрипт работает. Клики по иконке приложения происходят если иконка видима.

26 (изменено: Malcev, 2012-11-22 00:18:17)

Re: AHK: Как работать с областью System Tray

Говорит, что

Иконки указанного приложения не найдено!

Иконка видима.

#NoTrayIcon
WM_RBUTTONDOWN := 0x204, WM_RBUTTONUP := 0x205
 
PostMessageToTrayIcon("rgsender_gui.exe", WM_RBUTTONDOWN, WM_RBUTTONUP)
 
PostMessageToTrayIcon(ExeFileName, Messages*)
{
/*
Секретная структура TRAYDATA :)
typedef TRAYDATA
{
IntPtr hwnd;
uint uID;
uint uCallbackMessage;
uint Reserved;
uint Reserved2;
IntPtr hIcon;
}
*/
   PROCESS_VM_OPERATION := 0x8
   PROCESS_VM_READ := 0x10
   PROCESS_QUERY_INFORMATION := 0x400
   SizeOfTBBUTTON := 8 + A_PtrSize*3
   SizeOfTRAYDATA := 16 + A_PtrSize*2
   MEM_COMMIT := 0x1000
   MEM_RELEASE := 0x8000
   PAGE_READWRITE := 0x4
   WM_USER := 0x400
   TB_BUTTONCOUNT := WM_USER + 24
   TB_GETBUTTON := WM_USER + 23
 
   hShell_TrayWnd := WinExist("ahk_class Shell_TrayWnd")
   ChildClasses = TrayNotifyWnd|SysPager|ToolbarWindow32  ; классы окон в порядке вложенности
   Loop, parse, ChildClasses, |
      hChild := DllCall("FindWindowEx", Ptr, A_Index = 1 ? hShell_TrayWnd : hChild
                                      , UInt, 0, Str, A_LoopField, UInt, 0, Ptr)
   ; последнее вложенное — искомое окно — ToolbarWindow32 делаем последним найденным
   WinWait, ahk_id %hChild%
   WinGet, PID, PID
   hProcess := DllCall("OpenProcess", UInt, PROCESS_VM_OPERATION|PROCESS_VM_READ, UInt, 0, UInt, PID, Ptr)
   lpData := DllCall("VirtualAllocEx", Ptr, hProcess, UInt, 0
                                     , UInt, SizeOfTBBUTTON
                                     , UInt, MEM_COMMIT
                                     , UInt, PAGE_READWRITE, Ptr)
   DetectHiddenWindows, On
   VarSetCapacity(TBBUTTON, SizeOfTBBUTTON)
   VarSetCapacity(TRAYDATA, SizeOfTRAYDATA)
 
   SendMessage, TB_BUTTONCOUNT
   Loop % IconCount := ErrorLevel
   {
      SendMessage, TB_GETBUTTON, A_Index - 1, lpData
      DllCall("ReadProcessMemory", Ptr, hProcess, Ptr, lpData
                                 , Ptr, &TBBUTTON
                                 , UInt, SizeOfTBBUTTON, UInt, 0)
 
      DllCall("ReadProcessMemory", Ptr, hProcess, Ptr, NumGet(TBBUTTON, 8 + A_PtrSize)
                                 , Ptr, &TRAYDATA
                                 , UInt, SizeOfTRAYDATA, UInt, 0)
 
      hWnd := NumGet(TRAYDATA)
      WinGet, ProcessName, ProcessName, ahk_id %hWnd%
      if (ProcessName != ExeFileName)
         Continue
 
      uID := NumGet(TRAYDATA, A_PtrSize)
      nMsg := NumGet(TRAYDATA, A_PtrSize + 4)
      Break
   }
 
   DllCall("VirtualFreeEx", Ptr, hProcess, Ptr, lpData, UInt, 0, UInt, MEM_RELEASE)
   DllCall("CloseHandle", Ptr, hProcess)
 
   if (uID = "")
      MsgBox, Иконки указанного приложения не найдено!
   else
      for key, value in Messages
      {
         PostMessage, nMsg, uID, value,, ahk_id %hWnd%
         Sleep, 50
      }
}

27

Re: AHK: Как работать с областью System Tray

Для начала проверь, работает ли с иконкой скайпа.

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

28

Re: AHK: Как работать с областью System Tray

teadrinker пишет:

Если вместо хэндла используется 0, вполне подойдет и UInt.

Кто Вам сказал этот бред? И вообще там у Вас не везде тип корректно указан даже когда параметр не равен 0.

29

Re: AHK: Как работать с областью System Tray

Скайпа нету.
Но msseces.exe не находит.
Microsoft Security Essentials.

30

Re: AHK: Как работать с областью System Tray

Someone пишет:

Кто Вам сказал этот бред?

Ну, во-первых опыт (никогда не было с этим проблем), во-вторых, можно рассудить логически. Зачем в DllCall указывается тип данных? Чтобы было понятно, каков их размер в битах. А какой размер 0?

Someone пишет:

И вообще там у Вас не везде тип корректно указан даже когда параметр не равен 0.

А где конкретно?

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

31

Re: AHK: Как работать с областью System Tray

Malcev пишет:

Скайпа нету.

Странно, я вижу тебя в скайпе.

Malcev пишет:

Но msseces.exe не находит.

Ну не знаю. Скрипт предусматривает, что у приложения есть связанное с иконкой скрытое окно. Может, те, что у тебя, устроены как-то по-другому.

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

32

Re: AHK: Как работать с областью System Tray

teadrinker пишет:

А какой размер 0?

Размер значения "0" если оно является указателем зависит от архитектуры, под которую скомпилировано приложение: 4 или 8 байт для 32 и 64 битных приложений соотвественно.

teadrinker пишет:

А где конкретно?

Например в 3 местах

UInt, SizeOfTBBUTTON

т.к. размер типа SIZE_T зависит от архитектуры.

33

Re: AHK: Как работать с областью System Tray

Странно, я вижу тебя в скайпе.

У меня он на XP установлен.
Смотри, как можно сделать.
Вот программка, которая висит в трее (устанавливать не надо).
http://nosleephd.codeplex.com/
Так вот я только что проверил - На XP клик происходит, а на семерке нет (не может найти иконку).

34

Re: AHK: Как работать с областью System Tray

teadrinker пишет:

во-вторых, можно рассудить логически. Зачем в DllCall указывается тип данных? Чтобы было понятно, каков их размер в битах. А какой размер 0?

Ну логически-то как раз ошибка очевидна. Пусть нулевой хендл передаётся в первом параметре на x64 как 4-байтовое число. Тогда если в результате прошлых вычислений в регистре RCX, регистр ECX оказался обнулён, а старшее двойное слово нет, то его можно не обнулять и отправлять на вход функции.
Но на практике сложно встретить ситуацию, когда такие недочёты приведут к некорректной передаче аргумента.

35

Re: AHK: Как работать с областью System Tray

Александр_ пишет:

Пусть нулевой хендл передаётся в первом параметре на x64 как 4-байтовое число. Тогда если в результате прошлых вычислений в регистре RCX, регистр ECX оказался обнулён, а старшее двойное слово нет, то его можно не обнулять и отправлять на вход функции.

Но если указан тип UInt, то старшее слово просто не прочитается, вроде?

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

36

Re: AHK: Как работать с областью System Tray

Malcev, такой вариант попробуй:

#NoTrayIcon
WM_RBUTTONDOWN := 0x204, WM_RBUTTONUP := 0x205
 
PostMessageToTrayIcon("NoSleepHDv2.0.exe", WM_RBUTTONDOWN, WM_RBUTTONUP)
 
PostMessageToTrayIcon(ExeFileName, Messages*)
{
/*
Секретная структура TRAYDATA :)
typedef TRAYDATA
{
IntPtr hwnd;
uint uID;
uint uCallbackMessage;
uint Reserved;
uint Reserved2;
IntPtr hIcon;
}
*/
   PROCESS_VM_OPERATION := 0x8
   PROCESS_VM_READ := 0x10
   PROCESS_QUERY_INFORMATION := 0x400
   SizeOfTBBUTTON := 8 + A_PtrSize*3
   SizeOfTRAYDATA := 16 + A_PtrSize*2
   MEM_COMMIT := 0x1000
   MEM_RELEASE := 0x8000
   PAGE_READWRITE := 0x4
   WM_USER := 0x400
   TB_BUTTONCOUNT := WM_USER + 24
   TB_GETBUTTON := WM_USER + 23
 
   hShell_TrayWnd := WinExist("ahk_class Shell_TrayWnd")
   ChildClasses = TrayNotifyWnd|SysPager|ToolbarWindow32  ; классы окон в порядке вложенности
   Loop, parse, ChildClasses, |
      hChild := DllCall("FindWindowEx", Ptr, A_Index = 1 ? hShell_TrayWnd : hChild
                                      , Ptr, 0, Str, A_LoopField, UInt, 0, Ptr)
   ; последнее вложенное — искомое окно — ToolbarWindow32 делаем последним найденным
   WinWait, ahk_id %hChild%
   WinGet, PID, PID
   hProcess := DllCall("OpenProcess", UInt, PROCESS_VM_OPERATION|PROCESS_VM_READ, UInt, 0, UInt, PID, Ptr)
   lpData := DllCall("VirtualAllocEx", Ptr, hProcess, UInt, 0
                                     , Ptr, SizeOfTBBUTTON
                                     , UInt, MEM_COMMIT
                                     , UInt, PAGE_READWRITE, Ptr)
   DetectHiddenWindows, On
   VarSetCapacity(TBBUTTON, SizeOfTBBUTTON)
   VarSetCapacity(TRAYDATA, SizeOfTRAYDATA)
 
   SendMessage, TB_BUTTONCOUNT
   Loop % IconCount := ErrorLevel
   {
      SendMessage, TB_GETBUTTON, A_Index - 1, lpData
      DllCall("ReadProcessMemory", Ptr, hProcess, Ptr, lpData
                                 , Ptr, &TBBUTTON
                                 , Ptr, SizeOfTBBUTTON, Ptr, 0)
 
      DllCall("ReadProcessMemory", Ptr, hProcess, Ptr, NumGet(TBBUTTON, 8 + A_PtrSize)
                                 , Ptr, &TRAYDATA
                                 , Ptr, SizeOfTRAYDATA, Ptr, 0)
 
      hWnd := NumGet(TRAYDATA)
      WinGet, ProcessName, ProcessName, ahk_id %hWnd%
      if (ProcessName != ExeFileName)
         Continue
 
      uID := NumGet(TRAYDATA, A_PtrSize)
      nMsg := NumGet(TRAYDATA, A_PtrSize + 4)
      Break
   }
 
   DllCall("VirtualFreeEx", Ptr, hProcess, Ptr, lpData, Ptr, 0, UInt, MEM_RELEASE)
   DllCall("CloseHandle", Ptr, hProcess)
 
   if (uID = "")
      MsgBox, Иконки указанного приложения не найдено!
   else
      for key, value in Messages
      {
         PostMessage, nMsg, uID, value,, ahk_id %hWnd%
         Sleep, 50
      }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

37

Re: AHK: Как работать с областью System Tray

На семерке не находит, на XP находит.

38 (изменено: Александр_, 2012-11-22 01:20:07)

Re: AHK: Как работать с областью System Tray

teadrinker пишет:

Но если указан тип UInt, то старшее двойное слово просто не прочитается, вроде?

Не понял. На x64 всегда используется fastcall, и первый параметр всегда передаётся через RCX. А вызываемая функция ничего о типах не знает, что ей дали в регистрах и стеке, то она и использует.
Разумеется на практике AHK обнулит регистр перед передачей.

Someone пишет:

размер типа SIZE_T зависит от архитектуры.

Там пара байт всего читается, ошибка будет только если больше четырёх гигов копировать.

Malcev пишет:

На семерке не находит, на XP находит.

Посмотри что функции возвращают, может процесс даже не открывается.

39

Re: AHK: Как работать с областью System Tray

Malcev пишет:

На семерке не находит, на XP находит.

У меня на семёрке работают оба варианта кода. Другое дело, что иконка предложенного приложения вообще не реагирует на правый клик (у меня, по-крайней мере). Она зато реагирует на двойной клик, если приложение свёрнуто в трей. Вот так у меня работает (окно появляется из трея):

#NoTrayIcon
WM_LBUTTONDBLCLK := 0x203
 
PostMessageToTrayIcon("NoSleepHDv2.0.exe", WM_LBUTTONDBLCLK)
 
PostMessageToTrayIcon(ExeFileName, Messages*)
{
/*
Секретная структура TRAYDATA :)
typedef TRAYDATA
{
IntPtr hwnd;
uint uID;
uint uCallbackMessage;
uint Reserved;
uint Reserved2;
IntPtr hIcon;
}
*/
   PROCESS_VM_OPERATION := 0x8
   PROCESS_VM_READ := 0x10
   PROCESS_QUERY_INFORMATION := 0x400
   SizeOfTBBUTTON := 8 + A_PtrSize*3
   SizeOfTRAYDATA := 16 + A_PtrSize*2
   MEM_COMMIT := 0x1000
   MEM_RELEASE := 0x8000
   PAGE_READWRITE := 0x4
   WM_USER := 0x400
   TB_BUTTONCOUNT := WM_USER + 24
   TB_GETBUTTON := WM_USER + 23
 
   hShell_TrayWnd := WinExist("ahk_class Shell_TrayWnd")
   ChildClasses = TrayNotifyWnd|SysPager|ToolbarWindow32  ; классы окон в порядке вложенности
   Loop, parse, ChildClasses, |
      hChild := DllCall("FindWindowEx", Ptr, A_Index = 1 ? hShell_TrayWnd : hChild
                                      , UInt, 0, Str, A_LoopField, UInt, 0, Ptr)
   ; последнее вложенное — искомое окно — ToolbarWindow32 делаем последним найденным
   WinWait, ahk_id %hChild%
   WinGet, PID, PID
   hProcess := DllCall("OpenProcess", UInt, PROCESS_VM_OPERATION|PROCESS_VM_READ, UInt, 0, UInt, PID, Ptr)
   lpData := DllCall("VirtualAllocEx", Ptr, hProcess, UInt, 0
                                     , UInt, SizeOfTBBUTTON
                                     , UInt, MEM_COMMIT
                                     , UInt, PAGE_READWRITE, Ptr)
   DetectHiddenWindows, On
   VarSetCapacity(TBBUTTON, SizeOfTBBUTTON)
   VarSetCapacity(TRAYDATA, SizeOfTRAYDATA)
 
   SendMessage, TB_BUTTONCOUNT
   Loop % IconCount := ErrorLevel
   {
      SendMessage, TB_GETBUTTON, A_Index - 1, lpData
      DllCall("ReadProcessMemory", Ptr, hProcess, Ptr, lpData
                                 , Ptr, &TBBUTTON
                                 , UInt, SizeOfTBBUTTON, UInt, 0)
 
      DllCall("ReadProcessMemory", Ptr, hProcess, Ptr, NumGet(TBBUTTON, 8 + A_PtrSize)
                                 , Ptr, &TRAYDATA
                                 , UInt, SizeOfTRAYDATA, UInt, 0)
 
      hWnd := NumGet(TRAYDATA)
      WinGet, ProcessName, ProcessName, ahk_id %hWnd%
      if (ProcessName != ExeFileName)
         Continue
 
      uID := NumGet(TRAYDATA, A_PtrSize)
      nMsg := NumGet(TRAYDATA, A_PtrSize + 4)
      Break
   }
 
   DllCall("VirtualFreeEx", Ptr, hProcess, Ptr, lpData, UInt, 0, UInt, MEM_RELEASE)
   DllCall("CloseHandle", Ptr, hProcess)
 
   if (uID = "")
      MsgBox, Иконки указанного приложения не найдено!
   else
      for key, value in Messages
      {
         PostMessage, nMsg, uID, value,, ahk_id %hWnd%
         Sleep, 50
      }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

40

Re: AHK: Как работать с областью System Tray

На семерке не находит

Повторюсь

Скрипт работает. Клики по иконке приложения происходят если иконка видима.

Т.е. по иконке не спрятанной в NotifyIconOverflowWindow.

41 (изменено: Malcev, 2012-11-22 01:37:25)

Re: AHK: Как работать с областью System Tray

То что не реагирует на правый клик - это я знаю.
Но на висте 64бит и на семерке 64 бит у меня не находит иконки - выскакивает msgbox.
Функции возвращают числа, кроме  hWnd := NumGet(TRAYDATA)
msgbox % hWnd = 0
Может из-за этого?

Т.е. по иконке не спрятанной в NotifyIconOverflowWindow.

Иконки все видно.
Так у меня тоже клик не посылается.

ControlClick,  ToolBarWindow321, ahk_class Shell_TrayWnd, , right

42

Re: AHK: Как работать с областью System Tray

Посмотри, что возвращают обе ReadProcessMemory().

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

43

Re: AHK: Как работать с областью System Tray

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

44

Re: AHK: Как работать с областью System Tray

Вместо

      DllCall("ReadProcessMemory", Ptr, hProcess, Ptr, lpData
                                 , Ptr, &TBBUTTON
                                 , Ptr, SizeOfTBBUTTON, Ptr, 0)
 
      DllCall("ReadProcessMemory", Ptr, hProcess, Ptr, NumGet(TBBUTTON, 8 + A_PtrSize)
                                 , Ptr, &TRAYDATA
                                 , Ptr, SizeOfTRAYDATA, Ptr, 0)

напиши

      MsgBox, % DllCall("ReadProcessMemory", Ptr, hProcess, Ptr, lpData
                                 , Ptr, &TBBUTTON
                                 , Ptr, SizeOfTBBUTTON, Ptr, 0)
 
      MsgBox, % DllCall("ReadProcessMemory", Ptr, hProcess, Ptr, NumGet(TBBUTTON, 8 + A_PtrSize)
                                 , Ptr, &TRAYDATA
                                 , Ptr, SizeOfTRAYDATA, Ptr, 0)
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

45

Re: AHK: Как работать с областью System Tray

1
0
1
0
1
0
и т.д.

46

Re: AHK: Как работать с областью System Tray

Тогда такой код:

#NoTrayIcon
WM_LBUTTONDBLCLK := 0x203
 
PostMessageToTrayIcon("NoSleepHDv2.0.exe", WM_LBUTTONDBLCLK)
 
PostMessageToTrayIcon(ExeFileName, Messages*)
{
/*
Секретная структура TRAYDATA :)
typedef TRAYDATA
{
IntPtr hwnd;
uint uID;
uint uCallbackMessage;
uint Reserved;
uint Reserved2;
IntPtr hIcon;
}
*/
   PROCESS_VM_OPERATION := 0x8
   PROCESS_VM_READ := 0x10
   PROCESS_QUERY_INFORMATION := 0x400
   SizeOfTBBUTTON := 8 + A_PtrSize*3
   SizeOfTRAYDATA := 16 + A_PtrSize*2
   MEM_COMMIT := 0x1000
   MEM_RELEASE := 0x8000
   PAGE_READWRITE := 0x4
   WM_USER := 0x400
   TB_BUTTONCOUNT := WM_USER + 24
   TB_GETBUTTON := WM_USER + 23
 
   hShell_TrayWnd := WinExist("ahk_class Shell_TrayWnd")
   ChildClasses = TrayNotifyWnd|SysPager|ToolbarWindow32  ; классы окон в порядке вложенности
   Loop, parse, ChildClasses, |
      hChild := DllCall("FindWindowEx", Ptr, A_Index = 1 ? hShell_TrayWnd : hChild
                                      , Ptr, 0, Str, A_LoopField, UInt, 0, Ptr)
   ; последнее вложенное — искомое окно — ToolbarWindow32 делаем последним найденным
   WinWait, ahk_id %hChild%
   WinGet, PID, PID
   hProcess := DllCall("OpenProcess", UInt, PROCESS_VM_OPERATION|PROCESS_VM_READ, UInt, 0, UInt, PID, Ptr)
   lpData := DllCall("VirtualAllocEx", Ptr, hProcess, UInt, 0
                                     , Ptr, SizeOfTBBUTTON
                                     , UInt, MEM_COMMIT
                                     , UInt, PAGE_READWRITE, Ptr)
   DetectHiddenWindows, On
   VarSetCapacity(TBBUTTON, SizeOfTBBUTTON)
   VarSetCapacity(TRAYDATA, SizeOfTRAYDATA)
 
   SendMessage, TB_BUTTONCOUNT
   Loop % IconCount := ErrorLevel
   {
      SendMessage, TB_GETBUTTON, A_Index - 1, lpData
      DllCall("ReadProcessMemory", Ptr, hProcess, Ptr, lpData
                                 , Ptr, &TBBUTTON
                                 , Ptr, SizeOfTBBUTTON, Ptr, 0)
 
      if !DllCall("ReadProcessMemory", Ptr, hProcess, Ptr, NumGet(TBBUTTON, 8 + A_PtrSize)
                                 , Ptr, &TRAYDATA
                                 , Ptr, SizeOfTRAYDATA, Ptr, 0)
         MsgBox, % A_LastError
 
      hWnd := NumGet(TRAYDATA)
      WinGet, ProcessName, ProcessName, ahk_id %hWnd%
      if (ProcessName != ExeFileName)
         Continue
 
      uID := NumGet(TRAYDATA, A_PtrSize)
      nMsg := NumGet(TRAYDATA, A_PtrSize + 4)
      Break
   }
 
   DllCall("VirtualFreeEx", Ptr, hProcess, Ptr, lpData, Ptr, 0, UInt, MEM_RELEASE)
   DllCall("CloseHandle", Ptr, hProcess)
 
   if (uID = "")
      MsgBox, Иконки указанного приложения не найдено!
   else
      for key, value in Messages
      {
         PostMessage, nMsg, uID, value,, ahk_id %hWnd%
         Sleep, 50
      }
}

Какое число выводится?

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

47

Re: AHK: Как работать с областью System Tray

299

48

Re: AHK: Как работать с областью System Tray

MSDN пишет:

ERROR_PARTIAL_COPY

    299 (0x12B)

    Only part of a ReadProcessMemory or WriteProcessMemory request was completed.

Это к Александр_'у, наверное.

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

49

Re: AHK: Как работать с областью System Tray

Попробуй на 32-битном экзешнике запустить.

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

50

Re: AHK: Как работать с областью System Tray

У тебя вообще какой битности ahk?

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

51

Re: AHK: Как работать с областью System Tray

Все понятно, у меня была установлена 32-битная AHK.
Хотя я был уверен, что 64 бита.
Н-да. Лоханул чутка.

52

Re: AHK: Как работать с областью System Tray

Отсюда:

"Если указанный процесс -64-ехбитный процесс и вызывающий процесс 32-ухбитный, функция терпит неудачу и последний код ERROR_PARTIAL_COPY".

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

53

Re: AHK: Как работать с областью System Tray

В общем, в код нужно добавить проверку соответствия битности процессов.

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

54 (изменено: teadrinker, 2012-11-22 03:57:40)

Re: AHK: Как работать с областью System Tray

Окончательный вариант такой:

#NoTrayIcon
WM_LBUTTONDBLCLK := 0x203
 
PostMessageToTrayIcon("Skype.exe", WM_LBUTTONDBLCLK)
 
PostMessageToTrayIcon(ExeFileName, Messages*)
{
/*
Секретная структура TRAYDATA :)
typedef TRAYDATA
{
IntPtr hwnd;
uint uID;
uint uCallbackMessage;
uint Reserved;
uint Reserved2;
IntPtr hIcon;
}
*/
   if (A_PtrSize = 4 && A_Is64bitOS)
   {
      MsgBox, Вы пользуетесь 32-битной версией AHK на 64-битной системе! Функция не будет работать. Запустите скрипт под AHK x64!
      return
   }
   PROCESS_VM_OPERATION := 0x8
   PROCESS_VM_READ := 0x10
   PROCESS_QUERY_INFORMATION := 0x400
   SizeOfTBBUTTON := 8 + A_PtrSize*3
   SizeOfTRAYDATA := 16 + A_PtrSize*2
   MEM_COMMIT := 0x1000
   MEM_RELEASE := 0x8000
   PAGE_READWRITE := 0x4
   WM_USER := 0x400
   TB_BUTTONCOUNT := WM_USER + 24
   TB_GETBUTTON := WM_USER + 23
 
   hShell_TrayWnd := WinExist("ahk_class Shell_TrayWnd")
   ChildClasses = TrayNotifyWnd|SysPager|ToolbarWindow32  ; классы окон в порядке вложенности
   Loop, parse, ChildClasses, |
      hChild := DllCall("FindWindowEx", Ptr, A_Index = 1 ? hShell_TrayWnd : hChild
                                      , Ptr, 0, Str, A_LoopField, UInt, 0, Ptr)
   ; последнее вложенное — искомое окно — ToolbarWindow32 делаем последним найденным
   WinWait, ahk_id %hChild%
   WinGet, PID, PID
   hProcess := DllCall("OpenProcess", UInt, PROCESS_VM_OPERATION|PROCESS_VM_READ, UInt, 0, UInt, PID, Ptr)
   lpData := DllCall("VirtualAllocEx", Ptr, hProcess, UInt, 0
                                     , Ptr, SizeOfTBBUTTON
                                     , UInt, MEM_COMMIT
                                     , UInt, PAGE_READWRITE, Ptr)
   DetectHiddenWindows, On
   VarSetCapacity(TBBUTTON, SizeOfTBBUTTON)
   VarSetCapacity(TRAYDATA, SizeOfTRAYDATA)
 
   SendMessage, TB_BUTTONCOUNT
   Loop % IconCount := ErrorLevel
   {
      SendMessage, TB_GETBUTTON, A_Index - 1, lpData
      DllCall("ReadProcessMemory", Ptr, hProcess, Ptr, lpData
                                 , Ptr, &TBBUTTON
                                 , Ptr, SizeOfTBBUTTON, Ptr, 0)
 
      DllCall("ReadProcessMemory", Ptr, hProcess, Ptr, NumGet(TBBUTTON, 8 + A_PtrSize)
                                 , Ptr, &TRAYDATA
                                 , Ptr, SizeOfTRAYDATA, Ptr, 0)
 
      hWnd := NumGet(TRAYDATA)
      WinGet, ProcessName, ProcessName, ahk_id %hWnd%
      if (ProcessName != ExeFileName)
         Continue
 
      uID := NumGet(TRAYDATA, A_PtrSize, "UInt")
      nMsg := NumGet(TRAYDATA, A_PtrSize + 4, "UInt")
      Break
   }
 
   DllCall("VirtualFreeEx", Ptr, hProcess, Ptr, lpData, Ptr, 0, UInt, MEM_RELEASE)
   DllCall("CloseHandle", Ptr, hProcess)
 
   if (uID = "")
      MsgBox, Иконки указанного приложения не найдено!
   else
      for key, value in Messages
      {
         PostMessage, nMsg, uID, value,, ahk_id %hWnd%
         Sleep, 50
      }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

55

Re: AHK: Как работать с областью System Tray

1.1.08.00 - July 14, 2012 пишет:

Added A_Is64bitOS.

Можно изменить:

   if (A_PtrSize = 4 && A_Is64bitOS)
   {
      MsgBox, Вы пользуетесь 32-битной версией AHK на 64-битной системе! Функция не будет работать. Запустите скрипт под AHK x64!
      return
   }

56

Re: AHK: Как работать с областью System Tray

А, точно! Отредактировал.

Да, кстати!

Someone пишет:

VirtualAllocEx: Ptr, Ptr, Ptr, Int, Int

MSDN пишет:

LPVOID WINAPI VirtualAllocEx(
  _In_      HANDLE hProcess,
  _In_opt_  LPVOID lpAddress,
  _In_      SIZE_T dwSize,
  _In_      DWORD flAllocationType,
  _In_      DWORD flProtect
);

В то же время DllCall:

Types of Arguments and Return Values
Int
An unsigned Int (UInt) is also used quite frequently, such as for DWORD.

Так что правильно всё же: VirtualAllocEx: Ptr, Ptr, Ptr, UInt, UInt

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

57

Re: AHK: Как работать с областью System Tray

teadrinker пишет:

Так что правильно всё же: VirtualAllocEx: Ptr, Ptr, Ptr, UInt, UInt

В данном случае важна размерность параметров, а не их знаковость. Они все равно копируются как есть и от их знаковости значение, передаваемое в функцию никак не изменится.

58

Re: AHK: Как работать с областью System Tray

То есть, считаешь случайным, что в пункте статьи, озаглавленном Int, специально говорится, что для DWORD используется UInt? Так и я говорил, что если для размера структур использовать UInt вместо Ptr, ничего не изменится.

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

59

Re: AHK: Как работать с областью System Tray

teadrinker пишет:

Так и я говорил, что если для размера структур использовать UInt вместо Ptr, ничего не изменится.

Изменится, выше даже говорили в каком случае это произойдет.

60

Re: AHK: Как работать с областью System Tray

Ну, тогда ведь и разница между UInt и Int есть. UInt или DWORD — это целое число от 0 до 0xFFFFFFFF. Int — от -0x80000000 до 0x7FFFFFFF. Т. е. для числа 0xFDCBA987 Int не подойдёт, если его указать, возникнет ошибка.

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

61

Re: AHK: Как работать с областью System Tray

teadrinker пишет:

Т. е. для числа 0xFDCBA987 Int не подойдёт, если его указать, возникнет ошибка.

Нет, не возникает ошибки, и функция получает именно 0xFDCBA987. Другое дело, что если она ожидает Int, то она его интерпретирует как отрицательное число.

62 (изменено: Александр_, 2012-11-22 16:37:37)

Re: AHK: Как работать с областью System Tray

Someone, YMP:

DllCall("MyDll.dll\MyInc", "int", 0x80000000/2, "ptr")

Какое значение должно передаться в функцию MyInc?

63

Re: AHK: Как работать с областью System Tray

Александр_
0x40000000, а в чём подвох?

64

Re: AHK: Как работать с областью System Tray

YMP пишет:

Александр_
0x40000000, а в чём подвох?

В том, что на 32-битной машине 0x80000000/2 при знаковом делении даёт 0xС0000000, а при беззнаковом 0x40000000.

65 (изменено: Someone, 2012-11-22 16:59:48)

Re: AHK: Как работать с областью System Tray

Александр_ пишет:
YMP пишет:

Александр_
0x40000000, а в чём подвох?

В том, что на 32-битной машине 0x80000000/2 при знаковом делении даёт 0xС0000000, а при беззнаковом 0x40000000.

А как вы определили 0x80000000 знаковое или нет? Тип указанный в DllCall а данном случае никак не влияет на результат деления.

Это все равно что:

i:=0x80000000/2
DllCall("MyDll.dll\MyInc", "int", i, "ptr")

66

Re: AHK: Как работать с областью System Tray

YMP пишет:

Другое дело, что если она ожидает Int, то она его интерпретирует как отрицательное число.

А на каком этапе произойдёт эта интерпретация? При передаче числа в DllCall() или непосредственно в вызываемую API? Если только на втором, тогда какой смысл указания типов данных в DllCall()?

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

67

Re: AHK: Как работать с областью System Tray

teadrinker пишет:

Если только на втором, тогда какой смысл указания типов данных в DllCall()?

Смысл в размере передаваемых данных.

68

Re: AHK: Как работать с областью System Tray

Зачем в DllCall() тогда отдельно существуют Int и UInt? Можно было бы обойтись одним Int.

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

69

Re: AHK: Как работать с областью System Tray

teadrinker пишет:

А на каком этапе произойдёт эта интерпретация? При передаче числа в DllCall() или непосредственно в вызываемую API? Если только на втором, тогда какой смысл указания типов данных в DllCall()?

Уже сама API-функция будет интерпретировать число как знаковое или беззнаковое.
Зачем различные типы целых чисел, не совсем понятно. Если бы при выходе значения за пределы указанного типа это как-то сигнализировалось, например, в ErrorLevel, тогда понятно бы было. Но в ErrorLevel ноль. Поведение AutoHotkey в случае выхода за пределы типа разное для разных типов. Например, если послать "Char, 0x6600000", то и придёт в функцию 0x6600000, что уже явно не Char. Но если выйти за пределы Int64, то в этом случае передаётся максимально поддерживаемое значение, т.е. -0x8000000000000000 или 0x7FFFFFFFFFFFFFFF соответственно.

Как сказано в справке, типы имеют значение при передаче указателей на числа, т.е. "Char*", "Int*" и т.п. После вызова функции эти переменные обновляются, на случай, если функция их изменила. Числа там хранятся в виде строк. Чтобы правильно перевести записанное функцией число в строковый вид, нужно знать тип этого числа. В случае Char* значение 0xFF будет переведено в строку как "-1", а в случае UChar* как "255".
В возвращаемых значениях типы играют такую же роль, там тоже нужно знать, как правильно перевести число в строковое представление.

70

Re: AHK: Как работать с областью System Tray

Вообще да, справка говорит, что

Prepend the letter U to any of the integer types above to interpret it as an unsigned integer (UInt64, UInt, UShort, and UChar). Strictly speaking, this is necessary only for return values and asterisk variables because it does not matter whether an argument passed by value is unsigned or signed (except for Int64).

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

71

Re: AHK: Как работать с областью System Tray

Кстати говоря у AHK вообще полные ягодицы в плане приведения типов:

Msgbox % DllCall(A_ScriptDir "\TestDll00.dll\PervertInc", "char", -1, "uint64")

Где PervertInc:

__declspec(dllexport) UINT64 PervertInc(DWORD x) // просто прибавляем единицу, без знака.
{
    return (UINT64)x+1;
}

На выходе получаем 0x100000000(2^33). Т.е. в функцию передаётся нихрена не "char", а вполне себе "int". Отсюда следует и полная импотенция при работе со знаками.

72

Re: AHK: Как работать с областью System Tray

А какой смысл передавать char в функцию, принимающую dword?

73

Re: AHK: Как работать с областью System Tray

А что изменить в этом скрипте, чтобы при посылке нажатия правой кнопки мыши в окошо скайпа, меню появлялось не там где находится мышка, а там где находится иконка скайпа?

74

Re: AHK: Как работать с областью System Tray

54-ый пост.

Окончательный вариант такой:


А можно ли его изменить, чтобы работало на 32-битной версии AHK на 64-битной системе?

75

Re: AHK: Как работать с областью System Tray

Можно, но без гарантии. Вроде, я уже приводил примеры работы с иконками трея для любых соотношений битностей.
Завтра смогу написать.

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

76

Re: AHK: Как работать с областью System Tray

Я только это помню, но там немного другое:
http://forum.script-coding.com/viewtopi … 430#p92430

77 (изменено: serzh82saratov, 2015-09-11 04:31:23)

Re: AHK: Как работать с областью System Tray

У меня так работает:


#NoTrayIcon
WM_LBUTTONDBLCLK := 0x203
 
PostMessageToTrayIcon("Skype.exe", WM_LBUTTONDBLCLK)
 
PostMessageToTrayIcon(ExeFileName, Messages*)
{
/*
Недокументированная структура TRAYDATA
typedef TRAYDATA
{
IntPtr hwnd;
uint uID;
uint uCallbackMessage;
uint Reserved;
uint Reserved2;
IntPtr hIcon;
}
*/
    static WM_USER := 0x400, TB_BUTTONCOUNT := WM_USER + 24, TB_GETBUTTON := WM_USER + 23
      , PtrSize := A_Is64bitOS ? 8 : 4, SizeOfTBBUTTON := 8 + PtrSize*3, SizeOfTRAYDATA := 16 + PtrSize*2 
      
    hShell_TrayWnd := WinExist("ahk_class Shell_TrayWnd")
    ChildClasses = TrayNotifyWnd|SysPager|ToolbarWindow32  ; классы окон в порядке вложенности
    Loop, parse, ChildClasses, |
        hChild := DllCall("FindWindowEx", Ptr, A_Index = 1 ? hShell_TrayWnd : hChild
                                      , Ptr, 0, Str, A_LoopField, UInt, 0, Ptr)
    WinExist("ahk_id" hChild)
    WinGet, PID, PID
    if !IsObject(RemoteBuff := New RemoteBuffer(PID, SizeOfTBBUTTON))
        Return, 0, DllCall("MessageBox", Ptr, 0, Str, "Не удалось создать удалённый буфер`nОшибка " A_LastError, Str, "", UInt, 0) 
        
    DHW_Prev := A_DetectHiddenWindows
    DetectHiddenWindows, On
    SendMessage, TB_BUTTONCOUNT 

    Loop % ErrorLevel  {  
        SendMessage, TB_GETBUTTON, A_Index - 1, RemoteBuff.ptr   
        RemoteBuff.Read(TBBUTTON, SizeOfTBBUTTON) 
        TraydataOffset := NumGet(&TBBUTTON + 8  + PtrSize) - RemoteBuff.ptr  
        RemoteBuff.Read(TRAYDATA, SizeOfTRAYDATA, TraydataOffset)  
        hWnd := NumGet(&TRAYDATA) 
        WinGet, Name, ProcessName, % "ahk_id" hWnd
        if (Name != ExeFileName)
            Continue 
        uID := NumGet(&TRAYDATA, PtrSize, "UInt")
        nMsg := NumGet(&TRAYDATA, PtrSize + 4, "UInt") 
        Break 
    }
    if (uID = "")
        MsgBox, Иконки указанного приложения не найдено!
    else
        for key, value in Messages
        {
            PostMessage, nMsg, uID, value,, ahk_id %hWnd%
            Sleep, 50
        }
    DetectHiddenWindows, %DHW_Prev%
} 

Class RemoteBuffer
{
   __New(PID, size)
   {
      static PROCESS_VM_OPERATION := 0x8, PROCESS_VM_WRITE := 0x20, PROCESS_VM_READ := 0x10
         , MEM_COMMIT := 0x1000, PAGE_READWRITE := 0x4
         
      if !(this.hProc := DllCall("OpenProcess", UInt, PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE, Int, 0, UInt, PID, Ptr))
         Return
      
      if !(this.ptr := DllCall("VirtualAllocEx", Ptr, this.hProc, UInt, 0, Ptr, size, UInt, MEM_COMMIT, UInt, PAGE_READWRITE, Ptr))
         Return, "", DllCall("CloseHandle", Ptr, this.hProc)
   }
   
   __Delete()
   {
      DllCall("VirtualFreeEx", Ptr, this.hProc, Ptr, this.ptr, UInt, 0, UInt, MEM_RELEASE := 0x8000)
      DllCall("CloseHandle", Ptr, this.hProc)
   }
   
   Read(ByRef LocalBuff, size, offset = 0)
   {
      VarSetCapacity(LocalBuff, size, 0)
      if !DllCall("ReadProcessMemory", Ptr, this.hProc, Ptr, this.ptr + offset, Ptr, &LocalBuff, Ptr, size, Ptr, 0)
         Return, 0, DllCall("MessageBox", Ptr, 0, Str, "Не удалось прочитать данные`nОшибка " A_LastError, Str, "", UInt, 0)
      Return 1
   }
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

78

Re: AHK: Как работать с областью System Tray

Для последнего кода — с какой настройкой посылать один клик?

79

Re: AHK: Как работать с областью System Tray

Один клик состоит из двух сообщений.

80

Re: AHK: Как работать с областью System Tray

Штука в том, как их вписать — образцов чего не нашел.

81 (изменено: stealzy, 2017-05-30 11:29:35)

Re: AHK: Как работать с областью System Tray

Куда вписать, в ф-ию? Образец чего?
У себя откопал взятый где-то аналогичный скрипт, куда добавил возможность писать сообщения в стиле ahk (в вашем случае "Click" или "LButton" или "LCM"):

/*
Send mouse click to tray icon. Example:
PostMessage2TrayIconProcName("processX.exe", "Click Up Right") ; "WM_LBUTTONDOWN" / "RButton" / "RCM Dn" / "Click 2"
PostMessage2TrayIconProcName("proc.exe", [0x204, 0x205]) PostMessage2TrayIconProcName("proc.exe", 0x203)

Limitation:
1) Может работать неправильно, если одновременно происходит пользовательский ввод.
Возможное решение: блокировать ввод на время выполнения.
2) На строке
CurrentProcessName := oWMI.Get("Win32_Process.Handle=" PID).Name
возникает ошибка, если в трее остались иконки прибитых программ.

WM_LBUTTONDOWN = 0x201     WM_RBUTTONDOWN = 0x204     WM_MBUTTONDOWN = 0x207
WM_LBUTTONUP = 0x202       WM_RBUTTONUP = 0x205       WM_MBUTTONUP = 0x208
WM_LBUTTONDBLCLK = 0x203   WM_RBUTTONDBLCLK = 0x206   WM_MBUTTONDBLCLK = 0x209
WM_MOUSEMOVE = 0x200       WM_MOUSEWHEEL = 0x20A      WM_MOUSEHWHEEL = 0x20E
*/

PostMessage2TrayIconProcName(ProcessName, messages)
{
	if (InStr(messages, "C") || InStr(messages, "B")) ; string, contain Click/LButton/LCM
	{
		keyDirectionN := InStr(messages, "D") ? 1 : (InStr(messages, "Up") ? 2 : (InStr(messages, "2") ? 3 : 4))
		whatKeyN := InStr(messages, "R") ? 2 : InStr(messages, "M") ? 3 : 1 ; Right/Middle
		MouseClickWMCodesTable := [ [[WM_LBUTTONDOWN := 0x201], [WM_LBUTTONUP := 0x202], [WM_LBUTTONDBLCLK := 0x203], [0x201, 0x202]]
		, [[WM_RBUTTONDOWN := 0x204], [WM_RBUTTONUP := 0x205], [WM_RBUTTONDBLCLK := 0x206], [0x204, 0x205]]
		, [[WM_MBUTTONDOWN := 0x207], [WM_MBUTTONUP := 0x208], [WM_MBUTTONDBLCLK := 0x209], [0x207, 0x208]] ]
		messages := MouseClickWMCodesTable[whatKeyN, keyDirectionN]
	}
	static WM_USER := 0x400, TB_BUTTONCOUNT := WM_USER + 24, TB_GETBUTTON := WM_USER + 23
		, PtrSize := A_Is64bitOS ? 8 : 4, SizeOfTBBUTTON := 8 + PtrSize*3, SizeOfTRAYDATA := 16 + PtrSize*2
	oWMI := ComObjGet("winmgmts:")
	DHW_Prev := A_DetectHiddenWindows
	DetectHiddenWindows, On

	Loop 2
	{
		ControlGet, hWnd, hwnd,, ToolbarWindow321, % "ahk_class " . (A_Index = 1 ? "Shell_TrayWnd" : "NotifyIconOverflowWindow")
		WinExist("ahk_id" hWnd)
		WinGet, PID, PID

		if (A_Index = 1 && !IsObject(RemoteBuff := New RemoteBuffer(PID, SizeOfTRAYDATA))) {
			DetectHiddenWindows, %DHW_Prev%
			Return, 0, DllCall("MessageBox", Ptr, 0, Str, "Не удалось создать удалённый буфер`nОшибка " A_LastError, Str, "", UInt, 0)
		}

		SendMessage, TB_BUTTONCOUNT
		Loop % ErrorLevel
		{
			SendMessage, TB_GETBUTTON, A_Index - 1, RemoteBuff.ptr
			if ! ( pTBBUTTON := RemoteBuff.Read(SizeOfTBBUTTON) )
				|| !pTRAYDATA := RemoteBuff.Read(SizeOfTRAYDATA, NumGet(pTBBUTTON + 8 + PtrSize) - RemoteBuff.ptr) {
				DetectHiddenWindows, %DHW_Prev%
				Return 1
			}

			WinGet, PID, PID, % "ahk_id" hWnd := NumGet(pTRAYDATA+0)
			CurrentProcessName := oWMI.Get("Win32_Process.Handle=" PID).Name
			if (CurrentProcessName = "AutoHotkey.exe")
			{
				WinGetTitle, Title, % "ahk_id" hWnd
				CurrentProcessName := RegExReplace(Title, "i).*\\(.*) - autohotkey v[\.\d]+", "$1")
			}
			if (CurrentProcessName = ProcessName)
			{
				uID := NumGet(pTRAYDATA + PtrSize, "UInt")
				uCallbackMessage := NumGet(pTRAYDATA + PtrSize + 4, "UInt")
			; BlockInput, On
			; SendInput {Click Up}{Click Right Up} ; hack
				messages := IsObject(messages) ? messages : [messages]
				for i, message in messages
					PostMessage, uCallbackMessage, uID, message,, % "ahk_id" hWnd
			; BlockInput, Off
				DetectHiddenWindows, %DHW_Prev%
				Return 0
			}
		}
	}
	DetectHiddenWindows, %DHW_Prev%
	Return 1
}

Class RemoteBuffer
{
	__New(PID, size)
	{
		static PROCESS_VM_OPERATION := 0x8, PROCESS_VM_WRITE := 0x20, PROCESS_VM_READ := 0x10
			, MEM_COMMIT := 0x1000, PAGE_READWRITE := 0x4

		if !(this.hProc := DllCall("OpenProcess", UInt, PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE, Int, 0, UInt, PID, Ptr))
			Return

		if !(this.ptr := DllCall("VirtualAllocEx", UInt, this.hProc, UInt, 0, UInt, size, UInt, MEM_COMMIT, UInt, PAGE_READWRITE, Ptr))
			Return, "", DllCall("CloseHandle", Ptr, this.hProc)
	}

	__Delete()
	{
		DllCall("VirtualFreeEx", Ptr, this.hProc, Ptr, this.ptr, UInt, 0, UInt, MEM_RELEASE := 0x8000)
		DllCall("CloseHandle", Ptr, this.hProc)
	}

	Read(size, offset = 0)
	{
		static LocalBuff
		VarSetCapacity(LocalBuff, size, 0)
		if !DllCall("ReadProcessMemory", Ptr, this.hProc, Ptr, this.ptr + offset, Ptr, &LocalBuff, UInt, size, UInt, 0)
			Return, 0, DllCall("MessageBox", Ptr, 0, Str, "Не удалось прочитать данные`nОшибка " A_LastError, Str, "", UInt, 0)

		VarSetCapacity(LocalBuff, -1)
		Return &LocalBuff
	}

	Write(pLocalBuff, size, offset = 0)
	{
		res := DllCall("WriteProcessMemory", Ptr, this.hProc, Ptr, this.ptr + offset, Ptr, pLocalBuff, UInt, size, UInt, 0)
		Return res ? res : 0, (!res) ? DllCall("MessageBox", Ptr, 0, Str, "Не удалось записать данные`nОшибка " A_LastError, Str, "", UInt, 0)
	}
}
+ DD

82

Re: AHK: Как работать с областью System Tray

DD, в 77 коде идет обращение к этой функции - PostMessageToTrayIcon(ExeFileName, Messages*)
Звездочка в параметре функции означает, что передается несколько аргументов.
В данной функции они потом извлекаются тут:

        for key, value in Messages
        {
            PostMessage, nMsg, uID, value,, ahk_id %hWnd%
            Sleep, 50
        }

Следовательно, чтобы послать одиночное нажатие вам надо написать так:

WM_LBUTTONDOWN = 0x201, WM_LBUTTONUP = 0x202 
PostMessageToTrayIcon("Skype.exe", WM_LBUTTONDOWN, WM_LBUTTONUP)
+ DD

83 (изменено: DD, 2017-05-30 14:06:53)

Re: AHK: Как работать с областью System Tray

Спасибо, уважаемые! Почему-то, для значка облачного клиента MEGAsync.exe, никакие клики не отрабатывали — но нужное окно выводится через Run)).

stealzy
Не получалось правильно вписать в код "WM_LBUTTONDOWN" и "WM_LBUTTONUP", потому что нигде на форуме так, как их записал выше Malcev, они не проходят)).