LxP

_ControlGetHandleByPos() UDF (v1.0)

11 posts in this topic

#1 ·  Posted (edited)

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

Share this post


Link to post
Share on other sites



Nice job Alex!!


[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
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?

Share this post


Link to post
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?

Share this post


Link to post
Share on other sites

A pipe-separated list appeals to my uses. Is it much of a deal to change it to allow for multiple controls in the same space?


Who else would I be?

Share this post


Link to post
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?

Share this post


Link to post
Share on other sites

Most of the ones I remember either use pipes or @CRLF to separate, but usually not spaces. @CRLF is also acceptable in my case.


Who else would I be?

Share this post


Link to post
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.

Share this post


Link to post
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?

Share this post


Link to post
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.

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
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