Что нового

[Автоматизация] Сэмулировать нажатие "непонятного" контрола...

HukpoFuJl

AццkuЙ HukpoFuJl
Сообщения
98
Репутация
38
В общем есть программа (всё тот же CommFort чат), в которой есть контрол (кнопка), но это не обычный Button или что-либо иное, это по сути какой-то графический контрол и AutoIt Window Info на него не реагирует никак, т.е. как буд-то на её месте ничего нету... Пробовал получить список контролов, методом из темы [Элементы GUI] Все контролы окна., но тоже мимо...
Нужно как-то сэмулировать нажатие этой кнопки, или что-то подобное... По нажатию этой кнопки отображается окно настроек программы... Вычислить кнопку графически по пикселям и/или отправить клик по координатам - не вариант, т.к. программа имеет возможность смены графических оболочек, при этом меняется как вид, так и положение кнопки.

У меня появилась идея отправить meassage окну, на котором расположен контрол, только вот какой? Можно как-нить отлавливать все месаджи окна? Ну т.е. что-то вроде GUIGetMsg, только для стороннего приложения...
Пробовал в общем через шел-хук:
Код:
#Include <WinAPIEx.au3>

Opt('MustDeclareVars', 1)

Global $hForm = GUICreate('')
GUIRegisterMsg(_WinAPI_RegisterWindowMessage('shellhook'), '_ShellHookProc')
_WinAPI_RegisterShellHookWindow($hForm)

While 1
    Sleep(100)
WEnd

Func _ShellHookProc($hWnd, $iMsg, $wParam, $lParam)
	TrayTip (WinGetTitle($lParam),$iMsg&" | "&$wParam&" | "&$hWnd,5,1)
EndFunc   ;==>_ShellHookProc

Func OnAutoItExit()
    _WinAPI_DeregisterShellHookWindow($hForm)
EndFunc   ;==>OnAutoItExit
Но SHELLHOOK как я понимаю отлавливает только системные события, типо сворачивания/разворачивания/уничтожения/обновления окна и т.п.
Как можно поймать все сообщения определенного окна?

Ну или предложите другой вариант решения ИМХО...
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
ShellHook тебе не поможет. Можно кликнуть по кнопке только так, я думаю:

Код:
#Include <WinAPI.au3>
#Include <WindowsConstants.au3>

Opt('WinTitleMatchMode', 3)
Opt('WinWaitDelay', 0)

Global $hWnd = WinGetHandle('[TITLE:CommFort 5.00e; CLASS:TfChatClient]')
Global $X = 26
Global $Y = 190

WinActivate($hWnd)
_WinAPI_PostMessage($hWnd, $WM_LBUTTONDOWN, 1, _WinAPI_MakeLong($X, $Y))
Sleep(50)
_WinAPI_PostMessage($hWnd, $WM_LBUTTONUP, 1, _WinAPI_MakeLong($X, $Y))


Например в моем Калькуляторе, ты тоже не сможешь так просто нажимать на кнопки.
 
Автор
HukpoFuJl

HukpoFuJl

AццkuЙ HukpoFuJl
Сообщения
98
Репутация
38
HukpoFuJl сказал(а):
и/или отправить клик по координатам - не вариант, т.к. программа имеет возможность смены графических оболочек, при этом меняется как вид, так и положение кнопки.
Ты скачал обычный установочник, там только стандартные скины, отличающиеся только цветом, но есть и другие, напимер этот:

(кнопка настроек слева, сейчас фиолетовая)

Или или этот:

(Кнопка снизу)

Так что клик по координатам ничего не дает... =((
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Другого способа я не вижу. Эта кнопка не является каким-либо контролом, она часть скина (как в моем калькуляторе). Но в любом случае, если есть скин, то должны быть где-то в его настройках координаты для каждого графического элемента. Тебе нужно только их найти.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Можно вот так:

Код:
#Include <7Zip.au3>
#Include <WinAPIEx.au3>

Opt('WinTitleMatchMode', 3)
Opt('WinWaitDelay', 0)

; Получаем хендл окна
$hWnd = WinGetHandle('[TITLE:CommFort 5.00e; CLASS:TfChatClient]')
If (Not $hWnd) Or (Not BitAND(WinGetState($hWnd), 2)) Then
    Exit
EndIf

; Получаем путь к папке с программой
$Path = StringRegExpReplace(_WinAPI_GetWindowFileName($hWnd), '\\[^\\]*\Z', '')

; Получаем путь к .zip файлу текущего скина
$Skin = IniRead(@AppDataDir & '\CommFort\Config\Main.ini', 'Main', 'CurrentSkin', '')
If $Skin Then
    $Skin = $Path & '\Skins\' & $Skin & '.zip'
Else
    Exit
EndIf

; Разархивируем из .zip файла скина файл Main.ini во временный файл ...\Temp\Main.ini
_7ZIPExtract(0, $Skin, @TempDir, 1, 0, 1, 0, 0, 'Main.ini')
If @error Then
    Exit
EndIf

; Получаем координаты необходимой кнопки
$X = IniRead(@TempDir & '\Main.ini', 'Button_MainPanel_3', 'Left', '')
$Y = IniRead(@TempDir & '\Main.ini', 'Button_MainPanel_3', 'Top', '')

; Удаляем временный файл
FileDelete(@TempDir & '\Main.ini')

If ($X = '') Or ($Y = '') Then
    Exit
EndIf

; Преобразуем координаты относительно левого верхнего угла окна
$X = Number($X)
$Y = Number($Y)
If $X < 0 Then
    $X = _WinAPI_GetWindowWidth($hWnd) + $X
EndIf
If $Y < 0 Then
    $Y = _WinAPI_GetWindowHeight($hWnd) + $Y
EndIf

; Нажимаем на кнопку
$lParam = _WinAPI_MakeLong($X + 1, $Y + 1)
WinActivate($hWnd)
For $i = 0x0201 To 0x0202
    _WinAPI_PostMessage($hWnd, $i, 1, $lParam)
    Sleep(50)
Next


7Zip.7z
 
Автор
HukpoFuJl

HukpoFuJl

AццkuЙ HukpoFuJl
Сообщения
98
Репутация
38
Хм, хоть и длинное, но вполне подходящее решение :smile: Огромное спасибо ;)

Только единственное не понял в чем суть этого кусочка:
Код:
; Нажимаем на кнопку
$lParam = _WinAPI_MakeLong($X + 1, $Y + 1)
WinActivate($hWnd)
For $i = 0x0201 To 0x0202
    _WinAPI_PostMessage($hWnd, $i, 1, $lParam)
    Sleep(50)
Next
Можно каменты к строчкам?

Да и как я понимаю окно активируется для нажатия в любом случае, не проще ли тогда сделать так: MouseClick ("left",$X,$Y) ?
 

Sp01LeR

Знающий
Сообщения
45
Репутация
12
- у этой функции координаты относительно разрешения экрана, а не окна, поэтому легче кликать через _WinAPI_PostMessage, чем инжектить хук в процесс окна.
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Sp01LeR сказал(а):
- у этой функции координаты относительно разрешения экрана, а не окна, поэтому легче кликать через _WinAPI_PostMessage, чем инжектить хук в процесс окна.
Этой функции легко задать координаты относительно левого верхнего угла окна или же клиентской его области.
PixelCoordModeSets the way coords are used in the pixel functions, either absolute coords or coords relative to the window defined by hwnd (default active window):
0 = relative coords to the defined window
1 = absolute screen coordinates (default)
2 = relative coords to the client area of the defined window
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
HukpoFuJl сказал(а):
...не проще ли тогда сделать так: MouseClick ("left",$X,$Y) ?

Можно и так, но MouseClick() перемещает курсор мыши, а если использовать сообщения, то курсор остается на месте.
 
Верх