Что нового

Как эмулировать клик ПКМ по значку конкретной проги в системном трее ?

k_ok_o_s

Новичок
Сообщения
4
Репутация
0
Подскажите, пожалуйста, можно ли как-то эмулировать нажатия мышью по значку конкретной проги в системном трее? Т.е. что-то типа WinMenuSelectItem для трея? Попасть клавишами в трей не проблема, но как найти там нужный значёк? Ведь он не всегда на одном и том же месте.

Вот что можно о трее узнать:
Код:
>>>> Window <<<<
Title:	
Class:	Shell_TrayWnd
Position:	0, 993
Size:	1280, 31
Style:	0x96000000
ExStyle:	0x00000088
Handle:	0x0003004A

>>>> Control <<<<
Class:	ToolbarWindow32
Instance:	1
ClassnameNN:	ToolbarWindow321
Name:	
Advanced (Class):	[CLASS:ToolbarWindow32; INSTANCE:1]
ID:	
Text:	Область уведомлений
Position:	932, 6
Size:	288, 18
ControlClick Coords:	72, 13
Style:	0x56008B4D
ExStyle:	0x00000080
Handle:	0x00010062

>>>> Mouse <<<<
Position:	1004, 1012
Cursor ID:	0
Color:	0x0D8DEA

>>>> StatusBar <<<<

>>>> ToolsBar <<<<
1:	30	Orbit
2:	29	[email protected] 1 новое сообщение
[email protected] новых сообщений: 0
3:	20	Инет
Скорость: 100.0 Мбит/с
Состояние: Подключено
4:	28	Безопасное извлечение устройства
5:	27	Opera
6:	26	Mozilla Thunderbird
7:	25	NetLimiter 2
8:	24	Skype
9:	23	
10:	22	

>>>> Visible Text <<<<
пуск
19:34
Область уведомлений
Выполнение приложений
Выполнение приложений
Quick Launch


>>>> Hidden Text <<<<
или
Код:
>>>> Window <<<<
Title:	
Class:	Shell_TrayWnd
Position:	0, 993
Size:	1280, 31
Style:	0x96000000
ExStyle:	0x00000088
Handle:	0x0003004A

>>>> Control <<<<
Class:	TrayNotifyWnd
Instance:	1
ClassnameNN:	TrayNotifyWnd1
Name:	
Advanced (Class):	[CLASS:TrayNotifyWnd; INSTANCE:1]
ID:	303
Text:	
Position:	913, 0
Size:	367, 31
ControlClick Coords:	62, 5
Style:	0x56000000
ExStyle:	0x00000000
Handle:	0x0003004E

>>>> Mouse <<<<
Position:	975, 998
Cursor ID:	0
Color:	0x1290E8

>>>> StatusBar <<<<

>>>> ToolsBar <<<<
1:	30	Orbit
2:	29	[email protected] 1 новое сообщение
[email protected] новых сообщений: 0
3:	20	Инет
Скорость: 100.0 Мбит/с
Состояние: Подключено
4:	28	Безопасное извлечение устройства
5:	27	Opera
6:	26	Mozilla Thunderbird
7:	25	NetLimiter 2
8:	24	Skype
9:	23	
10:	22	

>>>> Visible Text <<<<
пуск
19:37
Область уведомлений
Выполнение приложений
Выполнение приложений
Quick Launch


>>>> Hidden Text <<<<

Конкретная задача: переключать режим загрузки канала - "Пауза всем" и "Запустить всё" в Orbit Downloader. Там это можно только через трей. Если нельзя в AutoIt, то как можно это реализовать?
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
По значку кликнуть можно так:

Код:
#NoTrayIcon
#include <SysTray_UDF.au3>
;

$Pid = ProcessExists("Orbit.exe")

If Not $Pid Then
    MsgBox(16, "Error", "This process not exists")
    Exit
EndIf

$Index = _SysTrayIconIndex($Pid)

If @error Then
    MsgBox(16, "Error", "This process not have tray icon")
    Exit
EndIf

_SysTrayIconClick($Index, "Right")

If @error Then
    MsgBox(16, "Error", "There was an error to click on the icon")
    Exit
EndIf

Func _SysTrayIconClick($iIndex, $sButton="Main")
    Local $TrayIcon_Pos = _SysTrayIconPos($iIndex)
    If Not IsArray($TrayIcon_Pos) Then Return SetError(1, 0, 0)

    Local $Old_Mouse_Pos = MouseGetPos()
    MouseClick($sButton, $TrayIcon_Pos[0], $TrayIcon_Pos[1], 1, 0)
    MouseMove($Old_Mouse_Pos[0], $Old_Mouse_Pos[1], 0)
EndFunc


SysTray_UDF.au3 прикрепил.

P.S
Но кроме вызова меню, нажать на пункты можно используя ID пунктов (узнать можно Reshacker'ом).
Код:
#include <WindowsConstants.au3>
#include <SendMessage.au3>
;

If Not ProcessExists("Regedit.exe") Then
	Run("Regedit.exe")
	WinWait("[CLASS:RegEdit_RegEdit]")
EndIf

$hRegEdit = WinGetHandle("[CLASS:RegEdit_RegEdit]")
WinActivate($hRegEdit)

_SendMessage($hRegEdit, $WM_COMMAND, 659, 0) ;Пункт "Экспортировать"
;_SendMessage($hRegEdit, $WM_COMMAND, 675, 0) ;Пункт "Копировать имя раздела"
 
Автор
K

k_ok_o_s

Новичок
Сообщения
4
Репутация
0
Спасибо! После такого профессионального ответа можно и тему закрывать, даже не попробовав :smile: Чуть позже отпишусь о результатах.
 

kuzyaka

Новичок
Сообщения
3
Репутация
0
CreatoR сказал(а):
...
Но кроме вызова меню, нажать на пункты можно используя ID пунктов (узнать можно Reshacker'ом).
Код:
#include <WindowsConstants.au3>
#include <SendMessage.au3>
;

If Not ProcessExists("Regedit.exe") Then
	Run("Regedit.exe")
	WinWait("[CLASS:RegEdit_RegEdit]")
EndIf

$hRegEdit = WinGetHandle("[CLASS:RegEdit_RegEdit]")
WinActivate($hRegEdit)

_SendMessage($hRegEdit, $WM_COMMAND, 659, 0) ;Пункт "Экспортировать"
;_SendMessage($hRegEdit, $WM_COMMAND, 675, 0) ;Пункт "Копировать имя раздела"

Скачал ResHacker 3.4.0.79, но с помощью него узнать ID контекстного меню Диспетчера очереди печати (spoolsv.exe) не удалось, потому как там нет никакого меню.

Не поможете ли мне выбрать пункт контекстного меню "Обновить ..." в Диспетчере очереди печати (spoolsv.exe)?
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
Последние сообщения перенёс (http://autoit-script.ru/index.php/topic,2775.0.html), демонстрируя этим самым как раз таки полезность двух разных тем, пусть даже и с двумя ответами, но тема будет полезной и другим, а если всё смешать, то найти именно этот вопрос, будет сложнее.
 

Favorite6233

Знающий
Сообщения
21
Репутация
5
Хочу от себя дополнить всё вышесказанное. Дело в том, что если панель задач автоматически убирается с экрана, то приведенный пример не работает, потому что неправильно вычисляется координата. Координата получается за пределами экрана, и при попытке щёлкнуть мышью, мышь попадает просто на панель задач, а не на нужный значок. Поэтому предлагаю от себя решение этой задачи:


Код:
Func _SysTrayIconClick($iIndex, $sButton="Main")
 Local $TrayIcon_Pos = _SysTrayIconPos($iIndex)
 If Not IsArray($TrayIcon_Pos) Then Return SetError(1, 0, 0)
 $trayHwnd = _FindTrayToolbarWindow()
 $ScreenPosTray = WinGetPos($trayHwnd)
 $TrayIcon_Pos[0] = $TrayIcon_Pos[0] - $ScreenPosTray[0]
 $TrayIcon_Pos[1] = $TrayIcon_Pos[1] - $ScreenPosTray[1]
 ControlClick($trayHwnd,"","",$sButton,1,$TrayIcon_Pos[0]+3, $TrayIcon_Pos[1]+3)
EndFunc


Немного поясню. ControlClick использует относительные координаты. Поэтому даём ей относительные координаты. +3 поставил, чтобы ПКМ попадало не на первый пиксель значка, а как бы подальше (эту цифру вообще можно взять произвольной в пределах значка).

Осталась только одна проблема: значок может быть скрыт. А вот как его открыть, а потом нажать ПКМ - не знаю.
 

AZJIO

Меценат
Меценат
Сообщения
2,892
Репутация
1,196
Favorite6233
В справке UDF добавлена, там есть функция _SysTrayIconVisible, но у меня она не работает (или сейчас не работает).
 

Favorite6233

Знающий
Сообщения
21
Репутация
5
AZJIO
От спасибо тебе, дорогой товарищ, выручил. Действительно есть такая функция. У меня сработала нормально. Более того, для нажатия ПКМ нужно ОБЯЗАТЕЛЬНО сначала вызывать эту функцию перед отправкой через ControlSend. Без неё иконка вроде как и видна, но программа работает через раз: то правильно нажмёт ПКМ, то попадёт на как бы пустое место и откроет контекстное меню для ToolbarWindow32, а не для той программы, которая нужна. А вот когда поставил _SysTrayIconVisible, то попадает каждый раз точно правильно.

Код:
#include "SysTray_UDF.au3"

$Pid = ProcessExists("egui.exe")

If Not $Pid Then
 MsgBox(16, "Error", "This process not exists")
 Exit
EndIf

$Index = _SysTrayIconIndex($Pid)
If @error Then Exit
_SysTrayIconClick($Index, "Right")
If @error Then Exit
;~ Send("{up 4}{enter}")

Func _SysTrayIconClick($iIndex, $sButton="Main")
 Local $TrayIcon_Pos = _SysTrayIconPos($iIndex)
 If Not IsArray($TrayIcon_Pos) Then Return SetError(1, 0, 0)
 $trayHwnd = _FindTrayToolbarWindow()
 $ScreenPosTray = WinGetPos($trayHwnd)
 $TrayIcon_Pos[0] = $TrayIcon_Pos[0] - $ScreenPosTray[0]
 $TrayIcon_Pos[1] = $TrayIcon_Pos[1] - $ScreenPosTray[1]
 _SysTrayIconVisible(0, $iIndex)
 ControlClick($trayHwnd,"","",$sButton,1,$TrayIcon_Pos[0]+3, $TrayIcon_Pos[1]+3)
EndFunc
 

vovsla

Осваивающий
Сообщения
607
Репутация
36
Скрипт рабочий, но я не смог найти ID пунктов.
Открывал Regedit.exe с помощью "ResourceHacker 4.2.5" и "Restorator 2009 4.0.1807"
Подскажите пожалуйста, где именно смотреть

Код:
#include <WindowsConstants.au3>
#include <SendMessage.au3>
;

If Not ProcessExists("Regedit.exe") Then
    Run("Regedit.exe")
    WinWait("[CLASS:RegEdit_RegEdit]")
EndIf

$hRegEdit = WinGetHandle("[CLASS:RegEdit_RegEdit]")
WinActivate($hRegEdit)

_SendMessage($hRegEdit, $WM_COMMAND, 659, 0) ;Пункт "Экспортировать"
;_SendMessage($hRegEdit, $WM_COMMAND, 675, 0) ;Пункт "Копировать имя раздела"
 

alex33

Скриптер
Сообщения
1,457
Репутация
186
Vovsla сказал(а):
Скрипт рабочий, но я не смог найти ID пунктов.
Открывал Regedit.exe с помощью "ResourceHacker 4.2.5" и "Restorator 2009 4.0.1807"
Подскажите пожалуйста, где именно смотреть
В Windows 7 и старше этого уже нет, а вот на XP есть. Для примера вложил файлы...
 

Вложения

  • regedit__xp_and_7.zip
    123.4 КБ · Просмотры: 8
Верх