1

Тема: AHK: HWND контекстного меню.

Добра всем.

Чтобы географически корректно жмякнуть ПКМ или ЛКМ в поле(контрол) окна посредством PostMessage(), нужно знать хендл поля(контрола) и хендл окна, которому оно/он принадлежит, чтобы в последствии высчитать разницу координат, вычитаемую из величин координат клика.


postLclick(new_x, new_y, varWin, varControl ) {
	WinGetPos, hw_x, hw_y, hw_w, hw_h, ahk_id %varControl%
	WinGetPos, hwWin_x, hwWin_y, hwWin_w, hwWin_h, ahk_id %varWin%
	l_param := % ((new_x - (hw_x - hwWin_x)) + ((new_y - (hw_y - hwWin_y)) * 65536))
	PostMessage, 0x0201, 0x0001, %l_param%, , ahk_id %varControl%
	sleep 50
	PostMessage, 0x0202, 0x0000, %l_param%, , ahk_id %varControl%
}
postRclick(new_x, new_y, varWin, varControl ) {
	WinGetPos, hw_x, hw_y, hw_w, hw_h, ahk_id %varControl%
	WinGetPos, hwWin_x, hwWin_y, hwWin_w, hwWin_h, ahk_id %varWin%
	l_param := % ((new_x - (hw_x - hwWin_x)) + ((new_y - (hw_y - hwWin_y)) * 65536))
	PostMessage, 0x0204, 0x0002, %l_param%, , ahk_id %varControl%
	sleep 50
	PostMessage, 0x0205, 0x0000, %l_param%, , ahk_id %varControl%
}

Например, в браузере, с этим можно легко справиться так:


WinGet, winVar, ID, Yandex
WinGet, ctrlVar, ControlListHwnd, Yandex
postRclick(100, 100, winVar, ctrlVar)

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

В прошлом софте, которым пользовался была функция, позволяющая получить хендл объекта имея лишь его координаты, ищу аналогию.

2

Re: AHK: HWND контекстного меню.

KusochekDobra пишет:

В прошлом софте, которым пользовался была функция, позволяющая получить хендл объекта имея лишь его координаты, ищу аналогию.

Команда MouseGetPos.

3

Re: AHK: HWND контекстного меню.

MouseGetPos - для этого тягает курсор по экрану, получая искомый хендл фокусом на нём. Если я ошибаюсь, опишите пожалуйста пример записи MouseGetPos, где этого не происходит. То о чём я упоминал выглядело примерно так:


myHwnd := GetHwnd(100, 100)

Помещая в переменную хендл объекта в указанных координатах. С MouseGetPos это будет выглядеть примерно так:


Send {Click, 100, 100, 0}
MouseGetPos,,, myHwnd,,2

Суть вопроса и состоит в том, чтобы не прибегать к манипуляциям с указателем. В первом примере вот приведён способ получения контрола принадлежащего основному окну посредством WinGet, а окно контекстного меню наверняка так же должно принадлежать этому окну или его контролу, относительно которого оно вызвано. Вероятно, что если то так, то нет даже необходимости искать его хендл по координатам. Но как это сделать иным способом, я бы очень хотел узнать из компетентных источников вашей мудрости, ибо вчерашний день поисков не увенчался успехом.

4

Re: AHK: HWND контекстного меню.

Задача не понята.

5

Re: AHK: HWND контекстного меню.

Ну как же. Для того, чтобы сообщить браузеру через контекстное меню вызываемое ПКМ, что я хочу сделать с объектом описанным на его странице, я должен в этом меню выбрать соответствующий пункт. Чтобы это было реализуемо, необходимо каждый раз при ПКМ получать его хендл, ибо это всякий раз окно с новым HWND. Хендл самого окна, как и его контрола, в котором протекает рендер страницы со всеми операциями я получаю так:


WinGet, winVar, ID, Yandex
WinGet, ctrlVar, ControlListHwnd, Yandex
postRclick(100, 100, winVar, ctrlVar)

Сообщая вместе с этим и ПКМ в интересующем меня месте страницы. Но как мне получить хендл контекстного меню, вызываемого ПКМ? Кликните например, по любой ссылке правой кнопкой мыши, там например пункт меню "Сохранить ссылку как...". Чтобы теперь сообщить в это меню функцией postLclick() что я кликаю в тот самый пункт, мне нужно сообщить ей последний параметр, в котором содержится HWND контекстного меню. Как мне его получить не перемещая курсор в область этого меню?

Возможности AHK потрясают конечно, после кажущегося теперь примитивным софта, которым я пользовался раньше и чтобы тут не оказалось возможности жмякнуть в контекстное меню не прибегая для этого к помощи указателя - НЕ ВЕРЮ!!!

6 (изменено: Alectric, 2016-06-21 20:03:33)

Re: AHK: HWND контекстного меню.

Может это поможет:

mx=100
my=100
WinID:=DllCall("WindowFromPoint", "int64", mX & 0x00000000FFFFFFFF | mY<<32)
Win 10 x64
AHK v1.1.33.02
                       Справка тебе в помощь.

7

Re: AHK: HWND контекстного меню.

KusochekDobra, короче говоря... Есть некая программа, в которой Вы тем или иным образом вызываете контекстное меню.
Под "географически корректно жмякнуть" надо понимать желание послать щелчок ЛКМ / ПКМ по пункту  контекстного меню, отталкиваясь от его координат.
Правильно?
Вы знаете, что существует также возможность выбрать пункт меню, используя клавиши-стрелки и Enter?
Ещё вариант - находить пункт меню с помощью конманды ImageSearch.
И ещё, контекстное меню - это точно элемент управления (контрол по-нашему), а не самостоятельное окно?

8

Re: AHK: HWND контекстного меню.

Вот оно! Вот то волшебство, которое я ищу!

Alectric пишет:

Может это поможет:

mx=100
my=100
WinID:=DllCall("WindowFromPoint", "int64", mX & 0x00000000FFFFFFFF | mY<<32)

При том, работает, даже без перевода значения в HEX. Так и должно быть? И ещё момент - клик происходит в нужные координаты контекстного меню лишь в том случае, если его окно в позиции х=0 у=0. Будто меню вызывается относительно рабочего стола, в то время как все ПКМ и ЛКМ внутри окна проходят как и требуется, независимо от его положения. Но это уже детали.

За доброту, спасибо!

9

Re: AHK: HWND контекстного меню.

Читай справку по CoordMode.

Win 10 x64
AHK v1.1.33.02
                       Справка тебе в помощь.

10 (изменено: KusochekDobra, 2016-06-23 04:45:11)

Re: AHK: HWND контекстного меню.

Да, как раз подобрался к этому моменту.


CoordMode, Mouse, Screen
SetTitleMatchMode, 2
; ###### FUNC #######
pLclk(new_x, new_y, varControl) {
	WinGetPos, hw_x, hw_y,,, ahk_id %varControl%						; Получить координаты контрола
	l_param := % (new_x - hw_x) + ((new_y - hw_y) * 65536)				; Вычесть из положения клика позицию контрола, получив координаты внутри него
	PostMessage, 0x0201, 0x0001, %l_param%, , ahk_id %varControl%		; Нажать
	sleep 50
	PostMessage, 0x0202, 0x0000, %l_param%, , ahk_id %varControl%		; Отпустить
}
pRclck(new_x, new_y, varControl) {
	WinGetPos, hw_x, hw_y,,, ahk_id %varControl%
	l_param := % (new_x - hw_x) + ((new_y - hw_y) * 65536)
	PostMessage, 0x0204, 0x0002, %l_param%, , ahk_id %varControl%
	sleep 50
	PostMessage, 0x0205, 0x0000, %l_param%, , ahk_id %varControl%
}
Hget(x, y) {
	return % DllCall("WindowFromPoint", "int64", x & 0x00000000FFFFFFFF | y<<32)
}
; ##### EXAMPLE #####
; Сообщает контролу ЛКМ при нажатии Q
sc10::
	MouseGetPos, myX, myY
	pLclck(myX, myY, Hget(myX, myY))
return

; Сообщает контролу ПКМ при нажатии W
sc11::
	MouseGetPos, myX, myY
	pRclck(myX, myY, Hget(myX, myY))
return

Ещё много раз моя благодарность!

** Подправил некоторую избыточность кода.