[Func] AccMatchTextAll - Easily search for Acc info
Posted: 12 Sep 2021, 18:23
Acc.ahk has been very useful to me in automating tasks, however it's always been a pain when having to manually look up paths which would often break if the application was updated. This function I've put together has made the process much easier for me, once you've found one or two of the values for the controls you're looking for with AccViewer.ahk or even by modifying the example, you can then retrieve info for specific controls. This relies on a simple modification to jeeswg's JEE_AccGetTextAll which is in the second code block, it now has the option to return an object containing all Acc data, which is then parsed by the function. This object is cached and is looked up when doing subsequent queries, which is significantly faster than running AccGetTextAll every time, however the reload option can be set to refresh that. Let me know if anyone has any suggestions or feedback, cheers.
Get AccV2.ahk from here viewtopic.php?t=40532
Get AccV2.ahk from here viewtopic.php?t=40532
Code: Select all
#Include AccV2.ahk
; Example
q::
hwnd := "ahk_exe chrome.exe"
menuPath := AccMatchTextAll(hwnd,{name:"Chrome",roletext:"menu button"})
backPath := AccMatchTextAll(hwnd,{name:"Back",role:43})
addressPath := AccMatchTextAll(hwnd,{name:"address and search"})
addressRole := AccMatchTextAll(hwnd,{path:addressPath},"roletext")
addressValue := Acc_Get("Value",addressPath,,hwnd) ; Get the current value rather than the cached value
Msgbox, % Format("Menu path: {}`r`nBack button path: {}`r`nAddress bar path: {}`r`nAddress bar role: {}`r`nURL: {}",menuPath,backPath,addressPath,addressRole,addressValue)
Return
; Acceptable values for matchlist & get:
; name,value,role,roletext,state
; matchlist is formatted as an array, i.e. AccMatchTextAll("Google Chrome",{name:"Chrome",roletext:"menu button"})
AccMatchTextAll(hwnd, matchList, get := "path", regex := 0, reload := 0) {
static
if !IsObject(foundPaths)
foundPaths := Object()
nWindow := WinExist(hwnd)
, matchStr := ""
, idx := 0
if (!IsObject(%nWindow%) || reload = 1)
%nWindow% := JEE_AccGetTextAll(nWindow, , ,"o")
for k, v in matchList {
idx++
matchStr .= k . ":" . StrReplace(v,A_Space) . (idx<matchList.Count()?",":"")
}
if !IsObject(foundPaths[nWindow] || reload = 1)
foundPaths[nWindow] := Object()
else if foundPaths[nWindow].HasKey(matchStr)
return foundPaths[nWindow,matchStr,get]
for i, e in %nWindow% {
found := 0
for k, v in e {
if (v <> "" && matchList.HasKey(k))
if (regex = 0 && InStr(v,matchlist[k])
|| (regex = 1 && RegExMatch(v, matchList[k])))
found++
}
if (found = matchList.Count()) {
foundPaths[nWindow,matchStr] := e
return e[get]
}
}
return 0
}
Code: Select all
JEE_AccGetTextAll(hWnd:=0, vSep:="`n", vIndent:="`t", vOpt:="")
{
vLimN := 20, vLimV := 20, retObj := 0, oOutput := []
Loop, Parse, vOpt, % " "
{
vTemp := A_LoopField
if (SubStr(vTemp, 1, 1) = "n")
vLimN := SubStr(vTemp, 2)
else if (SubStr(vTemp, 1, 1) = "v")
vLimV := SubStr(vTemp, 2)
else if (SubStr(vTemp, 1, 1) = "o")
retObj := 1, vLimN := vLimV := 255
}
oMem := {}, oPos := {}
;OBJID_WINDOW := 0x0
oMem[1, 1] := Acc_ObjectFromWindow(hWnd, 0x0)
oPos[1] := 1, vLevel := 1
VarSetCapacity(vOutput, 1000000*2)
Loop
{
if !vLevel
break
if !oMem[vLevel].HasKey(oPos[vLevel])
{
oMem.Delete(vLevel)
oPos.Delete(vLevel)
vLevelLast := vLevel, vLevel -= 1
oPos[vLevel]++
continue
}
oKey := oMem[vLevel, oPos[vLevel]]
vName := "", vValue := ""
if IsObject(oKey)
{
vRole := oKey.accRole(0)
vRoleText := Acc_GetRoleText(vRole)
vState := Acc_State(oKey)
try vName := oKey.accName(0)
try vValue := oKey.accValue(0)
}
else
{
oParent := oMem[vLevel-1,oPos[vLevel-1]]
vChildId := IsObject(oKey) ? 0 : oPos[vLevel]
vRole := oParent.accRole(vChildID)
vRoleText := Acc_GetRoleText(vRole)
vState := Acc_State(oParent)
try vName := oParent.accName(vChildID)
try vValue := oParent.accValue(vChildID)
}
if (StrLen(vName) > vLimN)
vName := SubStr(vName, 1, vLimN) "..."
if (StrLen(vValue) > vLimV)
vValue := SubStr(vValue, 1, vLimV) "..."
vName := RegExReplace(vName, "[`r`n]", " ")
vValue := RegExReplace(vValue, "[`r`n]", " ")
vAccPath := ""
if IsObject(oKey)
{
Loop, % oPos.Length() - 1
vAccPath .= (A_Index=1?"":".") oPos[A_Index+1]
}
else
{
Loop, % oPos.Length() - 2
vAccPath .= (A_Index=1?"":".") oPos[A_Index+1]
vAccPath .= " c" oPos[oPos.Length()]
}
vOutput .= vAccPath "`t" JEE_StrRept(vIndent, vLevel-1) vRoleText " [" vName "][" vValue "]" vSep
oOutput.Push({path:vAccPath,name:vName,value:vValue,roletext:vRoleText,role:vRole,state:vState})
oChildren := Acc_Children(oKey)
if !oChildren.Length()
oPos[vLevel]++
else
{
vLevelLast := vLevel, vLevel += 1
oMem[vLevel] := oChildren
oPos[vLevel] := 1
}
}
return retObj = 1 ? oOutput : SubStr(vOutput, 1, -StrLen(vSep))
}
JEE_StrRept(vText, vNum)
{
if (vNum <= 0)
return
return StrReplace(Format("{:" vNum "}", ""), " ", vText)
;return StrReplace(Format("{:0" vNum "}", 0), 0, vText)
}