junkew

IAccessible/IAccessible2

9 posts in this topic

I need some help in fixing this on W10 / 64 bits system either compiled with #AutoIt3Wrapper_UseX64=Y or #AutoIt3Wrapper_UseX64=N

@Larsj : Did you ever migrate this to W10 /64 bits system. Post #154

I tried in different ways on $tagVARIANT lengths but application stops. I did partly get it running for spied object when useX64=N but then quickly after that fails on child objects when using iAccessible

 

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Hello. I did just a little adjutments. Working for me in Windows 7x86 and Windows 10 x64 (compiled x64 and x86 Version)

 

#AutoIt3Wrapper_UseX64=Y
#RequireAdmin
#include "CUIAutomation2.au3"
#include "MSAccessibility.au3"
#include "ISimpleDOM.au3"
#include <Array.au3>

Opt("MustDeclareVars", 1)

Global $aInfo[10000], $iInfo = 0

MainFunc()


Func MainFunc()

    HotKeySet("^w", "GetWindowInfo")
    HotKeySet("{ESC}", "Close")

    While Sleep(100)
    WEnd

EndFunc   ;==>MainFunc


Func GetWindowInfo()
    Local $aMousePos = MouseGetPos(), $pObject, $tVarChild, $vt, $err = 0
    If AccessibleObjectFromPoint($aMousePos[0], $aMousePos[1], $pObject, $tVarChild) = $S_OK Then
        $vt = BitAND(DllStructGetData($tVarChild, 1, 1), 0xFFFF)
        If $vt = $VT_I4 Then
            Local $oObject, $hWnd, $sName = ""
            If WindowFromAccessibleObject($pObject, $hWnd) = $S_OK Then

                AccessibleObjectFromWindow($hWnd, $OBJID_CLIENT, $tIID_IAccessible, $pObject)
                $oObject = ObjCreateInterface($pObject, $sIID_IAccessible, $dtagIAccessible)

                ; Get parent objects to top window
                Local $pParent, $pPrev, $oPrev, $iRole
                Do
                    $pPrev = $pParent
                    $oPrev = $oObject
                    If IsObj($oObject) Then
                        $oObject.get_accParent($pParent)
                        $oObject = ObjCreateInterface($pParent, $sIID_IAccessible, $dtagIAccessible)
                    EndIf

                    If IsObj($oObject) Then
                        $oObject.get_accName($CHILDID_SELF, $sName)
                    EndIf

                Until String($sName) = "Escritorio";"Desktop"

                ; Info for top window (previous to desktop)
                PrintElementInfoToArray($pPrev, $oPrev, $CHILDID_SELF, "")

                ; Info for child objects of the top window
                If $oPrev.get_accRole($CHILDID_SELF, $iRole) = $S_OK And $iRole = $ROLE_SYSTEM_WINDOW Then
                    WindowFromAccessibleObject($pPrev, $hWnd)
                    PrintWindowObjects($hWnd)
                Else
                    $err = 1
                EndIf

            Else
                $err = 1
            EndIf
        Else
            $err = 1
        EndIf
    Else
        $err = 1
    EndIf
    If $err Then _
            MsgBox(0, "ISimpleDOM interfaces", _
            "AccessibleObjectFromPoint failed." & @CRLF & _
            "Try another point e.g. the window title bar.")
EndFunc   ;==>GetWindowInfo


Func PrintWindowObjects($hWindow)

    ; Object from window
    Local $pWindow, $oWindow
    AccessibleObjectFromWindow($hWindow, $OBJID_CLIENT, $tIID_IAccessible, $pWindow)
    $oWindow = ObjCreateInterface($pWindow, $sIID_IAccessible, $dtagIAccessible)
    If Not IsObj($oWindow) Then Return

    ; Get window objects
    WalkTreeWithAccessibleChildren($pWindow, 0, 8)

    ; Print window objects
    ReDim $aInfo[$iInfo]
    _ArrayDisplay($aInfo, "ISimpleDOM interfaces")
    ReDim $aInfo[10000]
    $iInfo = 0

EndFunc   ;==>PrintWindowObjects


Func WalkTreeWithAccessibleChildren($pAcc, $iLevel, $iLevels = 0)

    If $iLevels And $iLevel = $iLevels Then Return

    ; Create object
    Local $oAcc = ObjCreateInterface($pAcc, $sIID_IAccessible, $dtagIAccessible)
    If Not IsObj($oAcc) Then Return
    $oAcc.AddRef()

    ; Indentation
    Local $sIndent = ""
    For $i = 0 To $iLevel - 1
        $sIndent &= "    "
    Next

    Local $iChildCount, $iReturnCount, $tVarChildren

    ; Get children
    If $oAcc.get_accChildCount($iChildCount) Or Not $iChildCount Then Return
    If AccessibleChildren($pAcc, 0, $iChildCount, $tVarChildren, $iReturnCount) Then Return

    Local $vt, $pChildObj, $oChildObj
    Local $pService, $oService, $pISimpleDOMNode, $oISimpleDOMNode, $pISimpleDOM, $oISimpleDOM

    ; $oISimpleDOMNode.nodeInfo
    Local $sNodeName, $iNameSpaceID, $sNodeValue, $iNumChildren, $iUniqueID, $iNodeType, $sInnerHTML

    ; $oISimpleDOMNode.attributes
    Local $iMaxAttribs = 100, $iNumAttribs
    Local $tAttribNames = DllStructCreate("ptr[" & $iMaxAttribs & "]"), $sAttribName
    Local $tNameSpaceIDs = DllStructCreate("short[" & $iMaxAttribs & "]"), $iNameSpaceID
    Local $tAttribValues = DllStructCreate("ptr[" & $iMaxAttribs & "]"), $sAttribValue

    ; $oISimpleDOMNode.computedStyle
    Local $iMaxStyleProperties = 100, $iNumStyleProperties
    Local $tStyleProperties = DllStructCreate("ptr[" & $iMaxStyleProperties & "]"), $sStyleProperty
    Local $tStyleValues = DllStructCreate("ptr[" & $iMaxStyleProperties & "]"), $sStyleValue

    ; For each child
    For $i = 1 To $iReturnCount

        ; $tVarChildren is an array of VARIANTs with information about the children
        $vt = BitAND(DllStructGetData($tVarChildren, $i, 1), 0xFFFF)

        If $vt = $VT_DISPATCH Then



            ; Child object; get correct ptr x64 or x86 version
            Local $tVariant = DllStructCreate("word vt;word r1;word r2;word r3;ptr data; ptr;", DllStructGetPtr($tVarChildren, $i))
            $pChildObj = DllStructGetData($tVariant, 5)

            ;this is wrong. You will never get the x64 ptr
;~          ; Child object
;~          $pChildObj = DllStructGetData($tVarChildren, $i, 3)
;~          $oChildObj = ObjCreateInterface($pChildObj, $sIID_IAccessible, $dtagIAccessible)




            $oChildObj = ObjCreateInterface(($pChildObj), $sIID_IAccessible, $dtagIAccessible)

            If IsObj($oChildObj) Then

                ; Try to get an ISimpleDOMNode interface pointer for the child object
                If $oChildObj.QueryInterface(DllStructGetPtr($tIID_IServiceProvider), $pService) = $S_OK Then
                    $oService = ObjCreateInterface($pService, $sIID_IServiceProvider, $dtagIServiceProvider)
                    If $oService.QueryService($tIID_ISimpleDOMNode, $tIID_ISimpleDOMNode, $pISimpleDOMNode) = $S_OK Then
                        $aInfo[$iInfo] = $sIndent & "$pISimpleDOMNode = " & Ptr($pISimpleDOMNode)
                        $iInfo += 1
                        $oISimpleDOMNode = ObjCreateInterface($pISimpleDOMNode, $sIID_ISimpleDOMNode, $dtagISimpleDOMNode)
                        If IsObj($oISimpleDOMNode) Then
                            $oISimpleDOMNode.nodeInfo($sNodeName, $iNameSpaceID, $sNodeValue, $iNumChildren, $iUniqueID, $iNodeType)
                            $aInfo[$iInfo + 0] = $sIndent & "$sNodeName       = " & $sNodeName
                            $aInfo[$iInfo + 1] = $sIndent & "$iNameSpaceID    = " & $iNameSpaceID
                            $aInfo[$iInfo + 2] = $sIndent & "$sNodeValue      = " & $sNodeValue
                            $aInfo[$iInfo + 3] = $sIndent & "$iNumChildren    = " & $iNumChildren
                            $aInfo[$iInfo + 4] = $sIndent & "$iUniqueID       = " & $iUniqueID
                            $aInfo[$iInfo + 5] = $sIndent & "$iNodeType       = " & $iNodeType & " (" & GetNodeType($iNodeType) & ")"
                            $iInfo += 6

                            ; $oISimpleDOMNode.attributes
                            $oISimpleDOMNode.attributes($iMaxAttribs, $tAttribNames, $tNameSpaceIDs, $tAttribValues, $iNumAttribs)
                            $aInfo[$iInfo] = $sIndent & "$iNumAttribs     = " & $iNumAttribs
                            $iInfo += 1
                            For $j = 1 To $iNumAttribs
                                $sAttribName = SysReadString(DllStructGetData($tAttribNames, 1, $j))
                                $sAttribValue = SysReadString(DllStructGetData($tAttribValues, 1, $j))
                                $iNameSpaceID = DllStructGetData($tNameSpaceIDs, 1, $j)
                                $aInfo[$iInfo + 0] = "    " & $sIndent & "$iAttrib      = " & $j
                                $aInfo[$iInfo + 1] = "    " & $sIndent & "$sAttribName  = " & $sAttribName
                                $aInfo[$iInfo + 2] = "    " & $sIndent & "$sAttribValue = " & $sAttribValue
                                $aInfo[$iInfo + 3] = "    " & $sIndent & "$iNameSpaceID = " & $iNameSpaceID
                                $iInfo += 4
                                ; Free memory allocated by BSTRs
                                SysFreeString(DllStructGetData($tAttribNames, 1, $j))
                                SysFreeString(DllStructGetData($tAttribValues, 1, $j))
                            Next

                            ; $oISimpleDOMNode.computedStyle
                            $oISimpleDOMNode.computedStyle($iMaxStyleProperties, 0, $tStyleProperties, $tStyleValues, $iNumStyleProperties)
                            $aInfo[$iInfo] = $sIndent & "$iNumStyleProps  = " & $iNumStyleProperties
                            $iInfo += 1
                            For $j = 1 To $iNumStyleProperties
                                $sStyleProperty = SysReadString(DllStructGetData($tStyleProperties, 1, $j))
                                $sStyleValue = SysReadString(DllStructGetData($tStyleValues, 1, $j))
                                $aInfo[$iInfo + 0] = "    " & $sIndent & "$iStyle       = " & $j
                                $aInfo[$iInfo + 1] = "    " & $sIndent & "$sStyleProp   = " & $sStyleProperty
                                $aInfo[$iInfo + 2] = "    " & $sIndent & "$sStyleValue  = " & $sStyleValue
                                $iInfo += 3
                                ; Free memory allocated by BSTRs
                                SysFreeString(DllStructGetData($tStyleProperties, 1, $j))
                                SysFreeString(DllStructGetData($tStyleValues, 1, $j))
                            Next

                            ;$oISimpleDOMNode.innerHTML( $sInnerHTML )
                            ;If String( $sInnerHTML ) <> "0" Then
                            ;  $aInfo[$iInfo] = $sIndent & "$sInnerHTML      = " & $sInnerHTML
                            ;  $iInfo += 1
                            ;EndIf

                            If $iNodeType = 3 Then ; $NODETYPE_TEXT
                                ; Try to get an ISimpleDOMText interface pointer with $oISimpleDOMNode.QueryInterface
                                If $oISimpleDOMNode.QueryInterface(DllStructGetPtr($tIID_ISimpleDOMText), $pISimpleDOM) = $S_OK Then
                                    $aInfo[$iInfo] = $sIndent & "$pISimpleDOMText = " & Ptr($pISimpleDOM)
                                    $iInfo += 1
                                    $oISimpleDOM = ObjCreateInterface($pISimpleDOM, $sIID_ISimpleDOMText, $dtagISimpleDOMText)
                                    If IsObj($oISimpleDOM) Then
                                        Local $sDomText
                                        $oISimpleDOM.domText($sDomText)
                                        $aInfo[$iInfo] = $sIndent & "$sDomText        = " & $sDomText
                                        $iInfo += 1
                                    EndIf
                                EndIf

                            ElseIf $iNodeType = 9 Then ; $NODETYPE_DOCUMENT
                                ; Try to get an ISimpleDOMDocument interface pointer with $oISimpleDOMNode.QueryInterface
                                If $oISimpleDOMNode.QueryInterface(DllStructGetPtr($tIID_ISimpleDOMDocument), $pISimpleDOM) = $S_OK Then
                                    $aInfo[$iInfo] = $sIndent & "$pISimpleDOMDocument = " & Ptr($pISimpleDOM)
                                    $iInfo += 1
                                    $oISimpleDOM = ObjCreateInterface($pISimpleDOM, $sIID_ISimpleDOMDocument, $dtagISimpleDOMDocument)
                                    If IsObj($oISimpleDOM) Then
                                        Local $sURL, $sTitle, $sMimeType, $sDocType
                                        $oISimpleDOM.URL($sURL)
                                        $oISimpleDOM.title($sTitle)
                                        $oISimpleDOM.mimeType($sMimeType)
                                        $oISimpleDOM.docType($sDocType)
                                        $aInfo[$iInfo + 0] = $sIndent & "$sURL                = " & $sURL
                                        $aInfo[$iInfo + 1] = $sIndent & "$sTitle              = " & $sTitle
                                        $aInfo[$iInfo + 2] = $sIndent & "$sMimeType           = " & $sMimeType
                                        $aInfo[$iInfo + 3] = $sIndent & "$sDocType            = " & $sDocType
                                        $iInfo += 4
                                    EndIf
                                EndIf
                            EndIf

                        EndIf
                    EndIf
                EndIf

                PrintElementInfoToArray($pChildObj, $oChildObj, $CHILDID_SELF, $sIndent)
                WalkTreeWithAccessibleChildren($pChildObj, $iLevel + 1, $iLevels)

            EndIf

        EndIf

    Next

EndFunc   ;==>WalkTreeWithAccessibleChildren


Func PrintElementInfoToArray($pElement, $oElement, $iChild, $sIndent)
    Local $hWnd, $sName, $iRole, $sRole, $iRoleLen
    Local $iState, $sState, $iStateLen
    Local $sValue, $x, $y, $w, $h
    If $iChild <> $CHILDID_SELF Then
        $aInfo[$iInfo] = $sIndent & "$iChildElem = " & $iChild
        $iInfo += 1
    EndIf
    If $iChild = $CHILDID_SELF And $oElement.get_accRole($CHILDID_SELF, $iRole) = $S_OK And $iRole = $ROLE_SYSTEM_WINDOW Then
        WindowFromAccessibleObject($pElement, $hWnd)
        $aInfo[$iInfo] = $sIndent & "$hWnd   = " & $hWnd
        $iInfo += 1
    EndIf
    $oElement.get_accName($iChild, $sName)
    $aInfo[$iInfo] = $sIndent & "$sName  = " & $sName
    $iInfo += 1
    If $oElement.get_accRole($iChild, $iRole) = $S_OK Then
        $aInfo[$iInfo] = $sIndent & "$iRole  = 0x" & Hex($iRole)
        $iInfo += 1
        $iRoleLen = GetRoleText($iRole, 0, 0) + 1
        $sRole = DllStructCreate("wchar[" & $iRoleLen & "]")
        GetRoleText($iRole, DllStructGetPtr($sRole), $iRoleLen)
        $aInfo[$iInfo] = $sIndent & "$sRole  = " & DllStructGetData($sRole, 1)
        $iInfo += 1
    EndIf
    If $oElement.get_accState($iChild, $iState) = $S_OK Then
        $aInfo[$iInfo] = $sIndent & "$iState = 0x" & Hex($iState)
        $iInfo += 1
        $iStateLen = GetStateText($iState, 0, 0) + 1
        $sState = DllStructCreate("wchar[" & $iStateLen & "]")
        GetStateText($iState, DllStructGetPtr($sState), $iStateLen)
        $aInfo[$iInfo] = $sIndent & "$sState = " & DllStructGetData($sState, 1)
        $iInfo += 1
    EndIf
    If $oElement.get_accValue($iChild, $sValue) = $S_OK Then
        $aInfo[$iInfo] = $sIndent & "$sValue = " & $sValue
        $iInfo += 1
    EndIf
    If $oElement.accLocation($x, $y, $w, $h, $iChild) = $S_OK Then
        $aInfo[$iInfo] = $sIndent & "$x, $y, $w, $h = " & $x & ", " & $y & ", " & $w & ", " & $h
        $iInfo += 1
    EndIf
    $aInfo[$iInfo] = ""
    $iInfo += 1
EndFunc   ;==>PrintElementInfoToArray


Func Close()
    Exit
EndFunc   ;==>Close

 

Saludos

Edited by Danyfirex

 

venezuela.png Would you like to say thank to Danyfirex using a warmy way?  offer me a cup of coffee... coffee.png

autoit_scripter_blue_userbar.png

       AutoIt...

 

 

Share this post


Link to post
Share on other sites

I've not tested these interfaces (IAccessible, IAccessible2, IAccessibleEx, ISimpleDOM) or the examples on 64 bit or Windows 10. A few minor issues cannot be excluded.

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Weird doing nothing on my system when trying as X64

I changed some constants to come from include in MSACCESSIBILITY.AU3

#include "CUIAutomation2.au3"
#include <autoitconstants.au3>
#include <winapiconstants.au3>
#include <menuconstants.au3>

to prevent some compile errors removed const

If @AutoItX64 Then
    global $tagVARIANT = "dword[6];" ; Use this form to be able to build an
Else                               ; array in function AccessibleChildren.
    global $tagVARIANT = "dword[4];"
EndIf

using above source from @Danyfirex I get with some translation in the name of top level object in my case dutch Bureaublad

#AutoIt3Wrapper_UseX64=N
;~ #RequireAdmin

...


    consolewrite("GetWindowInfo name " & String($sName) & @CRLF)
Until stringinstr("Desktop Bureaublad Escritorio",String($sName))>0

The hotkey is calling the GetWindowInfo function when pressing ctrl+w above htmlDocument of google browser and then it works for above nice dump of elements

The problem starts when working with X64

#AutoIt3Wrapper_UseX64=Y
#RequireAdmin
Func GetWindowInfo()
    consolewrite("GetWindowInfo before first if" & @CRLF)
;~  MsgBox(0, "GetWindowInfo", "GetWindowInfo'before first if" & @CRLF)
    Local $aMousePos = MouseGetPos(), $pObject, $tVarChild, $vt, $err = 0

Consolewrite statements seems not to work at all (probably as I now am elevated running as admin? happens also in X86) but msgbox goes fine.

Testing further gives me the feeling it goes wrong in AccessibleObjectFromWindow

AccessibleObjectFromPoint gives a correct value when making an iaccessible object from it

maybe after googling hitting this feature https://bugs.webkit.org/show_bug.cgi?id=141391

Before comparing this value against the OBJID_ values, the server must cast it to DWORD; otherwise, on 64-bit Windows, the sign extension of the lParam can interfere with the comparison.

But it does not say anything on the clientside

https://groups.google.com/a/chromium.org/forum/#!topic/chromium-reviews/TY6rBImbySQ

So most likely I need to fix this function to call differently in X64 compared to X86 for the $OBJID_CLIENT value 
which is defined as Global Const $OBJID_CLIENT            = 0xFFFFFFFC

Func AccessibleObjectFromWindow( $hWnd, $iObjectID, $tRIID, ByRef $pObject )
    If @AutoItX64 Then
;~      Local $aRet = DllCall( $hdllOleacc, "int", "AccessibleObjectFromWindow", "hwnd", $hWnd, "uint64", 0xfffffffffffffffc, "struct*", $tRIID, "int*", 0 )
        Local $aRet = DllCall( $hdllOleacc, "int", "AccessibleObjectFromWindow", "hwnd", $hWnd, "uint64", 0x00000000fffffffc, "struct*", $tRIID, "int*", 0 )
    else
        Local $aRet = DllCall( $hdllOleacc, "int", "AccessibleObjectFromWindow", "hwnd", $hWnd, "dword", $iObjectID, "struct*", $tRIID, "int*", 0 )
    endif
    If @error Then
        msgbox(0,"Error",$aRet)
        Return SetError(1, 0, $S_FALSE)
    EndIf

    If $aRet[0] Then Return SetError(2, 0, $aRet[0])
    $pObject = $aRet[4]
    Return $S_OK
EndFunc

source for testing includes messageboxes

#AutoIt3Wrapper_UseX64=Y
#RequireAdmin
#include "CUIAutomation2.au3"
#include "MSAccessibility.au3"
#include "ISimpleDOM.au3"
#include <Array.au3>

Opt("MustDeclareVars", 1)

Global $aInfo[10000], $iInfo = 0

MainFunc()

Func MainFunc()

    HotKeySet("^w", "GetWindowInfo")
    HotKeySet("{ESC}", "Close")

    While Sleep(100)
    WEnd

EndFunc   ;==>MainFunc


Func GetWindowInfo()
;~  consolewrite("GetWindowInfo before first if" & @CRLF)
;~  MsgBox(0, "GetWindowInfo", "GetWindowInfo before first if" & @CRLF)
    Local $aMousePos = MouseGetPos(), $pObject, $tVarChild, $vt, $err = 0
    Local $oObject, $hWnd, $sName = ""

    If AccessibleObjectFromPoint($aMousePos[0], $aMousePos[1], $pObject, $tVarChild) = $S_OK Then
;~      MsgBox(0, "GetWindowInfo", "GetWindowInfo after first if" & @CRLF)
;~      consolewrite("GetWindowInfo after first if" & @CRLF)
        $oObject = ObjCreateInterface($pObject, $sIID_IAccessible, $dtagIAccessible)
        $oObject.get_accName($CHILDID_SELF, $sName)
;~      consolewrite("GetWindowInfo name " & String($sName) & @CRLF)
        MsgBox(0, "GetWindowInfo", "GetWindowInfo name " & String($sName) & @CRLF)
        $vt = BitAND(DllStructGetData($tVarChild, 1, 1), 0xFFFF)
        If $vt = $VT_I4 Then
;~          consolewrite("GetWindowInfo after 2nd if VT_I4" & @CRLF)
;~          MsgBox(0, "GetWindowInfo", "GetWindowInfo after 2nd if VT_I4" & @CRLF)

            If WindowFromAccessibleObject($pObject, $hWnd) = $S_OK Then
                MsgBox(0, "GetWindowInfo", "GetWindowInfo after 3rd if" & @CRLF)
;~              consolewrite("GetWindowInfo after 3rd if " & @CRLF)
                AccessibleObjectFromWindow($hWnd, $OBJID_CLIENT, $tIID_IAccessible, $pObject)
                MsgBox(0, "GetWindowInfo", "Yeah we did not break" & @CRLF)
                $oObject = ObjCreateInterface($pObject, $sIID_IAccessible, $dtagIAccessible)
                MsgBox(0, "GetWindowInfo", "But unfortunately did not come here" & @CRLF)
                $oObject.get_accName($CHILDID_SELF, $sName)
;~      consolewrite("GetWindowInfo name " & String($sName) & @CRLF)
                MsgBox(0, "GetWindowInfo", "GetWindowInfo name after 3rd if " & String($sName) & @CRLF)

                ; Get parent objects to top window
                Local $pParent, $pPrev, $oPrev, $iRole
                Do
                    $pPrev = $pParent
                    $oPrev = $oObject
                    If IsObj($oObject) Then
                        $oObject.get_accParent($pParent)
                        $oObject = ObjCreateInterface($pParent, $sIID_IAccessible, $dtagIAccessible)
                    EndIf

                    If IsObj($oObject) Then
                        $oObject.get_accName($CHILDID_SELF, $sName)
                    EndIf
;~                  consolewrite("GetWindowInfo name " & String($sName) & @CRLF)
                    MsgBox(0, "GetWindowInfo", "GetWindowInfo name " & String($sName) & @CRLF)
                Until stringinstr("Desktop Bureaublad Escritorio",String($sName))>0
;~              String($sName) = "Desktop" or "Bureaublad" ;"Escritorio";"Desktop"

                ; Info for top window (previous to desktop)
                PrintElementInfoToArray($pPrev, $oPrev, $CHILDID_SELF, "")

                ; Info for child objects of the top window
                If $oPrev.get_accRole($CHILDID_SELF, $iRole) = $S_OK And $iRole = $ROLE_SYSTEM_WINDOW Then
                    WindowFromAccessibleObject($pPrev, $hWnd)
                    PrintWindowObjects($hWnd)
                Else
                    $err = 1
                EndIf

            Else
                $err = 1
            EndIf
        Else
            $err = 1
        EndIf
    Else
        $err = 1
    EndIf
    If $err Then _
            MsgBox(0, "ISimpleDOM interfaces", _
            "Accessible function xxxxx failed." & @CRLF & _
            "Try another point e.g. the window title bar.")
EndFunc   ;==>GetWindowInfo


Func PrintWindowObjects($hWindow)

    ; Object from window
    Local $pWindow, $oWindow
    AccessibleObjectFromWindow($hWindow, $OBJID_CLIENT, $tIID_IAccessible, $pWindow)
    $oWindow = ObjCreateInterface($pWindow, $sIID_IAccessible, $dtagIAccessible)
    If Not IsObj($oWindow) Then Return

    ; Get window objects
    WalkTreeWithAccessibleChildren($pWindow, 0, 8)

    ; Print window objects
    ReDim $aInfo[$iInfo]
    _ArrayDisplay($aInfo, "ISimpleDOM interfaces")
    ReDim $aInfo[10000]
    $iInfo = 0

EndFunc   ;==>PrintWindowObjects


Func WalkTreeWithAccessibleChildren($pAcc, $iLevel, $iLevels = 0)

    If $iLevels And $iLevel = $iLevels Then Return

    ; Create object
    Local $oAcc = ObjCreateInterface($pAcc, $sIID_IAccessible, $dtagIAccessible)
    If Not IsObj($oAcc) Then Return
    $oAcc.AddRef()

    ; Indentation
    Local $sIndent = ""
    For $i = 0 To $iLevel - 1
        $sIndent &= "    "
    Next

    Local $iChildCount, $iReturnCount, $tVarChildren

    ; Get children
    If $oAcc.get_accChildCount($iChildCount) Or Not $iChildCount Then Return
    If AccessibleChildren($pAcc, 0, $iChildCount, $tVarChildren, $iReturnCount) Then Return

    Local $vt, $pChildObj, $oChildObj
    Local $pService, $oService, $pISimpleDOMNode, $oISimpleDOMNode, $pISimpleDOM, $oISimpleDOM

    ; $oISimpleDOMNode.nodeInfo
    Local $sNodeName, $iNameSpaceID, $sNodeValue, $iNumChildren, $iUniqueID, $iNodeType, $sInnerHTML

    ; $oISimpleDOMNode.attributes
    Local $iMaxAttribs = 100, $iNumAttribs
    Local $tAttribNames = DllStructCreate("ptr[" & $iMaxAttribs & "]"), $sAttribName
    Local $tNameSpaceIDs = DllStructCreate("short[" & $iMaxAttribs & "]"), $iNameSpaceID
    Local $tAttribValues = DllStructCreate("ptr[" & $iMaxAttribs & "]"), $sAttribValue

    ; $oISimpleDOMNode.computedStyle
    Local $iMaxStyleProperties = 100, $iNumStyleProperties
    Local $tStyleProperties = DllStructCreate("ptr[" & $iMaxStyleProperties & "]"), $sStyleProperty
    Local $tStyleValues = DllStructCreate("ptr[" & $iMaxStyleProperties & "]"), $sStyleValue

    ; For each child
    For $i = 1 To $iReturnCount

        ; $tVarChildren is an array of VARIANTs with information about the children
        $vt = BitAND(DllStructGetData($tVarChildren, $i, 1), 0xFFFF)

        If $vt = $VT_DISPATCH Then



            ; Child object; get correct ptr x64 or x86 version
            Local $tVariant = DllStructCreate("word vt;word r1;word r2;word r3;ptr data; ptr;", DllStructGetPtr($tVarChildren, $i))
            $pChildObj = DllStructGetData($tVariant, 5)

            ;this is wrong. You will never get the x64 ptr
;~          ; Child object
;~          $pChildObj = DllStructGetData($tVarChildren, $i, 3)
;~          $oChildObj = ObjCreateInterface($pChildObj, $sIID_IAccessible, $dtagIAccessible)




            $oChildObj = ObjCreateInterface(($pChildObj), $sIID_IAccessible, $dtagIAccessible)

            If IsObj($oChildObj) Then

                ; Try to get an ISimpleDOMNode interface pointer for the child object
                If $oChildObj.QueryInterface(DllStructGetPtr($tIID_IServiceProvider), $pService) = $S_OK Then
                    $oService = ObjCreateInterface($pService, $sIID_IServiceProvider, $dtagIServiceProvider)
                    If $oService.QueryService($tIID_ISimpleDOMNode, $tIID_ISimpleDOMNode, $pISimpleDOMNode) = $S_OK Then
                        $aInfo[$iInfo] = $sIndent & "$pISimpleDOMNode = " & Ptr($pISimpleDOMNode)
                        $iInfo += 1
                        $oISimpleDOMNode = ObjCreateInterface($pISimpleDOMNode, $sIID_ISimpleDOMNode, $dtagISimpleDOMNode)
                        If IsObj($oISimpleDOMNode) Then
                            $oISimpleDOMNode.nodeInfo($sNodeName, $iNameSpaceID, $sNodeValue, $iNumChildren, $iUniqueID, $iNodeType)
                            $aInfo[$iInfo + 0] = $sIndent & "$sNodeName       = " & $sNodeName
                            $aInfo[$iInfo + 1] = $sIndent & "$iNameSpaceID    = " & $iNameSpaceID
                            $aInfo[$iInfo + 2] = $sIndent & "$sNodeValue      = " & $sNodeValue
                            $aInfo[$iInfo + 3] = $sIndent & "$iNumChildren    = " & $iNumChildren
                            $aInfo[$iInfo + 4] = $sIndent & "$iUniqueID       = " & $iUniqueID
                            $aInfo[$iInfo + 5] = $sIndent & "$iNodeType       = " & $iNodeType & " (" & GetNodeType($iNodeType) & ")"
                            $iInfo += 6

                            ; $oISimpleDOMNode.attributes
                            $oISimpleDOMNode.attributes($iMaxAttribs, $tAttribNames, $tNameSpaceIDs, $tAttribValues, $iNumAttribs)
                            $aInfo[$iInfo] = $sIndent & "$iNumAttribs     = " & $iNumAttribs
                            $iInfo += 1
                            For $j = 1 To $iNumAttribs
                                $sAttribName = SysReadString(DllStructGetData($tAttribNames, 1, $j))
                                $sAttribValue = SysReadString(DllStructGetData($tAttribValues, 1, $j))
                                $iNameSpaceID = DllStructGetData($tNameSpaceIDs, 1, $j)
                                $aInfo[$iInfo + 0] = "    " & $sIndent & "$iAttrib      = " & $j
                                $aInfo[$iInfo + 1] = "    " & $sIndent & "$sAttribName  = " & $sAttribName
                                $aInfo[$iInfo + 2] = "    " & $sIndent & "$sAttribValue = " & $sAttribValue
                                $aInfo[$iInfo + 3] = "    " & $sIndent & "$iNameSpaceID = " & $iNameSpaceID
                                $iInfo += 4
                                ; Free memory allocated by BSTRs
                                SysFreeString(DllStructGetData($tAttribNames, 1, $j))
                                SysFreeString(DllStructGetData($tAttribValues, 1, $j))
                            Next

                            ; $oISimpleDOMNode.computedStyle
                            $oISimpleDOMNode.computedStyle($iMaxStyleProperties, 0, $tStyleProperties, $tStyleValues, $iNumStyleProperties)
                            $aInfo[$iInfo] = $sIndent & "$iNumStyleProps  = " & $iNumStyleProperties
                            $iInfo += 1
                            For $j = 1 To $iNumStyleProperties
                                $sStyleProperty = SysReadString(DllStructGetData($tStyleProperties, 1, $j))
                                $sStyleValue = SysReadString(DllStructGetData($tStyleValues, 1, $j))
                                $aInfo[$iInfo + 0] = "    " & $sIndent & "$iStyle       = " & $j
                                $aInfo[$iInfo + 1] = "    " & $sIndent & "$sStyleProp   = " & $sStyleProperty
                                $aInfo[$iInfo + 2] = "    " & $sIndent & "$sStyleValue  = " & $sStyleValue
                                $iInfo += 3
                                ; Free memory allocated by BSTRs
                                SysFreeString(DllStructGetData($tStyleProperties, 1, $j))
                                SysFreeString(DllStructGetData($tStyleValues, 1, $j))
                            Next

                            ;$oISimpleDOMNode.innerHTML( $sInnerHTML )
                            ;If String( $sInnerHTML ) <> "0" Then
                            ;  $aInfo[$iInfo] = $sIndent & "$sInnerHTML      = " & $sInnerHTML
                            ;  $iInfo += 1
                            ;EndIf

                            If $iNodeType = 3 Then ; $NODETYPE_TEXT
                                ; Try to get an ISimpleDOMText interface pointer with $oISimpleDOMNode.QueryInterface
                                If $oISimpleDOMNode.QueryInterface(DllStructGetPtr($tIID_ISimpleDOMText), $pISimpleDOM) = $S_OK Then
                                    $aInfo[$iInfo] = $sIndent & "$pISimpleDOMText = " & Ptr($pISimpleDOM)
                                    $iInfo += 1
                                    $oISimpleDOM = ObjCreateInterface($pISimpleDOM, $sIID_ISimpleDOMText, $dtagISimpleDOMText)
                                    If IsObj($oISimpleDOM) Then
                                        Local $sDomText
                                        $oISimpleDOM.domText($sDomText)
                                        $aInfo[$iInfo] = $sIndent & "$sDomText        = " & $sDomText
                                        $iInfo += 1
                                    EndIf
                                EndIf

                            ElseIf $iNodeType = 9 Then ; $NODETYPE_DOCUMENT
                                ; Try to get an ISimpleDOMDocument interface pointer with $oISimpleDOMNode.QueryInterface
                                If $oISimpleDOMNode.QueryInterface(DllStructGetPtr($tIID_ISimpleDOMDocument), $pISimpleDOM) = $S_OK Then
                                    $aInfo[$iInfo] = $sIndent & "$pISimpleDOMDocument = " & Ptr($pISimpleDOM)
                                    $iInfo += 1
                                    $oISimpleDOM = ObjCreateInterface($pISimpleDOM, $sIID_ISimpleDOMDocument, $dtagISimpleDOMDocument)
                                    If IsObj($oISimpleDOM) Then
                                        Local $sURL, $sTitle, $sMimeType, $sDocType
                                        $oISimpleDOM.URL($sURL)
                                        $oISimpleDOM.title($sTitle)
                                        $oISimpleDOM.mimeType($sMimeType)
                                        $oISimpleDOM.docType($sDocType)
                                        $aInfo[$iInfo + 0] = $sIndent & "$sURL                = " & $sURL
                                        $aInfo[$iInfo + 1] = $sIndent & "$sTitle              = " & $sTitle
                                        $aInfo[$iInfo + 2] = $sIndent & "$sMimeType           = " & $sMimeType
                                        $aInfo[$iInfo + 3] = $sIndent & "$sDocType            = " & $sDocType
                                        $iInfo += 4
                                    EndIf
                                EndIf
                            EndIf

                        EndIf
                    EndIf
                EndIf

                PrintElementInfoToArray($pChildObj, $oChildObj, $CHILDID_SELF, $sIndent)
                WalkTreeWithAccessibleChildren($pChildObj, $iLevel + 1, $iLevels)

            EndIf

        EndIf

    Next

EndFunc   ;==>WalkTreeWithAccessibleChildren


Func PrintElementInfoToArray($pElement, $oElement, $iChild, $sIndent)
    Local $hWnd, $sName, $iRole, $sRole, $iRoleLen
    Local $iState, $sState, $iStateLen
    Local $sValue, $x, $y, $w, $h
    If $iChild <> $CHILDID_SELF Then
        $aInfo[$iInfo] = $sIndent & "$iChildElem = " & $iChild
        $iInfo += 1
    EndIf
    If $iChild = $CHILDID_SELF And $oElement.get_accRole($CHILDID_SELF, $iRole) = $S_OK And $iRole = $ROLE_SYSTEM_WINDOW Then
        WindowFromAccessibleObject($pElement, $hWnd)
        $aInfo[$iInfo] = $sIndent & "$hWnd   = " & $hWnd
        $iInfo += 1
    EndIf
    $oElement.get_accName($iChild, $sName)
    $aInfo[$iInfo] = $sIndent & "$sName  = " & $sName
    $iInfo += 1
    If $oElement.get_accRole($iChild, $iRole) = $S_OK Then
        $aInfo[$iInfo] = $sIndent & "$iRole  = 0x" & Hex($iRole)
        $iInfo += 1
        $iRoleLen = GetRoleText($iRole, 0, 0) + 1
        $sRole = DllStructCreate("wchar[" & $iRoleLen & "]")
        GetRoleText($iRole, DllStructGetPtr($sRole), $iRoleLen)
        $aInfo[$iInfo] = $sIndent & "$sRole  = " & DllStructGetData($sRole, 1)
        $iInfo += 1
    EndIf
    If $oElement.get_accState($iChild, $iState) = $S_OK Then
        $aInfo[$iInfo] = $sIndent & "$iState = 0x" & Hex($iState)
        $iInfo += 1
        $iStateLen = GetStateText($iState, 0, 0) + 1
        $sState = DllStructCreate("wchar[" & $iStateLen & "]")
        GetStateText($iState, DllStructGetPtr($sState), $iStateLen)
        $aInfo[$iInfo] = $sIndent & "$sState = " & DllStructGetData($sState, 1)
        $iInfo += 1
    EndIf
    If $oElement.get_accValue($iChild, $sValue) = $S_OK Then
        $aInfo[$iInfo] = $sIndent & "$sValue = " & $sValue
        $iInfo += 1
    EndIf
    If $oElement.accLocation($x, $y, $w, $h, $iChild) = $S_OK Then
        $aInfo[$iInfo] = $sIndent & "$x, $y, $w, $h = " & $x & ", " & $y & ", " & $w & ", " & $h
        $iInfo += 1
    EndIf
    $aInfo[$iInfo] = ""
    $iInfo += 1
EndFunc   ;==>PrintElementInfoToArray


Func Close()
    Exit
EndFunc   ;==>Close

 

MSAccessibility.au3

Edited by junkew

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

above my hat

https://bugzilla.mozilla.org/show_bug.cgi?id=649236

It seems to be AccessibleObjectFromWindow with the actual problem, though AccessibleObjectFromEvent calls it internally.
A work around has been implemented in NVDA changeset:main,4474 which replaces a call to AccessibleObjectFromEvent with custom code that  sends WM_GETOBJECT, calls ObjectFromLresult, and tries accChild. All the things that I'd think AccessibleObjectFromEvent/AccessibleObjectFromWindow would do normally.

http://hg.mozilla.org/mozilla-central/rev/62cb7ce43f42 has an actual workaround but no clue for me on how to do this in AutoIT

  •  AccessibleObjectFromWindow API sends WM_GETOBJECT message to the Window so that could be used as a workaround.
Edited by junkew

Share this post


Link to post
Share on other sites

probably change this from @trancexx

Should then try something like this

;~ Func _IEControlGetObjFromHWND($hWin)
Func _AccessibleObjectFromWindow( $hWnd, $iObjectID, $tRIID, ByRef $pObject )
    Local $aCall = DllCall("user32.dll", "dword", "RegisterWindowMessageW", "wstr", "WM_GETOBJECT")

    If @error Or Not $aCall[0] Then
        Return SetError(1, 0, "")
    EndIf

    Local Const $WM_GETOBJECT = $aCall[0]

    $aCall = DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $hWnd, "dword", $WM_GETOBJECT, "wparam", 0, "lparam", $iObjectID0)

    Local $lResult = $aCall[0]

;~ Global Const $sIID_IAccessible="{618736E0-3C3D-11CF-810C-00AA00389B71}"
Local $tUUID = _WinAPI_GUIDFromString("{618736E0-3C3D-11CF-810C-00AA00389B71}") 
;~     Local $tUUID = _WinAPI_GUIDFromString("{626FC520-A41E-11CF-A731-00A0C9082637}") ; IID_IHTMLDocument

    DllCall("ole32.dll", "int", "CoInitializeEx", "ptr", 0, "dword", 2) ;COINIT_APARTMENTTHREADED

    $aCall = DllCall("oleacc.dll", "dword", "ObjectFromLresult", _
            "lresult", $lResult, _
            "ptr", DllStructGetPtr($tUUID), _
            "wparam", 0, _
            "idispatch*", 0)


    If IsObj($aCall[4]) Then
        return $aCall[4]
    Else
        Return SetError(1, 0, 0)
    EndIf

EndFunc   ;==>_AccessibleObjectFromWindow

 

Share this post


Link to post
Share on other sites

Hello. try the call this way

 

Local $aRet = DllCall( $hdllOleacc, "int", "AccessibleObjectFromWindow", "hwnd", $hWnd, "dword", $iObjectID, "struct*", $tRIID, "ptr*", 0 )

Saludos

1 person likes this

 

venezuela.png Would you like to say thank to Danyfirex using a warmy way?  offer me a cup of coffee... coffee.png

autoit_scripter_blue_userbar.png

       AutoIt...

 

 

Share this post


Link to post
Share on other sites

that works:sweating: I learned a lot by reading all stuff above

Func AccessibleObjectFromWindow( $hWnd, $iObjectID, $tRIID, ByRef $pObject )
;~      Local $aRet = DllCall( $hdllOleacc, "int", "AccessibleObjectFromWindow", "hwnd", $hWnd, "dword", $iObjectID, "struct*", $tRIID, "int*", 0 )
        Local $aRet = DllCall( $hdllOleacc, "int", "AccessibleObjectFromWindow", "hwnd", $hWnd, "dword", $iObjectID, "struct*", $tRIID, "ptr*", 0 )

 

Share this post


Link to post
Share on other sites

I forgot to tell you that in the first post. I did that change when I tried code lastnight then  I forgot that I did lol.

 

Saludos


 

venezuela.png Would you like to say thank to Danyfirex using a warmy way?  offer me a cup of coffee... coffee.png

autoit_scripter_blue_userbar.png

       AutoIt...

 

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now