Jump to content

_ControlGetHandleByPos() UDF (v1.0)


LxP
 Share

Recommended Posts

While working on a particular problem we found that a window was creating its controls in a random order, and hence the only way to address them was by their position in the window.

This UDF will allow you to do just that. Any feedback whatsoever is encouraged!

 

Download: _ControlGetHandleByPos.au3_ControlGetHandleByPos.txt_ControlGetHandleByPos_Example.au3

 

; ==============================================================================
;
; Function Name:    _ControlGetHandleByPos()
; Description:      Retrieves the internal handle of a control that matches a
;                   given position.
; Parameter(s):     $sTitle -- the title of the window containing the control
;                   $sText  -- the text of the window containing the control
;                   $iX     -- the X coordinate of the control
;                   $IY     -- the Y coordinate of the control
; Requirement(s):   None
; Return Value(s):  On success -- returns the control's handle
;                   On failure -- return and sets @error:
;                                   1 -- could not find window
;                                   2 -- could not find control
; Author(s):        Alex Peters
;
; ==============================================================================

v1.0 (5/Aug/2005):

  • Initial release
Edited by LxP
Link to comment
Share on other sites

What about multiple stacked controls? I know that sometimes Au3Info returns the wrong information considering that it looks at the bottommost control in some windows. Does your UDF suffer from the same problem?

Who else would I be?
Link to comment
Share on other sites

At the moment I'm relying on the assumption that a window won't create more than one control with a common (X, Y) position.

In the situation where there's more than one control, the function would return the control that's highest in the WinGetClassList() for that window.

What would be the best way in your opinion to handle that sort of situation? Return an array of handles? Return a space-separated string of handles perhaps?

Link to comment
Share on other sites

Changing the function to output all controls matching a position is easy enough.

Do many UDFs delimit their output using vertical bars? I'm guessing that this would mostly be useful for outputting to a combo box or similar?

Link to comment
Share on other sites

When i tried this I got the following error

C:\Program Files\AutoIt3\Examples\Controlgethandlebypos.au3 (61) : ==> Expected a "=" operator in assignment statement.

I assume that the lines where there are += should infact be =

These are line

$avUniqueControls[$iLoop][1] += 1

and

$iUniqueControls += 1

I am getting zero returned for some controls that exist but they are contained within other controls.

Link to comment
Share on other sites

$avUniqueControls[$iLoop][1] += 1
···
$iUniqueControls += 1

This is shorthand code for:

$avUniqueControls[$iLoop][1] = $avUniqueControls[$iLoop][1] + 1
···
$iUniqueControls = $iUniqueControls + 1

Presumably this functionality is only available in the beta. Sorry about that. I don't think that any other parts of the code require the beta.

I am getting zero returned for some controls that exist but they are contained within other controls.

I am guessing that a control contained in the top-left-hand corner of another control would report a position of (0, 0) regardless of the position of the parent control.

If I'm right then I don't think that I can adapt the code to such a situation. I think that you would need to search for the inner control using the position given by AutoIt Window Info.

Can anyone please disagree with me on this?

Link to comment
Share on other sites

No the reason I was getting the zero return for some controls was that your script did not seem to handle Edit 2 etc they were being renamed as Edit 1

I have modified the script slightly and this seemed to work for me

; ==============================================================================
;
; Function Name:    _ControlGetHandleByPos()
; Description:    Retrieves the internal handle of a control that matches a
;                  given position.
; Parameter(s):  $sTitle -- the title of the window containing the control
;                  $sText  -- the text of the window containing the control
;                  $iX   -- the X coordinate of the control
;                  $IY   -- the Y coordinate of the control
; Requirement(s):   None
; Return Value(s):  On success -- returns the control's handle
;                  On failure -- return and sets @error:
;                                  1 -- could not find window
;                                  2 -- could not find control
; Author(s):        Alex Peters
;
; ==============================================================================

Func _ControlGetHandleByPos($sTitle, $sText, $iX, $iY)

    Local $hWin, $hControl
    Local $iControls, $iLoop, $iUniqueControls
    Local $sClassList, $sClass, $sClassID
    Local $aiControlPos, $avUniqueControls[1][2]

; Determine that the window exists
    $hWin = WinGetHandle($sTitle, $sText)
    If @error Then
        SetError(2)
        Return 0
    EndIf

; Determine the control classes and total number of controls
    $sClassList = WinGetClassList($hWin)
    $iControls = StringLen($sClassList) - StringLen(StringReplace($sClassList, @LF, ""))
    ReDim $avUniqueControls[$iControls][2]

    $iUniqueControls = 0
    While $sClassList
        $sClass = StringLeft($sClassList, StringInStr($sClassList, @LF) - 1)
        $sClassList = StringMid($sClassList, StringLen($sClass) + 2)
        $sClassID = ""
        For $iLoop = 0 To $iUniqueControls - 1
            If $avUniqueControls[$iLoop][0] = $sClass Then;If there is another button then make button 2 loop
                $avUniqueControls[$iLoop][1] = $avUniqueControls[$iLoop][1] + 1;Starts at 0 then increments 1 each time a match is made giving button 2 etc
                $sClassID = $sClass & $avUniqueControls[$iLoop][1];Makes up the correct class ID from above
                ExitLoop
            EndIf
        Next

        If $sClassID = "" Then;This numbers the first controls eg Edit 1
            $avUniqueControls[$iUniqueControls][0] = $sClass
            $avUniqueControls[$iUniqueControls][1] = 1
            $iUniqueControls = $iUniqueControls + 1
            $sClassID = $sClass & "1"
        EndIf
    ; Determine the position of the control in question
        $hControl = ControlGetHandle($hWin, "", $sClassID)
        $aiControlPos = ControlGetPos($hWin, "", $hControl)
        
        If ($aiControlPos[0] = $iX And $aiControlPos[1] = $iY) Then _ 
                Return $hControl
    WEnd

; If we reach this point then no matching control was found
    SetError(1)
    Return 0

EndFunc

The If Not section did not seem to be working for me so I changed it to

If $sClassID = ""
and this seems to work.
Link to comment
Share on other sites

  • 2 years later...

Hello

I stumbled over your function _ControlGetHandleByPos(), this seams to me a very important function. I'm currently using the COM component of the latest AutoIt release. When will this function be implemented into the COM lib?

Thanks for your help

Daniel

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...