Jump to content
Atzi

array and loop problems

Recommended Posts

Atzi

Hi there,

got a Problem with Arrays it seems, didnt get how it works from my researches it seems.

Maybe someone can help me out on this. 

Want to save coordinates returned from pixelfind to an Array and call that Array again.

also want to save predefined Arrays to others so i dont have to set that much variables and simply can copy parts of the codes for other sections.

For the Loop... it should do every step of the Code until the conditions are fulfilled (maybe someone got a better solution for that as well - also not sure yet if it resets the $todo to 1 after the script is quit and restarted - but hope so for now).

For the "Sleep(1000) after Pixelsearch i am not sure if i really Need that but can test it out after i solved my other Problems.

opt("CaretCoordMode",0)

Global $MainHWnd
Global $GotPos[2]
Global $SearAr[4]
Global $SearCol
Global $todo = 1 ;this should be 1 on each start

Global $OkAnAr = [469,412,503,430]
Global $OkAnCol = 0xCAFFFF
Global $OkAdAr = [459,489,505,507]
Global $OkAdCol = 0x800000
Global $SIRAr = [922,47,944,67]
Global $SIRCol = 0xCEFCFC
Global $DoneAr = [910,511,934,535]
Global $DoneCol = 0xFDF5B3

While $todo = 1
    OkAn()
    Sleep(50)
WEnd
While $todo = 2
    OkAd()
    Sleep(50)
WEnd
While $todo = 3
    SIR()
    Sleep(50)
WEnd
While $todo = 4
Done()
WEnd
Exit



Func OkAn()
    WinActivate ("Main")
    sleep(100)
    $MainHWnd = WinGetHandle("Main")
    $SearAr = $OkAnAr ;Array 0 to 3 should be set according to predefined coords
    $SearCol = $OkAnCol
    $GotPos = PixelSearch($SearAr[0],$SearAr[1],$SearAr[2],$SearAr[3],$SearCol,20,1,$MainHwnd) ;x and y should be saved to this array
    Sleep(1000)
    If Not @error Then
        ControlClick("Main","","","left",1,$GotPos[0],$GotPos[1]) ;x and y should be taken from this array
    ElseIf @error Then
        $todo = 2
        OkAd()
    EndIf
EndFunc

Func OkAd()
    WinActivate ("Main")
    sleep(100)
    $MainHWnd = WinGetHandle("Main")
    $SearAr = $OkAdAr ;Array 0 to 3 should be set according to predefined coords
    $SearCol = $OkAdAr ;color code should be set according to predefined settings
    $GotPos = PixelSearch($SearAr[0],$SearAr[1],$SearAr[2],$SearAr[3],$SearCol,20,1,$MainHwnd) ;x and y should be saved to this array
    Sleep(1000)
    If Not @error Then
        ControlClick("Main","","","left",1,$GotPos[0],$GotPos[1]) ;x and y should be taken from this array
    ElseIf @error Then
        $todo = 3
        SIR()
    EndIf
EndFunc

Func SIR()
    WinActivate ("Main")
    sleep(100)
    $MainHWnd = WinGetHandle("Main")
    $SearAr = $SIRAr ;Array 0 to 3 should be set according to predefined coords
    $SearCol = $SIRCol ;color code should be set according to predefined settings
    $GotPos = PixelSearch($SearAr[0],$SearAr[1],$SearAr[2],$SearAr[3],$SearCol,20,1,$MainHwnd) ;x and y should be saved to this array
    Sleep(1000)
    If Not @error Then
        ControlClick("Main","","","left",1,$GotPos[0],$GotPos[1]) ;x and y should be taken from this array
    ElseIf @error Then
        $todo = 4
        OkAd()
    EndIf
EndFunc

Func Done()
    WinActivate ("Main")
    sleep(100)
    $MainHWnd = WinGetHandle("Main")
    $SearAr = $DoneAr ;Array 0 to 3 should be set according to predefined coords
    $SearCol = $DoneCol ;color code should be set according to predefined settings
    $GotPos = PixelSearch($SearAr[0],$SearAr[1],$SearAr[2],$SearAr[3],$SearCol,20,1,$MainHwnd) ;x and y should be saved to this array
    Sleep(1000)
    If @error Then
        ControlClick("Main","","","left",1,$GotPos[0],$GotPos[1]) ;x and y should be taken from this array
    ElseIf Not @error Then
        $todo = 5
        OkAd()
    EndIf
EndFunc

What i get using this Code is:

ControlClick("Main","","","left",1,$GotPos[0],$GotPos[1])
ControlClick("Main","","","left",1,$GotPos^ ERROR
->01:37:46 AutoIt3.exe ended.rc:1

Hope you can help me out on this as i am only about to get started using autoit.

Share this post


Link to post
Share on other sites
Subz

Remove the Sleep after PixelSearch otherwise your @error is returning Sleep function error rather than the PixelSearch function error.

  • Like 1

Share this post


Link to post
Share on other sites
Bilgus
Opt("CaretCoordMode", 0)
HotKeySet("{ESC}", "_Exit")
Opt("MouseCoordMode", 0) ;Relative to window Remove Later

Global $todo = 1 ;this should be 1 on each start

Global $OkAnAr = [469, 412, 503, 430]
Global $OkAnCol = 0xCAFFFF
Global $OkAdAr = [459, 489, 505, 507]
Global $OkAdCol = 0x800000
Global $SIRAr = [922, 47, 944, 67]
Global $SIRCol = 0xCEFCFC
Global $DoneAr = [910, 511, 934, 535]
Global $DoneCol = 0xFDF5B3

While $todo = 1
    $todo = Search_nClick("Main", $OkAnAr, $OkAnCol, $todo)
    Sleep(50)
WEnd
While $todo = 2
    $todo = Search_nClick("Main", $OkAdAr, $OkAdCol, $todo)
    Sleep(50)
WEnd
While $todo = 3
    $todo = Search_nClick("Main", $SIRAr, $SIRCol, $todo)
    Sleep(50)
WEnd
While $todo = 4
    $todo = Search_nClick("Main", $DoneAr, $DoneCol, $todo)
WEnd
Exit
Func _Exit()
    Exit
EndFunc   ;==>_Exit

Func Search_nClick($sMain, ByRef $aSearch, $iColor, $iTodo)

    Local $MainHWnd = WinActivate($sMain) ;WinActivate returns a hWnd
    If Not $MainHWnd Then
        MsgBox(0, "Error", $sMain & " was not found")
        Return 0 ;Fall through to exit
    EndIf

    If UBound($aSearch) = 4 Then
        Local $GotPos = PixelSearch($aSearch[0], $aSearch[1], $aSearch[2], $aSearch[3], $iColor, 20, 1, $MainHWnd) ;x and y should be saved to this array
        ;Sleep(1000)
        If IsArray($GotPos) And Not @error Then
            ConsoleWrite("Click* " & $GotPos[0] & " x " & $GotPos[1])

            MouseMove($GotPos[0], $GotPos[1]) ;Just to verify Remove Later

            ControlClick("Main", "", "", "left", 1, $GotPos[0], $GotPos[1]) ;x and y should be taken from this array
        Else
            ConsoleWrite("Failed!" & @CRLF)
            $iTodo += 1
        EndIf
    Else
        MsgBox(0, "Error", "Bounds ;Array 0 to 3 should be set according to predefined coords")
        $iTodo += 1
    EndIf
    Return $iTodo
EndFunc   ;==>Search_nClick

I condensed down your functions and added some error checking

I also added movement of the mouse so you can see where it clicks REMOVE THIS ASAP lol I put in ESC hotkey set so you can quit the script

Next ControlClick should do this finding for you if you give it the name of the control and a classname (See helpfile)

you can use the windowinfo tool to grab this info

Share this post


Link to post
Share on other sites
Atzi
8 hours ago, Bilgus said:
Opt("CaretCoordMode", 0)
HotKeySet("{ESC}", "_Exit")
Opt("MouseCoordMode", 0) ;Relative to window Remove Later

Global $todo = 1 ;this should be 1 on each start

Global $OkAnAr = [469, 412, 503, 430]
Global $OkAnCol = 0xCAFFFF
Global $OkAdAr = [459, 489, 505, 507]
Global $OkAdCol = 0x800000
Global $SIRAr = [922, 47, 944, 67]
Global $SIRCol = 0xCEFCFC
Global $DoneAr = [910, 511, 934, 535]
Global $DoneCol = 0xFDF5B3

While $todo = 1
    $todo = Search_nClick("Main", $OkAnAr, $OkAnCol, $todo)
    Sleep(50)
WEnd
While $todo = 2
    $todo = Search_nClick("Main", $OkAdAr, $OkAdCol, $todo)
    Sleep(50)
WEnd
While $todo = 3
    $todo = Search_nClick("Main", $SIRAr, $SIRCol, $todo)
    Sleep(50)
WEnd
While $todo = 4
    $todo = Search_nClick("Main", $DoneAr, $DoneCol, $todo)
WEnd
Exit
Func _Exit()
    Exit
EndFunc   ;==>_Exit

Func Search_nClick($sMain, ByRef $aSearch, $iColor, $iTodo)

    Local $MainHWnd = WinActivate($sMain) ;WinActivate returns a hWnd
    If Not $MainHWnd Then
        MsgBox(0, "Error", $sMain & " was not found")
        Return 0 ;Fall through to exit
    EndIf

    If UBound($aSearch) = 4 Then
        Local $GotPos = PixelSearch($aSearch[0], $aSearch[1], $aSearch[2], $aSearch[3], $iColor, 20, 1, $MainHWnd) ;x and y should be saved to this array
        ;Sleep(1000)
        If IsArray($GotPos) And Not @error Then
            ConsoleWrite("Click* " & $GotPos[0] & " x " & $GotPos[1])

            MouseMove($GotPos[0], $GotPos[1]) ;Just to verify Remove Later

            ControlClick("Main", "", "", "left", 1, $GotPos[0], $GotPos[1]) ;x and y should be taken from this array
        Else
            ConsoleWrite("Failed!" & @CRLF)
            $iTodo += 1
        EndIf
    Else
        MsgBox(0, "Error", "Bounds ;Array 0 to 3 should be set according to predefined coords")
        $iTodo += 1
    EndIf
    Return $iTodo
EndFunc   ;==>Search_nClick

I condensed down your functions and added some error checking

I also added movement of the mouse so you can see where it clicks REMOVE THIS ASAP lol I put in ESC hotkey set so you can quit the script

Next ControlClick should do this finding for you if you give it the name of the control and a classname (See helpfile)

you can use the windowinfo tool to grab this info

Thx for the help. I even understand most of ur changes from a logical point of view, which pretty much surprises myself and i do have to do some testing later today to confirm this ;) however what i didnt really get is what you mean with

Next ControlClick should do this finding for you if you give it the name of the control and a classname (See helpfile)

Could you plz specify this so i know whatelse can be changed

Share this post


Link to post
Share on other sites
Bilgus

Now this doesn't hold true for all trype of controls some you just have to do a pixel search / blind click

But.

Lets use the Windows Calculator as a For instance

First put it in Standard Mode

Start up the autoit v3 Window Info Tool and click the tab Control

Now drag the finder bullseye over the controls(buttons) on the calculator

For instance When I drag over the '7' button I get this..

>>>> Control <<<<
Class:  Button
Instance:   3
ClassnameNN:    Button3
Name:   
Advanced (Class):   [CLASS:Button; INSTANCE:3]
ID: 137
Text:   
Position:   13, 162
Size:   43, 33
ControlClick Coords:    28, 15
Style:  0x50000000
ExStyle:    0x00000004
Handle: 0x0000000001160E4C

So Lets do this for a few other buttons CE, 3, +, =

And now we can do something like this

Local $hWnd = WinWait("[Title:Calculator; CLASS:CalcFrame; INSTANCE:1]")
consoleWrite("Calc hWnd =" & $hWnd & @CRLF)
Local $iRes = ControlClick ( $hWnd, "", "[CLASS:Button; INSTANCE:8]", "left", 1) ; CE Button
if $iRes Then $iRes = ControlClick ( $hWnd, "", "[CLASS:Button; INSTANCE:3]", "left", 7) ;7 Button
if $iRes Then $iRes = ControlClick ( $hWnd, "", "[CLASS:Button; INSTANCE:23]", "left", 1) ; + Button
if $iRes Then $iRes = ControlClick ( $hWnd, "", "[CLASS:Button; INSTANCE:16]", "left", 1) ; 3 Button
if $iRes Then $iRes = ControlClick ( $hWnd, "", "[CLASS:Button; INSTANCE:28]", "left", 1) ; = Button
ConsoleWrite("Success = " & $iRes & @CRLF) ; 7777780

Assuming your control IDs are the same this script should put 7777780 on your calculator

Now notice we didn't even activate the window try [(clearing the calc) and] minimizing the window and running the script again

Edited by Bilgus
[(clearing the calc) and]

Share this post


Link to post
Share on other sites
Atzi

Got what you mean now thx. Gonna check this out on various applications as well then... seems to be lots more comfortable with the control click directly sent to the button as it has a 100÷ success i guess and also should response if the button was actually clicked

Share this post


Link to post
Share on other sites
Atzi
On ‎18‎.‎03‎.‎2018 at 6:41 AM, Bilgus said:
Opt("CaretCoordMode", 0)
HotKeySet("{ESC}", "_Exit")
Opt("MouseCoordMode", 0) ;Relative to window Remove Later

Global $todo = 1 ;this should be 1 on each start

Global $OkAnAr = [469, 412, 503, 430]
Global $OkAnCol = 0xCAFFFF
Global $OkAdAr = [459, 489, 505, 507]
Global $OkAdCol = 0x800000
Global $SIRAr = [922, 47, 944, 67]
Global $SIRCol = 0xCEFCFC
Global $DoneAr = [910, 511, 934, 535]
Global $DoneCol = 0xFDF5B3

While $todo = 1
    $todo = Search_nClick("Main", $OkAnAr, $OkAnCol, $todo)
    Sleep(50)
WEnd
While $todo = 2
    $todo = Search_nClick("Main", $OkAdAr, $OkAdCol, $todo)
    Sleep(50)
WEnd
While $todo = 3
    $todo = Search_nClick("Main", $SIRAr, $SIRCol, $todo)
    Sleep(50)
WEnd
While $todo = 4
    $todo = Search_nClick("Main", $DoneAr, $DoneCol, $todo)
WEnd
Exit
Func _Exit()
    Exit
EndFunc   ;==>_Exit

Func Search_nClick($sMain, ByRef $aSearch, $iColor, $iTodo)

    Local $MainHWnd = WinActivate($sMain) ;WinActivate returns a hWnd
    If Not $MainHWnd Then
        MsgBox(0, "Error", $sMain & " was not found")
        Return 0 ;Fall through to exit
    EndIf

    If UBound($aSearch) = 4 Then
        Local $GotPos = PixelSearch($aSearch[0], $aSearch[1], $aSearch[2], $aSearch[3], $iColor, 20, 1, $MainHWnd) ;x and y should be saved to this array
        ;Sleep(1000)
        If IsArray($GotPos) And Not @error Then
            ConsoleWrite("Click* " & $GotPos[0] & " x " & $GotPos[1])

            MouseMove($GotPos[0], $GotPos[1]) ;Just to verify Remove Later

            ControlClick("Main", "", "", "left", 1, $GotPos[0], $GotPos[1]) ;x and y should be taken from this array
        Else
            ConsoleWrite("Failed!" & @CRLF)
            $iTodo += 1
        EndIf
    Else
        MsgBox(0, "Error", "Bounds ;Array 0 to 3 should be set according to predefined coords")
        $iTodo += 1
    EndIf
    Return $iTodo
EndFunc   ;==>Search_nClick

I condensed down your functions and added some error checking

I also added movement of the mouse so you can see where it clicks REMOVE THIS ASAP lol I put in ESC hotkey set so you can quit the script

Next ControlClick should do this finding for you if you give it the name of the control and a classname (See helpfile)

you can use the windowinfo tool to grab this info

Still didnt have the time to test the code but think i found sth that might be not working the way i thought of... the last pixelsearch was actually meant to be the opposite direction... should mean if it doesnt find the pixel click and dont click if found but end function/call new function

Just tried your script and all i get is:

Failed!
Failed!
Failed!
Failed!

EDIT: really trying to fiddle the Problem out and looking closer to it it Looks like an Array Problem with $asearch... and $GotPos not beeing an array

If UBound($aSearch) = 4 Then
        Local $GotPos = PixelSearch($aSearch[0], $aSearch[1], $aSearch[2], $aSearch[3], $iColor, 20, 1, $MainHWnd) ;x and y should be saved to this array
        ;Sleep(1000)
        If IsArray($GotPos) And Not @error Then   ;<=== doesnt seem to be true as it doesnt return the consolewrite!
            ConsoleWrite("Click* " & $GotPos[0] & " x " & $GotPos[1])

            MouseMove($GotPos[0], $GotPos[1]) ;Just to verify Remove Later

            ControlClick("Main", "", "", "left", 1, $GotPos[0], $GotPos[1])
        Else
            ConsoleWrite("Failed!" & @CRLF) ;<=== confirms it is an If IsArray($GotPos) problem if i got this right
            $iTodo += 1
        EndIf

EDIT2: oddly enough putting the window to another Location on the Screen seems to have done the trick... really dont know why tho. Gotta test again with moving the window to 0,0 added i guess

Edited by Atzi

Share this post


Link to post
Share on other sites
Bilgus

Thats why I added that mouse move

You probably need to look into 

Opt("MouseCoordMode", 0) ;Relative to window Remove Later

and change it to 2

or even #AutoIt3Wrapper_Res_HiDpi=Y

Thats why its better to use the IDs or classname / instance

Share this post


Link to post
Share on other sites
Atzi

The Mousemove looked like working fine actually but the pixelfind seemed to act strange on different positions of the Screen actually.

For now i added a WinGetPos and WinMove If in the first function to call untill i got a better solution for that.

Dont understand the DPI Thing after reading a whole bunch... i set my Windows to Standard 100% which should be 96dpi and i am running it on 1920x1080 also the Window i am looking for Pixels is set to 960x540 and according to our IT @ Workspace should be running in Standard Win10dpi - also 96dps.

Really dunno if and how this could mess up here.

 

Worked out something that seems to work pretty good for what it yet is tho:

Wasnt too sure about removing your error Outputs but seemed to be lots easier for me to work with Little less lines per function for now - might add some error Messages mack in later if you recommend to tho as i am really willing to learn sth from the once who know what they do ;)

Opt("CaretCoordMode", 0)
HotKeySet("{ESC}", "_Exit")

Global $todo = 1
Global $WinTitle = "Main"
Global $WinPosSh = [1, 1]
Global $NAr = [740, 255, 764, 277]
Global $NCol = 0x3AA4C2
Global $SAr = [444, 487, 524, 507]
Global $SCol = 0x97FFEE
Global $OkAnAr = [469, 412, 503, 430]
Global $OkAnCol = 0xEEFFFF
Global $OkAdAr = [442, 481, 522, 503]
Global $OkAdCol = 0xFFF954
Global $SIRAr = [922, 47, 944, 67]
Global $SIRCol = 0xCEFCFC
Global $DoneAr = [906, 509, 936, 535]
Global $DoneCol = 0xFDF5B3

While $todo = 1
    $todo = Search_nClickStart($WinTitle, $NAr, $NCol, $todo)
    Sleep (50)
WEnd
While $todo = 2
    $todo = Search_nClickStart($WinTitle, $SAR, $SCol, $todo)
    Sleep (50)
WEnd
While $todo = 3
    $todo = Search_nClick($WinTitle, $OkAnAr, $OkAnCol, $todo)
    Sleep(50)
WEnd
While $todo = 4
    $todo = Search_nClick($WinTitle, $OkAdAr, $OkAdCol, $todo)
    Sleep(50)
WEnd
While $todo = 5
    $todo = Search_nClick($WinTitle, $SIRAr, $SIRCol, $todo)
    Sleep(50)
WEnd
While $todo = 6
    $todo = Search_nClickDone($WinTitle, $DoneAr, $DoneCol, $todo)
    Sleep(50)
WEnd
_Exit()

Func Search_nClickStart($sMain, ByRef $aSearch, $iColor, $iTodo)

    Local $MainHWnd = WinActivate($sMain)
    Local $WinPosIS = WinGetPos($Wintitle)
    If not $WinPosIs[0] = $WinPosSh[0] And $WinPosIs[1] = $WinPosSh[1] Then
        WinMove ($WinTitle,"",$WinPosSh[0],$WinPosSh[1])
    EndIf
        Local $GotPos = PixelSearch($aSearch[0], $aSearch[1], $aSearch[2], $aSearch[3], $iColor, 0, 1, $MainHWnd)
        If IsArray($GotPos) And Not @error Then
            ConsoleWrite(" Clicked " & $GotPos[0] & " x " & $GotPos[1] & " - move on!" & @CRLF)
            ControlClick($WinTitle, "", "", "left", 1, $GotPos[0], $GotPos[1])
            $iTodo += 1
            Sleep(20000)
        Else
            ConsoleWrite(" Not found - move on!" &  @CRLF)
        EndIf
     Return $iTodo
EndFunc   ;==>Search_nClickStart

Func Search_nClick($sMain, ByRef $aSearch, $iColor, $iTodo)

        Local $MainHWnd = WinActivate($sMain)
        Local $GotPos = PixelSearch($aSearch[0], $aSearch[1], $aSearch[2], $aSearch[3], $iColor, 0, 1, $MainHWnd)
        If IsArray($GotPos) And Not @error Then
            ConsoleWrite(" Clicked " & $GotPos[0] & " x " & $GotPos[1])
            ControlClick($WinTitle, "", "", "left", 1, $GotPos[0], $GotPos[1])
        Else
            ConsoleWrite(" - move on!"& @CRLF)
            $iTodo += 1
        EndIf
    Return $iTodo
EndFunc   ;==>Search_nClick

Func Search_nClickDone($sMain, ByRef $aSearch, $iColor, $iTodo)

    Local $MainHWnd = WinActivate($sMain)
        ConsoleWrite(" Clicked " & $DoneAr[0] & " x " & $DoneAr[1])
        ControlClick($WinTitle, "", "", "left", 1, $DoneAr[0], $DoneAr[1])
        Sleep(1000)
    Local $GotPos = PixelSearch($aSearch[0], $aSearch[1], $aSearch[2], $aSearch[3], $iColor, 0, 1, $MainHWnd)
        If IsArray($GotPos) And Not @error Then
            $itodo += 1
            ConsoleWrite(" Finally Done!" & @CRLF)

        Else
            ConsoleWrite("Search again!" & @CRLF)

        EndIf
    Return $iTodo
EndFunc   ;==>Search_nClickDone

Func _Exit()
    Exit
EndFunc   ;==>_Exit

Search_nClickStart is for starting up the program (which will be 1 click per button always)

Search_nClickDone i added for the last button as it has to check if ist there after clicking another and if yes dont click it anymore (at least for now as Long i dunno what to do next ;) ) here the sleep(1000) seems to be necassary to get a good result but i will test tomorrow if i can get lower on that if i dont have a more clean solution for this ;)

 

Share this post


Link to post
Share on other sites
Bilgus

Looks Good to me

The errors were only there for you to see where things failed

The only thing I would probably change though, its from my original code 

If IsArray($GotPos) And Not @error Then
;make this 

If IsArray($GotPos) Then

;Or

If Not @error and IsArray($GotPos) Then

I can never seem to remember other function calls wipe out @error

but being in this case that there is only 1 error for (not found) for PixelSearch

'If IsArray($GotPos) Then' Should be fine

 

Edited by Bilgus

Share this post


Link to post
Share on other sites
Atzi

Also will try to combine start function with regular one using variable vor sleep ... should make things more clean i guess...

Will have a cloder look on the isarray once i got some time

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

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.