Re: AHK: Замена "Window Spy"
В таком случае завершить можно с помощью Return, а в чём тогда вопрос?
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Страницы Назад 1 … 13 14 15 16 17 18 19 Далее
Чтобы отправить ответ, вы должны войти или зарегистрироваться
В таком случае завершить можно с помощью Return, а в чём тогда вопрос?
Как завершить другой поток, а не текущий.
Ну разве что придумать какое-нибудь условие, которое будет в одном потоке проверяться, а в другом меняться.
Я про безусловное завершение, как в случае с АСС, когда оно уходит в ожидание окна, там условие не проверишь.
В winapi есть же:
GetCurrentThreadld
TerminateThread
В AutoHotkey_H кажется тоже.
Так завершается сам скрипт.
ThreadID := DllCall("GetCurrentThreadId")
THREAD_TERMINATE := 0x0001
MsgBox % hThread := DllCall("OpenThread", "uint", THREAD_TERMINATE, "int", 0, "uint", ThreadID, "ptr")
MsgBox % DllCall( "TerminateThread", UInt, hThread, UInt, 0)
Проверил у себя.
Без машинного кода вообще не срабатывает.
Так работает ок.
f11::
Send {LWin}
sleep 500
ToolTip % hwnd := DllCall("FindWindowEx", "ptr", 0, "ptr", 0, "str", "Windows.UI.Core.CoreWindow", "str", "Начальный экран", "ptr")
DllCall("LoadLibrary","str","oleacc","ptr")
VarSetCapacity(IID_IAccessible, 16)
DllCall("ole32\CLSIDFromString", "wstr", "{618736e0-3c3d-11cf-810c-00aa00389b71}", "ptr", &IID_IAccessible)
DllCall("oleacc\AccessibleObjectFromWindow", "ptr", hwnd, "uint", OBJID_CLIENT := 0xFFFFFFFC, "ptr", &IID_IAccessible, "ptr*", pacc)
Send {LWin}
Sleep 500
UnFreeze(1200, Func("MyFunc"))
VarSetCapacity(variant, 8+A_PtrSize*2, 0)
NumPut(VT_I4 := 3, variant, 0, "ushort")
if (A_PtrSize = 4)
DllCall(NumGet(NumGet(pacc+0)+10*A_PtrSize), "ptr", pacc, "int64", NumGet(variant, 0, "int64"), "int64", NumGet(variant, 8, "int64"), "ptr*", name) ; get_accName
else
DllCall(NumGet(NumGet(pacc+0)+10*A_PtrSize), "ptr", pacc, "ptr", &variant, "ptr*", name) ; get_accName
msgbox % StrGet(name)
Return
Esc:: ExitApp
MyFunc()
{
msgbox timer
Send {LWin}
}
UnFreeze(timeOut, userFunc) {
static SYNCHRONIZE := 0x100000, oInfo := {}
, msg := DllCall("RegisterWindowMessage", "Str", "WM_INFO")
, _ := OnMessage(msg, Func("WM_INFO").Bind(oInfo))
hProc := DllCall("OpenProcess", UInt, SYNCHRONIZE, UInt, 0, UInt, DllCall("GetCurrentProcessId"), Ptr)
pPtr := GetProcAddr(hProc, A_ScriptHwnd, msg, timeOut)
oInfo.func := userFunc, oInfo.hProc := hProc
DllCall("CreateThread", Ptr, 0, Ptr, 0, Ptr, pPtr, Ptr, 0, UInt, 0, Ptr, 0)
}
WM_INFO(oInfo)
{
DllCall("CloseHandle", Ptr, oInfo.hProc)
oInfo.func.Call()
}
GetProcAddr(Handle, hWnd, Msg, Timeout=-1)
{ ; на основе http://forum.script-coding.com/viewtopic.php?pid=56073#p56073
static MEM_COMMIT := 0x1000, PAGE_EXECUTE_READWRITE := 0x40
ptr := DllCall("VirtualAlloc", Ptr, 0, Ptr, A_PtrSize = 4 ? 49 : 85, UInt, MEM_COMMIT, UInt, PAGE_EXECUTE_READWRITE, Ptr)
, hModule := DllCall("GetModuleHandle", Str, "kernel32.dll", Ptr)
, pWaitForSingleObject := DllCall("GetProcAddress", Ptr, hModule, AStr, "WaitForSingleObject", Ptr)
, hModule := DllCall("GetModuleHandle", Str, "user32.dll", Ptr)
, pSendMessageW := DllCall("GetProcAddress", Ptr, hModule, AStr, "SendMessageW", Ptr)
, NumPut(pWaitForSingleObject, ptr*1)
, NumPut(pSendMessageW, ptr + A_PtrSize)
if (A_PtrSize = 4) {
NumPut(0x68, ptr + 8, "UChar")
, NumPut(Timeout, ptr + 9, "UInt"), NumPut(0x68, ptr + 13, "UChar")
, NumPut(Handle, ptr + 14), NumPut(0x15FF, ptr + 18, "UShort")
, NumPut(ptr, ptr + 20), NumPut(0x6850, ptr + 24, "UShort")
, NumPut(Handle, ptr + 26), NumPut(0x68, ptr + 30, "UChar")
, NumPut(Msg, ptr + 31, "UInt"), NumPut(0x68, ptr + 35, "UChar")
, NumPut(hWnd, ptr + 36), NumPut(0x15FF, ptr + 40, "UShort")
, NumPut(ptr+4, ptr + 42), NumPut(0xC2, ptr + 46, "UChar"), NumPut(4, ptr + 47, "UShort")
}
else {
NumPut(0x53, ptr + 16, "UChar")
, NumPut(0x20EC8348, ptr + 17, "UInt"), NumPut(0xBACB8948, ptr + 21, "UInt")
, NumPut(Timeout, ptr + 25, "UInt"), NumPut(0xB948, ptr + 29, "UShort")
, NumPut(Handle, ptr + 31), NumPut(0x15FF, ptr + 39, "UShort")
, NumPut(-45, ptr + 41, "UInt"), NumPut(0xB849, ptr + 45, "UShort")
, NumPut(Handle, ptr + 47), NumPut(0xBA, ptr + 55, "UChar")
, NumPut(Msg, ptr + 56, "UInt"), NumPut(0xB948, ptr + 60, "UShort")
, NumPut(hWnd, ptr + 62), NumPut(0xC18941, ptr + 70, "UInt")
, NumPut(0x15FF, ptr + 73, "UShort"), NumPut(-71, ptr + 75, "UInt")
, NumPut(0x20C48348, ptr + 79, "UInt"), NumPut(0xC35B, ptr + 83, "UShort")
}
return ptr + A_PtrSize*2
}
Работает также как в 1394, или это тоже самое.
teadrinker
По поводу потоков понял что как ты говорил, есть один поток, и по событиям в нём же происходит прерывание выполнения одного кода, и выполнение другого.
Так срабатывает только несколько раз.
proc()
proc()
{
Static i := 0
Send {LWin}
sleep 500
hwnd := DllCall("FindWindowEx", "ptr", 0, "ptr", 0, "str", "Windows.UI.Core.CoreWindow", "str", "Начальный экран", "ptr")
DllCall("LoadLibrary","str","oleacc","ptr")
VarSetCapacity(IID_IAccessible, 16)
DllCall("ole32\CLSIDFromString", "wstr", "{618736e0-3c3d-11cf-810c-00aa00389b71}", "ptr", &IID_IAccessible)
DllCall("oleacc\AccessibleObjectFromWindow", "ptr", hwnd, "uint", OBJID_CLIENT := 0xFFFFFFFC, "ptr", &IID_IAccessible, "ptr*", pacc)
; Send {LWin}
; Sleep 500
UnFreeze(1200, Func("proc"))
VarSetCapacity(variant, 8+A_PtrSize*2, 0)
NumPut(VT_I4 := 3, variant, 0, "ushort")
if (A_PtrSize = 4)
DllCall(NumGet(NumGet(pacc+0)+10*A_PtrSize), "ptr", pacc, "int64", NumGet(variant, 0, "int64"), "int64", NumGet(variant, 8, "int64"), "ptr*", name) ; get_accName
else
DllCall(NumGet(NumGet(pacc+0)+10*A_PtrSize), "ptr", pacc, "ptr", &variant, "ptr*", name) ; get_accName
msgbox % StrGet(name) "`n" ++i
}
Esc:: ExitApp
UnFreeze(timeOut, userFunc) {
static SYNCHRONIZE := 0x100000, oInfo := {}
, msg := DllCall("RegisterWindowMessage", "Str", "WM_INFO")
, _ := OnMessage(msg, Func("WM_INFO").Bind(oInfo))
hProc := DllCall("OpenProcess", UInt, SYNCHRONIZE, UInt, 0, UInt, DllCall("GetCurrentProcessId"), Ptr)
pPtr := GetProcAddr(hProc, A_ScriptHwnd, msg, timeOut)
oInfo.func := userFunc, oInfo.hProc := hProc
DllCall("CreateThread", Ptr, 0, Ptr, 0, Ptr, pPtr, Ptr, 0, UInt, 0, Ptr, 0)
}
WM_INFO(oInfo)
{
DllCall("CloseHandle", Ptr, oInfo.hProc)
oInfo.func.Call()
}
GetProcAddr(Handle, hWnd, Msg, Timeout=-1)
{ ; на основе http://forum.script-coding.com/viewtopic.php?pid=56073#p56073
static MEM_COMMIT := 0x1000, PAGE_EXECUTE_READWRITE := 0x40
ptr := DllCall("VirtualAlloc", Ptr, 0, Ptr, A_PtrSize = 4 ? 49 : 85, UInt, MEM_COMMIT, UInt, PAGE_EXECUTE_READWRITE, Ptr)
, hModule := DllCall("GetModuleHandle", Str, "kernel32.dll", Ptr)
, pWaitForSingleObject := DllCall("GetProcAddress", Ptr, hModule, AStr, "WaitForSingleObject", Ptr)
, hModule := DllCall("GetModuleHandle", Str, "user32.dll", Ptr)
, pSendMessageW := DllCall("GetProcAddress", Ptr, hModule, AStr, "SendMessageW", Ptr)
, NumPut(pWaitForSingleObject, ptr*1)
, NumPut(pSendMessageW, ptr + A_PtrSize)
if (A_PtrSize = 4) {
NumPut(0x68, ptr + 8, "UChar")
, NumPut(Timeout, ptr + 9, "UInt"), NumPut(0x68, ptr + 13, "UChar")
, NumPut(Handle, ptr + 14), NumPut(0x15FF, ptr + 18, "UShort")
, NumPut(ptr, ptr + 20), NumPut(0x6850, ptr + 24, "UShort")
, NumPut(Handle, ptr + 26), NumPut(0x68, ptr + 30, "UChar")
, NumPut(Msg, ptr + 31, "UInt"), NumPut(0x68, ptr + 35, "UChar")
, NumPut(hWnd, ptr + 36), NumPut(0x15FF, ptr + 40, "UShort")
, NumPut(ptr+4, ptr + 42), NumPut(0xC2, ptr + 46, "UChar"), NumPut(4, ptr + 47, "UShort")
}
else {
NumPut(0x53, ptr + 16, "UChar")
, NumPut(0x20EC8348, ptr + 17, "UInt"), NumPut(0xBACB8948, ptr + 21, "UInt")
, NumPut(Timeout, ptr + 25, "UInt"), NumPut(0xB948, ptr + 29, "UShort")
, NumPut(Handle, ptr + 31), NumPut(0x15FF, ptr + 39, "UShort")
, NumPut(-45, ptr + 41, "UInt"), NumPut(0xB849, ptr + 45, "UShort")
, NumPut(Handle, ptr + 47), NumPut(0xBA, ptr + 55, "UChar")
, NumPut(Msg, ptr + 56, "UInt"), NumPut(0xB948, ptr + 60, "UShort")
, NumPut(hWnd, ptr + 62), NumPut(0xC18941, ptr + 70, "UInt")
, NumPut(0x15FF, ptr + 73, "UShort"), NumPut(-71, ptr + 75, "UInt")
, NumPut(0x20C48348, ptr + 79, "UInt"), NumPut(0xC35B, ptr + 83, "UShort")
}
return ptr + A_PtrSize*2
}
Код из 1407 поста у меня работаетвсё время и без глюков.
По-моему нету такого апи, которое закрывает псевдопотоки.
Код из 1407 поста у меня работаетвсё время и без глюков.
У меня тоже. В 1409 код из него же.
По-моему нету такого апи, которое закрывает псевдопотоки.
Ясно. А псевдопотоки это общепринятый термин?
Если точнее, в процессе AHK на самом деле 4-6 потоков, но сам код выполняется в одном. Можно создать новый поток с помощью CreateThread, но он будет нестабильным, и выполнить в нём можно только несколько действий.
Про псевдопотоки можешь погуглить.
Про псевдопотоки можешь погуглить.
Гуглил конечно, но твоего определения этому не нашёл.
Какого именно моего?
Толкования немного разнятся, наверное не нашёл нормальную статью.
А зачем тебе? Если интересно знать как они устроены в автохотки, то надо читать исходный код.
Вот что авторы пишут:
AutoHotkey isn't designed to be multi-threaded. The threads will conflict when they try to use internal global variables that are needed to even execute script.
AutoHotkey isn't designed to support multiple threads except in the case of the keyboard/mouse hook (which both share a second thread when they're active). Therefore, AutoHotkey isn't thread-safe, particularly when it comes to reading/writing variables. Therefore if the second thread does anything that interferes with something the main thread is doing (or vice versa), using multiple threads in a script might cause unexpected behavior or possibly even crashes.
It's also possible there could be other problems just from the mere existence of a second thread that is running parts of the script in parallel with the main thread. The program simply isn't designed to do that. An extensive code-review would be necessary if anyone wants to verify that it's safe.
AutoHotkey doesn't currently support multiple process-threads due to the need to make many sections thread-safe, which in turn would:
1) Increase code size.
2) Reduce performance in many areas due to the need to enforce thread-safety.
3) Be very costly in development time (probably 4-8 weeks of full-time work).I guess it would be safe to combine Machine code functions with CreateThread(), but the extra threads couldn't be written in AHK. (I suppose they could use SendMessage to notify the main thread of events, though.)
Кстати, а что ты изменил в последнем апдейте?
Сейчас вообще нельзя пользоваться с автообновлением acc path - сильно тормозит.
Вот что авторы пишут:
Теперь ясно.
Сейчас вообще нельзя пользоваться с автообновлением acc path - сильно тормозит.
Ничего касаемо этого не трогал, у меня всё также работает.
Видно у меня что-то переглючило.
Возможно из-за этого дурацкого глюка.
Не думаешь его поправить?
Поставить хук на окно старта и если его состояние сменилось на EVENT_OBJECT_CLOAKED, тогда прекращать отправлять методы acc.
Понял в чем возможный баг - при запущенном адобе премьер и автообновлением acc path даже когда премьер не активен - жуткие тормоза.
Они появились после этого апдейта:
https://github.com/serzh82saratov/AhkSp … bb14edea43
после этого апдейта
Я не нашёл что может повлиять. адобе премьер у меня нет чтобы проверить.
Могу залить демку.
В смысле? Видео как глючит?
Премьер.
Давай.
Сделаем проще.
Запусти этот код
pixelsearch, x, y, 8, 110, 325, 945 0x32FDCF, 50, Fast
После чего запусти эту версию ahkspy
https://raw.githubusercontent.com/serzh … AhkSpy.ahk
После чего актуальную версию ahkspy.
Плюс ко всему где-то идет утечка - постоянно увеличивается расход памяти.
Ничего не заметил. Память в райное Working Size: 53 М.
View settings - +WordWrap + Dynamic accessible path.
Память постоянно увеличивается.
Ничего не заметил
Последняя версия загружается секунд 10.
А, забыл. Да на новой растет память на старой нет.
pixelsearch зачем?
Для того, чтобы ты воспроизвел у себя данный баг.
При запущенном
pixelsearch, x, y, 8, 110, 325, 945 0x32FDCF, 50, Fast
3.98 версия загружается сразу и без тормозов.
Текущая версия зависает на секунд 10.
Раз память постоянно увеличивается, значит где-то утечка.
Последняя версия загружается секунд 10.
Да, поймал.
Даже не знаю что сказать.
Вроде починил, спасибо за тесты.
Поставить хук на окно старта и если его состояние сменилось на EVENT_OBJECT_CLOAKED, тогда прекращать отправлять методы acc.
Это перед каждым обращением к объекту проверять переменную?
Да, теперь работает без тормозов.
Да, перед каждым обращением.
Если окно, которое проверяем (не только старт) меняет свое состояние на CLOAKED, значит больше к объекту не обращаемся.
Наверное эту проверку нужно сделать только для виндовс 10 до 1809 включительно.
Хотя я до 1809 не проверял, так как не на чем.
У меня 10.0.17763.
Мне кажется это редкая ситуация, во всяком случае проверять хотя бы только при запуске сбора.
У тебя есть пример кода с CLOAKED.
Ну у кого как.
У меня постоянно вылетает .
У тебя тоже версия виндовса 1809.
Примера нет, но можно передавать текущий хендл окна в колбек хука и проверять его там на соответствие с окнами которые стали cloaked.
Только надо будет в колбек Critical прописать.
А в чем ты видишь трудность проверять при каждом обращении к объекту, там же только условия добавить, не думаю, что должны быть из-за него тормоза.
Потестировал насчет утечки.
Она появилась начиная с апдейта версии 2.52 на 3.00:
https://github.com/serzh82saratov/AhkSp … bb14edea43
Проверял, вызвав task manager и держа мышку над окном task manager.
Да, понемногу растёт. За полчаса с 50 до 150мв, но не вылетает.
В 3.00 добавлен Jscript, как его на утечки тестировать не знаю.
Насчёт cloaked, я тоже не никогда не использовал. Будет время, надо попробовать.
В 3.00 добавлен Jscript, как его на утечки тестировать не знаю.
Наверное как и всегда - комментировать блоки кода, пока не останется та часть, где происходит утечка.
Может что-то из этого у тебя в коде используется?
https://learn.javascript.ru/memory-leaks
Добавил в 4.21 проверку CLOAKED при нажатии кнопок в окне.
Не знаю с точки зрения компактности кода как расставить везде такие проверки, и есть подозрение, что EVENT_OBJECT_CLOAKED теряется, если приходит во время обращения к АСС.
MsgBox не всегда появляется, когда идёт сбор данных.
EVENT_OBJECT_CLOAKED(hWinEventHook, event, hwnd, idObject, idChild) {
If (idObject || idChild)
Return
If (hwnd = oPubObj.Acc.WinID)
MsgBox % oPubObj.Acc.CLOAKED := 1
}
По счёт Jscript комментировал:
oDoc.Write("<!DOCTYPE html><head><meta http-equiv=""X-UA-Compatible"" content=""IE=8""></head>" html)
oDoc.Close()
ComObjConnect(onhkinput := oDoc.getElementById("hkinputevent"), "onhkinput_")
ComObjConnect(ontooltip := oDoc.getElementById("tooltipevent"), "tooltip_")
Всё равно растёт память.
MsgBox не всегда появляется, когда идёт сбор данных.
А если Critical добавить?
А если Critical добавить?
Так лучше.
Может что-то из этого у тебя в коде используется?
Дело в этом:
Например, при разработке графических компонент – бывает удобно присвоить DOM-элементу ссылку на JavaScript-объект, который представляет собой компонент. Это упрощает делегирование и, в общем-то, логично, что DOM-элемент знает о компоненте на себе. Но в IE8- прямая привязка ведёт к утечке памяти!
Убрал ссылки из элементов, решил перевести с IE 8 на IE 11, но почему то onmouseleave без ссылки в элементе нигде не работает.
#SingleInstance Force
#NoEnv
FixIE(1)
Gui, +DPIScale
Gui, Add, ActiveX, w444 h333 voDoc, HTMLFile
Gui, Show
html =
(
<script type="text/javascript">
onmouseover = function () {
// alert(window.event.srcElement.tagName + " onmouseover");
document.getElementById('info').innerText = window.event.srcElement.id + " onmouseover";
}
onmouseleave = function() {
alert(window.event.srcElement.id + " onmouseleave");
document.getElementById('info').innerText = window.event.srcElement.id + " onmouseleave";
}
onmousedown = function () {
document.getElementById('info').innerText = window.event.srcElement.id + " onmousedown";
}
onfocus = function () {
document.getElementById('info').innerText = window.event.srcElement.id + " onfocus";
}
onblur = function () {
document.getElementById('info').innerText = window.event.srcElement.id + " onblur";
}
</script>
)
oDoc.Write("<!DOCTYPE html><head><meta http-equiv=""X-UA-Compatible"" content=""IE=11""></head>" html)
oDoc.Close()
html =
(
<body>
<span id='span1'> span1 </span><br>
<span id='span2'> span2 </span><br>
<span id='span3'> span3 </span><br>
<input id='input'><br>
<span id='info'></span>
</body>
)
oDoc.body.innerhtml := html
return
+1:: MsgBox % oDoc.compatMode "`n" oDoc.documentMode
FixIE(Fix) {
Static Key := "Software\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION"
If A_IsCompiled
ExeName := A_ScriptName
Else
SplitPath, A_AhkPath, ExeName
RegRead, OutputVar, HKCU, %Key%, %ExeName%
If Fix
RegWrite, REG_DWORD, HKCU, %Key%, %ExeName%, 11000
Else
RegDelete, HKCU, %Key%, %ExeName%
}
Escape::
GuiEscape:
GuiClose:
ExitApp
Поменял на onmouseout.
Отвалилось свойство name, на нём построено выделение текста при наведении.
#SingleInstance Force
#NoEnv
FixIE(1)
Gui, +DPIScale
Gui, Add, ActiveX, w444 h333 voDoc, HTMLFile
Gui, Show
html =
(
<script type="text/javascript">
onmouseover = function () {
// alert(window.event.srcElement.tagName + " onmouseover");
document.getElementById('info').innerText = window.event.srcElement.id + "\nonmouseover\n" + window.event.srcElement.name
}
onmouseout = function() {
// alert(window.event.srcElement.id + " onmouseout");
document.getElementById('info').innerText = window.event.srcElement.id + "\nonmouseout\n" + window.event.srcElement.name
}
</script>
)
oDoc.Write("<!DOCTYPE html><head><meta http-equiv=""X-UA-Compatible"" content=""IE=11""></head>" html)
oDoc.Close()
html =
(
<body>
<span id='span1' name='name1'> span1 </span><br>
<span id='span2' name='name2'> span2 </span><br>
<span id='span3' name='name3'> span3 </span><br>
<input id='input' name='input'><br>
<span id='info'></span>
</body>
)
oDoc.body.innerhtml := html
return
+1:: MsgBox % oDoc.compatMode "`n" oDoc.documentMode
FixIE(Fix) {
Static Key := "Software\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION"
If A_IsCompiled
ExeName := A_ScriptName
Else
SplitPath, A_AhkPath, ExeName
RegRead, OutputVar, HKCU, %Key%, %ExeName%
If Fix
RegWrite, REG_DWORD, HKCU, %Key%, %ExeName%, 11001
Else
RegDelete, HKCU, %Key%, %ExeName%
}
Escape::
GuiEscape:
GuiClose:
ExitApp
Свойство name поменял на lang, но на 11 заметно больше тормозит.
https://raw.githubusercontent.com/serzh … 20ie11.ahk
На 8 не работают все сообщения, если их из атрибутов переместить в javascript.
#SingleInstance Force
#NoEnv
FixIE(1)
Gui, +DPIScale
Gui, Add, ActiveX, w444 h333 voDoc, HTMLFile
Gui, Show
html =
(
<script type="text/javascript">
onmousedown = function () {
alert(window.event.srcElement.tagName + " onmousedown");
document.getElementById('info').innerText = window.event.srcElement.id + "\n onmousedown\n" + window.event.srcElement.name
}
onmouseenter = function () {
alert(window.event.srcElement.tagName + " onmouseenter");
document.getElementById('info').innerText = window.event.srcElement.id + "\n onmouseenter\n" + window.event.srcElement.name
}
onmouseout = function() {
alert(window.event.srcElement.id + " onmouseout");
document.getElementById('info').innerText = window.event.srcElement.id + "\n onmouseout\n" + window.event.srcElement.name
}
</script>
)
oDoc.Write("<!DOCTYPE html><head><meta http-equiv=""X-UA-Compatible"" content=""IE=8""></head>" html)
oDoc.Close()
html =
(
<body>
<span name='name1' id='span1' > ёйя </span><br>
<span id='span2' name='name2'> span2 </span><br>
<span id='span3' name='name3'> span3 </span><br>
<input id='input' name='input'><br>
<span id='info'></span>
</body>
)
oDoc.body.innerhtml := html
; MsgBox % oDoc.getElementById("span1").name
return
+1:: MsgBox % oDoc.compatMode "`n" oDoc.documentMode
FixIE(Fix) {
Static Key := "Software\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION"
If A_IsCompiled
ExeName := A_ScriptName
Else
SplitPath, A_AhkPath, ExeName
RegRead, OutputVar, HKCU, %Key%, %ExeName%
If Fix
RegWrite, REG_DWORD, HKCU, %Key%, %ExeName%, 8000
Else
RegDelete, HKCU, %Key%, %ExeName%
}
Escape::
GuiEscape:
GuiClose:
ExitApp
4.22
В общем перенёс события в обработчик анк, и оказалось что у них другие имена, не те что были в атрибутах.
https://stackoverflow.com/questions/231 … onfocusout
4.30
При использовании якоря не должно мелькать. Большие правки в коде.
Вроде не мелькает, но утечка не прекратилась.
Не знаю с точки зрения компактности кода как расставить везде такие проверки
Думаю, придется либо оставлять как есть, либо пожертвовать компактностью и проверять перед каждым обращением к методу.
Или еще можно попробовать обнулять объект при данном событии.
У меня выше 70мб не поднимается. У тебя течёт также как в предыдущих, или медленнее?
Или еще можно попробовать обнулять объект при данном событии.
Сделал Acc глобальным, попробовал Acc := "", не помогает.
4.31
+ Dark theme
+ Font bold
У меня так получается:
Send {LWin}
sleep 500
hwnd := DllCall("FindWindowEx", "ptr", 0, "ptr", 0, "str", "Windows.UI.Core.CoreWindow", "str", "Start", "ptr")
DllCall("LoadLibrary","str","oleacc","ptr")
VarSetCapacity(IID_IAccessible, 16)
DllCall("ole32\CLSIDFromString", "wstr", "{618736e0-3c3d-11cf-810c-00aa00389b71}", "ptr", &IID_IAccessible)
DllCall("oleacc\AccessibleObjectFromWindow", "ptr", hwnd, "uint", OBJID_CLIENT := 0xFFFFFFFC, "ptr", &IID_IAccessible, "ptr*", pacc)
acc := ComObject(9, pacc, 1)
a := acc, acc := ""
msgbox % a.accName(0)
Send {LWin}
sleep 500
a := ""
msgbox % a.accName(0)
На счет памяти я до 70 не ждал, но она постоянно увеличивается, так что не вижу причины, почему она на 70 должна остановиться.
Проверял, держа курсор над taskmgr на вкладке details.
По поводу скорости сказать не могу, нужно засечь время и сравнивать 2 конкретные версии.
У меня так получается:
А зачем потом снова показывать пуск?
При появлении первого msgbox надо скрыть пуск, нажать ок, и тогда уже смотреть. У меня виснет как и всегда, до появления пуск.
Send {LWin}
sleep 500
hwnd := DllCall("FindWindowEx", "ptr", 0, "ptr", 0, "str", "Windows.UI.Core.CoreWindow", "str", "Начальный экран")
DllCall("LoadLibrary","str","oleacc","ptr")
VarSetCapacity(IID_IAccessible, 16)
DllCall("ole32\CLSIDFromString", "wstr", "{618736e0-3c3d-11cf-810c-00aa00389b71}", "ptr", &IID_IAccessible)
DllCall("oleacc\AccessibleObjectFromWindow", "ptr", hwnd, "uint", OBJID_CLIENT := 0xFFFFFFFC, "ptr", &IID_IAccessible, "ptr*", pacc)
acc := ComObject(9, pacc, 1)
a := acc
acc := ""
msgbox % a.accName(0)
sleep 500
a := ""
msgbox % a.accName(0)
Return
На счет памяти я до 70 не ждал
Не знаю, может сборщик мусора в IE не даёт больше расти.
Я имею в виду, что после создания объекта "acc", его нужно скопировать в новый объект "a", после чего "acc" освободить.
Пользоваться объектом "a", а при срабатывании события освобождать объект "a".
Не пойму, зная что окно скрыто, очищается "a", и при обращении к нему всё равно виснет, то есть он видимо и не очищается.
Ну да, виснет на строчке:
a := ""
Тогда так:
Send {LWin}
sleep 500
hwnd := DllCall("FindWindowEx", "ptr", 0, "ptr", 0, "str", "Windows.UI.Core.CoreWindow", "str", "Start", "ptr")
DllCall("LoadLibrary","str","oleacc","ptr")
VarSetCapacity(IID_IAccessible, 16)
DllCall("ole32\CLSIDFromString", "wstr", "{618736e0-3c3d-11cf-810c-00aa00389b71}", "ptr", &IID_IAccessible)
DllCall("oleacc\AccessibleObjectFromWindow", "ptr", hwnd, "uint", OBJID_CLIENT := 0xFFFFFFFC, "ptr", &IID_IAccessible, "ptr*", pacc)
acc := ComObject(9, pacc, 1), ObjAddRef(pacc)
Send {LWin}
sleep 500
acc := ""
msgbox done
Только нужно сохранять pacc и при следующем событии EVENT_OBJECT_UNCLOAKED окна "Windows.UI.Core.CoreWindow" освобождать pacc.
Не знаю, может сборщик мусора в IE не даёт больше расти.
До 90 дошло и дальше растет.
Спустя 10 минут - 120.
Сделал тест приближенный к программе, работает отлично без зависаний.
Интересно как тут можно сделать Acc неглобальным.
Только нужно сохранять pacc и при следующем событии EVENT_OBJECT_UNCLOAKED окна "Windows.UI.Core.CoreWindow" освобождать pacc.
ObjRelease(oPubObj.Acc.pacc) - правильно?
#SingleInstance Force
#NoEnv
#Persistent
#UseHook
SetWinEventHook("EVENT_OBJECT_CLOAKED", 0x8017)
SetWinEventHook("EVENT_OBJECT_UNCLOAKED", 0x8018)
Global oPubObj := {}
WM_GETOBJECT := 0x003D
If Not h
h := DllCall("LoadLibrary", "Str", "oleacc", "Ptr")
1::
Send {LWin}
sleep 800
MouseGetPos, mx, my, WinID, ControlID, 2
If DllCall("oleacc\AccessibleObjectFromPoint"
, "Int64", mx&0xFFFFFFFF|my<<32, "Ptr*", pacc
, "Ptr", VarSetCapacity(varChild,8+2*A_PtrSize,0)*0+&varChild) = 0
Acc := ComObject(9, pacc, 1)
ObjAddRef(pacc)
child := NumGet(varChild, 8, "UInt")
If !IsObject(Acc)
Return
oPubObj.Acc := {AccObj: Object(Acc), child: child, WinID: WinID, ControlID: ControlID, pacc: pacc}
SendMessage, WM_GETOBJECT, 0, 1, , ahk_id %ControlID%
msgbox,,, % acc.accName(child), 12
msgbox % acc.accName(child)
Return
Escape:: ExitApp
EVENT_OBJECT_CLOAKED(hWinEventHook, event, hwnd, idObject, idChild) {
Critical
Global Acc
If (idObject || idChild) || (hwnd != oPubObj.Acc.WinID)
Return
ToolTip % A_ThisFunc
Acc := ""
oPubObj.Acc.CLOAKED := 1
}
EVENT_OBJECT_UNCLOAKED(hWinEventHook, event, hwnd, idObject, idChild) {
Critical
If (idObject || idChild) || (hwnd != oPubObj.Acc.WinID)
Return
ToolTip % A_ThisFunc
ObjRelease(oPubObj.Acc.pacc)
oPubObj.Acc.CLOAKED := 0
}
SetWinEventHook(EventProc, eventMin, eventMax = 0) {
; DllCall("CoInitialize", UInt, 0)
Return DllCall("SetWinEventHook"
, "UInt", eventMin, "UInt", eventMax := !eventMax ? eventMin : eventMax
, "Ptr", hmodWinEventProc := 0, "Ptr", lpfnWinEventProc := RegisterCallback(EventProc, "F")
, "UInt", idProcess := 0, "UInt", idThread := 0
, "UInt", dwflags := 0x0|0x2, "Ptr") ;; WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS
}
В программе сделал идентично, иногда всё таки зависает, но реже чем было.
https://raw.githubusercontent.com/serzh … AhkSpy.ahk
Насчёт памяти, всё таки течёт, у меня видимо это происходит медленнее чем у тебя, и медленнее чем в прежних версиях.
Запускал тест без innerHTML, не растёт. Где ещё в HTML смотреть не знаю.
ObjRelease(oPubObj.Acc.pacc) - правильно?
Да. Но необязательно дожидаться нажатия старта, это может быть любое окно с классом Windows.UI.Core.CoreWindow.
Как я понимаю данный баг только с окнами этого класса и происходит.
4.35
Библиотеку UIA заменил на свой код.
После чего тестил память над окном диспетчера в режиме контрол с включенным UIA и Spot together, и выключенным accesible path, за час +15 мб, лучше чем было.
У меня перестал работать якорь.
Желтым выделяется, но позицию не сохраняет.
И желтым тоже не всегда выделяет.
Перекачал с гитхаб, всё норм. На всякий у тебя инклуда нет.
Понял в чем причина - у меня джаваскрипт в IE был отключен.
А как он отключился, ты сам в настройках выключил, или какое то ПО.
Сам. При этом раньше отключение джаваскрипта на позицию якоря не влияло.
Странно почему это изменилось. А возможно включить джаваскрипт только для скрипта?
Это изменилось, начиная с 4.30 версии.
А возможно включить джаваскрипт только для скрипта?
Не слышал о такой возможности.
Это изменилось, начиная с 4.30 версии.
Тогда понятно, я подумал ты про последнюю версию.
Хотя можно при запуске проверять в реестре настройки active script, если выключены, то включать, после чего запускать AhkSpy и менять настройки в реестре на изначальные.
На Win10 - Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\3 1400.
Сделал и прочитал твоё сообщение.
Active script allow change - Разрешить выполнение сценариев в Internet Explorer на время работы AhkSpy.
А зачем так сложно?
Просто без всяких меню, до загрузки ActiveX в гуи, проверяй настройки в реестре 1400 и если там не равно 0, то вставляй 0, создавай гуи, после чего вставляй изначальное значение.
Да, сразу после создания HTMLFile можно отменить, получается никакого ущерба безопасности.
В меню оставлю всё таки, может для кого это важно, но сделал по умолчанию включенным
По поводу UIA интерфейса.
При наведении на значок громкости у меня выдает следующие значения:
PID: 5236 ▪ HWND undefined
AutomationId: {7820AE73-23E3-4229-82C1-E41CB67D5B9C} ▪ ControlType: Button ▪ 0xC350 ▪ LocalizedControlType: button
ProcessName: explorer.exe ▪ ProcessPath: C:\Windows\explorer.exe
1) Не определяет hwnd (хотя inspect определяет).
2) Такого ControlType как Button в UIA нету, есть UIA_ButtonControlTypeId.
3) Такого свойства как ControlClass в UIA нету, а есть ClassName.
1) Не определяет hwnd (хотя inspect определяет).
ElementFromPoint не определяет, мне интересен именно он, поэтому надо знать где возвращает, а где нет.
Я UIA добавил из за AutomationId и ControlType под курсором, другого полезного я пока в интерфейсе не вижу (при наличии данных MSAA). Для более глубокого анализа UIA интерфейса сам понимаешь есть другие утилиты. Возможно в будущем можно сделать аналог "AccPath", думаю должно быть быстрее и надёжнее.
2) Такого ControlType как Button в UIA нету, есть UIA_ButtonControlTypeId.
Я делал на основе библиотеки jethrow, он правильно сделал что убрал обёртку UIA_*ControlTypeId, она ни к чему, и нигде не используется, а читается намного проще. Эта строка получается из пользовательского списка по индексу из CurrentControlType, поэтому уникален может быть только индекс.
3) Такого свойства как ControlClass в UIA нету, а есть ClassName.
Точнее CurrentClassName и CachedClassName.
Кстати не в курсе зачем все свойства делятся на Current и Cached. Не видел чтобы в Cached были данные.
Переименую в ClassName.
Возможно в будущем можно сделать аналог "AccPath", думаю должно быть быстрее и надёжнее
В UIA для этого есть встроенные методы типа: IUIAutomationElement::FindFirst.
Вот так тыкнет на значок громкости:
f11::
if !hVolume
{
ControlGet, hVolume, hwnd,, ToolbarWindow323, ahk_class Shell_TrayWnd
IUIAutomation := ComObjCreate(CLSID_CUIAutomation := "{ff48dba4-60ef-4201-aa87-54103eef594e}", IID_IUIAutomation := "{30cbe57d-d9d0-452a-ab13-7ac5ac4825ee}")
DllCall(NumGet(NumGet(IUIAutomation+0)+6*A_PtrSize), "ptr", IUIAutomation, "ptr", hVolume, "ptr*", tray) ; IUIAutomation::ElementFromHandle
VOLUME_GUID := DllCall("oleaut32\SysAllocString", "str", "{7820AE73-23E3-4229-82C1-E41CB67D5B9C}", "ptr")
VarSetCapacity(variant, 8+A_PtrSize*2, 0)
NumPut(VT_BSTR := 8, variant, 0, "ushort")
NumPut(VOLUME_GUID, variant, 8, "ptr")
if (A_PtrSize = 4)
DllCall(NumGet(NumGet(IUIAutomation+0)+23*A_PtrSize), "ptr", IUIAutomation, "int", UIA_AutomationIdPropertyId := 30011, "int64", NumGet(variant, 0, "int64"), "int64", NumGet(variant, 8, "int64"), "ptr*", condition) ; IUIAutomation::CreatePropertyCondition
else
DllCall(NumGet(NumGet(IUIAutomation+0)+23*A_PtrSize), "ptr", IUIAutomation, "int", UIA_AutomationIdPropertyId := 30011, "ptr", &variant, "ptr*", condition) ; IUIAutomation::CreatePropertyCondition
DllCall("oleaut32\SysFreeString", "ptr", VOLUME_GUID)
VarSetCapacity(GUID, 16)
DllCall("ole32\CLSIDFromString", "wstr", IID_IUIAutomationLegacyIAccessiblePattern := "{828055ad-355b-4435-86d5-3b51c14a9b1b}", "ptr", &GUID)
}
DllCall(NumGet(NumGet(tray+0)+5*A_PtrSize), "ptr", tray, "int", TreeScope_Descendants := 0x4, "ptr", condition, "ptr*", element) ; IUIAutomationElement::FindFirst
DllCall(NumGet(NumGet(element+0)+14*A_PtrSize), "ptr", element, "int", UIA_LegacyIAccessiblePatternId := 10018, "ptr", &GUID, "ptr*", legacy) ; IUIAutomationElement::GetCurrentPatternAs
DllCall(NumGet(NumGet(legacy+0)+4*A_PtrSize), "ptr", legacy) ; IUIAutomationLegacyIAccessiblePattern::DoDefaultAction
ObjRelease(element)
ObjRelease(legacy)
Я делал на основе библиотеки jethrow, он правильно сделал что убрал обёртку UIA_*ControlTypeId, она ни к чему, и нигде не используется, а читается намного проще.
И по-моему зря. Для того, чтобы читалось проще есть LocalizedControlType.
Во всяком случае, в других утилитах я такого сокращения не встречал.
Эта строка получается из пользовательского списка по индексу из CurrentControlType, поэтому уникален может быть только индекс
Может тогда его как-то приписать к ControlType, а то он сейчас висит отдельно:
ControlType: Pane ▪ 0xC371 ▪ LocalizedControlType: pane
Точнее CurrentClassName и CachedClassName
Нет.
UIA_ClassNamePropertyId
30012Identifies the ClassName property, which is a string containing the class name for the automation element as assigned by the control developer.
The class name depends on the implementation of the UI Automation provider and therefore is not always in a standard format. However, if the class name is known, it can be used to verify that an application is working with the expected automation element.
Variant type: VT_BSTR
Default value: empty string
https://docs.microsoft.com/en-us/window … nt-propids
зачем все свойства делятся на Current и Cached
В UIA для этого есть встроенные методы типа: IUIAutomationElement::FindFirst.
Да видел, там их достаточно, главное есть Compare для создания пути.
Может тогда его как-то приписать к ControlType, а то он сейчас висит отдельно:
Оно как бы между ControlType и LocalizedControlType, в целях экономии места, не хочется добавлять строку "ControlType index".
UIA_ClassNamePropertyId
Интересно. Вижу у тебя в коде есть UIA_AutomationIdPropertyId := 30011, но не пойму как извлечь строку, можешь привести пример.
Current и Cached
Не уверен что точно понял - можно отправить запрос о кэшировании, и после более производительно извлекать значения свойств на момент запроса?
Всплыл ещё нюанс с "Windows.UI.Core.CoreWindow" или скорее с WinGet ProcessName, WinGet не работает с ним по PID, при том что по хэндлу работает.
Send {LWin}
sleep 500
hwnd := DllCall("FindWindowEx", "ptr", 0, "ptr", 0, "str", "Windows.UI.Core.CoreWindow", "str", "Начальный экран", "ptr")
WinGet, WinPID, PID, ahk_id %hwnd%
WinGet, WinProcessName, ProcessName, ahk_pid %WinPID%
; WinGet, WinProcessName, ProcessName, ahk_id %hwnd%
MsgBox % WinProcessName
MsgBox % hwnd "`n" WinPID
Return
Вижу у тебя в коде есть UIA_AutomationIdPropertyId := 30011, но не пойму как извлечь строку, можешь привести пример.
Не понимаю, что ты хочешь?
можно отправить запрос о кэшировании, и после более производительно извлекать значения свойств на момент запроса?
Типа да, но я не пробовал.
WinGet ProcessName, WinGet не работает с ним по PID,
Да, тут мы обсуждали:
https://www.autohotkey.com/boards/viewt … 21#p324621
Было бы неплохо EnumWindows заменить, но не уверен, что lexikos будет с этим возиться.
Не понимаю, что ты хочешь?
Ты предлагал выводить UIA_ClassNamePropertyId, я не понимаю как получать его строковое значение.
Типа да, но я не пробовал.
У nepter был такой код, сейчас этого нет в его репо.
https://github.com/neptercn/UIAutomation
#SingleInstance,force
#Persistent
#Include uia.ahk
CoordMode,mouse,screen
global $n:={} ; store tree node
,$u:=new IUIAutomation
,$e:=new IUIAutomationElement
,$c:=new IUIAutomationCondition
,$r:=new IUIAutomationCacheRequest
,$t:=new IUIAutomationTreeWalker
global $x:=ComObjCreate("MSXML2.DOMDocument")
$x.setProperty("SelectionLanguage","XPath")
gui,1:add,TreeView,w300 h600 gtvevent
gui,1:add,tab2,X+5 yp w500 +0x100,% " Info | Pool | Tree2Xml | Xml2AHK | Settings | Help "
gui,1:tab,1
gui,1:add,edit,w500 h580 X+0 Y+0 vedit1 ReadOnly -wrap HScroll
return
1::
F8::
MouseGetPos,x,y,hwnd, hc, 2
BuildElementTree(hc)
gui,1:show
return
tvevent:
if A_GuiEvent = S
ShowSelection(TV_GetSelection())
return
BuildElementTree(hwnd){
static init:=1,root,_r
if init{
init:=0, root:=$u.GetRootElement(), $r.(_r:=$u.CreateCacheRequest()).TreeScope:=UIA_Enum("TreeScope_Subtree"), t:={}
loop 111
t.Insert(29999+A_Index) ;Array to contain UIA_Properties
$r.AddProperty(t)
}
for k,v in $n
ObjRelease(v)
$n:={}, TV_Delete()
;msgbox, % hwnd
_e:=$u.ElementFromHandleBuildCache(hwnd,_r)
;msgbox, % """" . $e.(_e).CachedName() . """"
if (!_e){
msgbox, An error occurred while getting element. Reloading application...
reload
}
if $u.CompareElements(_e,root)
return ;Do nothing if F8 while desktop selected ; ToDo: EventBased cache search
$n[id:=TV_Add($e.(_e).CachedName())]:=_e
,((type:=$e.GetCachedPropertyValue(UIA_Property("ControlType")))=UIA_ControlType("Menu"))||(type=UIA_ControlType("ToolBar"))?AddNode(_e,id,1):AddNode(_e,id)
; AddChildren(_e,id)
}
AddNode(element,id,mode=0){
static init:=1,_r,_t
if init{
init:=0,$t.(_t:=$u.RawViewWalker()),$r.(_r:=$u.CreateCacheRequest()).TreeScope:=1, t:={}
loop 111
t.Insert(29999+A_Index)
$r.3(t)
}
if mode{
if (newElement:=$t.GetCurrentPropertyValue(element,_r)){
$n[newId:=TV_Add("""" $e.(newElement).CachedName() """ " $e.CachedLocalizedControlType(),id)]:=newElement
,((type:=$e.GetCachedPropertyValue(UIA_Property("ControlType")))=UIA_ControlType("Menu"))||(type=UIA_ControlType("ToolBar"))?AddNode(newElement,newId,1):AddNode(newElement,newId)
loop
if (newElement:=$t.GetCachedPropertyValue(newElement,_r))
$n[newId:=TV_Add("""" $e.(newElement).CachedName() """ " $e.CachedLocalizedControlType(),id)]:=newElement
,((type:=$e.GetCachedPropertyValue(UIA_Property("ControlType")))=UIA_ControlType("Menu"))||(type=UIA_ControlType("ToolBar"))?AddNode(newElement,newId,1):AddNode(newElement,newId)
else break
}
}else{
if !array:=$e.(element).GetCachedChildren()
return
loop % $e.(array).length()
$n[newId:=TV_Add("""" $e.(newElement:=$e.(array).element(A_Index-1)).CachedName() """ " $e.CachedLocalizedControlType(),id)]:=newElement
,((type:=$e.GetCachedPropertyValue(UIA_Property("ControlType")))=UIA_ControlType("Menu"))||(type=UIA_ControlType("ToolBar"))?AddNode(newElement,newId,1):AddNode(newElement,newId)
ObjRelease(array)
}
}
AddChildren(element,id){
if !array:=$e.(element).GetCachedChildren()
return
loop % $e.(array).length()
$n[newId:=TV_Add("""" $e.(newElement:=$e.(array).element(A_Index-1)).CachedName() """ " $e.CachedLocalizedControlType(),id)]:=newElement
,AddChildren(newElement,newId)
ObjRelease(array)
}
AddRawNode(e,id,pid){ ; RawTreeWalker, slow speed
static init:=1,_r,_t
if init{
init:=0,$t.(_t:=$u.RawViewWalker()),$r.(_r:=$u.CreateCacheRequest()).TreeScope:=UIA_Enum("TreeScope_Element"), t:={}
loop 111
t.Insert(29999+A_Index)
$r.AddProperty(t)
}
if ne:=$t.GetCurrentPropertyValue(e,_r){
$n[nid:=TV_Add("""" $e.(ne).CachedName() """ " $e.CachedLocalizedControlType(),id)]:=ne
AddRawNode(ne,nid,id)
}
if (pid!=0) && (ne:=$t.GetCachedPropertyValue(e,_r)){
$n[nid:=TV_Add("""" $e.(ne).CachedName() """ " $e.CachedLocalizedControlType(),pid)]:=ne
AddRawNode(ne,nid,pid)
}
}
ShowSelection(id){
global edit1
$e.($n[id]) ; UIA_Property("")
cont:="Name: " $e.GetCachedPropertyValue(UIA_Property("Name")) "`n"
. "ControlType: " UIA_ControlType($e.GetCachedPropertyValue(UIA_Property("ControlType"))) "`n" ;
. "LocalizedControlType: " $e.GetCachedPropertyValue(UIA_Property("LocalizedControlType")) "`n" ;
. "BoundingRectangle: " BoundingRectangle($e.GetCachedPropertyValue(UIA_Property("BoundingRectangle"))) "`n" ;
. "IsEnabled: " Bool($e.GetCachedPropertyValue(UIA_Property("IsEnabled"))) "`n" ;
. "IsOffscreen: " Bool($e.GetCachedPropertyValue(UIA_Property("IsOffscreen"))) "`n" ;
. "IsKeyboardFocusable: " Bool($e.GetCachedPropertyValue(UIA_Property("IsKeyboardFocusable"))) "`n" ;
. "HasKeyboardFocus: " Bool($e.GetCachedPropertyValue(UIA_Property("HasKeyboardFocus"))) "`n" ;
. "AccessKey: " $e.GetCachedPropertyValue(UIA_Property("AccessKey")) "`n" ;
. "ProcessId: " $e.GetCachedPropertyValue(UIA_Property("ProcessId")) "`n" ;
. "RuntimeId: " RuntimeId($e.GetCachedPropertyValue(UIA_Property("RuntimeId"))) "`n" ;
. "AutomationId: " $e.GetCachedPropertyValue(UIA_Property("AutomationId")) "`n" ;
. "FrameworkId: " $e.GetCachedPropertyValue(UIA_Property("FrameworkId")) "`n" ;
. "ClassName: " $e.GetCachedPropertyValue(UIA_Property("ClassName")) "`n" ;
. "NativeWindowHandle: " $e.GetCachedPropertyValue(UIA_Property("NativeWindowHandle")) "`n" ;
. "IsContentElement: " Bool($e.GetCachedPropertyValue(UIA_Property("IsContentElement"))) "`n" ;
. "ProviderDescription: " $e.GetCachedPropertyValue(UIA_Property("IsContentElement")) "`n" ;
. "IsPassword: " Bool($e.GetCachedPropertyValue(UIA_Property("IsPassword"))) "`n" ;
. "HelpText: " $e.GetCachedPropertyValue(UIA_Property("HelpText")) "`n" ;
cont.="IsDockPatternAvailable: " Bool($e.GetCachedPropertyValue(UIA_Property("IsDockPatternAvailable"))) "`n" ;
cont.=$e.GetCachedPropertyValue(UIA_Property("IsDockPatternAvailable"))? "DockDockPosition: " $e.GetCachedPropertyValue(UIA_Property("DockDockPosition")) "`n" :"" ;
cont.="IsExpandCollapsePatternAvailable: " Bool($e.GetCachedPropertyValue(UIA_Property("IsExpandCollapsePatternAvailable"))) "`n" ;
cont.=$e.GetCachedPropertyValue(UIA_Property("IsExpandCollapsePatternAvailable"))?"ExpandCollapseExpandCollapseState: " $e.GetCachedPropertyValue(UIA_Property("ExpandCollapseExpandCollapseState")) "`n" :"" ;
cont.="IsGridItemPatternAvailable: " Bool($e.GetCachedPropertyValue(UIA_Property("IsGridItemPatternAvailable"))) "`n" ;
cont.=$e.GetCachedPropertyValue(UIA_Property("IsGridItemPatternAvailable"))? getGridPattern($e):""
cont.="IsGridPatternAvailable: " Bool($e.GetCachedPropertyValue(UIA_Property("IsGridPatternAvailable"))) "`n" ;
cont.=$e.GetCachedPropertyValue(UIA_Property("IsGridPatternAvailable"))? getGridPattern($e) : ""
cont.="IsInvokePatternAvailable: " Bool($e.GetCachedPropertyValue(UIA_Property("IsInvokePatternAvailable"))) "`n" ;
cont.="IsItemContainerPatternAvailable: " Bool($e.GetCachedPropertyValue(UIA_Property("IsItemContainerPatternAvailable"))) "`n" ;
cont.="IsLegacyIAccessiblePatternAvailable:" Bool($e.GetCachedPropertyValue(UIA_Property("IsLegacyIAccessiblePatternAvailable"))) "`n" ;
cont.=$e.GetCachedPropertyValue(UIA_Property("IsLegacyIAccessiblePatternAvailable"))? getLegacyPattern($e) : ""
cont.="IsMultipleViewPatternAvailable: " Bool($e.GetCachedPropertyValue(UIA_Property("IsMultipleViewPatternAvailable"))) "`n" ;
cont.=$e.GetCachedPropertyValue(UIA_Property("IsMultipleViewPatternAvailable"))? getMultiviewPattern($e) : ""
cont.="IsRangeValuePatternAvailable: " Bool($e.GetCachedPropertyValue(UIA_Property("IsRangeValuePatternAvailable"))) "`n" ;
cont.=$e.GetCachedPropertyValue(UIA_Property("IsRangeValuePatternAvailable"))? getRangePattern($e) : ""
cont.="IsScrollItemPatternAvailable: " Bool($e.GetCachedPropertyValue(UIA_Property("IsScrollItemPatternAvailable"))) "`n" ;
cont.="IsScrollPatternAvailable: " Bool($e.GetCachedPropertyValue(UIA_Property("IsScrollPatternAvailable"))) "`n" ;
cont.=$e.GetCachedPropertyValue(UIA_Property("IsScrollPatternAvailable"))? getScrollPattern($e) : ""
cont.="IsSelectionItemPatternAvailable: " Bool($e.GetCachedPropertyValue(UIA_Property("IsSelectionItemPatternAvailable"))) "`n" ;
cont.=$e.GetCachedPropertyValue(UIA_Property("IsSelectionItemPatternAvailable"))? getSelectionItemPattern($e) : ""
cont.="IsSelectionPatternAvailable: " Bool($e.GetCachedPropertyValue(UIA_Property("IsSelectionPatternAvailable"))) "`n" ;
cont.=$e.GetCachedPropertyValue(UIA_Property("IsSelectionPatternAvailable"))? getSelectionPattern($e) : ""
cont.="IsSynchronizedInputPatternAvailable:" Bool($e.GetCachedPropertyValue(UIA_Property("IsSynchronizedInputPatternAvailable"))) "`n" ;
cont.="IsTablePatternAvailable: " Bool($e.GetCachedPropertyValue(UIA_Property("IsTablePatternAvailable"))) "`n" ;
cont.=$e.GetCachedPropertyValue(UIA_Property("IsTablePatternAvailable"))? getTablePattern($e) : ""
cont.="IsTextPatternAvailable: " Bool($e.GetCachedPropertyValue(UIA_Property("IsTextPatternAvailable"))) "`n" ;
cont.="IsTogglePatternAvailable: " Bool($e.GetCachedPropertyValue(UIA_Property("IsTogglePatternAvailable"))) "`n" ;
cont.=$e.GetCachedPropertyValue(UIA_Property("IsTogglePatternAvailable"))? getTogglePattern($e) : ""
cont.="IsTransformPatternAvailable: " Bool($e.GetCachedPropertyValue(UIA_Property("IsTransformPatternAvailable"))) "`n" ;
cont.=$e.GetCachedPropertyValue(UIA_Property("IsTransformPatternAvailable"))? getTransformPattern($e) : ""
cont.="IsValuePatternAvailable: " Bool($e.GetCachedPropertyValue(UIA_Property("IsValuePatternAvailable"))) "`n" ;
cont.=$e.GetCachedPropertyValue(UIA_Property("IsValuePatternAvailable"))? getValuePattern($e) : ""
cont.="IsVirtualizedItemPatternAvailable: " Bool($e.GetCachedPropertyValue(UIA_Property("IsVirtualizedItemPatternAvailable"))) "`n" ;
cont.="IsWindowPatternAvailable: " Bool($e.GetCachedPropertyValue(UIA_Property("IsWindowPatternAvailable"))) "`n" ;
cont.=$e.GetCachedPropertyValue(UIA_Property("IsWindowPatternAvailable"))?getWindowPattern($e): ""
GuiControl,1:,edit1,% cont
}
getGridItemPattern($e){
cont:="GridItemRow: " $e.GetCachedPropertyValue(UIA_Property("GridItemRow")) "`n"
. "GridItemColumn: " $e.GetCachedPropertyValue(UIA_Property("GridItemColumn")) "`n"
. "GridItemRowSpan: " $e.GetCachedPropertyValue(UIA_Property("GridItemRowSpan")) "`n"
. "GridItemColumnSpan: " $e.GetCachedPropertyValue(UIA_Property("GridItemColumnSpan")) "`n"
. "GridItemContainingGrid: " $e.GetCachedPropertyValue(UIA_Property("GridItemContainingGrid")) "`n"
return cont
}
getGridPattern($e){
cont:="GridRowCount: " $e.GetCachedPropertyValue(UIA_Property("GridRowCount")) "`n"
. "GridColumnCount: " $e.GetCachedPropertyValue(UIA_Property("GridColumnCount")) "`n"
return cont
}
getLegacyPattern($e){
cont:="LegacyIAccessibleChildId: " $e.GetCachedPropertyValue(UIA_Property("LegacyIAccessibleChildId")) "`n"
. "LegacyIAccessibleName: " $e.GetCachedPropertyValue(UIA_Property("LegacyIAccessibleName")) "`n"
. "LegacyIAccessibleValue: " $e.GetCachedPropertyValue(UIA_Property("LegacyIAccessibleValue")) "`n"
. "LegacyIAccessibleDescription: " $e.GetCachedPropertyValue(UIA_Property("LegacyIAccessibleDescription")) "`n"
. "LegacyIAccessibleRole: " $e.GetCachedPropertyValue(UIA_Property("LegacyIAccessibleRole")) "`n"
. "LegacyIAccessibleState: " $e.GetCachedPropertyValue(UIA_Property("LegacyIAccessibleState")) "`n"
. "LegacyIAccessibleHelp: " $e.GetCachedPropertyValue(UIA_Property("LegacyIAccessibleHelp")) "`n"
. "LegacyIAccessibleKeyboardShortcut: " $e.GetCachedPropertyValue(UIA_Property("LegacyIAccessibleKeyboardShortcut")) "`n"
. "LegacyIAccessibleSelection: " $e.GetCachedPropertyValue(UIA_Property("LegacyIAccessibleSelection")) "`n"
. "LegacyIAccessibleDefaultAction: " $e.GetCachedPropertyValue(UIA_Property("LegacyIAccessibleDefaultAction")) "`n"
return cont
}
getMultiviewPattern($e){
cont:="MultipleViewCurrentView: " $e.GetCachedPropertyValue(UIA_Property("MultipleViewCurrentView")) "`n"
. "MultipleViewSupportedViews: " $e.GetCachedPropertyValue(UIA_Property("MultipleViewSupportedViews")) "`n"
return cont
}
getRangePattern($e){
cont:="RangeValueValue: " $e.GetCachedPropertyValue(UIA_Property("RangeValueValue")) "`n"
. "RangeValueIsReadOnly: " $e.GetCachedPropertyValue(UIA_Property("RangeValueIsReadOnly")) "`n"
. "RangeValueMinimum: " $e.GetCachedPropertyValue(UIA_Property("RangeValueMinimum")) "`n"
. "RangeValueMaximum: " $e.GetCachedPropertyValue(UIA_Property("RangeValueMaximum")) "`n"
. "RangeValueLargeChange: " $e.GetCachedPropertyValue(UIA_Property("RangeValueLargeChange")) "`n"
. "RangeValueSmallChange: " $e.GetCachedPropertyValue(UIA_Property("RangeValueSmallChange")) "`n"
return cont
}
getScrollPattern($e){
cont:="ScrollHorizontalScrollPercent: " $e.GetCachedPropertyValue(UIA_Property("ScrollHorizontalScrollPercent")) "`n"
. "ScrollHorizontalViewSize: " $e.GetCachedPropertyValue(UIA_Property("ScrollHorizontalViewSize")) "`n"
. "ScrollVerticalScrollPercent: " $e.GetCachedPropertyValue(UIA_Property("ScrollVerticalScrollPercent")) "`n"
. "ScrollVerticalViewSize: " $e.GetCachedPropertyValue(UIA_Property("ScrollVerticalViewSize")) "`n"
. "ScrollHorizontallyScrollable: " $e.GetCachedPropertyValue(UIA_Property("ScrollHorizontallyScrollable")) "`n"
. "ScrollVerticallyScrollable: " $e.GetCachedPropertyValue(UIA_Property("ScrollVerticallyScrollable")) "`n"
return cont
}
getSelectionItemPattern($e){
cont:="SelectionItemIsSelected: " $e.GetCachedPropertyValue(UIA_Property("SelectionItemIsSelected")) "`n"
. "SelectionItemSelectionContainer: " $e.GetCachedPropertyValue(UIA_Property("SelectionItemSelectionContainer")) "`n"
return cont
}
getSelectionPattern($e){
cont:="SelectionSelection: " $e.GetCachedPropertyValue(UIA_Property("SelectionSelection")) "`n"
. "SelectionCanSelectMultiple: " $e.GetCachedPropertyValue(UIA_Property("SelectionCanSelectMultiple")) "`n"
. "SelectionIsSelectionRequired: " $e.GetCachedPropertyValue(UIA_Property("SelectionIsSelectionRequired")) "`n"
return cont
}
getTablePattern($e){
cont:="TableRowHeaders: " $e.GetCachedPropertyValue(UIA_Property("TableRowHeaders")) "`n"
. "TableColumnHeaders: " $e.GetCachedPropertyValue(UIA_Property("TableColumnHeaders")) "`n"
. "TableRowOrColumnMajor: " $e.GetCachedPropertyValue(UIA_Property("TableRowOrColumnMajor")) "`n"
. "TableItemRowHeaderItems: " $e.GetCachedPropertyValue(UIA_Property("TableItemRowHeaderItems")) "`n"
. "TableItemColumnHeaderItems: " $e.GetCachedPropertyValue(UIA_Property("TableItemColumnHeaderItems")) "`n"
return cont
}
getTogglePattern($e){
cont:="ToggleToggleState: " $e.GetCachedPropertyValue(UIA_Property("ToggleToggleState")) "`n"
return cont
}
getTransformPattern($e){
cont:="TransformCanMove: " Bool($e.GetCachedPropertyValue(UIA_Property("TransformCanMove"))) "`n"
. "TransformCanResize: " Bool($e.GetCachedPropertyValue(UIA_Property("TransformCanResize"))) "`n"
. "TransformCanRotate: " Bool($e.GetCachedPropertyValue(UIA_Property("TransformCanRotate"))) "`n"
return cont
}
getValuePattern($e){
cont:="ValueValue: " $e.GetCachedPropertyValue(UIA_Property("ValueValue")) "`n"
. "ValueIsReadOnly: " Bool($e.GetCachedPropertyValue(UIA_Property("ValueIsReadOnly"))) "`n"
return cont
}
getWindowPattern($e){
cont:="WindowCanMaximize: " Bool($e.GetCachedPropertyValue(UIA_Property("WindowCanMaximize"))) "`n"
. "WindowCanMinimize: " Bool($e.GetCachedPropertyValue(UIA_Property("WindowCanMinimize"))) "`n"
. "WindowWindowVisualState: " $e.GetCachedPropertyValue(UIA_Property("WindowWindowVisualState")) "`n"
. "WindowWindowInteractionState: " $e.GetCachedPropertyValue(UIA_Property("WindowWindowInteractionState")) "`n"
. "WindowIsModal: " Bool($e.GetCachedPropertyValue(UIA_Property("WindowIsModal"))) "`n"
. "WindowIsTopmost: " Bool($e.GetCachedPropertyValue(UIA_Property("WindowIsTopmost"))) "`n"
return cont
}
;;
;;Output Function
;;
RuntimeId(p){
SetFormat,integer,hex
VarSetCapacity(a,4)
for k,v in p
NumPut(v,a,"int")
,s.=SubStr(NumGet(a,"uint"),3) "."
StringTrimRight,s,s,1
SetFormat,integer,d
return s
}
BoundingRectangle(t){
return (IsObject(t)?"l:" SubStr(t.1,1,InStr(t.1,".")-1) " t:" SubStr(t.2,1,InStr(t.2,".")-1) " w:" SubStr(t.3,1,InStr(t.3,".")-1) " h:" SubStr(t.4,1,InStr(t.4,".")-1):)
}
Bool(b){
return b?"True":"False"
}
;;
;;Tree Functions
;;
AnalysisTree(id){
$x.loadxml("")
AnalysisNode(id)
}
AnalysisNode(id){
; check Control Type
if !newId:=TV_GetChild(id)
return
loop {
ct:=$e.($n[newId]).GetCachedPropertyValue(30003)
if (ct=50000){ ;Button
}else if (ct=50001){ ;Calendar
}else if (ct=50002){ ;CheckBox
}else if (ct=50003){ ;ComboBox
}else if (ct=50004){ ;Edit
}else if (ct=50005){ ;link
}else if (ct=50006){ ;Image
}else if (ct=50007){ ;ListItem
}else if (ct=50008){ ;ListView
}else if (ct=50009){ ;Menu
}else if (ct=50010){ ;MenuBar
GetMenuBar(newId)
}else if (ct=50011){ ;MenuItem
}else if (ct=50012){ ;ProgressBar
}else if (ct=50013){ ;Radio
}else if (ct=50017){ ;StatusBar
}else if (ct=50018){ ;Tab
}else if (ct=50019){ ;Tab Item
}else if (ct=50020){ ;Text
}else if (ct=50021){ ;ToolBar
}else if (ct=50023){ ;TreeView
}else if (ct=50032){ ;Window
}else if (ct=50033){ ;pane
}else if (ct=50034){ ;Header
}else if (ct=50035){ ;HeaderItem
}else if (ct=50037){ ;TitleBar
}else{
}
if !newId:=TV_GetNext(newId)
break
}
}
Winget(id){
if !hwnd:=$e.($n[id]).GetCachedPropertyValue(30020)
return
SetFormat,integer,hex
WinGet,style,style,ahk_id %hwnd%
WinGet,exstyle,exstyle,ahk_id %hwnd%
WinGetClass,class,ahk_id %hwnd%
SetFormat,integer,d
return {hwnd:hwnd,class:class,style:style,exstyle:exstyle}
}
GetMenuBar(id){
}
;;
;;xml to AHK code
;;
xml2ahk(){
}
Ты предлагал выводить UIA_ClassNamePropertyId, я не понимаю как получать его строковое значение.
Так ты же его получаешь через метод IUIAutomationElement::CurrentClassName.
Ну да, у него много чего интересного было - только никому это не нужно.
А времени потратил, думаю, вагон и маленькую тележку.
Да и есть у него этот код:
https://github.com/neptercn/UIAutomatio … oneGui.ahk
Я UIA добавил из за AutomationId и ControlType под курсором, другого полезного я пока в интерфейсе не вижу (при наличии данных MSAA).
Еще через UIA можно посылать действия на кнопки переключения, через MSAA нельзя.
Тут рассматривали:
https://www.autohotkey.com/boards/viewt … mp;t=69627
Да и есть у него этот код:
Ага, не посмотрел, у меня файл по другому называется.
Так ты же его получаешь через метод IUIAutomationElement::CurrentClassName.
Значит я тебя не так понял.
Точнее CurrentClassName и CachedClassName
Нет.
UIA_ClassNamePropertyId
30012
В чём тогда разница этих свойств?
class IUIAutomationElement
{
__new(){
this._p:=0,this._i:={0:"QueryInterface",1:"AddRef",2:"Release",3:"SetFocus",4:"GetRuntimeId",5:"FindFirst",6:"FindAll",7:"FindFirstBuildCache",8:"FindAllBuildCache",9:"BuildUpdatedCache",10:"GetCurrentPropertyValue",11:"GetCurrentPropertyValueEx",12:"GetCachedPropertyValue",13:"GetCachedPropertyValueEx",14:"GetCurrentPatternAs",15:"GetCachedPatternAs",16:"GetCurrentPattern",17:"GetCachedPattern",18:"GetCachedParent",19:"GetCachedChildren",20:"CurrentProcessId",21:"CurrentControlType",22:"CurrentLocalizedControlType",23:"CurrentName",24:"CurrentAcceleratorKey",25:"CurrentAccessKey",26:"CurrentHasKeyboardFocus",27:"CurrentIsKeyboardFocusable",28:"CurrentIsEnabled",29:"CurrentAutomationId",30:"CurrentClassName",31:"CurrentHelpText",32:"CurrentCulture",33:"CurrentIsControlElement",34:"CurrentIsContentElement",35:"CurrentIsPassword",36:"CurrentNativeWindowHandle",37:"CurrentItemType",38:"CurrentIsOffscreen",39:"CurrentOrientation",40:"CurrentFrameworkId",41:"CurrentIsRequiredForForm",42:"CurrentItemStatus",43:"CurrentBoundingRectangle",44:"CurrentLabeledBy",45:"CurrentAriaRole",46:"CurrentAriaProperties",47:"CurrentIsDataValidForForm",48:"CurrentControllerFor",49:"CurrentDescribedBy",50:"CurrentFlowsTo",51:"CurrentProviderDescription",52:"CachedProcessId",53:"CachedControlType",54:"CachedLocalizedControlType",55:"CachedName",56:"CachedAcceleratorKey",57:"CachedAccessKey",58:"CachedHasKeyboardFocus",59:"CachedIsKeyboardFocusable",60:"CachedIsEnabled",61:"CachedAutomationId",62:"CachedClassName",63:"CachedHelpText",64:"CachedCulture",65:"CachedIsControlElement",66:"CachedIsContentElement",67:"CachedIsPassword",68:"CachedNativeWindowHandle",69:"CachedItemType",70:"CachedIsOffscreen",71:"CachedOrientation",72:"CachedFrameworkId",73:"CachedIsRequiredForForm",74:"CachedItemStatus",75:"CachedBoundingRectangle",76:"CachedLabeledBy",77:"CachedAriaRole",78:"CachedAriaProperties",79:"CachedIsDataValidForForm",80:"CachedControllerFor",81:"CachedDescribedBy",82:"CachedFlowsTo",83:"CachedProviderDescription",84:"GetClickablePoint"}
}
UIA_Property(n){
static id:={RuntimeId:30000,BoundingRectangle:30001,ProcessId:30002,ControlType:30003,LocalizedControlType:30004,Name:30005,AcceleratorKey:30006,AccessKey:30007,HasKeyboardFocus:30008,IsKeyboardFocusable:30009,IsEnabled:30010,AutomationId:30011,ClassName:30012,HelpText:30013,ClickablePoint:30014,Culture:30015,IsControlElement:30016,IsContentElement:30017,LabeledBy:30018,IsPassword:30019,NativeWindowHandle:30020,ItemType:30021,IsOffscreen:30022,Orientation:30023,FrameworkId:30024,IsRequiredForForm:30025,ItemStatus:30026,IsDockPatternAvailable:30027,IsExpandCollapsePatternAvailable:30028,IsGridItemPatternAvailable:30029,IsGridPatternAvailable:30030,IsInvokePatternAvailable:30031,IsMultipleViewPatternAvailable:30032,IsRangeValuePatternAvailable:30033,IsScrollPatternAvailable:30034,IsScrollItemPatternAvailable:30035,IsSelectionItemPatternAvailable:30036,IsSelectionPatternAvailable:30037,IsTablePatternAvailable:30038,IsTableItemPatternAvailable:30039,IsTextPatternAvailable:30040,IsTogglePatternAvailable:30041,IsTransformPatternAvailable:30042,IsValuePatternAvailable:30043,IsWindowPatternAvailable:30044,ValueValue:30045,ValueIsReadOnly:30046,RangeValueValue:30047,RangeValueIsReadOnly:30048,RangeValueMinimum:30049,RangeValueMaximum:30050,RangeValueLargeChange:30051,RangeValueSmallChange:30052,ScrollHorizontalScrollPercent:30053,ScrollHorizontalViewSize:30054,ScrollVerticalScrollPercent:30055,ScrollVerticalViewSize:30056,ScrollHorizontallyScrollable:30057,ScrollVerticallyScrollable:30058,SelectionSelection:30059,SelectionCanSelectMultiple:30060,SelectionIsSelectionRequired:30061,GridRowCount:30062,GridColumnCount:30063,GridItemRow:30064,GridItemColumn:30065,GridItemRowSpan:30066,GridItemColumnSpan:30067,GridItemContainingGrid:30068,DockDockPosition:30069,ExpandCollapseExpandCollapseState:30070,MultipleViewCurrentView:30071,MultipleViewSupportedViews:30072,WindowCanMaximize:30073,WindowCanMinimize:30074,WindowWindowVisualState:30075,WindowWindowInteractionState:30076,WindowIsModal:30077,WindowIsTopmost:30078,SelectionItemIsSelected:30079,SelectionItemSelectionContainer:30080,TableRowHeaders:30081,TableColumnHeaders:30082,TableRowOrColumnMajor:30083,TableItemRowHeaderItems:30084,TableItemColumnHeaderItems:30085,ToggleToggleState:30086,TransformCanMove:30087,TransformCanResize:30088,TransformCanRotate:30089,IsLegacyIAccessiblePatternAvailable:30090,LegacyIAccessibleChildId:30091,LegacyIAccessibleName:30092,LegacyIAccessibleValue:30093,LegacyIAccessibleDescription:30094,LegacyIAccessibleRole:30095,LegacyIAccessibleState:30096,LegacyIAccessibleHelp:30097,LegacyIAccessibleKeyboardShortcut:30098,LegacyIAccessibleSelection:30099,LegacyIAccessibleDefaultAction:30100,AriaRole:30101,AriaProperties:30102,IsDataValidForForm:30103,ControllerFor:30104,DescribedBy:30105,FlowsTo:30106,ProviderDescription:30107,IsItemContainerPatternAvailable:30108,IsVirtualizedItemPatternAvailable:30109,IsSynchronizedInputPatternAvailable:30110}
,
Верхние - это методы.
Нижние свойства.
Еще через UIA можно посылать действия на кнопки переключения
Интересно, Toggle это как ещё один вариант DoDefaultAction.
Верхние - это методы.
Нижние свойства.
Хм, я воспринимаю разницу между методом и свойством - как между Set и Get.
Тут получается что метод CurrentClassName ничего не делает, а только возвращает строку, то есть по сути является свойством.
Интересно, Toggle это как ещё один вариант DoDefaultAction.
В UIA такого понятия как DoDefaultAction нету.
https://docs.microsoft.com/en-us/window … iauto-msaa
Чтобы получить свойства, либо отправить что-нибудь мы выполняем методы.
Например, чтобы получить ClassName мы можем выполнить метод
IUIAutomationElement::CurrentClassName
либо выполнить метод
IUIAutomationElement::GetCurrentPropertyValue, указав константу UIA_ClassNamePropertyId.
В UIA такого понятия как DoDefaultAction нету.
Какие именно действия доступны, и как их определить. Как ты нашёл Toggle для элемента?
Я нашел через inspect.
Если хочешь получить все возможные patterns, то наверное только перебором:
https://docs.microsoft.com/en-us/window … ty-propids
Метод GetSupportedPatterns есть только в Net.
https://docs.microsoft.com/en-us/dotnet … etcore-3.1
Ну а метод DoDefaultAction ты можешь вызывать через LegacyIAccessible Control Pattern, что я и сделал в примере с нажатием громкости.
https://docs.microsoft.com/en-us/window … accessible
Тёмный лес, в общем в долгий ящик.
Ну а метод DoDefaultAction ты можешь вызывать через LegacyIAccessible Control Pattern, что я и сделал в примере с нажатием громкости.
А зачем, там же что-то вроде Invoke есть.
А вот не знаю зачем, плюс еще GetCurrentPatternAs можно смело на GetCurrentPattern заменить.
f11::
if !hVolume
{
ControlGet, hVolume, hwnd,, ToolbarWindow323, ahk_class Shell_TrayWnd
IUIAutomation := ComObjCreate(CLSID_CUIAutomation := "{ff48dba4-60ef-4201-aa87-54103eef594e}", IID_IUIAutomation := "{30cbe57d-d9d0-452a-ab13-7ac5ac4825ee}")
DllCall(NumGet(NumGet(IUIAutomation+0)+6*A_PtrSize), "ptr", IUIAutomation, "ptr", hVolume, "ptr*", tray) ; IUIAutomation::ElementFromHandle
VOLUME_GUID := DllCall("oleaut32\SysAllocString", "str", "{7820AE73-23E3-4229-82C1-E41CB67D5B9C}", "ptr")
VarSetCapacity(variant, 8+A_PtrSize*2, 0)
NumPut(VT_BSTR := 8, variant, 0, "ushort")
NumPut(VOLUME_GUID, variant, 8, "ptr")
if (A_PtrSize = 4)
DllCall(NumGet(NumGet(IUIAutomation+0)+23*A_PtrSize), "ptr", IUIAutomation, "int", UIA_AutomationIdPropertyId := 30011, "int64", NumGet(variant, 0, "int64"), "int64", NumGet(variant, 8, "int64"), "ptr*", condition) ; IUIAutomation::CreatePropertyCondition
else
DllCall(NumGet(NumGet(IUIAutomation+0)+23*A_PtrSize), "ptr", IUIAutomation, "int", UIA_AutomationIdPropertyId := 30011, "ptr", &variant, "ptr*", condition) ; IUIAutomation::CreatePropertyCondition
DllCall("oleaut32\SysFreeString", "ptr", VOLUME_GUID)
}
DllCall(NumGet(NumGet(tray+0)+5*A_PtrSize), "ptr", tray, "int", TreeScope_Descendants := 0x4, "ptr", condition, "ptr*", element) ; IUIAutomationElement::FindFirst
DllCall(NumGet(NumGet(element+0)+16*A_PtrSize), "ptr", element, "int", UIA_InvokePatternId := 10000, "ptr*", invoke) ; IUIAutomationElement::GetCurrentPattern
DllCall(NumGet(NumGet(invoke+0)+3*A_PtrSize), "ptr", invoke) ; IInvokeProvider::Invoke
ObjRelease(element)
ObjRelease(invoke)
Еще из возможностей UIA посылать контекстное меню, c помощью IUIAutomationElement3::ShowContextMenu метода (Win8.1+)
Правда срабатывает не на всех элементах.
https://docs.microsoft.com/en-us/window … ontextmenu
Вот так посылается на иконку This PC на десктопе:
name := "This PC"
f11::
if !hwnd
{
ControlGet, hwnd, hwnd,, SysListView321, ahk_class Progman
if (hwnd = "")
ControlGet, hwnd, hwnd,, SysListView321, ahk_class WorkerW
IUIAutomation := ComObjCreate(CLSID_CUIAutomation := "{ff48dba4-60ef-4201-aa87-54103eef594e}", IID_IUIAutomation := "{30cbe57d-d9d0-452a-ab13-7ac5ac4825ee}")
DllCall(NumGet(NumGet(IUIAutomation+0)+6*A_PtrSize), "ptr", IUIAutomation, "ptr", hwnd, "ptr*", element) ; IUIAutomation::ElementFromHandle
name := DllCall("oleaut32\SysAllocString", "str", name, "ptr")
VarSetCapacity(variant, 8+A_PtrSize*2, 0)
NumPut(VT_BSTR := 8, variant, 0, "ushort")
NumPut(name, variant, 8, "ptr")
DllCall("oleaut32\SysFreeString", "ptr", name)
if (A_PtrSize = 4)
DllCall(NumGet(NumGet(IUIAutomation+0)+23*A_PtrSize), "ptr", IUIAutomation, "int", UIA_NamePropertyId := 30005, "int64", NumGet(variant, 0, "int64"), "int64", NumGet(variant, 8, "int64"), "ptr*", condition) ; IUIAutomation::CreatePropertyCondition
else
DllCall(NumGet(NumGet(IUIAutomation+0)+23*A_PtrSize), "ptr", IUIAutomation, "int", UIA_NamePropertyId := 30005, "ptr", &variant, "ptr*", condition) ; IUIAutomation::CreatePropertyCondition
}
DllCall(NumGet(NumGet(element+0)+5*A_PtrSize), "ptr", element, "int", TreeScope_Descendants := 0x4, "ptr", condition, "ptr*", FoundElement) ; IUIAutomationElement::FindFirst
DllCall(NumGet(NumGet(FoundElement+0)+91*A_PtrSize), "ptr", FoundElement) ; IUIAutomationElement3::ShowContextMenu
ObjRelease(FoundElement)
Было бы неплохо придумать, чтобы якорь был привязан к верхней части окна.
Так а сейчас как?
У меня так не привязывается - скачет как и раньше.
Что значит скачет?
Full scroll with existing anchor - включено?
А точно, забыл это меню включить.
Может изначально его включенным делать?
Может изначально его включенным делать?
Так и есть, видимо ты его сам выключил.