Jump to content

Ignore Invisible Controls


Recommended Posts

Hi.

Is there a possibility to ignore an invisible control.

I mean such that when I do ControlGetHandle("", "", "CLASS:Button; TEXT:Test") i only want to get the handle of a visible button.

The background of my question:

I want to automate a program using a wizard (you know, those Next, Next, Finish dialogs). Unfortunately when clicking next, the contents of the previous page is still present in memory, the window tree looks like this:

#32770 "Wizard"
|- #32770 ""
|  | - Control 1 of page 1
|  | - Control 2 of page 1
|   - Button "Test" 
- #32770 ""
   | - Control 1 of page 2
   | - Control 2 of page 2
    - Button "Test"

So when I search using string above, I might get (and I do actually) the wrong Button. A possibility to avoid the problem is ignoring the invisible controls, since the button of the first page is invisible.

Any other suggestions?

Did anyone of you have the same problem?

Regards

Link to comment
Share on other sites

Perhaps do a check with ControlCommand() first on the control.

Look at using "IsVisible" and "IsEnabled" parameters.

ControlCommand('', '', '', 'IsVisible')
ControlCommand('', '', '', 'IsEnabled')

:)

Yeah, but if I am checking the control returned from ControlGetHandle(), it is already too late.

I need ControlGetHandle() to ignore the invisible Controls.

Link to comment
Share on other sites

Why is it too late? Check the visibility of the control after each handle is found, if its invisible then break the loop.

$cID = ;ControlID

;Not required yet since ControlCommand requires ControlID, NOT HWND.

;$handle = ControlGetHandle("")

If ControlCommand('', '', $cID, 'IsVisible') AND ControlCommand('', '', $cID, 'IsEnabled') Then

;Perform action

EndIf

Link to comment
Share on other sites

Why is it too late? Check the visibility of the control after each handle is found, if its invisible then break the loop.

Hmm which loop?

I have two buttons, both with the same text, one visible, the other one invisible. I want to click at the visible button. Where do you see a loop there?

But anyway, I think I found a solution: Just add the INSTANCE: parameter and keep increasing the instance number until no more components are found.

Not very elegant though...

Is there another possibility, like ControlGetAllHandles("", "", "[.....]") which returns all handles that match a condition?

Regards

Link to comment
Share on other sites

I use this for an auto-installer I made for winamp:

Func _ControlWaitVisible($ivWindowhWnd, $svText, $ivControlID, $ivTimeout = 0)
    
    If Not WinExists($ivWindowhWnd, $svText) Then
        SetError(1) ; window doesn't exist
        Return 0
    EndIf
    
    Local $ivTimer = TimerInit()
    
    Do
        Sleep(250)
    Until ControlCommand($ivWindowhWnd, "", $ivControlID, "IsVisible", "") Or ($ivTimeout > 0 And TimerDiff($ivTimer) > $ivTimeout)
    
    If $ivTimeout > 0 And TimerDiff($ivTimer) > $ivTimeout Then
        SetError(2) ; Timeout
        Return 0
    EndIf
    
    SetError(0)
    Return 1
    
EndFunc

Works like WinWait does..

Link to comment
Share on other sites

I use this for an auto-installer I made for winamp:

Func _ControlWaitVisible($ivWindowhWnd, $svText, $ivControlID, $ivTimeout = 0)
    
    If Not WinExists($ivWindowhWnd, $svText) Then
        SetError(1) ; window doesn't exist
        Return 0
    EndIf
    
    Local $ivTimer = TimerInit()
    
    Do
        Sleep(250)
    Until ControlCommand($ivWindowhWnd, "", $ivControlID, "IsVisible", "") Or ($ivTimeout > 0 And TimerDiff($ivTimer) > $ivTimeout)
    
    If $ivTimeout > 0 And TimerDiff($ivTimer) > $ivTimeout Then
        SetError(2) ; Timeout
        Return 0
    EndIf
    
    SetError(0)
    Return 1
    
EndFunc

Works like WinWait does..

But is not solving my problem. Let my quote myself:

I have two buttons, both with the same text, one visible, the other one invisible. I want to click at the visible button.

Anyway, I found some solutions (not very nice, though).

Link to comment
Share on other sites

just use INSTANCE: in the control ID part if that's the case.

Or you could create a function that finds the visible button of all the classnames... Something like this?:

Func _ControlFindVisible($svTitle, $svText, $svCtrlClass)
    
    Local $i = 1
    
    Do
        If ControlCommand($svTitle, $svText, "[CLASS:" & $svCtrlClass & "; INSTANCE:" & $i & "]", "IsVisible", "") Then ExitLoop
        $i += 1
    Until $i >= 100
    
    If $i >= 100 Then
        SetError(1) ; None was found
        Return 0
    EndIf
    
    SetError(0)
    Return String($svCtrlClass & $i)
    
EndFunc
Link to comment
Share on other sites

If INSTANCE of each button is not constant, then

$hWndParent = WinGetHandle("Test window")
$hX = 0
Do 
    $hX = _FindWindowEx($hWndParent,$hX,"Button","Test")
Until $hX = 0 Or BitAND(WinGetState($hX), 2)


Func _FindWindowEx($hWndParent, $hWndChildAfter, $sClassName, $sWinTitle="")
    Local $aRet = DllCall('user32.dll','hwnd','FindWindowEx', 'hwnd',$hWndParent, 'hwnd',$hWndChildAfter, 'str',$sClassName, 'str',$sWinTitle)
    Return $aRet[0]
EndFunc
Edited by Siao

"be smart, drink your wine"

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