Jump to content
GezJohnJones

Need help Creating an Application Switcher

Recommended Posts

GezJohnJones

Hello, 

 I have a problem needing a solution.  I need a bit of script that will switch between active applications every 30 seconds or so.  Being an absolute beginner I looked around and came up with this. 

While 1 ;loop indefinitely
    WinActivate("notepad","") ;give focus to notepad
    Sleep(30000) ;sleep 30 seconds
    WinActivate("wordpad","") ;give focus to wordpad
    Sleep(30000) ;sleep 30 seconds
WEnd

This works for my purposes as a basic switcher.  But I'd like to take it a step further and be able to set parameters.  I'd like the user to be able to see a list of active applications in a GUI, be able to select multiple applications to switch between, and select the switch frequency.  

I'm finding out how to do each part of the puzzle including creating the GUI, populating the list with data, having a textbox set the frequency etc., but I don't know how to bring it all together.

Thank you for any help you can provide.

GezJohnJones 

Share this post


Link to post
Share on other sites
Melba23

GezJohnJones,

Welcome to the AutoIt forums.

I suggest you post the code you have already cobbled together (see here how to do it) so that we have some idea of how you want to proceed - otherwise any code we might suggest could well not fit into your base idea.

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
GezJohnJones

Hi John & Melba.  Apologies for the ignorance!!  Apart from messing around in VBA, this is the first bit of coding I've got involved in and only really being doing since yesterday!  If this isn't the appropriate forum for this kind of thing, or if my skill level is too low to be thinking about this just yet, please let me know.  But I will do my best to show you what I got and where I want to get to. 

So I set out what my GUI will look like.  I've used a treeview box with checkboxes because visually that seemed to do what I want.  However, after some research Im thinking a multi-selectable list my be more appropriate?  Here's the GUI 

#Region INCLUDES
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <TreeViewConstants.au3>
#include <WindowsConstants.au3>
#EndRegion INCLUDES


#Region ### START Koda GUI section ### Form=c:\users\geraint\documents\autoit\appswitcherconfig.kxf

#Region GUI
$AppSwitcherConfig = GUICreate("AppSwitcher!", 265, 357, 192, 124)
$lbl_AppSwitcher = GUICtrlCreateLabel("AppSwitcher!", 88, 16, 93, 23)
GUICtrlSetFont(-1, 12, 800, 0, "Times New Roman")
#EndRegion GUI

#Region BUTTONS
$Btn_Start = GUICtrlCreateButton("Start", 8, 320, 75, 25)
$btn_Stop = GUICtrlCreateButton("Stop", 96, 320, 75, 25)
$btn_close = GUICtrlCreateButton("Close", 184, 320, 75, 25)
#EndRegion BUTTONS

#Region FREQUENCY
$lbl_freq = GUICtrlCreateLabel("Cycle Time (secs)", 56, 288, 87, 17)
$txt_freq = GUICtrlCreateInput("30", 152, 286, 33, 21)
#EndRegion FREQUENCY

#Region Applications
Local $TVS_Applications = GUICtrlCreateTreeView(8, 40, 249, 241, BitOR($GUI_SS_DEFAULT_TREEVIEW,$TVS_CHECKBOXES))
GUICtrlCreateTreeViewItem("NotePad", $TVS_Applications)
GUICtrlSetState(-1, $GUI_CHECKED)
GUICtrlCreateTreeViewItem("Chrome", $TVS_Applications)
GUICtrlSetState(-1, $GUI_CHECKED)
GUICtrlCreateTreeViewItem("Steam", $TVS_Applications)
GUICtrlSetState(-1, $GUI_CHECKED)
#EndRegion Applications


GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $btn_close
            Exit
    EndSwitch
WEnd

I want the createtreeviewitems to be populated by a function that retrieves the active windows.  The examples I have seen bring through everything that's happening in the backgroud.  I don't have anything to show in terms of code for this part, but I know I should be looking at something around WinList and arrays(?).  

The frequency or cycle time is set by the user.  

Lastly, given the settings selected in the GUI (i.e. the applications and the cycle time, I want the Start button to run this as a function, stop to stop the function but keep the GUI up, and close to close the GUI and stop any running scripts. 

While 1 ;loop indefinitely
    WinActivate("notepad","") ;give focus to notepad
    Sleep(30000) ;sleep 30 seconds
    WinActivate("wordpad","") ;give focus to wordpad
    Sleep(30000) ;sleep 30 seconds
WEnd

Putting it down like this makes it evident that what was so simple in my head is actually quite complex :/

GezJohnJones

 

 

Share this post


Link to post
Share on other sites
JohnOne

Winlist would be an apt place to start like you mention

Perhaps you should create a function that employs it. The function should also loop through the windows returned by WinList testing them with WinGetState to ensure they are at least visible.

I would start by creating a new array in your function the same size as the array WinList returns, adding only those handles of visible windows, and maybe some other criteria, then redim (Adjust the size) of your array before returning it from the function.

Keep your tasks in the project modular and focus on one task at a time.


AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Share this post


Link to post
Share on other sites
GezJohnJones

Thanks John,

So I've updated the script to get the active running windows in.  Here's the updated code.  Before I get on to the next step and send results to the switcher code, I have a problem with the close button and the exit button.  I have to click the exit button 3 times to close, and the close button isn't working at all.  

#include <array.au3>
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <GUIListBox.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
$AppSwitcherConfig = GUICreate("AppSwitcher!", 265, 357, 311, 154)
$ApplicationList = GUICtrlCreateList("", 8, 48, 249, 227, BitOR($GUI_SS_DEFAULT_LIST, $LBS_MULTIPLESEL))
GUISetState()
$lbl_AppSwitcher = GUICtrlCreateLabel("AppSwitcher!", 88, 16, 93, 23)
GUICtrlSetFont(-1, 12, 800, 0, "Times New Roman")
$Btn_Start = GUICtrlCreateButton("Start", 8, 320, 75, 25)
$btn_Stop = GUICtrlCreateButton("Stop", 96, 320, 75, 25)
$btn_close = GUICtrlCreateButton("Close", 184, 320, 75, 25)
$lbl_freq = GUICtrlCreateLabel("Cycle Time (secs)", 56, 288, 87, 17)
$txt_freq = GUICtrlCreateInput("30", 152, 286, 33, 21)
PopulateList()
While GUIGetMsg() <> -3
    Sleep(50)
WEnd

Func PopulateList()
    $WinArray = WinList()
    For $i = 1 To $WinArray[0][0]
        If _isVisible($WinArray[$i][1]) And $WinArray[$i][0] <> "" Then
            GUICtrlSetData($ApplicationList, $WinArray[$i][0])
        EndIf
    Next
EndFunc   ;==>PopulateList

Func _isVisible($hWin)
    $state = WinGetState($hWin)
    If BitAND($state, 2) Then
        Return True
    Else
        Return False
    EndIf
EndFunc   ;==>_isVisible

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $btn_close
            Exit
        Case $Btn_Start
    EndSwitch
WEnd

 

Share this post


Link to post
Share on other sites
GezJohnJones

Perfect!  

Right, on to sending the results to the switcher script.  Using the help files best I can so I'm assuming I'm looking at a GUIctrlread. 

 

Thanks for the help.  

 

 

Share this post


Link to post
Share on other sites
GezJohnJones

OK I'm stuck again.  How do you return multiple values chosen from the list and put them into an array?  I can only get it to return the last application I clicked. 

Edited by GezJohnJones
spelling

Share this post


Link to post
Share on other sites
Melba23

GezJohnJones,

Time for you to discover the UDFs which offer a wider range of functionality then the native functions:

#include <GUIConstantsEx.au3>
#include <Array.au3>
#include <GUIListBox.au3>

$hGUI = GUICreate("Test", 500, 500)

$ApplicationList = GUICtrlCreateList("", 10, 10, 400, 400, BitOR($GUI_SS_DEFAULT_LIST, $LBS_MULTIPLESEL))

$cButton = GUICtrlCreateButton("Read", 10, 450, 80, 30)

GUISetState()

PopulateList()

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $cButton

            $aSelections = _GUICtrlListBox_GetSelItems($ApplicationList) ; UDF function to get all selections

            _ArrayDisplay($aSelections, "", Default, 8)
    EndSwitch



WEnd



Func PopulateList()
    $WinArray = WinList()
    For $i = 1 To $WinArray[0][0]
        If _isVisible($WinArray[$i][1]) And $WinArray[$i][0] <> "" Then
            GUICtrlSetData($ApplicationList, $WinArray[$i][0])
        EndIf

    Next
EndFunc   ;==>PopulateList



Func _isVisible($hWin)
    $state = WinGetState($hWin)
    If BitAND($state, 2) Then
        Return True
    Else
        Return False
    EndIf

EndFunc   ;==>_isVisible

Please ask if you have any questions.


M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
GezJohnJones

Thanks Melba,

  This is a steep learning curve for me but I think I get it.  The UDF gets the selected item in the listbox and puts them in an array, the _ArrayDisplay shows me the results.  

The results shows as the following.  [0] being how many selections, [1] the first selected, [2] the second selected.  The selected items come through as the place on the list, not the application name. 

Row|Col 0
[0]|2
[1]|1
[2]|4

So how do I then get on to the next step of placing the applications names in a loop to activate the selected windows? So I need something like this, or similar.  

While 1
    WinActivate(selection1, "")
    Sleep($frequency) 
    WinActivate(selection2,"")
    Sleep($frequency)
WEnd

 

 

Share this post


Link to post
Share on other sites
Melba23

GezJohnJones,

Look at the list of _GUICtrlListBox_* functions in the Help file - you will find another function _GUICtrlListBox_GetSelItemsText which looks as if it might be what you need.  Looking through similar functions in the Help file should always be the first thing you do - it is often faster then asking here.

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
GezJohnJones

OK thanks for the help, it's much appreciated.  I'll see if I can finish it off without pestering now haha.  

Cheers

Share this post


Link to post
Share on other sites
Melba23

GezJohnJones,

You are not "pestering" at all - my comment was aimed much more generally. Do not hesitate to ask in the future if you need help - after having done some "due diligence" in the Help file, of course.

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
GezJohnJones

Hello again!  So I made some progress and the script is doing what I need.....kind of.  

So I have a GUI that pops up with a listbox showing me active applications.  I can select multiple applications, set how long before they cycle.  I press start, and the applications cycle.  Good stuff.  However, as you see in the code, the only way I've found to do it is to name each array index individually and make the window active in an infinite while loop.   So my problems are as follows

- I can only select the amount of indices I specify in the loop, i.e. if I put in array[1], [2] and [3], I must select 3 applications otherwise the loop breaks and the script closes.  I've tried doing this with a "For In" but I can't specify the sleep delay. Is there another way of doing this?  Note [0] returns the number of selected applications, don't know if anything can be done with this. 

- Once the loop starts, I can't stop it.  The close button doesn't stop the script and it keeps looping. I'd like to stop it when $btn_stop, $btn_close or the exit button is pressed.  I tried incorporating an exit loop but can't get it to work.  

 

Can someone take a look, please?

 

#include <array.au3>
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <GUIListBox.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>

$AppSwitcherConfig = GUICreate("AppSwitcher!", 265, 357)

$ApplicationList = GUICtrlCreateList("", 8, 48, 249, 227, BitOR($GUI_SS_DEFAULT_LIST, $LBS_MULTIPLESEL))
GUISetState()

$lbl_AppSwitcher = GUICtrlCreateLabel("AppSwitcher!", 88, 16, 93, 23)
GUICtrlSetFont(-1, 12, 800, 0, "Times New Roman")

$Btn_Start = GUICtrlCreateButton("Start", 8, 320, 75, 25)
$btn_Stop = GUICtrlCreateButton("Stop", 96, 320, 75, 25)
$btn_close = GUICtrlCreateButton("Close", 184, 320, 75, 25)
$lbl_freq = GUICtrlCreateLabel("Cycle Time (secs)", 56, 288, 87, 17)
$txt_freq = GUICtrlCreateInput("30", 152, 286, 33, 21)

PopulateList()

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $btn_close
            Exit
        Case $Btn_Start
            $aSelections = _GUICtrlListBox_GetSelItemsText($ApplicationList)
            Start()
        Case $btn_Stop



    EndSwitch
WEnd


Func PopulateList()
    $WinArray = WinList()
    For $i = 1 To $WinArray[0][0]
        If _isVisible($WinArray[$i][1]) And $WinArray[$i][0] <> "" Then
            GUICtrlSetData($ApplicationList, $WinArray[$i][0])
        EndIf
    Next
EndFunc   ;==>PopulateList

Func _isVisible($hWin)
    $state = WinGetState($hWin)
    If BitAND($state, 2) Then
        Return True
    Else
        Return False
    EndIf
EndFunc   ;==>_isVisible



Func Start()

    $a = $aSelections[0]
    $freq = GUICtrlRead($txt_freq) * 1000

    While 1

        WinActivate($aSelections[1], "")
        Sleep($freq)
        WinActivate($aSelections[2], "")
        Sleep($freq)
        WinActivate($aSelections[3], "")
        Sleep($freq)
        
    WEnd


EndFunc   ;==>Start

 

Share this post


Link to post
Share on other sites
Melba23

GezJohnJones,

I have made a few changes:

; Only need these includes
#include <GUIConstantsEx.au3>
#include <GUIListBox.au3>


$AppSwitcherConfig = GUICreate("AppSwitcher!", 265, 357)

$ApplicationList = GUICtrlCreateList("", 8, 48, 249, 227, BitOR($GUI_SS_DEFAULT_LIST, $LBS_MULTIPLESEL))

GUICtrlCreateLabel("AppSwitcher!", 88, 16, 93, 23) ; No need to store ControlID if you never use it
GUICtrlSetFont(-1, 12, 800, 0, "Times New Roman")


$Btn_Start = GUICtrlCreateButton("Start", 8, 320, 75, 25)
$btn_Stop = GUICtrlCreateButton("Stop", 96, 320, 75, 25)
$btn_close = GUICtrlCreateButton("Close", 184, 320, 75, 25)
GUICtrlCreateLabel("Cycle Time (secs)", 56, 288, 87, 17)
$txt_freq = GUICtrlCreateInput("30", 152, 286, 33, 21)

GUISetState()

PopulateList()

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE, $btn_close ; Can use multiple events
            Exit
        Case $Btn_Start
            Start()
    EndSwitch

WEnd





Func PopulateList()
    $WinArray = WinList()
    For $i = 1 To $WinArray[0][0]
        If _isVisible($WinArray[$i][1]) And $WinArray[$i][0] <> "" Then
            GUICtrlSetData($ApplicationList, $WinArray[$i][0])
        EndIf

    Next
EndFunc   ;==>PopulateList



Func _isVisible($hWin)
    $state = WinGetState($hWin)
    If BitAND($state, 2) Then
        Return True
    Else
        Return False
    EndIf

EndFunc   ;==>_isVisible



Func Start()

    ; Read selections
    $aSelections = _GUICtrlListBox_GetSelItemsText($ApplicationList)
    ; Check there is at least 1
    If $aSelections[0] = 0 then Return

    $freq = Number(GUICtrlRead($txt_freq)) * 1000
    ; Perhaps a check for a minimum time?

    While 1
        ; Loop through each selection in turn
        For $i = 1 To $aSelections[0]

            ConsoleWrite("Activating: " & $aSelections[$i] & @CRLF)
            ;WinActivate($aSelections[$i])

            ; Now wait
            If _Wait($freq) Then
                ; If we get True returned then stop
                ConsoleWrite("Rotation stopped" & @CRLF)
                Return
            EndIf

        Next
    WEnd



EndFunc   ;==>Start

Func _Wait($freq)

    ; Get a timestamp
    $nTimeStamp = TimerInit()

    While 1
        ; Check if any buttons pressed
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE, $btn_close
                ; Exit the whole script
                Exit
            Case $btn_Stop
                ; Return true - that will stop the rotation
                Return True
        EndSwitch



        ; See if the delay is passed
        If TimerDiff($nTimeStamp) > $freq Then
            ; return Flase - the rotation will continue
            Return False
        EndIf

    WEnd

EndFunc

I hope the comments are clear enough, but please do ask if you have any questions.

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
GezJohnJones

That's perfect.  I was way out with what I was thinking I needed to do.  Still, I've learnt a lot from that and that's what counts.  Really, really appreciate it.  

 

Thanks again, 

 

Geraint

Share this post


Link to post
Share on other sites
Melba23

GezJohnJones,

Delighted I could help.

And to anyone else reading, this thread is an excellent example of how to get focused advice. Post some code which shows you have made an effort to solve the problem yourself and explain exactly why it does not work as expected - that way we have something with which to work and more importantly the knowledge that the OP is not just expecting us to do all the work.

M23

  • Like 1

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

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

×