Jump to content

Recommended Posts

Posted

Hello there

below you can see a script that works really well:

#include <CUIAutomation2.au3>
Opt("MustDeclareVars", 1)

; CAD-Fenster: erstes Fenster, dessen Titel mit "Gruppe: " beginnt
Global Const $g_sCADWin = "[REGEXPTITLE:^Gruppe:\s]"

; COM-Error-Handler (für sicheres Array-Iterieren)
Global $g_bComError = False
Global $g_oComErr = ObjEvent("AutoIt.Error", "_ComErrHandler")

Func _ComErrHandler($oError)
    $g_bComError = True
EndFunc

; ================== Beispielaufruf =====================
ClickGeschossButton("EG")
; =======================================================


; Klickt "Toolbar Options" und danach den Geschoss-Button $sName
Func ClickGeschossButton($sName)

    ; 1) CAD-Fenster holen
    Local $hCAD = WinGetHandle($g_sCADWin)
    If @error Or $hCAD = 0 Then
        MsgBox(16, "Fehler", "CAD-Fenster nicht gefunden: " & $g_sCADWin)
        Return
    EndIf
    WinActivate($hCAD)

    ; 2) UIAutomation initialisieren
    Local $oUIA = ObjCreateInterface($sCLSID_CUIAutomation, _
                                     $sIID_IUIAutomation, _
                                     $dtagIUIAutomation)
    If Not IsObj($oUIA) Then
        MsgBox(16, "Fehler", "UIAutomation konnte nicht initialisiert werden.")
        Return
    EndIf

    ; 3) UIA-Element für CAD-Fenster
    Local $pWindow, $oWindow
    $oUIA.ElementFromHandle($hCAD, $pWindow)
    If Not $pWindow Then
        MsgBox(16, "Fehler", "UIA-Element für CAD-Fenster nicht gefunden.")
        Return
    EndIf
    $oWindow = ObjCreateInterface($pWindow, _
                                  $sIID_IUIAutomationElement, _
                                  $dtagIUIAutomationElement)

    ; 4) Zuerst MenuItem "Toolbar Options" klicken
    If Not _ClickMenuItemByName($oUIA, $oWindow, "Toolbar Options") Then
        MsgBox(16, "Fehler", "'Toolbar Options' wurde nicht gefunden / konnte nicht geklickt werden.")
        Return
    EndIf

    Sleep(150) ; kleines Delay, bis die Toolbar reagiert

    ; 5) Danach den gewünschten Button (z.B. "OG") klicken
    If Not _ClickButtonByNameOnElement($oUIA, $oWindow, $sName) Then
        MsgBox(16, "Fehler", "Button '" & $sName & "' wurde nicht gefunden / konnte nicht geklickt werden.")
        Return
    EndIf
EndFunc


; ======= Hilfsfunktion: MenuItem nach Name suchen & klicken =========
Func _ClickMenuItemByName($oUIA, $oRoot, $sName)
    Local $oElem = _FindElementByNameEnum($oUIA, $oRoot, _
                                          $UIA_MenuItemControlTypeId, _
                                          $sName)
    If Not IsObj($oElem) Then Return False

    Local $pInvoke, $oInvoke
    $oElem.GetCurrentPattern($UIA_InvokePatternId, $pInvoke)
    If Not $pInvoke Then Return False

    $oInvoke = ObjCreateInterface($pInvoke, _
                                  $sIID_IUIAutomationInvokePattern, _
                                  $dtagIUIAutomationInvokePattern)
    $oInvoke.Invoke()
    Return True
EndFunc


; ======= Hilfsfunktion: Button nach Name suchen & klicken ===========
Func _ClickButtonByNameOnElement($oUIA, $oRoot, $sButtonName)
    Local $oElem = _FindElementByNameEnum($oUIA, $oRoot, _
                                          $UIA_ButtonControlTypeId, _
                                          $sButtonName)
    If Not IsObj($oElem) Then Return False

    Local $pInvoke, $oInvoke
    $oElem.GetCurrentPattern($UIA_InvokePatternId, $pInvoke)
    If Not $pInvoke Then Return False

    $oInvoke = ObjCreateInterface($pInvoke, _
                                  $sIID_IUIAutomationInvokePattern, _
                                  $dtagIUIAutomationInvokePattern)
    $oInvoke.Invoke()
    Return True
EndFunc


; ======= Generische Suche: erstes Element eines ControlTypes, dessen Name passt =======
Func _FindElementByNameEnum($oUIA, $oRoot, $iControlType, $sNeedleName)

    ; Alle Elemente vom gewünschten ControlType holen
    Local $pCond, $pArray
    $oUIA.CreatePropertyCondition($UIA_ControlTypePropertyId, _
                                  $iControlType, _
                                  $pCond)

    $oRoot.FindAll($TreeScope_Descendants, $pCond, $pArray)
    If Not $pArray Then Return SetError(1, 0, 0)

    Local $oArr = ObjCreateInterface($pArray, _
                                     $sIID_IUIAutomationElementArray, _
                                     $dtagIUIAutomationElementArray)
    If Not IsObj($oArr) Then Return SetError(2, 0, 0)

    Local $sTarget = StringUpper(StringStripWS($sNeedleName, 3))

    Local $i = 0
    While True
        $g_bComError = False
        Local $pElem = 0
        $oArr.GetElement($i, $pElem)

        If $g_bComError Or Not $pElem Then ExitLoop ; Ende des Arrays

        Local $oElem = ObjCreateInterface($pElem, _
                                          $sIID_IUIAutomationElement, _
                                          $dtagIUIAutomationElement)
        If Not IsObj($oElem) Then
            $i += 1
            ContinueLoop
        EndIf

        Local $vName, $sName
        $oElem.GetCurrentPropertyValue($UIA_NamePropertyId, $vName)
        $sName = StringUpper(StringStripWS(String($vName), 3))

        ; exakter Vergleich, case-insensitive
        If $sName = $sTarget Then
            Return $oElem
        EndIf

        $i += 1
    WEnd

    Return SetError(3, 0, 0)
EndFunc

This code is used to click a button within our CAD application that is nested in a XTPToolBar. 

The script above is a part of a bigger software that is used to run tasks in the CAD app without any user interaction.

As long as I run the script and watch what is happening it works.

The intention of the script is that the main application should run on a virtual desktop where there is no display output - but in this case it doesn't work. When I connect to the virtual desktop (Citrix Receiver environment) and watch then it works fine again.

I have plenty of AutoIT scripts without UIA that work since years in such an environment - this tool uses UIA and it does not. Is there any requirement for graphical output to a screen or something else when using UIA?

"Normal" AutoIT commands like "ControlClick" don't work for that button, the UIA method is the only one I found that is working.

Does anyone have an idea for me how to solve that issue?

 

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
  • Recently Browsing   0 members

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