BigDaddyO Posted December 17, 2019 Share Posted December 17, 2019 (edited) 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 expandcollapse popup#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 : expandcollapse popup#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 December 19, 2019 by BigDaddyO Added Opt 4 robertocm and Gianni 2 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now