Jump to content

_ControlFind_VisualRelation


BigDaddyO
 Share

Recommended Posts

This function is used to find a control that is at a specified position from a known control (Anchor).  This is loosely based on the UFT Object Repository feature called Visual Relation Identifier

edit:  12/19 added option 4 to search for a control that is contained within the area of the Anchor control itself.  I needed this to find a fake scrollbar inside a fake edit box for an ancient app I'm automating.

 

Example:  I want to find the first Button to the Right of the Label that says "To Continue, Click Here >"

;Get the handle to that label which will be our Anchor point.
    $hAnchor = ControlGetHandle("My Application", "", "[TEXT:To Continue, Click Here >]")

;Find the first button to the right of our Anchor point
    $hwnd = _ControlFind_VisualRelation(1, "Button", 3, $hAnchor)

;Now click on that control
    ControlClick("My Application", "", $hwnd)


Below is a much larger example that I used when building the function to assist with the more advanced features such as Padding, Visibility, and Debugging along with the function

#include <GUIConstantsEx.au3>
#include <GuiEdit.au3>
#include <StaticConstants.au3>
#include "_VisualRelationIdentifier.au3"


$hGUI = GUICreate("Visual Relation TestApp", 600, 400)
$hInfo = GUICtrlCreateLabel("F1 = find Left, F2 = Find Top, F3 = Find Right, F4 = find Bottom", 5, 3, 590, 17, $SS_CENTER)
$Edit = GUICtrlCreateEdit("This is the Anchor Control", 200, 150, 200, 100)
$hContained = GUICtrlCreateInput("Contained", 220, 210, 100, 20)



GUICtrlCreateLabel("Search Padding:  ", 350, 23, 200, 17, $SS_RIGHT)
$hPadding = GUICtrlCreateInput("0", 550, 20, 40, 20)
GUICtrlCreateUpdown(-1)
GUICtrlCreateLabel("Instance:  ", 350, 48, 200, 17, $SS_RIGHT)
$hInstance = GUICtrlCreateInput("1", 550, 45, 40, 20)
GUICtrlCreateUpdown(-1)
GUICtrlSetLimit(-1, 999, 1)


;Controls on the left of the Anchor, not created in the order they are displayed
GUICtrlCreateLabel("Label", 10, 133, 80, 17)
GUICtrlCreateButton("btn1", 10, 155, 80, 20)
GUICtrlCreateButton("btn2", 95, 130, 100, 20)   ;Technically Above, but adding padding should catch this on left
GUICtrlCreateButton("btn3", 95, 155, 100, 20)
GUICtrlCreateButton("btn4", 95, 230, 100, 20)
GUICtrlCreateButton("btn5", 95, 180, 100, 20)
GUICtrlCreateButton("btn6", 10, 255, 80, 20)    ;Technically below, but adding padding should catch this on left
GUICtrlCreateButton("btn7", 95, 255, 100, 20)   ;Technically below, but adding padding should catch this on left
GUICtrlCreateButton("btn8", 95, 205, 100, 20)


;Controls on the Top of the Anchor
GUICtrlCreateLabel("Label", 10, 30, 100, 17)
GUICtrlCreateButton("btn9", 10, 50, 100, 20)    ;Could be Above, or Left with enough padding
GUICtrlCreateButton("btn10", 120, 50, 100, 20)  ;Could be Above, or Left with enough padding
GUICtrlCreateButton("btn11", 450, 75, 100, 20)  ;Could be Above, or Right with enough padding
GUICtrlCreateButton("btn12", 120, 75, 100, 20)  ;Could be Above, or Left with enough padding
GUICtrlCreateButton("btn13", 230, 50, 100, 20)
GUICtrlCreateButton("btn14", 230, 75, 100, 20)
GUICtrlCreateButton("btn15", 10, 75, 100, 20)   ;Could be Above, or Left with enough padding
GUICtrlCreateButton("btn16", 230, 125, 100, 20)
GUICtrlCreateButton("btn17", 340, 100, 100, 20) ;Could be Above, or Right with enough padding
GUICtrlCreateButton("btn18", 340, 125, 100, 20) ;Could be Above, or Right with enough padding
GUICtrlCreateButton("btn19", 230, 100, 100, 20)
GUICtrlCreateButton("btn20", 450, 100, 100, 20) ;Could be Above, or Right with enough padding

;Controls on the Right of the Anchor
GUICtrlCreateLabel("Label", 410, 153, 80, 17)
GUICtrlCreateButton("btn21", 410, 175, 80, 20)
GUICtrlCreateButton("btn22", 500, 225, 80, 20)
GUICtrlCreateButton("btn23", 500, 175, 80, 20)
GUICtrlCreateButton("btn24", 500, 200, 80, 20)
GUICtrlCreateButton("btn25", 500, 150, 80, 20)
GUICtrlCreateButton("btn26", 410, 200, 80, 20)
GUICtrlCreateButton("btn27", 410, 225, 80, 20)

;Controls on the Bottom of the Anchor
GUICtrlCreateLabel("Label", 205, 253, 80, 17)
GUICtrlCreateButton("btn28", 500, 251, 80, 20)
GUICtrlCreateButton("btn29", 440, 280, 100, 20)
GUICtrlCreateButton("btn30", 10, 280, 100, 20)
GUICtrlCreateButton("btn31", 220, 280, 100, 20)
GUICtrlCreateButton("btn32", 110, 280, 100, 20)
GUICtrlCreateButton("btn33", 330, 280, 100, 20)
GUICtrlCreateButton("btn34", 10, 310, 100, 20)
GUICtrlCreateButton("btn35", 410, 251, 80, 20)
GUICtrlCreateButton("btn36", 110, 305, 100, 20)
GUICtrlCreateButton("btn37", 440, 350, 100, 20)

GUISetState(@SW_SHOW, $hGUI)

$hEdit = ControlGetHandle($hGUI, "", $Edit)
HotKeySet("{F1}", "_GetLeft")   ;Adjust Padding and Instance within the GUI
HotKeySet("{F2}", "_GetAbove")  ;Adjust Padding and Instance within the GUI
HotKeySet("{F3}", "_GetRight")  ;Adjust Padding and Instance within the GUI
HotKeySet("{F4}", "_GetBelow")  ;Adjust Padding and Instance within the GUI
HotKeySet("{F5}", "_GetContained")

; Loop until the user exits.
While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
    EndSwitch
WEnd

;Get the control that is contained within the area of the Anchor control
Func _GetContained()
    _GUICtrlEdit_AppendText($hEdit, @CRLF & "F5 (Get Contained Within)")    ;Update the Edit to show what was selected

    $Foundhwnd = _ControlFind_VisualRelation(GUICtrlRead($hInstance), "Edit", 4, $hEdit, 0, True, True) ;Find the first button to the left of Anchor where Vertical padding is +- Specified
    If @error Then
        MsgBox(0, "Error " & @error, "Failed to find the specified control Button" & GUICtrlRead($hInstance))
        Return
    EndIf

    ControlSetText($hGUI, "", $Foundhwnd, "FOUND!")                     ;Update the text for the control it identified
    ConsoleWrite("Handle returned = (" & $Foundhwnd & ")" & @CRLF)
    GUICtrlSetData($hInfo, "Buttons renamed to order they were found.  The requested control changed to FOUND!")

EndFunc


Func _GetLeft()
    _GUICtrlEdit_AppendText($hEdit, @CRLF & "F1 [Get Button" & GUICtrlRead($hInstance) & " to Left, " & GUICtrlRead($hPadding) & " padding]")   ;Update the Edit to show what was selected

    $Foundhwnd = _ControlFind_VisualRelation(GUICtrlRead($hInstance), "Button", 2, $hEdit, GUICtrlRead($hPadding), True, True)  ;Find the first button to the left of Anchor where Vertical padding is +- Specified
    If @error Then
        MsgBox(0, "Error " & @error, "Failed to find the specified control Button" & GUICtrlRead($hInstance))
        Return
    EndIf

    ControlSetText($hGUI, "", $Foundhwnd, "FOUND!")                     ;Update the text for the control it identified
    ConsoleWrite("Handle returned = (" & $Foundhwnd & ")" & @CRLF)
    GUICtrlSetData($hInfo, "Buttons renamed to order they were found.  The requested control changed to FOUND!")
EndFunc



Func _GetAbove()
    _GUICtrlEdit_AppendText($hEdit, @CRLF & "F2 (Get Above selected)")  ;Update the Edit to show what was selected

    $Foundhwnd = _ControlFind_VisualRelation(GUICtrlRead($hInstance), "Button", 0, $hEdit,  GUICtrlRead($hPadding), True, True)     ;Find the first button above the anchor where Horizontal padding is +- specified
    If @error Then
        MsgBox(0, "Error " & @error, "Failed to find the specified control Button" & GUICtrlRead($hInstance))
        Return
    EndIf

    ControlSetText($hGUI, "", $Foundhwnd, "FOUND!")                     ;Update the text for the control it identified
    ConsoleWrite("Handle returned = (" & $Foundhwnd & ")" & @CRLF)
    GUICtrlSetData($hInfo, "Buttons renamed to order they were found.  The requested control changed to FOUND!")
EndFunc



Func _GetRight()
    _GUICtrlEdit_AppendText($hEdit, @CRLF & "F3 (Get Right selected)")  ;Update the Edit to show what was selected

    $Foundhwnd = _ControlFind_VisualRelation(GUICtrlRead($hInstance), "Button", 3, $hEdit, GUICtrlRead($hPadding), True, True)  ;Find the first button to the left of Anchor where Vertical padding is +- Specified
    If @error Then
        MsgBox(0, "Error " & @error, "Failed to find the specified control Button" & GUICtrlRead($hInstance))
        Return
    EndIf

    ControlSetText($hGUI, "", $Foundhwnd, "FOUND!")                     ;Update the text for the control it identified
    ConsoleWrite("Handle returned = (" & $Foundhwnd & ")" & @CRLF)
    GUICtrlSetData($hInfo, "Buttons renamed to order they were found.  The requested control changed to FOUND!")
EndFunc



Func _GetBelow()
    _GUICtrlEdit_AppendText($hEdit, @CRLF & "F4 (Get Below selected)")  ;Update the Edit to show what was selected

    $Foundhwnd = _ControlFind_VisualRelation(GUICtrlRead($hInstance), "Button", 1, $hEdit,  GUICtrlRead($hPadding), True, True)
    If @error Then
        MsgBox(0, "Error " & @error, "Failed to find the specified control Button" & GUICtrlRead($hInstance))
        Return
    EndIf

    ControlSetText($hGUI, "", $Foundhwnd, "FOUND!")                     ;Update the text for the control it identified
    ConsoleWrite("Handle returned = (" & $Foundhwnd & ")" & @CRLF)
    GUICtrlSetData($hInfo, "Buttons renamed to order they were found.  The requested control changed to FOUND!")
EndFunc

 

The Function which needs Melba23's _ArrayMultiColSort :

#include-once

#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
#include "ArrayMultiColSort.au3"


;-----------------------------------------------------------------------------------------------------
; Name...........   _ControlFind_VisualRelation
; Description....   Find a specific control depending on its location to a known control (Anchor point)
;                       Control search order is closest to the control and cascade out in direction specified
; Syntax.........   _ControlFind_VisualRelation($iInstance, $sClass, $sDirection, $hAnchor)
; Parameters ....   $iInstance  = which instance found from the Anchor
;                                   1 = First control found in direction specified from Anchor
;                                   2 = Second control found in the direction specified from Anchor
;                                   etc...
;                   $sClass     = Class name of the control, do not use ClassnameNN or any other type
;                   $sDirection = 0 = Above Anchor, 1 = Below Anchor, 2 = Left of Anchor, 3 = Right of Anchor, 4 = Fully contained within Anchor (Padding is ignored)
;                   $hAnchor    = hwnd of the known control we are identifying from
;                   $iPadding   = amount to + or - from each side of Anchor size to match control within, Default = 0
;                                   ex:  10, Above: find the control above the Anchor where x between (Anchor X - 10  and  Anchor X + Anchor W + 10)
;                                   ex:  5, Right:  find the control to the right of the Anchor where Y between (Anchor Y - 5  and Anchor Y + Anchor H + 5)
;                   $bIsVisible = True = Only identify those controls that are visible (Default).  False will return any control visible or not.
;                   $bDebug     = True will draw lines on the screen where its searching, Default = False
; Return values..   Success = Returns the hwnd
;                   Failure = Sets @error
;                               1 = The Anchor was not passed as a hwnd
;                               2 = Failed to find the parent window of the Anchor
;                               3 = Unable to identify the position of the Anchor control
;                               4 = Could not find any of the specified Classes within the Anchor window
;                               5 = Could not find the Instance specified in the position specified
; Author ........   BigDaddyO
; Modified by....
; Remarks .......   requires Include:  WinAPI.au3, WindowsConstants.au3, Melba23's _ArrayMultiColSort (https://www.autoitscript.com/forum/topic/155442-arraymulticolsort-new-release-06-april-2019/)
; Example........   $sClassnameNN = _ControlFind_VisualRelation(1, "Button", 2, $hEdit, 0)
;-----------------------------------------------------------------------------------------------------
Func _ControlFind_VisualRelation($iInstance, $sClass, $sDirection, $hAnchor, $iPadding = 0, $bIsVisible = True, $bDebug = False)

;Ensure the $hAnchor is a handle
    If IsHWnd($hAnchor) = 0 Then Return SetError(1)

;Get the handle for the window the $hAnchor control is in
    $hAnchorWin = _WinAPI_GetAncestor($hAnchor, $GA_ROOT)
    If IsHWnd($hAnchorWin) = 0 Then Return SetError(2)

    If $bDebug Then ConsoleWrite("Anchor Window Handle = (" & $hAnchorWin & ")" & @CRLF)

;Get the current position of the Anchor control
    $aAnchorPos = ControlGetPos($hAnchorWin, "", $hAnchor)
    If @error Then Return SetError(3)

    If $bDebug Then ConsoleWrite("Anchor Window position:  x=" & $aAnchorPos[0] & ", y=" & $aAnchorPos[1] & @CRLF)

    Local $iInstanceFound = 0
    Local $inst = 0                 ;The control instance that we are looking at
    Local $v = 0                    ;The control count we are adding to the search array
    Local $aFound[9999][5]          ;[][0] = hwnd, [][1] = X coord, [][2] = Y coord, [][3] = x + w, [][4] = y + h

;Find every Control with the specified $sClass THAT IS CURRENTLY VISIBLE
;Need to keep the Control Find loop # seperate from the Array Storage to ignore the hidden controls!
    While 1
        $inst += 1
        $hCtrl = ControlGetHandle($hAnchorWin, "", "[CLASS:" & $sClass & "; INSTANCE:" & $inst & "]")
        If @error Then
            If $inst = 1 Then
                Return SetError(4)  ;Did not find any of the Class type in the window
            Else
                ExitLoop            ;No more of this Class were found stop looking and start trying to match the requested area
            EndIf
        EndIf

        If $bIsVisible Then         ;Do we only want the visible controls?
            If ControlCommand($hAnchorWin, "", $hCtrl, "IsVisible", "") = 0 Then ContinueLoop
        EndIf

        $v += 1                     ;If we got this far, we need to add this control to our array

        $aCtrlPos = ControlGetPos($hAnchorWin, "", $hCtrl)
        If $bDebug = True Then
            ConsoleWrite($sClass & $v & " - hwnd(" & $hCtrl & ") found at " & $aCtrlPos[0] & ", " & $aCtrlPos[1] & @CRLF)
            ControlSetText($hAnchorWin, "", $hCtrl, $sClass & $v)
        EndIf

        ;Save this control:  Handle, X1, Y1, X2, Y2
        $aFound[$v - 1][0] = $hCtrl                         ;Save the Instance # so we can find again
        $aFound[$v - 1][1] = $aCtrlPos[0]                   ;X coord of left side
        $aFound[$v - 1][2] = $aCtrlPos[1]                   ;Y coord of top
        $aFound[$v - 1][3] = $aCtrlPos[0] + $aCtrlPos[2]    ;X coord of right side
        $aFound[$v - 1][4] = $aCtrlPos[1] + $aCtrlPos[3]    ;Y coord of bottom

    WEnd


;~ ;Resize and rearrange the found controls so they cascase out from the Anchor control
    ReDim $aFound[$v][5]

;Now to get the control at the location we were looking for
    Local $iFoundInstance = 0

    Switch $sDirection

        Case 0  ;Above Anchor control and within the X padding

            ;0 = TOP: SORT BY Y DESCENDING, THEN BY X ASCENDING
            Local $aSortData[][] = [[2, 1],[1,0]]
            _ArrayMultiColSort($aFound, $aSortData)

            If $bDebug = True Then ;Draw lines to show where it was looking
                $hVRIgdi = _GDIPlus_Startup(Default, True)
                $hVRIgraphic = _GDIPlus_GraphicsCreateFromHWND($hAnchorWin)
                $hVRIpen = _GDIPlus_PenCreate(0xFFFF0000)
                _GDIPlus_GraphicsDrawLine($hVRIgraphic, $aAnchorPos[0] - $iPadding, $aAnchorPos[1], $aAnchorPos[0] - $iPadding, 0, $hVRIpen)
                _GDIPlus_GraphicsDrawLine($hVRIgraphic, $aAnchorPos[0] + $aAnchorPos[2] + $iPadding, $aAnchorPos[1], $aAnchorPos[0] + $aAnchorPos[2] + $iPadding, 0, $hVRIpen)
            EndIf

            ;Loop through the control found array
            For $d = 0 to UBound($aFound) - 1
                If $aFound[$d][0] = $hAnchor Then ContinueLoop  ;Possible that we will see the anchor if looking for the same class type

                ;If the right of the control is  greater than the left of the Anchor minus the padding, AND the left of the control is less than the Anchor plus the padding
                If ( $aFound[$d][3] >= ($aAnchorPos[0] - $iPadding) ) and ( $aFound[$d][1] <= ($aAnchorPos[0] + $aAnchorPos[2] + $iPadding) ) Then

                    ;if the top of the control is less than the top of the Anchor
                    If $aFound[$d][2] <= $aAnchorPos[1] Then

                        $iFoundInstance += 1
                        If $iFoundInstance = $iInstance Then
                            If $bDebug = True Then
                                ;Move the mouse to the center of the control we will be returning
                                $aWinPos = WinGetPos($hAnchorWin, "")
                                $aClient = WinGetClientSize($hAnchorWin, "")
                                $iAddX = ($aWinPos[2] - $aClient[0] - 2)                    ;Generate the X Coord that the ControlGetPos will reference from
                                $iAddY = ($aWinPos[3] - $aClient[1] - 2)                    ;Generate the Y Coord that the ControlGetPos will reference from
                                $x = $aWinPos[0] + $aFound[$d][1] + (($aFound[$d][3] - $aFound[$d][1]) / 2) + $iAddX
                                $y = $aWinPos[1] + $aFound[$d][2] + (($aFound[$d][4] - $aFound[$d][2]) / 2) + $iAddY
                                MouseMove($x, $y, 0)
                            EndIf
                            Return $aFound[$d][0]
                        Else
                            ContinueLoop
                        EndIf

                    Else

                        ContinueLoop        ;This control is not within the Vertical limits of the Anchor and Padding

                    EndIf


                Else

                    ContinueLoop            ;This control is not within the Horizontal limits of the Anchor and Padding

                EndIf

            Next


        Case 1  ;Below Anchor control and within the X padding

            ;1 = BOTTOM:  SORT BY Y ASCENDING, THEN BY X ASCENDING
            Local $aSortData[][] = [[2, 0],[1,0]]
            _ArrayMultiColSort($aFound, $aSortData)

            If $bDebug = True Then ;Draw lines to show where it was looking
                $hVRIgdi = _GDIPlus_Startup(Default, True)
                $hVRIgraphic = _GDIPlus_GraphicsCreateFromHWND($hAnchorWin)
                $hVRIpen = _GDIPlus_PenCreate(0xFFFF0000)
                _GDIPlus_GraphicsDrawLine($hVRIgraphic, $aAnchorPos[0] - $iPadding, $aAnchorPos[1] + $aAnchorPos[3], $aAnchorPos[0] - $iPadding, $aAnchorPos[1] + 1000, $hVRIpen)
                _GDIPlus_GraphicsDrawLine($hVRIgraphic, $aAnchorPos[0] + $aAnchorPos[2] + $iPadding, $aAnchorPos[1] + $aAnchorPos[3], $aAnchorPos[0] + $aAnchorPos[2] + $iPadding, $aAnchorPos[1] + 1000, $hVRIpen)
            EndIf

            ;Loop through the control found array
            For $d = 0 to UBound($aFound) - 1
                If $aFound[$d][0] = $hAnchor Then ContinueLoop  ;Possible that we will see the anchor if looking for the same class type

                ;If the right of the control is  greater than the left of the Anchor minus the padding, AND the left of the control is less than the Anchor plus the padding
                If ( $aFound[$d][3] >= ($aAnchorPos[0] - $iPadding) ) and ( $aFound[$d][1] <= ($aAnchorPos[0] + $aAnchorPos[2] + $iPadding) ) Then

                    ;if the top of the control is greater than the bottom of the Anchor
                    If $aFound[$d][2] >= ($aAnchorPos[1] + $aAnchorPos[3]) Then

                        $iFoundInstance += 1
                        If $iFoundInstance = $iInstance Then
                            If $bDebug = True Then
                                ;Move the mouse to the center of the control we will be returning
                                $aWinPos = WinGetPos($hAnchorWin, "")
                                $aClient = WinGetClientSize($hAnchorWin, "")
                                $iAddX = ($aWinPos[2] - $aClient[0] - 2)                    ;Generate the X Coord that the ControlGetPos will reference from
                                $iAddY = ($aWinPos[3] - $aClient[1] - 2)                    ;Generate the Y Coord that the ControlGetPos will reference from
                                $x = $aWinPos[0] + $aFound[$d][1] + (($aFound[$d][3] - $aFound[$d][1]) / 2) + $iAddX
                                $y = $aWinPos[1] + $aFound[$d][2] + (($aFound[$d][4] - $aFound[$d][2]) / 2) + $iAddY
                                MouseMove($x, $y, 0)
                            EndIf
                            Return $aFound[$d][0]
                        Else
                            ContinueLoop
                        EndIf

                    Else

                        ContinueLoop        ;This control is not within the Vertical limits of the Anchor and Padding

                    EndIf


                Else

                    ContinueLoop            ;This control is not within the Horizontal limits of the Anchor and Padding

                EndIf

            Next


        Case 2  ;Left of Anchor control and within the Y padding
            ;2 = LEFT:  SORT BY Y ASCENDING, THEN BY X DESCENDING SO CLOSEST CONTROL WOULD BE 1
            Local $aSortData[][] = [[1, 1],[2,0]]
            _ArrayMultiColSort($aFound, $aSortData)

            If $bDebug = True Then ;Draw lines to show where it was looking
                $hVRIgdi = _GDIPlus_Startup(Default, True)
                $hVRIgraphic = _GDIPlus_GraphicsCreateFromHWND($hAnchorWin)
                $hVRIpen = _GDIPlus_PenCreate(0xFFFF0000)
                _GDIPlus_GraphicsDrawLine($hVRIgraphic, $aAnchorPos[0], $aAnchorPos[1] - $iPadding, 0, $aAnchorPos[1] - $iPadding, $hVRIpen)
                _GDIPlus_GraphicsDrawLine($hVRIgraphic, $aAnchorPos[0], $aAnchorPos[1] + $aAnchorPos[3] + $iPadding, 0, $aAnchorPos[1] + $aAnchorPos[3] + $iPadding, $hVRIpen)
            EndIf

            ;Loop through the control found array
            For $d = 0 to UBound($aFound) - 1
                If $aFound[$d][0] = $hAnchor Then ContinueLoop  ;Possible that we will see the anchor if looking for the same class type

                If $bDebug Then ConsoleWrite("Is " & ControlGetText($hAnchorWin, "", $aFound[$d][0]) & " bottom (" & $aFound[$d][4] & ") located vertically below " & ($aAnchorPos[1] - $iPadding) & " and top (" & $aFound[$d][2] & ") is above " & ($aAnchorPos[1] + $aAnchorPos[3] + $iPadding) )
                ;If the top of the control is above the bottom of the anchor plus the padding AND the bottom of the control is below the top of the Anchor minus the padding
                If ( $aFound[$d][2] <= ($aAnchorPos[1] + $aAnchorPos[3] + $iPadding) ) and ( $aFound[$d][4] > ($aAnchorPos[1] - $iPadding) ) Then
                    If $bDebug Then ConsoleWrite(@TAB & "YES" & @CRLF)

                    If $bDebug Then ConsoleWrite(@TAB & "Is the controls Left (" & $aFound[$d][1] & ") located horizontally left of " & $aAnchorPos[0] )
                    ;If the left of the control is < the left of the Anchor
                    If $aFound[$d][1] < $aAnchorPos[0] Then

                        If $bDebug Then ConsoleWrite(@TAB & "YES" & @CRLF)

                        $iFoundInstance += 1
                        If $iFoundInstance = $iInstance Then

                            If $bDebug = True Then
                                ;Move the mouse to the center of the control we will be returning
                                $aWinPos = WinGetPos($hAnchorWin, "")
                                $aClient = WinGetClientSize($hAnchorWin, "")
                                $iAddX = ($aWinPos[2] - $aClient[0] - 2)                    ;Generate the X Coord that the ControlGetPos will reference from
                                $iAddY = ($aWinPos[3] - $aClient[1] - 2)                    ;Generate the Y Coord that the ControlGetPos will reference from
                                $x = $aWinPos[0] + $aFound[$d][1] + (($aFound[$d][3] - $aFound[$d][1]) / 2) + $iAddX
                                $y = $aWinPos[1] + $aFound[$d][2] + (($aFound[$d][4] - $aFound[$d][2]) / 2) + $iAddY
                                MouseMove($x, $y, 0)
                            EndIf

                            Return $aFound[$d][0]
                        Else
                            ContinueLoop
                        EndIf

                    Else

                        If $bDebug Then ConsoleWrite(@TAB & "NO" & @CRLF)
                        ContinueLoop    ;This control is not within the Horizontal limits Left of the Anchor

                    EndIf

                Else

                    If $bDebug Then ConsoleWrite(@TAB & "NO" & @CRLF)
                    ContinueLoop        ;This control is not within the Vertical limits of the Anchor and Padding

                EndIf

            Next

        Case 3  ;Right of Anchor control
            ;3 = RIGHT:  SORT BY Y ASCENDING, THEN BY X ASCENDING
            Local $aSortData[][] = [[1, 0],[2,0]]
            _ArrayMultiColSort($aFound, $aSortData)

            If $bDebug = True Then ;Draw lines to show where it was looking
                $hVRIgdi = _GDIPlus_Startup(Default, True)
                $hVRIgraphic = _GDIPlus_GraphicsCreateFromHWND($hAnchorWin)
                $hVRIpen = _GDIPlus_PenCreate(0xFFFF0000)
                _GDIPlus_GraphicsDrawLine($hVRIgraphic, $aAnchorPos[0] + $aAnchorPos[2], $aAnchorPos[1] - $iPadding, $aAnchorPos[0] + 1000, $aAnchorPos[1] - $iPadding, $hVRIpen)
                _GDIPlus_GraphicsDrawLine($hVRIgraphic, $aAnchorPos[0] + $aAnchorPos[2], $aAnchorPos[1] + $aAnchorPos[3] + $iPadding, $aAnchorPos[0] + 1000, $aAnchorPos[1] + $aAnchorPos[3] + $iPadding, $hVRIpen)
            EndIf

            ;Loop through the control found array
            For $d = 0 to UBound($aFound) - 1
                If $aFound[$d][0] = $hAnchor Then ContinueLoop  ;Possible that we will see the anchor if looking for the same class type

                ;If the top of the control is above the bottom of the anchor plus the padding AND the bottom of the control is below the top of the Anchor minus the padding
                If ( $aFound[$d][2] <= ($aAnchorPos[1] + $aAnchorPos[3] + $iPadding) ) and ( $aFound[$d][4] > ($aAnchorPos[1] - $iPadding) ) Then

                    ;If the Right of the control is > the Right of the Anchor
                    If $aFound[$d][3] > ($aAnchorPos[0] + $aAnchorPos[2]) Then

                        $iFoundInstance += 1
                        If $iFoundInstance = $iInstance Then
                            If $bDebug = True Then
                                ;Move the mouse to the center of the control we will be returning
                                $aWinPos = WinGetPos($hAnchorWin, "")
                                $aClient = WinGetClientSize($hAnchorWin, "")
                                $iAddX = ($aWinPos[2] - $aClient[0] - 2)                    ;Generate the X Coord that the ControlGetPos will reference from
                                $iAddY = ($aWinPos[3] - $aClient[1] - 2)                    ;Generate the Y Coord that the ControlGetPos will reference from
                                $x = $aWinPos[0] + $aFound[$d][1] + (($aFound[$d][3] - $aFound[$d][1]) / 2) + $iAddX
                                $y = $aWinPos[1] + $aFound[$d][2] + (($aFound[$d][4] - $aFound[$d][2]) / 2) + $iAddY
                                MouseMove($x, $y, 0)
                            EndIf
                            Return $aFound[$d][0]
                        Else
                            ContinueLoop
                        EndIf

                    Else

                        ContinueLoop    ;This control is not within the Horizontal limits Right of the Anchor

                    EndIf

                Else

                    ContinueLoop        ;This control is not within the Vertical limits of the Anchor and Padding

                EndIf

            Next

        Case 4  ;Contained within the Anchor controls area
            ;4 = Contained Within:  SORT BY Y ASCENDING, THEN BY X ASCENDING
            Local $aSortData[][] = [[1, 0],[2,0]]
            _ArrayMultiColSort($aFound, $aSortData)

            If $bDebug = True Then ;Draw lines to show where it was looking
                $hVRIgdi = _GDIPlus_Startup(Default, True)
                $hVRIgraphic = _GDIPlus_GraphicsCreateFromHWND($hAnchorWin)
                $hVRIpen = _GDIPlus_PenCreate(0xFFFF0000)
                _GDIPlus_GraphicsDrawLine($hVRIgraphic, $aAnchorPos[0] - 1, $aAnchorPos[1] - 1, $aAnchorPos[0] + $aAnchorPos[2] + 1, $aAnchorPos[1] - 1, $hVRIpen)  ;Draw across the tope
                _GDIPlus_GraphicsDrawLine($hVRIgraphic, $aAnchorPos[0] + $aAnchorPos[2] + 1, $aAnchorPos[1] - 1, $aAnchorPos[0] + $aAnchorPos[2] + 1, $aAnchorPos[1] + $aAnchorPos[3] + 1, $hVRIpen)    ;Draw down right side
                _GDIPlus_GraphicsDrawLine($hVRIgraphic, $aAnchorPos[0] + $aAnchorPos[2] + 1, $aAnchorPos[1] + $aAnchorPos[3] + 1, $aAnchorPos[0] - 1, $aAnchorPos[1] + $aAnchorPos[3] + 1, $hVRIpen)    ;Draw across bottom
                _GDIPlus_GraphicsDrawLine($hVRIgraphic, $aAnchorPos[0] - 1, $aAnchorPos[1] + $aAnchorPos[3] + 1, $aAnchorPos[0] - 1, $aAnchorPos[1] - 1, $hVRIpen)  ;Draw up left side
            EndIf

            ;Loop through the control found array
            For $d = 0 to UBound($aFound) - 1
                If $aFound[$d][0] = $hAnchor Then ContinueLoop  ;Possible that we will see the anchor if looking for the same class type

                ;Move through them to ensure they are completely contained within the area of the Known Control
                If $aFound[$d][1] >= $aAnchorPos[0] and $aFound[$d][3] <= $aAnchorPos[0] + $aAnchorPos[2] and $aFound[$d][2] >= $aAnchorPos[1] and $aFound[$d][4] <= $aAnchorPos[1] + $aAnchorPos[3] Then

                    $iFoundInstance += 1
                    If $iFoundInstance = $iInstance Then

                        If $bDebug = True Then
                            ;Move the mouse to the center of the control we will be returning
                            $aWinPos = WinGetPos($hAnchorWin, "")
                            $aClient = WinGetClientSize($hAnchorWin, "")
                            $iAddX = ($aWinPos[2] - $aClient[0] - 2)                    ;Generate the X Coord that the ControlGetPos will reference from
                            $iAddY = ($aWinPos[3] - $aClient[1] - 2)                    ;Generate the Y Coord that the ControlGetPos will reference from
                            $x = $aWinPos[0] + $aFound[$d][1] + (($aFound[$d][3] - $aFound[$d][1]) / 2) + $iAddX
                            $y = $aWinPos[1] + $aFound[$d][2] + (($aFound[$d][4] - $aFound[$d][2]) / 2) + $iAddY
                            MouseMove($x, $y, 0)
                        EndIf
                        Return $aFound[$d][0]

                    Else

                        ContinueLoop

                    EndIf

                Else

                    ContinueLoop        ;This control is not within the Vertical limits of the Anchor and Padding

                EndIf
            Next

;~  $aFound[$v - 1][0] = $hCtrl                         ;Save the Instance # so we can find again
;~  $aFound[$v - 1][1] = $aCtrlPos[0]                   ;X coord of left side
;~  $aFound[$v - 1][2] = $aCtrlPos[1]                   ;Y coord of top
;~  $aFound[$v - 1][3] = $aCtrlPos[0] + $aCtrlPos[2]    ;X coord of right side
;~  $aFound[$v - 1][4] = $aCtrlPos[1] + $aCtrlPos[3]    ;Y coord of bottom




    EndSwitch

    Return SetError(5)  ;If we got this far, then we found something but not the instance we wanted.

EndFunc

 

Any feedback you could offer would be appreciated as aside from my test gui and my one app I needed this for I haven't done a lot of testing.

Thanks

Edited by BigDaddyO
Added Opt 4
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...