[Solved] IAccessible - Accessible Objects

Get help with using AutoHotkey and its commands and hotkeys
just me
Posts: 5980
Joined: 02 Oct 2013, 08:51
Location: Germany

[Solved] IAccessible - Accessible Objects

17 Dec 2015, 03:02

I'm currently playing around with the Acc library to understand how things are working. I tried to create own functions for the IAccessible properties and succeeded in most cases except IAccessible.accSelection (description).

When used with a 'modern' explorer file list (DirectUIHWND) it returns something recognized as an object by AHK, but I found no way to access this object. ComObjValue() and also ComObjType() return empty strings and ComObjQuery() throws the exeption 'No valid COM object!'.

The following test script will get this result if select a single item and press Ctrl+Shift+s while the mouse cursor is over an an empty area of the explorer file list. Can anyone tell me how to access this object?

Code: Select all

#NoEnv
SetBatchLines, -1

^+s::
   Acc := Acc_ObjectFromPoint()
   MsgBox, % Acc_GetRoleText(Acc_Role(Acc))
   Selection := Acc_Selection(Acc)
   If !Selection.Length()
      MsgBox, 0, Selection, Not Found!
   Else {
      Msg := ""
      For Each, Selected In Selection {
         If IsObject(Selected)
            Msg .= Acc_Name(Selected) . " - " . Acc_GetRoleText(Acc_Role(Selected)) . "`n"
         Else
            Msg .= Acc_Name(Acc, Selected) . " - " . Acc_GetRoleText(Acc_Role(Acc, Selected)) . "`n"
      }
      MsgBox, 0, Selection, %Msg%
   }
Return

; ----------------------------------------------------------------------------------------------------------------------------------
; Retrieves the address of the IAccessible interface pointer for the object displayed at a specified point on the screen.
; msdn.microsoft.com/en-us/library/windows/desktop/dd317977(v=vs.85).aspx
; ----------------------------------------------------------------------------------------------------------------------------------
Acc_ObjectFromPoint(ByRef ChildID := "", X := "", Y := "") {
   If (X = "") || (Y = "")
      DllCall("GetCursorPos", "Int64P", PT)
   Else
      PT := (X & 0xFFFFFFFF) | ((Y & 0xFFFFFFFF) << 32)
   VarSetCapacity(CID, 24, 0)
   RC := DllCall("Oleacc.dll\AccessibleObjectFromPoint", "Int64", PT, "PtrP", pAcc, "Ptr", &CID)
   ChildID := NumGet(CID, 8, "Ptr")
   Return (RC = 0 ? ComObj(9, pAcc, 1) : RC)
}
; ----------------------------------------------------------------------------------------------------------------------------------
; Retrieves the localized string that describes the object's role for the specified role value.
; msdn.microsoft.com/en-us/library/windows/desktop/dd318089(v=vs.85).aspx
; ----------------------------------------------------------------------------------------------------------------------------------
Acc_GetRoleText(Role) {
   If (Size := DllCall("Oleacc.dll\GetRoleText", "UInt", Role, "Ptr", 0, "UInt", 0)) {
      VarSetCapacity(RoleText, Size * 2, 0)
      DllCall("Oleacc.dll\GetRoleText", "UInt", Role, "Str", RoleText, "UInt", Size + 1)
      Return RoleText
   }
}
; ----------------------------------------------------------------------------------------------------------------------------------
; Retrieves the name of the object. All objects support this property.
; ----------------------------------------------------------------------------------------------------------------------------------
Acc_Name(Acc, ChildID := 0) {
   Try
      Name := Acc.accName(ChildID)
   Catch E
      Return Acc_Error(A_ThisFunc, E)
   Return Name
}
; ----------------------------------------------------------------------------------------------------------------------------------
; Retrieves information that describes the role of the specified object. All objects support this property.
; Role constants: msdn.microsoft.com/en-us/library/dd373608(v=vs.85).aspx
; ----------------------------------------------------------------------------------------------------------------------------------
Acc_Role(Acc, ChildID := 0) {
   Try
      Role := Acc.accRole(ChildID)
   Catch E
      Return Acc_Error(A_ThisFunc, E)
   Return Role
}
; ----------------------------------------------------------------------------------------------------------------------------------
; Retrieves the selected children of this object. All objects that support selection must support this property
; ----------------------------------------------------------------------------------------------------------------------------------
Acc_Selection(Acc) {
   Selection := []
   Try
      Selected := Acc.accSelection
   Catch E
      Return Acc_Error(A_ThisFunc, E)
   If IsObject(Selected) {
      MsgBox, % "Object type: " . ComObjType(Selected)
      If !(ComObjType(Selected, "Name") = "IUnknown")
         Selection := Acc_EnumVariant(Selected)
      Else If (ComObjType(Selected, "Name") = "IAccessible")
         Selection.Push(Selected)
      Else
         Selection.Push(Acc_Query(Selected))
   }
   Else If (Selected <> "")
      Selection.Push(Selected)
   Return (Selection.Length() > 0 ? Selection : "")
}
; ==================================================================================================================================
; Auxiliary Functions - Do not call!
; ==================================================================================================================================
; ----------------------------------------------------------------------------------------------------------------------------------
; Loads the Oleacc.dll on start-up
; ----------------------------------------------------------------------------------------------------------------------------------
Acc_Load() {
   Static AccMod := DllCall("LoadLibrary", "Str", "Oleacc.dll", "UPtr")
   Return AccMod
}
; ----------------------------------------------------------------------------------------------------------------------------------
; Enumerates children using the IEnumVariant interface.
; ----------------------------------------------------------------------------------------------------------------------------------
Acc_EnumVariant(pUnk) {
   Static Next := A_PtrSize * 3
   Try
      pEnumVariant := ComObjQuery(pUnk, "{00020404-0000-0000-C000-000000000046}") ; IEnumVariant
   Catch E
      Return Acc_Error(A_ThisFunc, E)
   pVTBL := NumGet(pEnumVariant + 0, "UPtr")
   Selection := []
   MsgBox, Bingo!
   Loop {
      VarSetCapacity(V, 24, 0) ; VARIANT structure
      Fetched := 0
      DllCall(NumGet(pVTBL + Next, "UInt"), 1, "Ptr", &V, "UIntP", Fetched)
      If (Fetched = 0)
         Break
      VarType := NumGet(V, 0, "UShort")
      Selected := NumGet(V, 8, VarType = 9 ? "UPtr" : "Int")
      If (VarType = 9) {
         If (ComObjType(Child, "Name") = "IAccessible")
            Selection.Push(Selected)
         Else
            Selection.Push(Acc_Query(Selected))
      }
      Else
         Selection.Push(Selected)
   }
   Return Selection.Length() ? Selection : ""
}
; ----------------------------------------------------------------------------------------------------------------------------------
; Reports COM errors, if wanted.
; Set ReportAccError to True for testing.
; ----------------------------------------------------------------------------------------------------------------------------------
Acc_Error(Func, E, RetVal := "") {
   Static ReportAccError := 1
   If (ReportAccError) {
      If IsObject(E)
         ErrorMsg := "Exception thrown!`n`nWhat: " . E.What . "`nFile: " . E.File . "`nLine: " . E.Line
                   . "`n`nMessage: " . E.Message . "`n`nExtra: " . E.Extra
      Else
         ErrorMsg := E
      MsgBox, 20, Error in %Func%(), %ErrorMsg%`n`n`Do you want to continue?
      IfMsgBox, No
         ExitApp
   }
   Return RetVal
}
; ----------------------------------------------------------------------------------------------------------------------------------
; Retrieves the IAccessible interface from an IDispatch interface, if any, and releases the IDispatch interface on success.
; Thanks Lexikos - www.autohotkey.com/forum/viewtopic.php?t=81731&p=509530#509530
; ----------------------------------------------------------------------------------------------------------------------------------
Acc_Query(Acc) {
   Try
      IA := ComObjQuery(Acc, "{618736e0-3c3d-11cf-810c-00aa00389b71}")
   Catch E
      Return Acc_Error(A_ThisFunc, E)
   ObjRelease(Acc)
   Return ComObj(9, IA, 1)
}
Last edited by just me on 17 Dec 2015, 09:35, edited 1 time in total.
lexikos
Posts: 6214
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: IAccessible - Accessible Objects

17 Dec 2015, 04:35

It's an enumerator object - IEnumVARIANT is wrapped automatically to support for-loops. The only thing you can do with it is call Next.

At the moment, you can safely assume that any object returned by a COM method/property is either a ComObject or an enumerator.

In v2, type(Selected) returns "ComEnum".
just me
Posts: 5980
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: IAccessible - Accessible Objects

17 Dec 2015, 05:29

lexikos wrote:At the moment, you can safely assume that any object returned by a COM method/property is either a ComObject or an enumerator.
Thanks a lot, lexikos, I have to keep this in mind.

An additional question, is it safe to use something like

Code: Select all

If ComObjType(Object)
   it's a COM object
Else
   it's an enumarator object
to distinct between the two types?
lexikos
Posts: 6214
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: IAccessible - Accessible Objects

17 Dec 2015, 06:54

It's hard to say.

ComObjType is documented to return an empty string if the parameters are invalid, so it comes down to how the parameters should be interpreted:
ComObject: A wrapper object containing a COM object or typed value.
ComEnum is a kind of wrapper object containing a COM object (IEnumVARIANT), but it's not the kind of wrapper object expected by the function; i.e. it's currently invalid, so an empty string will be returned.

I suppose that in a future version, ComObjType could return VT_UNKNOWN and ComObjValue could return the interface pointer. If you want to be future-proof, you could allow for that possibility as well. I don't foresee any other possibilities.

I think ComEnum was really only intended to be used internally by the for-loop. I've just realized that if you try to pass it back to a COM method, it will actually pass the ComEnum object, not the IEnumVARIANT interface pointer. ComEnum objects also aren't recognized by any of the COM functions, as you've found with ComObjQuery.

I don't think ComObjType(Selected, "Name") = "IUnknown" will ever be true. The two-parameter modes of ComObjType use type information retrieved via IDispatch::GetTypeInfo. That won't work with interfaces not derived from IDispatch, like IEnumVARIANT, for obvious reasons.

Also, there appears to be a flaw of logic in the following code:

Code: Select all

      If !(ComObjType(Selected, "Name") = "IUnknown")
         Selection := Acc_EnumVariant(Selected)
      Else If (ComObjType(Selected, "Name") = "IAccessible")
         Selection.Push(Selected)
If the type is "IAccessible", it is obviously not "IUnknown". Unless I'm misreading the code, the second branch can never be executed. Actually, since it will probably never return "IUnknown", I suppose the third branch can never be executed either.
just me
Posts: 5980
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: [Solved] IAccessible - Accessible Objects

17 Dec 2015, 09:58

Thanks, lexikos, for your answer and for looking at my code sample. I tried to solve the problem for several hours before I posted this help request and changed everything in the related code again and again trying to get and access an IUnknown interface, because I was absolutely clueless about the enumerator objects. So the posted version won't work correctly, but is showing the problematic result for the given example.

This is working for me now:

Code: Select all

; ----------------------------------------------------------------------------------------------------------------------------------
; Retrieves the selected children of this object. All objects that support selection must support this property
; ----------------------------------------------------------------------------------------------------------------------------------
Acc_Selection(Acc) {
   Selection := []
   Try
      Selected := Acc.accSelection
   Catch E
      Return Acc_Error(A_ThisFunc, E)
   If IsObject(Selected) {
      If (Name := ComObjType(Selected, "Name")) {
         If (Name = "IAccessible")
            Selection.Push(Selected)
         Else If (IA := Acc_Query(Selected))
            Selection.Push(IA)
      }
      Else {
         While Selected.Next(Value, VarType)
            Selection.Push(Value)
      }
   }
   Else If (Selected <> "")
      Selection.Push(Selected)
   Return (Selection.Length() ? Selection : "")
}
Is it future-proof?
lexikos
Posts: 6214
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: [Solved] IAccessible - Accessible Objects

17 Dec 2015, 16:13

No, I suppose not.
I wrote:I suppose that in a future version, ComObjType could return VT_UNKNOWN and ComObjValue could return the interface pointer. If you want to be future-proof, you could allow for that possibility as well. I don't foresee any other possibilities.
I was referring to the IEnumVARIANT interface pointer, which Acc_EnumVariant accepts.
just me
Posts: 5980
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: [Solved] IAccessible - Accessible Objects

18 Dec 2015, 02:56

I do not understand you.
You wrote:I don't think ComObjType(Selected, "Name") = "IUnknown" will ever be true. The two-parameter modes of ComObjType use type information retrieved via IDispatch::GetTypeInfo. That won't work with interfaces not derived from IDispatch, like IEnumVARIANT, for obvious reasons.
So do you mean the type of the returned object will be changed in future releases?
lexikos
Posts: 6214
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: [Solved] IAccessible - Accessible Objects

18 Dec 2015, 04:33

No, I think you understand me; I just hadn't thought it through properly.

ComObjType not supporting enumerator objects could be considered a bug and might be fixed, but the ability to call .Next() must be retained, so your script is safe in that respect.

However, it's just occurred to me that ComObjType(Selected, "Name") can fail in other cases, such as for objects lacking type information or with a poor IDispatch implementation. It would be safer to check ComObjType(Selected). If blank, it's probably an enumerator object. If VT_UNKNOWN (13), you can query for IEnumVARIANT or try Acc_EnumVariant - but to test it you would have to get hold of an IEnumVARIANT pointer and manually wrap it.

Note: As of v1.1.17, it is possible for a COM method/property to return an AutoHotkey object, but only if your script passed one to a COM method/property in the first place. For instance, you can store AutoHotkey objects in a Scripting.Dictionary. However, I don't imagine there's any risk of an AutoHotkey object being returned by an IAccessible object.
just me
Posts: 5980
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: [Solved] IAccessible - Accessible Objects

18 Dec 2015, 05:05

Thanks again. I removed the Acc_IEnumVariant() function, but I will hopefully keep in mind, that it might be an option for future releases (if implemented correctly).
DanielToward13
Posts: 63
Joined: 18 May 2017, 10:56

Re: [Solved] IAccessible - Accessible Objects

29 Jul 2017, 21:17

I am trying to click/toggle a button using ACC library. The code works but it returns an error after click:

Code: Select all

Error: 0x80004005 - Unspecified error 
Source: (null) 
Description: (null) 
HelpFile: (null) 
HelpContext: 0 

Specifically: accDoDefaultAction 


	Line# 
	133: Acc_Init() 
	134: objected := Acc_Get("Object","4.3.1.1.7"„"Audacity") 
	136: MsgBox,isobject(objected) 
	137: MsgBox,objected.accName(0) 
	138: MsgBox,objected.accValue(0) 
	139: MsgBox,ComObjType(objected, "Name") 
	140: MsgBox,ComObjValue(objected) 
--->143: objected.accDoDefaultAction(0) 
	163: Return 
	166: WinActivate,ahk_pid %myPID% 
	167: ControlSend„{Space},ahk_pid %myPID% 
	168: WinMinimize,ahk_pid %myPID% 
	169: Return 
	172: WinActivate,ahk_pid %myPID% 
	173: ControlSend„{Ctrl down}{Shift down}e{Ctrl up}{Shift up},ahk_pid %myPID% 

Continue running the script?
I have commented the result of each MsgBox for debugging purpose. Some part of my code:

Code: Select all

up::
Acc_Init()
objected := Acc_Get("Object","4.3.1.1.7",,"Audacity")
MsgBox % isobject(objected) ;;; return 1
MsgBox, % objected.accName(0) ;;; return Record
MsgBox, % objected.accValue(0) ;;; null return
MsgBox % ComObjType(objected, "Name") ;;; return IAccessible
MsgBox % ComObjValue(objected) ;;; return 95970560
;ComObjError(0)
objected.accDoDefaultAction(0)
;ComObjError(1)
The acc.ahk library (is this the latest version?):

Code: Select all

; http://www.autohotkey.com/board/topic/77303-acc-library-ahk-l-updated-09272012/
; https://dl.dropbox.com/u/47573473/Web%20Server/AHK_L/Acc.ahk
;------------------------------------------------------------------------------
; Acc.ahk Standard Library
; by Sean
; Updated by jethrow:
; 	Modified ComObjEnwrap params from (9,pacc) --> (9,pacc,1)
; 	Changed ComObjUnwrap to ComObjValue in order to avoid AddRef (thanks fincs)
; 	Added Acc_GetRoleText & Acc_GetStateText
; 	Added additional functions - commented below
; 	Removed original Acc_Children function
; last updated 2/25/2010
;------------------------------------------------------------------------------

Acc_Init()
{
	Static	h
	If Not	h
		h:=DllCall("LoadLibrary","Str","oleacc","Ptr")
}
Acc_ObjectFromEvent(ByRef _idChild_, hWnd, idObject, idChild)
{
	Acc_Init()
	If	DllCall("oleacc\AccessibleObjectFromEvent", "Ptr", hWnd, "UInt", idObject, "UInt", idChild, "Ptr*", pacc, "Ptr", VarSetCapacity(varChild,8+2*A_PtrSize,0)*0+&varChild)=0
	Return	ComObjEnwrap(9,pacc,1), _idChild_:=NumGet(varChild,8,"UInt")
}

Acc_ObjectFromPoint(ByRef _idChild_ = "", x = "", y = "")
{
	Acc_Init()
	If	DllCall("oleacc\AccessibleObjectFromPoint", "Int64", x==""||y==""?0*DllCall("GetCursorPos","Int64*",pt)+pt:x&0xFFFFFFFF|y<<32, "Ptr*", pacc, "Ptr", VarSetCapacity(varChild,8+2*A_PtrSize,0)*0+&varChild)=0
	Return	ComObjEnwrap(9,pacc,1), _idChild_:=NumGet(varChild,8,"UInt")
}

Acc_ObjectFromWindow(hWnd, idObject = -4)
{
	Acc_Init()
	If	DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject&=0xFFFFFFFF, "Ptr", -VarSetCapacity(IID,16)+NumPut(idObject==0xFFFFFFF0?0x46000000000000C0:0x719B3800AA000C81,NumPut(idObject==0xFFFFFFF0?0x0000000000020400:0x11CF3C3D618736E0,IID,"Int64"),"Int64"), "Ptr*", pacc)=0
	Return	ComObjEnwrap(9,pacc,1)
}

Acc_WindowFromObject(pacc)
{
	If	DllCall("oleacc\WindowFromAccessibleObject", "Ptr", IsObject(pacc)?ComObjValue(pacc):pacc, "Ptr*", hWnd)=0
	Return	hWnd
}

Acc_GetRoleText(nRole)
{
	nSize := DllCall("oleacc\GetRoleText", "Uint", nRole, "Ptr", 0, "Uint", 0)
	VarSetCapacity(sRole, (A_IsUnicode?2:1)*nSize)
	DllCall("oleacc\GetRoleText", "Uint", nRole, "str", sRole, "Uint", nSize+1)
	Return	sRole
}

Acc_GetStateText(nState)
{
	nSize := DllCall("oleacc\GetStateText", "Uint", nState, "Ptr", 0, "Uint", 0)
	VarSetCapacity(sState, (A_IsUnicode?2:1)*nSize)
	DllCall("oleacc\GetStateText", "Uint", nState, "str", sState, "Uint", nSize+1)
	Return	sState
}

Acc_SetWinEventHook(eventMin, eventMax, pCallback)
{
	Return	DllCall("SetWinEventHook", "Uint", eventMin, "Uint", eventMax, "Uint", 0, "Ptr", pCallback, "Uint", 0, "Uint", 0, "Uint", 0)
}

Acc_UnhookWinEvent(hHook)
{
	Return	DllCall("UnhookWinEvent", "Ptr", hHook)
}
/*	Win Events:

	pCallback := RegisterCallback("WinEventProc")
	WinEventProc(hHook, event, hWnd, idObject, idChild, eventThread, eventTime)
	{
		Critical
		Acc := Acc_ObjectFromEvent(_idChild_, hWnd, idObject, idChild)
		; Code Here:

	}
*/

; Written by jethrow
Acc_Role(Acc, ChildId=0) {
	try return ComObjType(Acc,"Name")="IAccessible"?Acc_GetRoleText(Acc.accRole(ChildId)):"invalid object"
}
Acc_State(Acc, ChildId=0) {
	try return ComObjType(Acc,"Name")="IAccessible"?Acc_GetStateText(Acc.accState(ChildId)):"invalid object"
}
Acc_Location(Acc, ChildId=0, byref Position="") { ; adapted from Sean's code
	try Acc.accLocation(ComObj(0x4003,&x:=0), ComObj(0x4003,&y:=0), ComObj(0x4003,&w:=0), ComObj(0x4003,&h:=0), ChildId)
	catch
		return
	Position := "x" NumGet(x,0,"int") " y" NumGet(y,0,"int") " w" NumGet(w,0,"int") " h" NumGet(h,0,"int")
	return	{x:NumGet(x,0,"int"), y:NumGet(y,0,"int"), w:NumGet(w,0,"int"), h:NumGet(h,0,"int")}
}
Acc_Parent(Acc) { 
	try parent:=Acc.accParent
	return parent?Acc_Query(parent):
}
Acc_Child(Acc, ChildId=0) {
	try child:=Acc.accChild(ChildId)
	return child?Acc_Query(child):
}
Acc_Query(Acc) { ; thanks Lexikos - www.autohotkey.com/forum/viewtopic.php?t=81731&p=509530#509530
	try return ComObj(9, ComObjQuery(Acc,"{618736e0-3c3d-11cf-810c-00aa00389b71}"), 1)
}
Acc_Error(p="") {
	static setting:=0
	return p=""?setting:setting:=p
}
Acc_Children(Acc) {
	if ComObjType(Acc,"Name") != "IAccessible"
		ErrorLevel := "Invalid IAccessible Object"
	else {
		Acc_Init(), cChildren:=Acc.accChildCount, Children:=[]
		if DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc), "Int",0, "Int",cChildren, "Ptr",VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*",cChildren)=0 {
			Loop %cChildren%
				i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i), Children.Insert(NumGet(varChildren,i-8)=9?Acc_Query(child):child), NumGet(varChildren,i-8)=9?ObjRelease(child):
			return Children.MaxIndex()?Children:
		} else
			ErrorLevel := "AccessibleChildren DllCall Failed"
	}
	if Acc_Error()
		throw Exception(ErrorLevel,-1)
}
Acc_ChildrenByRole(Acc, Role) {
	if ComObjType(Acc,"Name")!="IAccessible"
		ErrorLevel := "Invalid IAccessible Object"
	else {
		Acc_Init(), cChildren:=Acc.accChildCount, Children:=[]
		if DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc), "Int",0, "Int",cChildren, "Ptr",VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*",cChildren)=0 {
			Loop %cChildren% {
				i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i)
				if NumGet(varChildren,i-8)=9
					AccChild:=Acc_Query(child), ObjRelease(child), Acc_Role(AccChild)=Role?Children.Insert(AccChild):
				else
					Acc_Role(Acc, child)=Role?Children.Insert(child):
			}
			return Children.MaxIndex()?Children:, ErrorLevel:=0
		} else
			ErrorLevel := "AccessibleChildren DllCall Failed"
	}
	if Acc_Error()
		throw Exception(ErrorLevel,-1)
}
Acc_Get(Cmd, ChildPath="", ChildID=0, WinTitle="", WinText="", ExcludeTitle="", ExcludeText="") {
	static properties := {Action:"DefaultAction", DoAction:"DoDefaultAction", Keyboard:"KeyboardShortcut"}
	AccObj :=   IsObject(WinTitle)? WinTitle
			:   Acc_ObjectFromWindow( WinExist(WinTitle, WinText, ExcludeTitle, ExcludeText), 0 )
	if ComObjType(AccObj, "Name") != "IAccessible"
		ErrorLevel := "Could not access an IAccessible Object"
	else {
		StringReplace, ChildPath, ChildPath, _, %A_Space%, All
		AccError:=Acc_Error(), Acc_Error(true)
		Loop Parse, ChildPath, ., %A_Space%
			try {
				if A_LoopField is digit
					Children:=Acc_Children(AccObj), m2:=A_LoopField ; mimic "m2" output in else-statement
				else
					RegExMatch(A_LoopField, "(\D*)(\d*)", m), Children:=Acc_ChildrenByRole(AccObj, m1), m2:=(m2?m2:1)
				if Not Children.HasKey(m2)
					throw
				AccObj := Children[m2]
			} catch {
				ErrorLevel:="Cannot access ChildPath Item #" A_Index " -> " A_LoopField, Acc_Error(AccError)
				if Acc_Error()
					throw Exception("Cannot access ChildPath Item", -1, "Item #" A_Index " -> " A_LoopField)
				return
			}
		Acc_Error(AccError)
		StringReplace, Cmd, Cmd, %A_Space%, , All
		properties.HasKey(Cmd)? Cmd:=properties[Cmd]:
		try {
			if (Cmd = "Location")
				AccObj.accLocation(ComObj(0x4003,&x:=0), ComObj(0x4003,&y:=0), ComObj(0x4003,&w:=0), ComObj(0x4003,&h:=0), ChildId)
			  , ret_val := "x" NumGet(x,0,"int") " y" NumGet(y,0,"int") " w" NumGet(w,0,"int") " h" NumGet(h,0,"int")
			else if (Cmd = "Object")
				ret_val := AccObj
			else if Cmd in Role,State
				ret_val := Acc_%Cmd%(AccObj, ChildID+0)
			else if Cmd in ChildCount,Selection,Focus
				ret_val := AccObj["acc" Cmd]
			else
				ret_val := AccObj["acc" Cmd](ChildID+0)
		} catch {
			ErrorLevel := """" Cmd """ Cmd Not Implemented"
			if Acc_Error()
				throw Exception("Cmd Not Implemented", -1, Cmd)
			return
		}
		return ret_val, ErrorLevel:=0
	}
	if Acc_Error()
		throw Exception(ErrorLevel,-1)
}
What is the problem and how to solve it?

Return to “Ask For Help”

Who is online

Users browsing this forum: boardtc, Brazolek123, Kobaltauge, SALZKARTOFFEEEL and 55 guests