Jump to content

How to get the child and control it with MSAA


Recommended Posts

I want to use AutoIt and MSAA to test the Calulator for my first step to learn the MSAA

The goal to get the button and try to click it

Now, I can use "AccessibleObjectFromPoint" to get the button, the codes are

Opt("MustDeclareVars", 1)
Opt("GUIOnEventMode", 1)

Global $oMyError = ObjEvent("AutoIt.Error", "MyErrFunc")

Global Const $hOLEACC = DllOpen("oleacc.dll")

Run("calc")

Global $aMousePos, $aCall

While 1
    $aMousePos = MouseGetPos()
    $aCall = DllCall($hOLEACC, "int", "AccessibleObjectFromPoint", _
            "int", $aMousePos[0], _
            "int", $aMousePos[1], _
            "idispatch*", 0, _
            "ptr*", 0)

    If @error Then ContinueLoop

    If IsObj($aCall[3]) Then        
        ConsoleWrite("Title: " & $aCall[3] .accName & "       Child count: " & $aCall[3] .accChildCount & @CRLF)
        If $aCall[3].accName == "3" Then
            ConsoleWrite("accName: " & $aCall[3].accName & @CRLF)       
            ConsoleWrite("accRole: " & $aCall[3].accRole & @CRLF)
            ConsoleWrite("accState: " & $aCall[3].accState & @CRLF)     
            $aCall[3].accDoDefaultAction(); it can work
        EndIf
    Else
        ConsoleWrite("! NOT OBJECT" & @CRLF)
    EndIf

    Sleep(800)

WEnd


Func MyErrFunc()
    ConsoleWrite("!COM Error!   " & "Number is: " & Hex($oMyError.number, 8) & "  description is: " & $oMyError.windescription & @CRLF)
EndFunc   ;==>MyErrFunc

Func _Quit()
    Exit
EndFunc   ;==>_Quit

But, the "AccessibleObjectFromPoint" is not my choice, because it must need the user uses mouse hove the button.

The "AccessibleObjectFromWindow" looks like my need, but I can not get the button, I only get the Calucator

How to get the button? use the acc_getChild? I have no any idea how to use it in AutoIt

The following is the codes use "AccessibleObjectFromPoint"

#include <WinAPI.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>


Global $oMyError = ObjEvent("AutoIt.Error", "_ErrFunc")

Global $hOLEACC = DllOpen("oleacc.dll")

Local $hWnd = ControlGetHandle("[CLASS:SciCalc]", "", "")

; New function
Global $oAccessibleObject = _AccessibleObjectFromWindow($hWnd)

; Gained:
If IsObj($oAccessibleObject) Then
    ConsoleWrite("accName: " & $oAccessibleObject.accName & @CRLF)
    ConsoleWrite("accRole: " & $oAccessibleObject.accRole & @CRLF)  
    ConsoleWrite("accState: " & $oAccessibleObject.accState & @CRLF)
EndIf

ConsoleWrite(@CRLF)

Func _GetObjectWinHandle($oObject)

    Local $aCall = DllCall("oleacc.dll", "int", "WindowFromAccessibleObject", _
            "idispatch", $oObject, _
            "hwnd*", 0)

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

    Return $aCall[2]

EndFunc   ;==>_GetObjectWinHandle


Func _AccessibleObjectFromWindow($hWnd)

    Local $sIID_IAccessible = "{618736E0-3C3D-11CF-810C-00AA00389B71}"
    Local $tGUID = _WinAPI_GUIDFromString($sIID_IAccessible)
    Local $pGUID = DllStructGetPtr($tGUID)

    Local $aCall = DllCall($hOLEACC, "int", "AccessibleObjectFromWindow", _
            "hwnd", $hWnd, _
            "dword", 0, _ ; OBJID_WINDOW
            "ptr", $pGUID, _
            "idispatch*", 0)

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

    Return $aCall[4]

EndFunc   ;==>_AccessibleObjectFromWindow


Func _ErrFunc()

    ConsoleWrite("--- COM Error, number = " & Ptr($oMyError.number) & ", description: " & $oMyError.windescription)

EndFunc   ;==>_ErrFunc


Func _Quit()

    Exit

EndFunc   ;==>_Quit
;
Link to comment
Share on other sites

Did you try ControlGetHandle() on the button you wanted? For example, the "=" button would be something like:

$hEquButton = ControlGetHandle("[CLASS:SciCalc]", "", "[CLASS:Button; INSTANCE:65]")
$oAccEquButton = _AccessibleObjectFromWindow($hEquButton)

:idea:

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

I used the ControlGetHandle("[CLASS:SciCalc]", "", "[CLASS:Button; INSTANCE:15]") to get the obj, but the result is window, not the button,

That mean the role text of [CLASS:Button; INSTANCE:15] is "window", it has not default action

the role text of the button should be "PushButton" and the default action is "Push"

How can get the button, not the window

Thanks in advanced

Link to comment
Share on other sites

If you insist on that approach then find AutoItObject.au3 and use _AutoItObject_WrapperCreate() function to wrap IAccessible interface.

In the package you'll find several examples of how's that done with some other interfaces.

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

read this topic carefully and you have the working examples

http://www.autoitscript.com/forum/index.php?showtopic=95176&st=0&p=773353&hl=msaa&fromsearch=1&#entry773353

I looked this topic, but they used "AccessibleObjectFromPoint" to get the object, not the "AccessibleObjectFromWindow".

I want to test the Caculator, get the number button and click them, if use "AccessibleObjectFromPoint", it need the operation of users.

I think I don't know the button position, just know the ClassName, InstanceName.

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...