By Adde @ 2+2 forums (HstreamPoker at gmail dot com). The corresponding thread on 2+2 is here.


Window Guard

Customizable AutoHotkey (AHK) script to handle pop-up windows while playing poker.

The script looks for the presence of various windows/dialogs, and performs actions on them. It may be to automatically close a dialog, click a button or move a window to a specific position on the screen.

This script has Scriptpad support. Scriptpad is a tool where you can connect any number of scripts to a Scriptpad, a small pop-up window with buttons for all available commands in these scripts. You access the Scriptpad by clicking a hotkey, for instance the middle mouse button.

How To Use This Script

  1. Read instructions for AutoHotkey, and make sure you have the latest version installed.

  2. Read all instructions on this page.

  3. Save the script code below in a file named "WindowGuard.ahk"

  4. Open script file in a text editor and edit settings.

  5. Create a "WindowGuard.ini" settings file and edit it to your liking.

  6. Run the script (double-click the file).

A green AHK icon will show in the system tray as long as the script is running. Right-click this icon and choose "Exit" to exit the script. If the script seems to have gone wild, choose "Reload this script".

Settings

You need to create a settings file "WindowGuard.ini" in the same directory as this script, and then edit it according to the following format (tems are separated by a semi-colon):

Command ; Match Mode ; Window Class ; Title ; Text ; Value1 ; Value2 ; [Value3 ; Value4 ; ...]

Command

This defines what action should be performed. See section below for available commands.

Title / Text / Class

To find a window, TITLE will be looked for in window title, TEXT will be looked for in window contents, and CLASS has to match with the class name for the window. Each of these can be omitted.

Match Mode

This setting defines how the search for TITLE should be performed. Possible values are:

  1. Window title must begin with TITLE

  2. Window title must contain TITLE

  3. Window title must be exactly TITLE

Value1 / Value2 / etc

These settings may contain parameters to a specific command. For instance (x,y) coordinates.

Commands

CLOSE

Window will be closed.

MOVE

Window will be moved to (x,y) screen coordinates, given in (VALUE1,VALUE2)

BUTTON

Button with name (VALUE1), as shown in AHK Window Spy, will be clicked in window/dialog.

PARTY_LEAVE

When clicking Leave Table button, and holding down modifier key (VALUE1), table will be left automatically.

PARTY_REBUY

When clicking Rebuy button (or taking a seat), and holding down modifier key (VALUE1), you will automatically be (re-) bought in with (VALUE2) percent of the default amount shown in the buy-in dialog.

PARTY_WAITLIST

This command has three modifier keys (VALUE1-3). Depending on what key you hold down when you click Join Wait List button, different things will happen. For the Auto and Repeat functions to work, you also need to use the PARTY_SEAT command.

VALUE1 = Normal function. Nothing will happen. That is, you get to manage the waitlist dialog yourself.

VALUE2 = Auto function. You will automatically join one (1) table.

VALUE3 = Repeat function. You will automatically join (VALUE5) number of tables.

VALUE4 = Min players. If the number you choose is not present, the nearest number below will be chosen. If you set this number to zero (0), you will join a waitlist for that specific table (instead of any table with min players), if that option is present; otherwise you will join the default value for min players.

VALUE5 = Number of tables to join when using Repeat function.

Example usage:

1. Leave (VALUE1) empty for normal usage when you don't hold any modifier keys down; set (VALUE2=Shift) to auto-join one table when you press down shift key; set (VALUE3=Control) to auto-join many tables when you hold down control key.

2. Set (VALUE1=Shift) for normal usage; set (VALUE2=Control) to auto-join one table; leave (VALUE3) empty to always join many tables when you click Join Wait List with no modifier keys hold down.

NUMBER KEYS: if you hold down any number key when clicking Join Wait List, you will auto-join that number of tables.

PARTY_SEAT

This command will automatically get you seated and bought in when a reserved seat dialog pops up. Table will be moved to (x,y) screen coordinates, given in (VALUE3,VALUE4)

VALUE1 = Percent to buy in with (of the default amount shown in the buy-in dialog).

VALUE2 = Choose if you should sit out (1) or not (0) when you are seated.

PARTY_HH

Hand History window will be moved to (VALUE1,VALUE2), resized to max height, and last hand will be selected.

PARTY_CODE

Code Verification window will be moved to (VALUE1,VALUE2), and (VALUE3) number of sounds, with duration (VALUE4) and frequency (VALUE5) will be played as a reminder.

Troubleshooting

If things don't seem to work, restart the script from the system tray.

The waitlist function at Partypoker can at times be less reliable, which might affect Window Guard (WG).

Join Wait List button can get stuck in "Unjoin this table" mode, or other strange things can happen; for instance, when opening a table from the reserved seat dialog, the window will disappear. In these cases, WG Auto/Repeat functions will stop. Close all open dialogs and start over again by clicking Join button.

When taking a seat and sitting out (clicking Deal Me Out checkbox), Partypoker client can at times be slow to update the sitout status to their servers. In these cases a Sit Out button may still popup. Either click it yourself, or let the short timer run out to sitout.

Sample Settings File

: Save this in a file named "WindowGuard.ini" in the same folder as the script.
: All lines starting with a colon, left parenthes or the text "REM", are comments.
: By default, some lines may be comments, so you have to un-comment them to enable a specific setting.
: See web page for details of specific settings.


: Close a bunch of annoying Partypoker dialogs.

        CLOSE;          1;      #32770;         PartyPoker.com;         Additional chips;
        CLOSE;          1;      #32770;         PartyPoker.com;         You can have maximum;
        CLOSE;          1;      #32770;         PartyPoker.com;         You can bring a maximum;
        CLOSE;          1;      #32770;         PartyPoker.com;         You may select;
        CLOSE;          1;      #32770;         PartyPoker.com;         You have been picked up from the table;

: Move Statistics window to rightmost position on monitor 2.

REM     MOVE;           1;      #32770;         Statistics;             Reset Stats;                    2967;   0;

: Click NO button when asked if I really want to fold a hand.

REM     BUTTON;         1;      #32770;         Confirm fold;           Are you sure;                   2;

: Auto-request hand history for Sit-n-Go.

REM     BUTTON;         1;      #32770;         Tournament Result;      summary;                        1;

: Move Partypoker Code Verification window to right side of monitor 2 and play a reminder sound.

REM     PARTY_CODE;     1;      #32770;         Code Verification;      ;                               2762;   814;    4;      100;   500;

: Automatically leave a Partypoker table when a modifier key is pressed down.

REM     PARTY_LEAVE;    1;      #32770;         ;                       Do you really want to stand-up and leave the table;     Shift;

: Automatically rebuy at Partypoker when a modifier key is pressed down.

REM     PARTY_REBUY;    1;      #32770;         Buy-In;                 Decide the amount;              Shift;  100;

: Move Partypoker Hand History window to rightmost position on monitor 2

REM     PARTY_HH;       1;      #32770;         HH;                     Click a hand;                   2713;   0;

: Automatically join one or more Partypoker waitlists.

REM     PARTY_WAITLIST; 1;      #32770;         Join Wait List;         First Available;                ;       Shift;  Control;        8;      5;

: Automatically get seated at a Partypoker table.

REM     PARTY_SEAT;     1;      #32770;         Seat Available;         A seat has been reserved;       100;    1;      2395;   0;

Script Code

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;   Code begins here   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;------------------------------------------------------------------------------------------------
;       Window Guard v0.16 
;------------------------------------------------------------------------------------------------
;       Date: 2006-05-23
;       AHK version: 1.0.44.01
;------------------------------------------------------------------------------------------------
;       Author(s): Adde @ 2+2 forums
;       Contact: HstreamPoker at gmail dot com
;------------------------------------------------------------------------------------------------
;       Customizable script to handle pop-up windows while playing poker.
;       See web page for more details.
;
;       http://overcards.com/wiki/moin.cgi/WindowGuard
;
;       All rights reserved. Use at your own risk.
;------------------------------------------------------------------------------------------------

;________________________________________________________________________________________________
;
;       EDIT THESE SETTINGS
;________________________________________________________________________________________________

; Once every interval below (in milliseconds), script will check for new windows/dialogs.
; Default value (200) should work, but if your processor gets overloaded you might try to
; increase to 400 or higher.

wg_timer_msecs = 150

;________________________________________________________________________________________________
;
;       DO NOT EDIT BELOW HERE
;________________________________________________________________________________________________

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;   auto-execute   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

#NoEnv
#SingleInstance Ignore
#Persistent

wg_scriptpad_command_header = Other Tools
wg_scriptpad_command_name = Disable Window Guard
wg_scriptpad_command_label = WG_EnableDisable_Label
wg_scriptpad_command_enabled = 1

ahk_version = 1.0.44.01
if A_AhkVersion < %ahk_version%
{
        msgbox, 4, , This script needs AutoHotkey version %ahk_version% or newer (you are using version %A_AhkVersion%). Script will exit`n`nGo to web page and download new version now?
        IfMsgBox, Yes
                Run, http://www.autohotkey.com
        ExitApp
} 

/*
wg_web_page = http://overcards.com/wiki/moin.cgi/WindowGuard
IfNotExist, PokerCodeLibrary.ahk
{
        msgbox, 4, , File "PokerCodeLibrary.ahk" is missing. This file is needed for the script to work.`nSee web page for more instructions. Script will exit.`n`nGo to web page now?
        IfMsgBox, Yes
                Run, %wg_web_page%
        ExitApp
} 
#Include PokerCodeLibrary.ahk
*/
        
IfNotExist, WindowGuard.ini
{
        msgbox, 4, , File "WindowGuard.ini" is missing. This file is needed for the script to work.`nSee web page for more instructions. Script will exit.`n`nGo to web page now?
        IfMsgBox, Yes
                Run, %ps_web_page%
        ExitApp
}

WG_InitData()

SetTimer, WG_Process_Label, %wg_timer_msecs%
        
goto WG_Scriptpad_End

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;   labels   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
WG_EnableDisable_Label:
        WG_EnableDisable()
return

WG_Process_Label:
        WG_Process()
return

WG_DisableJoinTables:
        wg_enable_join_tables := false
return

WG_EnableJoinTables:
        wg_enable_join_tables := true
return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;       

WG_InitData()
 {
        global
        local idx1, idx2, line, prefix, value           

        wg_pp_waitlist_repeat = 0
        wg_pp_waitlist_numof_tables = 0
        wg_pp_seat_pause = 0    
        wg_pp_max_tables = 10   
        wg_enabled = true
        wg_enable_join_tables = true
        wg_current_win_id =     
        wg_prefs_count := 0
        
        idx1 := 0
        Loop, read, WindowGuard.ini
        {
                line := A_LoopReadLine
                line = %line%
                StringMid, prefix, line, 1, 4
                StringUpper, prefix, prefix
                if (prefix = "REM ")
                        continue
                StringMid, prefix, line, 1, 1
                if (prefix = "(" or prefix = ":")
                        continue
                if InStr(A_LoopReadLine, ";")
                        idx1++
                idx2 := 0
                Loop, parse, A_LoopReadLine, ";"
                {
                        idx2 := a_index
                        value := A_LoopField
                        value = %value%
                        wg_prefs%idx1%%idx2% = %value%
                }
                if (idx2 > 0)
                        wg_prefs_count++
        }
} 

WG_EnableDisable()
{
        global
        if (wg_enabled)
        {
                wg_enabled := false
                wg_scriptpad_command_name = Enable Window Guard 
        }
        else
        {
                wg_enabled := true
                wg_scriptpad_command_name = Disable Window Guard
        }
        Soundbeep, , 50
}

WG_Process()
{
        global wg_enabled, wg_enable_join_tables, wg_prefs_count, wg_current_win_id
        global wg_action, wg_mode, wg_class, wg_title, wg_text
        global wg_value1, wg_value2, wg_value3, wg_value4, wg_value5
        global wg_pp_waitlist_repeat, wg_pp_waitlist_numof_tables, wg_pp_seat_pause, wg_pp_max_tables   
        
        if (NOT wg_enabled)
                return
        Loop, %wg_prefs_count%
        {
                idx := a_index          
                wg_action := wg_prefs%idx%1
                StringUpper, wg_action, wg_action               
                wg_mode := wg_prefs%idx%2
                wg_class := wg_prefs%idx%3
                wg_title := wg_prefs%idx%4
                wg_text := wg_prefs%idx%5
                wg_value1 := wg_prefs%idx%6
                wg_value2 := wg_prefs%idx%7
                wg_value3 := wg_prefs%idx%8
                wg_value4 := wg_prefs%idx%9
                wg_value5 := wg_prefs%idx%10            

                if (wg_mode <> "")
                        SetTitleMatchMode, %wg_mode%
                if (wg_class = "")
                        WinGet, idList, List, %wg_title% , %wg_text%
                else
                        WinGet, idList, List, %wg_title% ahk_class %wg_class% , %wg_text%                       
                        
                Loop, %idList%
                {
                        ;msgbox %wg_action% x %wg_mode% x %wg_class% x %wg_title% x %wg_text%
                        wg_current_win_id := idList%a_index%
                        IfWinNotExist, ahk_id %wg_current_win_id%
                                continue
                        if (wg_current_win_id = "")
                                continue                                        
                        if (wg_action = "CLOSE")
                                WG_Command_Close(wg_current_win_id)     
                        if (wg_action = "BUTTON")
                                WG_Command_Button(wg_current_win_id, wg_value1)         
                        if (wg_action = "MOVE")
                                WG_Command_Move(wg_current_win_id, wg_value1, wg_value2)                
                        if (wg_action = "PARTY_HH")
                                WG_Command_Party_HH(wg_current_win_id, wg_value1, wg_value2)
                        if (wg_action = "PARTY_CODE")
                                WG_Command_Party_Code(wg_current_win_id, wg_value1, wg_value2, wg_value3, wg_value5, wg_value4)                         
                        if (wg_action = "PARTY_LEAVE")
                                WG_Command_Party_Leave(wg_current_win_id, wg_value1)                            
                        if (wg_action = "PARTY_REBUY")
                                WG_Command_Party_Rebuy(wg_current_win_id, wg_value1, wg_value2)                         
                        if (wg_action = "PARTY_WAITLIST")
                                WG_Command_Party_Waitlist(wg_current_win_id, wg_value1, wg_value2, wg_value3, wg_value4, wg_value5)     
                        if (wg_action = "PARTY_SEAT")
                                WG_Command_Party_Seat(wg_current_win_id, wg_value1, wg_value2, wg_value3, wg_value4)    
                }
        }
}

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;    command functions    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

WG_Command_Close(winID)
{
        Lib_WG_WinCloseID(winID)
}
                                
WG_Command_Move(winID, x, y)
{
        if (x = "" or y = "")
                return
        WG_WinMoveID(winID, x, y)
}
                
WG_Command_Button(winID, name)
{
        if (name = "")
                return
        Lib_WG_WinActivateID(winID)                     
        ControlGet, result, Visible, , Button%name%, ahk_id %winID%
        if (result = false)
                return
        thisButton = Button%name%
        Lib_WG_ClickButton(winID, 3, thisButton)        
}
                
WG_Command_Party_Leave(winID, modkey)
{
        Lib_WG_SaveMousePosition()
        if (modkey <> "" and GetKeyState(modkey))
                goto WG_Command_Party_Leave_Do
        if (modkey <> "")
                return  
  WG_Command_Party_Leave_Do:
        Lib_WG_Partypoker_ClickLeaveTable(winID, false)
        Lib_WG_RestoreMousePosition()
}
                
WG_Command_Party_Rebuy(winID, modkey, buyinPct)
{
        global wg_enable_join_tables
        if (wg_enable_join_tables = false)
                return
        if (modkey <> "" and GetKeyState(modkey))
                goto WG_Command_Party_Rebuy_Do
        if (modkey <> "")
                return  
  WG_Command_Party_Rebuy_Do:  
        Lib_WG_Partypoker_ClickRebuy(winID, false, true, buyinPct)
}
                
WG_Command_Party_Code(winID, x, y, times, length, freq)
{
        if (x = "" or y = "")
                return
        if NOT WG_WinMoveID(winID, x, y)
                return
        Lib_WG_Beep(times, freq, length)
}

WG_Command_Party_HH(winID, x, y)
{
        if (x = "" or y = "")
                return
        if NOT WG_WinMoveID(winID, x, y)
                return                          
        ControlGet, result, Visible, , ListBox1, ahk_id %winID%
        if (result = false)
                return
        ControlFocus, ListBox1, ahk_id %winID%
        Send {UP}                       
        ControlGet, result, Visible, , RICHEDIT1, ahk_id %winID%
        if (result = false)
                return
        ControlFocus, RICHEDIT1, ahk_id %winID%
        Send {END}
}
 
WG_Command_Party_Waitlist(winID, modkeyNormal, modkeyAuto, modkeyRepeat, minPlayers, numofTables)
{
        global wg_enable_join_tables, wg_pp_waitlist_autoclick, wg_pp_waitlist_repeat, wg_pp_waitlist_numof_tables
        
        if (wg_enable_join_tables = false)
                return          
        if (wg_pp_waitlist_autoclick = true)
        {
                wg_pp_waitlist_autoclick := false
                goto WG_Command_Party_Waitlist_Auto             
        }                               
        i := 0          
        Loop, 10
        {       
                i++
                if (GetKeyState(i))
                {
                        numofTables := i
                        goto WG_Command_Party_Waitlist_Repeat                   
                }
        }       
        if (modkeyNormal <> "" and GetKeyState(modkeyNormal))
                goto WG_Command_Party_Waitlist_Normal
        if (modkeyAuto <> "" and GetKeyState(modkeyAuto))
                goto WG_Command_Party_Waitlist_Auto
        if (modkeyRepeat <> "" and GetKeyState(modkeyRepeat))
                goto WG_Command_Party_Waitlist_Repeat
                
        if (modkeyNormal = "")
                goto WG_Command_Party_Waitlist_Normal
        if (modkeyAuto = "")
                goto WG_Command_Party_Waitlist_Auto
        if (modkeyRepeat = "")
                goto WG_Command_Party_Waitlist_Repeat           
        ; else
                goto WG_Command_Party_Waitlist_Normal
                                
  WG_Command_Party_Waitlist_Normal:
        Lib_WG_WinWaitCloseID(winID, "")
        return 
  
  WG_Command_Party_Waitlist_Repeat:
        if (wg_pp_waitlist_repeat = false)
                wg_pp_waitlist_numof_tables := numofTables
        wg_pp_waitlist_repeat := true   
        
  WG_Command_Party_Waitlist_Auto:
        Lib_WG_WinActivateID(winID)     
        if (minPlayers > 0)
        {
                Lib_WG_ClickButton(winID, 3, "Button2")
                ControlGet, nlist , List , Count, ComboBox1 ,  ahk_id %winID%
                Loop, Parse, nlist, `n
                        maxPlayers = %A_LoopField%
                if (maxPlayers < minPlayers)
                        minPlayers := maxPlayers
                Control, Choose , %wminPlayers% , ComboBox1 ,  ahk_id %winID%
                Sleep , 100                             
        }       
        Lib_WG_ClickButton(winID, 3, "Button3")
        return
}

WG_Command_Party_Seat(winID, buyinPct, sitout, x, y)
{                       
        global wg_enable_join_tables, wg_pp_waitlist_repeat
        global wg_pp_waitlist_numof_tables, wg_pp_waitlist_autoclick
        
        if (wg_enable_join_tables = false)
                return
        result := WG_PP_Seat_Run(winID, buyinPct, sitout, x, y)
        if (result = 0)
                return
        if (result < 1)
                wg_pp_waitlist_repeat := false          
        if (wg_pp_waitlist_repeat)
        {
                if (wg_pp_waitlist_numof_tables > 1)
                {
                        wg_pp_waitlist_numof_tables--
                        wg_pp_waitlist_autoclick := true
                        Lib_WG_Partypoker_ClickJoinWaitlistButton()
                }
                if (wg_pp_waitlist_numof_tables <= 1)
                        wg_pp_waitlist_repeat := false
        }       
}                                        

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;    partypoker functions    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;       
                        
WG_PP_Seat_Run(winID, buyinPct, sitout, x, y) 
{
        global wg_pp_max_tables, wg_pp_seat_pause
        
        Lib_WG_WinActivateID(winID)     
        ;wingettitle, title, ahk_id %wg_current_win_id% 
        
        ct := Lib_WG_Partypoker_CountTables()   
        if (ct >= wg_pp_max_tables)
        {
                Lib_WG_Partypoker_CloseAllSeats()
                ;msgbox debug: max tables ct=%ct%
                return (-1)     
        }       
        
        if not Lib_WG_WinExistID(winID)
        {
                ;msgbox debug: win not exist
                return (0)
        }       
        
        if (A_Now < wg_pp_seat_pause)
        {
                Lib_WG_Partypoker_CheckMaxTablesDialog(true)
                Lib_WG_Partypoker_CloseAllSeats()
                ;msgbox debug: paus triggered
                return (-1)             
        }               
        
        tableID := Lib_WG_Partypoker_JoinFirstAvailableSeat(temp, "")   
        if Lib_WG_Partypoker_CheckMaxTablesDialog(true)
                goto WG_PP_Seat_Run_Error       
        if (tableID = "")
                return (0)              
        result := WG_WinMoveID(tableID, x, y)           
        result := Lib_WG_Partypoker_TakeFirstAvailableSeat(tableID)     
        if (result = 1)
                result := Lib_WG_Partypoker_ClickRebuy("", false, true, buyinPct)
        if (result = 1 and sitout = 1)
        {
                result := Lib_WG_ClickCheckbox(tableID, 3, "Button5", true)
                sleep, 100
                result := Lib_WG_ClickButton(tableID, 3, "AfxWnd4218", false)
        }                               
        Lib_WG_Partypoker_CloseAllSeats()               
        if Lib_WG_Partypoker_CheckMaxTablesDialog(true)
                goto WG_PP_Seat_Run_Error       
        return (1)
        
  WG_PP_Seat_Run_Error: 
        ;msgbox debug: seat error       title=%title%
        Lib_WG_Partypoker_CheckMaxTablesDialog(true)
        Lib_WG_Partypoker_CloseAllSeats()       
        wg_pp_seat_pause := Lib_WG_CreateStopTimer(10)
        return (-1) 
}

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;   helpers   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

WG_WinMoveID(winID, x, y, w="", h="", timeoutSeconds=0)
{
        stopTimer := Lib_WG_CreateStopTimer(timeoutSeconds)                
        isMoved := false
        Loop
        {
                WinGetPos, x0, y0, w0, h0, ahk_id %winID%
                if (x0 = x AND y0 = y)
                {
                        isMoved := false
                        break
                }
                WinMove, ahk_id %winID%, , x, y, w, h
                Sleep, 25
                if (A_Now > stopTimer)
                        break           
        }
        return (isMoved)
}

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  library (partypoker)  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Lib_WG_Partypoker_Open(path, login=true, x="", y="", timeoutSeconds=20, silentMode=false)
{
        Process, Exist, PartyGaming.exe
        if (ErrorLevel <> 0)
                return (true)
        IfNotExist, %path%
                return (false)
        Run, %path% -P=PartyPoker
        winID := Lib_WG_Partypoker_GetLobbyWinID(timeoutSeconds)
        if (winID = "")
        {
                if (silentMode = false)
                        msgbox "Can't open connection to PartyPoker."
                return (false)
        }       
        if (x <> "" and y <> "")
                Lib_WG_WinMoveID(winID, x, y, "", "", 5)           
        winLoginID := Lib_WG_WinGetID(1, "PartyAccount Login", "", "#32770", timeoutSeconds)
        if (winLoginID = "")
        {
                if (silentMode = false)
                        msgbox "Can't find PartyPoker login window."
                return (false)
        }
        result := Lib_WG_WinCloseID(winLoginID)            
        if (login = true)       
        {
                WinActivate, ahk_id %winID%
                Lib_WG_ClickButton(winID, 1, "Button3")    
        }       
        return (true)
}

Lib_WG_Partypoker_Close()
{
        Process, Close, PartyGaming.exe
        return (true)
}

Lib_WG_Partypoker_ShowLobby()
{
        winID := Lib_WG_Partypoker_GetLobbyWinID()
        if (winID = "")
                return (false)
        WinActivate, ahk_id %winID%
        return (true)
}

Lib_WG_Partypoker_HideLobby()
{
        winID := Lib_WG_Partypoker_GetLobbyWinID()
        if (winID = "")
                return (false)
        WinMinimize, ahk_id %winID%
        return (true)
}

Lib_WG_Partypoker_GetLobbyWinID(timeoutSeconds=5)
{
        winID := Lib_WG_WinGetID(1, "PartyPoker.com: Poker Lobby", "", "#32770", timeoutSeconds)
        return (winID)
}

Lib_WG_Partypoker_ToggleBuddyList(hideLobby=true, x="", y="", timeoutSeconds=5)
{
        winID := Lib_WG_WinGetID(3, "Buddy List", "", "#32770")
        if (winID = "")
                result := Lib_WG_Partypoker_OpenBuddyList(timeoutSeconds, x, y, timeoutSeconds)
        else
                result := Lib_WG_Partypoker_CloseBuddyList(hideLobby, timeoutSeconds)
        return (result)
}

Lib_WG_Partypoker_OpenBuddyList(hideLobby=true, x="", y="", timeoutSeconds=5)
{       
        winID := Lib_WG_Partypoker_GetLobbyWinID(timeoutSeconds)
        if (winID = "")
                return (false)  
        WinActivate, ahk_id %winID%             
        PostMessage, 0x111, 3084, 0, , ahk_id %winID%
        if (ErrorLevel = 1)
                return (false)
        if (x <> "" and y <> "")
        {
                winID := Lib_WG_WinGetID(3, "Buddy List", "", "#32770", timeoutSeconds)
                if (winID <> "")
                        Lib_WG_WinMoveID(winID, x, y)
        }
        ;if (hideLobby)
        ;       Lib_WG_Partypoker_HideLobby()
        return (true)
}

Lib_WG_Partypoker_CloseBuddyList(hideLobby=true, timeoutSeconds=5)
{
        winID := Lib_WG_WinGetID(3, "Buddy List", "", "#32770")
        if (winID = "")
                return (true)
        result := Lib_WG_WinCloseID(winID, timeoutSeconds)
        if (hideLobby)
                Lib_WG_Partypoker_HideLobby()
        return (result)
}

Lib_WG_Partypoker_ToggleCashier(hideLobby=true, x="", y="", timeoutSeconds=5)
{
        winID := Lib_WG_WinGetID(3, "PartyPoker.com", "", "#32770")
        if (winID = "")
                result := Lib_WG_Partypoker_OpenCashier(hideLobby, x, y, timeoutSeconds)
        else
                result := Lib_WG_Partypoker_CloseCashier(hideLobby, timeoutSeconds)
        return (result)
}

Lib_WG_Partypoker_OpenCashier(hideLobby=true, x="", y="", timeoutSeconds=5)
{
        winID := Lib_WG_Partypoker_GetLobbyWinID(timeoutSeconds)
        if (winID = "")
                return (false)
        result := Lib_WG_ClickButton(winID, 1, "AfxWnd427")
        if (hideLobby)
                Lib_WG_Partypoker_HideLobby()
        if (result = true and x <> "" and y <> "")
        {
                winID := Lib_WG_WinGetID(3, "PartyPoker.com", "", "#32770", timeoutSeconds)
                if (winID = "")
                        return (false)
                if (winID <> "")
                {
                        Lib_WG_WinMoveID(winID, x, y)
                        Loop
                        {
                                WinGetPos, x2, y2, , , ahk_id %winID%
                                if (x2 <> x and y2 <> y)
                                {
                                        Lib_WG_WinMoveID(winID, x, y)                                      
                                        break
                                }
                        }
                }
        }
        return (result)
}

Lib_WG_Partypoker_CloseCashier(hideLobby=true, timeoutSeconds=5)
{
        winID := Lib_WG_WinGetID(3, "PartyPoker.com", "", "#32770")
        if (winID = "")
                return (false)
        result := Lib_WG_WinCloseID(winID, timeoutSeconds)
        return (result)
}

Lib_WG_Partypoker_ToggleStatistics(tableID, x="", y="", timeoutSeconds=5)
{
        winID := Lib_WG_WinGetID(3, "Statistics", "", "#32770")
        if (winID = "")
                result := Lib_WG_Partypoker_OpenStatistics(tableID, x, y, timeoutSeconds)
        else
                result := Lib_WG_Partypoker_CloseStatistics(timeoutSeconds)
        return (result)
}

Lib_WG_Partypoker_OpenStatistics(tableID, x="", y="", timeoutSeconds=5)
{
        if (tableID = "")
                return (false)          
        PostMessage, 0x111, 1016, 0, , ahk_id %tableID%
        if (ErrorLevel = 1)
                return (false)
        if (x <> "" and y <> "")
        {
                winID := Lib_WG_WinGetID(3, "Statistics", "", "#32770", timeoutSeconds)
                if (winID <> "")
                        Lib_WG_WinMoveID(winID, x, y, "", "", timeoutSeconds)
        }
        return (true)
}

Lib_WG_Partypoker_CloseStatistics(timeoutSeconds=5)
{
        winID := Lib_WG_WinGetID(3, "Statistics", "", "#32770")
        if (winID = "")
                return (false)
        result := Lib_WG_WinCloseID(winID, timeoutSeconds)
        return (result)
}

Lib_WG_Partypoker_TogglePlayerSearch(hideLobby=true, x="", y="", timeoutSeconds=5)
{
        winID := Lib_WG_WinGetID(1, "Search your selected players", "", "#32770")
        if (winID = "")
                result := Lib_WG_Partypoker_OpenPlayerSearch(hideLobby, x, y, timeoutSeconds)
        else
                result := Lib_WG_Partypoker_ClosePlayerSearch(hideLobby, timeoutSeconds)
        return (result)
}

Lib_WG_Partypoker_OpenPlayerSearch(hideLobby=true, x="", y="", timeoutSeconds=5)
{
        winID := Lib_WG_Partypoker_GetLobbyWinID(timeoutSeconds)
        if (winID = "")
                return (false)  
        WinActivate, ahk_id %winID%             
        PostMessage, 0x111, 3082, 0, , ahk_id %winID%
        if (ErrorLevel = 1)
                return (false)
        if (x <> "" and y <> "")
        {
                winID := Lib_WG_WinGetID(1, "Search your selected players", "", "#32770", timeoutSeconds)
                if (winID <> "")
                        Lib_WG_WinMoveID(winID, x, y, "", "", timeoutSeconds)
        }
        return (true)
}

Lib_WG_Partypoker_ClosePlayerSearch(hideLobby=true, timeoutSeconds=5)
{
        winID := Lib_WG_WinGetID(1, "Search your selected players", "", "#32770")
        if (winID = "")
                return (false)
        result := Lib_WG_WinCloseID(winID, timeoutSeconds)
        if (hideLobby)
                Lib_WG_Partypoker_HideLobby()
        return (result)
}

Lib_WG_Partypoker_NavigateToGameHome()
{
        winID := Lib_WG_Partypoker_GetLobbyWinID()
        if (winID = "")
                return (false)
        winactivate, ahk_id %winID%    
        ControlFocus, SysTreeView321, ahk_id %winID%    
        ControlClick, SysTreeView321, ahk_id %winID%    
        ControlClick, SysTreeView321, ahk_id %winID%    
        ControlClick, SysTreeView321, ahk_id %winID%    
        ControlClick, SysTreeView321, ahk_id %winID%            
        send {HOME}
        sleep, 300 
                return (true)
}

Lib_WG_Partypoker_NavigateToGame(gameType, gameBlinds, seats)
{
        winID := Lib_WG_Partypoker_GetLobbyWinID()
        if (winID = "")
                return (false)
        winactivate, ahk_id %winID%     
        
        ControlFocus, SysTreeView321, ahk_id %winID%    
        ControlClick, SysTreeView321, ahk_id %winID%    
        ControlClick, SysTreeView321, ahk_id %winID%    
        ControlClick, SysTreeView321, ahk_id %winID%    
        ControlClick, SysTreeView321, ahk_id %winID%            
        send {HOME}
        sleep, 300
        
        ControlFocus, SysTreeView321, ahk_id %winID%    
        if (gameType <> "Limit Hold'em")
        {
                send %gameType%
                sleep, 300
        }
                
        ControlFocus, SysTreeView321, ahk_id %winID%            
        IfInString, gameType, Pot-Limit Omaha
        {
                sleep, 300
                send %gameType%
                sleep, 300      
        }
        
        ControlFocus, SysTreeView321, ahk_id %winID%            
        send {right}
        sleep, 300
        send {right}
        sleep, 300

        Loop, 20
        {
                Loop
                {
                        ControlGet, result, List, , SysListView321, ahk_id %winID%
                                                IfInString, result, $
                                break
                        sleep, 50
                }
                IfInString, result, %gameBlinds%
                        break
                send {DOWN}
                sleep, 10
        }
        IfNotInString, result, %gameBlinds%
                return (false)
                        
        seatsToken1 = /%seats%  
        seatsToken2 = %seats%/%seats%   
        ControlGet, result, List, , SysListView321, ahk_id %winID%      
        Loop, parse, result, `n, `r
        {
                row := a_loopfield              
                IfInString, row, %seatsToken1%
                {
                        Loop, parse, row, %A_Tab%
                        {                       
                                col := a_loopfield
                                if (a_index = 1)
                                        firstCol := col
                                IfNotInString, col, %seatsToken1%
                                        continue
                                StringReplace, pl, col, %seatsToken1%, ,
                                if (pl > 0)
                                {
                                        tablename := firstCol
                                        break
                                }                               
                        }
                }       
                if (tablename <> "")
                        break                   
                /*
                IfInString, row, %seatsToken2%
                {
                        pos := InStr(row, "`t")
                        if (pos < 1)
                                continue
                        StringLeft, tableName, row, pos-1
                        break           
                }
                */      
        }
        if (tablename = "")
                return (false)
        ControlFocus, SysListView321, ahk_id %winID%    
        ControlClick, SysListView321, ahk_id %winID%            
        send %tablename%
        sleep, 200
        
        return (true)           
} 

Lib_WG_Partypoker_JoinOneTable(gameType, gameBlinds, seats, minPlayers, buyinPercent, sitout, x="", y="")
{
        if (gameType <> "")
        {
                result := Lib_WG_Partypoker_NavigateToGame(gameType, gameBlinds, seats)
                if (result = false)
                        return (-1)
        }       
        result := Lib_WG_Partypoker_ClickJoinWaitlistButton()
        if (result = false)
                return (-1)             
        winID := Lib_WG_WinGetID(1,"Join Wait List", "First Available", "#32770", "")
        if (winID = "")
                return (-1)             
        if (minPlayers > 0)
        {
                Lib_WG_ClickButton(winID, 3, "Button2")
                ControlGet, nlist , List , Count, ComboBox1 ,  ahk_id %winID%
                Loop, Parse, nlist, `n
                        maxPlayers = %A_LoopField%
                if (maxPlayers < minPlayers)
                        minPlayers := maxPlayers
                Control, Choose , %minPlayers% , ComboBox1 ,  ahk_id %winID%
                Sleep , 100                             
        }       
        Lib_WG_ClickButton(winID, 3, "Button3")            
        Lib_WG_WinWait(1, "Seat Available", "A seat has been reserved for you on", "#32770")
        tableID := Lib_WG_Partypoker_JoinFirstAvailableSeat(temp, "")      
        if Lib_WG_Partypoker_CheckMaxTablesDialog(true)
        {
                sleep, 1000
                Lib_WG_Partypoker_CloseAllSeats()  
                return (2)
        }               
        if (tableID = "")
                return (0)              
        Lib_WG_WinMoveID(tableID, x, y)            
        result := Lib_WG_Partypoker_TakeFirstAvailableSeat(tableID)
        if (result = false)
                return (0)
        result := Lib_WG_Partypoker_ClickRebuy("", false, true, buyinPercent)
        if (result = false)
                return (0)              
        if (sitout = 1)
        {
                result := Lib_WG_ClickCheckbox(tableID, 3, "Button5", true)
                sleep, 100
                result := Lib_WG_ClickButton(tableID, 3, "AfxWnd4218", false)
        }                               
        Lib_WG_Partypoker_CloseAllSeats()          
        if Lib_WG_Partypoker_CheckMaxTablesDialog(true)
                return (2)      
        return (1)
}
 
Lib_WG_Partypoker_ClickJoinWaitlistButton(timeoutSeconds=5, reactivateList=true)
{
        winID := Lib_WG_Partypoker_GetLobbyWinID(timeoutSeconds)
        if (winID = "")
                        return (false)
        ControlGet, result, List, Count Focused, SysListView321, ahk_id %winID%
        ControlFocus, SysListView321, ahk_id %winID%
                if (reactivateList)
                {
                        if (result > 1)
                        {
                                Send {UP}
                                sleep, 100
                                Send {DOWN}
                                sleep, 100      
                        }
                        else
                        {
                Send {DOWN}
                sleep, 100
                Send {UP}
                sleep, 100              
                        }
        }
        stopTimer := Lib_WG_CreateStopTimer(timeoutSeconds)
        Loop
        {
                ;ControlFocus, "AfxWnd4215", ahk_id %winID%
                Lib_WG_ClickButton(winID, 1, "AfxWnd4215")
                result := Lib_WG_WinWait(1,"Join Wait List", "First Available", "#32770", 1)
                if (result = true)
                        break
                if (A_Now > stopTimer)
                        return (false)
        }
        return (true)
}

Lib_WG_Partypoker_TakeFirstAvailableSeat(tableID, closeOnFailure=true)  
{
        ControlGet, result, Visible, , Button5, ahk_id %tableID%
        if (result = true)
                return (false)
    matchList  = 3|3|3|3|3|3|3|3|3|3
    stringList = AfxWnd424|AfxWnd425|AfxWnd426|AfxWnd427|AfxWnd428|AfxWnd429|AfxWnd4210|AfxWnd4211|AfxWnd4212|AfxWnd4213
        result := Lib_WG_ClickButtonList(tableID, matchList, stringList)
        if (result = FALSE and closeOnFailure)
                WinClose, ahk_id %tableID%
        return (result) 
}

Lib_WG_Partypoker_JoinFirstAvailableSeat(byref tableName, errorTables, timeoutSeconds=5)
{
        SetTitleMatchMode, 1
        WinGet, winID, IDLast, Seat Available ahk_class #32770, A seat has been reserved for you on  
        if (winID = "")
                return ("")
                
        WinGetText, winText, ahk_id %winID%
        tablename := Lib_WG_Partypoker_GetTablenameFromSeat(winText)
        token = xxx%tableName%xxx
        if InStr(errorTables, token)
        {
                        Lib_WG_ClickButton(winID, 3, "Button2")  
                        return ("")
        }
        Lib_WG_ClickButton(winID, 3, "Button1")    
        stopTimer := Lib_WG_CreateStopTimer(timeoutSeconds)
        loop
        {
                if Lib_WG_Partypoker_CheckMaxTablesDialog()
                        return ("")
                SetTitleMatchMode, 1
                IfWinExist, %tablename% ahk_class #32770
                        break
                if (A_Now > stopTimer)
                        break
        }
        winID := Lib_WG_WinGetID(1, tablename, "", "#32770")
        return (winID)
}

Lib_WG_Partypoker_CloseAllSeats()
{
        Lib_WG_Partypoker_ShowLobby()      
        SetTitleMatchMode, 1
        WinGet, idLIst, List, Seat Available ahk_class #32770, A seat has been reserved for you on
        Loop, %idList%
                Lib_WG_ClickButton(idList%a_index%, 3, "Button2")  
        return (true)
}       

Lib_WG_Partypoker_CheckMaxTablesDialog(close=false)  
{
        SetTitleMatchMode, 1
        IfWinExist, PartyPoker.com ahk_class #32770, If you would like to open a new table
        {
                if (close)
                        WinClose, PartyPoker.com ahk_class #32770, If you would like to open a new table
                return (true)
        }
        return (false)
}

Lib_WG_Partypoker_GetTablenameFromSeat(seatText)  
{
        str := seatText
        token := "A seat has been reserved for you on"  
        StringLen, len, token 
        StringMid, str, str, len+2, 9999
        StringGetPos, pos, str, (
        StringMid, str, str, 1, pos
        return (str)
}       

Lib_WG_Partypoker_CloseTables()
{
    SetTitleMatchMode, 2
    WinGet, pid, PID, PartyPoker.com:
    WinGet, idList, List, Good Luck ahk_pid%pid% ahk_class #32770,  , PartyPoker.com:
        Loop, %idList% 
        {
                id := idList%a_index%
                WinClose , ahk_id %id%
        }
    return (true)
}

Lib_WG_Partypoker_CountTables()
{
    SetTitleMatchMode, 2
    WinGet, pid, PID, PartyPoker.com:
    WinGet, idList, List, Good Luck ahk_pid%pid% ahk_class #32770,  , PartyPoker.com:
    return (idList)
}

Lib_WG_Partypoker_ClickLeaveTable(tableID, clickButton=true, timeoutSeconds=5)
{
        if (clickButton)
        {
                Lib_WG_ClickButton(tableID, 3, "AfxWnd423")
                sleep, 100
        }       
        if NOT Lib_WG_WinExistID(tableID)
                return (true)                   
        Loop, %timeoutSeconds%
        {
                result := Lib_WG_WinWait(1, "", "Do you really want to stand-up and leave the table", "#32770", 1)
                if (result = true)
                        break
                if NOT Lib_WG_WinExistID(tableID)
                        return (true)
        }                               
        winID := Lib_WG_WinGetID(1, "", "Do you really want to stand-up and leave the table", "#32770")
        if (winID = "")
                return (true)   
        Lib_WG_ClickButton(winID, 3, "Button1")    
        result := Lib_WG_WinWaitCloseID(winID, timeoutSeconds)
        return (result)
}

Lib_WG_Partypoker_ClickRebuy(tableID, clickButton=true, checkDialogs=false, buyinPercent=100, timeoutSeconds=5)
{
        if (clickButton)
        {
                Lib_WG_ClickButton(tableID, 3, "AfxWnd421")
                sleep, 100
        }               
        if (checkDialogs)
        {
                if Lib_WG_WinExist(1, "PartyPoker.com", "You can have maximum", "#32770")
                {
                        Lib_WG_WinClose(1, "PartyPoker.com", "You can have maximum", "#32770")
                        return (false)
                }
        }               
        winID := Lib_WG_WinGetID(1, "Buy-In", "Decide the amount", "#32770", timeoutSeconds)                       
        if (winID = "")
                return (false)  
        if (buyinPercent = "" or buyinPercent = 0)
                buyinPercent := 100     
        if (buyinPercent <> 100)
        {
                ControlGetText , amount, Edit1, ahk_id %winID%
                amount := Round(amount * (buyinPercent / 100) , 1)
                ControlSetText , Edit1, %amount%, ahk_id %winID%
        }       
        result := Lib_WG_ClickButton(winID, 3, "Button1")
        if (result = false)
        {
                WinClose, ahk_id %winID%
                return (false)
        }               
        sleep, 100      
        if (checkDialogs)
        {
                dialogs = Please enter an amount|You can bring a maximum|You do not have sufficient funds|The Minimum Buy-in required to sit at this table
                StringSplit, dialogs, dialogs, |,
                Loop, %dialogs0%
                {
                        thisDialog := dialogs%a_index%  
                        if Lib_WG_WinExist(1, "PartyPoker.com", thisDialog, "#32770")
                        {
                                Lib_WG_WinClose(1, "PartyPoker.com", thisDialog, "#32770")
                                Lib_WG_WinCloseID(winID)
                                return (false)
                        }
                }
        }       
        if NOT Lib_WG_WinWaitCloseID(winID, timeoutSeconds)
                return (false)                                  
        if (checkDialogs)
        {
                sleep, 100
                if Lib_WG_WinExist(1, "PartyPoker.com", "Additional chips", "#32770")
                        Lib_WG_WinClose(1, "PartyPoker.com", "Additional chips", "#32770")
        }               
        return (true)
}

Lib_WG_Partypoker_PostChatMessage(tableID, message)
{       
        ControlSendRaw, Edit1, %message%, ahk_id %tableID%
        sleep, 1200
        ;ControlSend, Edit1, {Enter}, ahk_id %tableID%
        ControlClick, Edit1, ahk_id %tableID%
        controlgetpos, x, y, w, h, Edit1, ahk_id %tableID%
        mouseclick, left, x, y
        sleep, 1200
        SendInput {enter}
        return (ErrorLevel = 0)
}

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  library (general)  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Lib_WG_WinActivateID(winID)
{
        WinActivate, ahk_id %winID%
}

Lib_WG_WinExist(matchMode, title, text, class="", titleEx="", textEx="")
{
        SetTitleMatchMode, %matchMode%
        if (class <> "")
        {
                IfWinExist, %title% ahk_class %class%, %text%, %titleEx%, %textEx%
                        return (true)
                else
                        return (false)  
        }
        else
        {
                IfWinExist, %title%, %text%, %titleEx%, %textEx%
                        return (true)
                else
                        return (false)  
        }
}

Lib_WG_WinExistID(winID)
{
        IfWinExist, ahk_id %winID%
                return (true)
        else
                return (false)  
}

Lib_WG_WinClose(matchMode, title, text, class="", timeoutSeconds=5, titleEx="", textEx="")
{
        SetTitleMatchMode, %matchMode%
        if (class <> "")
                WinClose, %title% ahk_class %class%, %text%, %titleEx%, %textEx%
        else
                WinClose, %title%, %text%, %titleEx%, %textEx%
        result := Lib_WG_WinWaitClose(matchMode, title, text, class, timeoutSeconds, titleEx, textEx)
        return (result)
}

Lib_WG_WinCloseID(winID, timeoutSeconds=5)
{
        WinClose, ahk_id %winID%        
        result := Lib_WG_WinWaitCloseID(winID, timeoutSeconds)
        return (result)
}

Lib_WG_WinWait(matchMode, title, text, class="", timeoutSeconds="", titleEx="", textEx="")
{
        SetTitleMatchMode, %matchMode%
        if (class <> "")
                WinWait, %title% ahk_class %class%, %text%, %timeoutSeconds%, %titleEx%, %textEx%
        else
                WinWait, %title%, %text%, %timeoutSeconds%, %titleEx%, %textEx%
        return (ErrorLevel = 0)
}

Lib_WG_WinWaitClose(matchMode, title, text, class="", timeoutSeconds="", titleEx="", textEx="")
{
        SetTitleMatchMode, %matchMode%
        if (class <> "")
                WinWaitClose, %title% ahk_class %class%, %text%, %timeoutSeconds%, %titleEx%, %textEx%
        else
                WinWaitClose, %title%, %text%, %timeoutSeconds%, %titleEx%, %textEx%
        return (ErrorLevel = 0)
}

Lib_WG_WinWaitCloseID(winID, timeoutSeconds="")
{       
        WinWaitClose, ahk_id %winID%, , %timeoutSeconds%
        if (ErrorLevel = 1)
                return (false)
        else
                return (true)
}

Lib_WG_WinMoveID(winID, x, y, w="", h="", timeoutSeconds=0)
{
        stopTimer := Lib_WG_CreateStopTimer(timeoutSeconds)                
        isMoved := false
        Loop
        {
                WinGetPos, x0, y0, w0, h0, ahk_id %winID%
                if (x0 = x AND y0 = y)
                {
                        isMoved := true
                        break
                }
                WinMove, ahk_id %winID%, , x, y, w, h
                Sleep, 25
                if (A_Now > stopTimer)
                        break           
        }
        return (isMoved)
}

Lib_WG_WinGetID(matchMode, title, text, class="", timeoutSeconds=0, titleEx="", textEx="")
{
        SetTitleMatchMode, %matchMode%
        stopTimer := Lib_WG_CreateStopTimer(timeoutSeconds)        
        winID := ""
        Loop
        {
                if (winID = "")
                        if (class <> "")
                                WinGet, winID, ID, %title% ahk_class %class%, %text%, %titleEx%, %textEx%
                        else
                                WinGet, winID, ID, %title%, %text%, %titleEx%, %textEx%
                else
                        break
                if (A_Now > stopTimer)
                        break
                sleep, 100
        }
        return (winID)
}

Lib_WG_ClickButton(winID, matchMode, buttonName, clickByKey="")
{       
        if (clickByKey = "")
        {
                StringUpper, str, buttonName
                StringLeft, str, str, 6
                if (str = "BUTTON")
                        clickByKey := true
                else
                        clickByKey := false
        }
        SetTitleMatchMode, %matchMode%
        WinActivate, ahk_id %winID%     
        ControlGet, result, Visible, , %buttonName%, ahk_id %winID%
        if (result = false)
                return (false)
        if (clickByKey)
        {
                ControlFocus, %buttonName%, ahk_id %winID%
                Send {SPACE}
        }
        else
                ControlClick, %buttonName%, ahk_id %winID%
        return (ErrorLevel = 0)
}

Lib_WG_ClickButtonList(winID, matchList, buttonList, clickByKey=false)
{
        StringSplit, buttonList, buttonList, |
        StringSplit, matchList, matchList, |    
        Loop, %buttonList0%
        {
                thisButton := buttonList%a_index%
                thisMatch := matchList%a_index%         
                SetTitleMatchMode, %thisMatch%
                ControlGet, result1, Visible, , %thisButton%, ahk_id %winID%
                ControlGet, result2, Enabled, , %thisButton%, ahk_id %winID%
                If (result1 AND result2)
                {
                        if (clickByKey)
                        {
                                ControlFocus, %thisButton%, ahk_id %winID%
                                Send {SPACE}
                        }
                        else
                                ControlClick, %thisButton%, ahk_id %winID%
                return (ErrorLevel = 0)
                }
        }
        return (false)
} 

Lib_WG_ClickCheckbox(winID, matchMode, checkboxName, checked, timeoutSeconds=5)
{
        stopTimer := Lib_WG_CreateStopTimer(timeoutSeconds)        
        SetTitleMatchMode, %matchMode%
        Loop
        {
                ControlGet, result, Visible, , %checkboxName%, ahk_id %winID%
                if (result = true)
                        break
                sleep, 50
                if (A_Now > stopTimer)
                        break
        }
        if (result = false)
                return (false)          
        stopTimer := Lib_WG_CreateStopTimer(timeoutSeconds)
        WinActivate, ahk_id %winID%     
        ControlGet, result, Checked, , %checkboxName%, ahk_id %winID%
        if (result = checked)
                return (true)   
        Loop  {
                if (checked)            
                        Control, Check, , %checkboxName%, ahk_id %winID%
                else
                        Control, Uncheck, , %checkboxName%, ahk_id %winID%
                sleep, 50
                ControlGet, result, Checked, , %checkboxName%, ahk_id %winID%
                if (result = checked)
                        return (true)                   
                if (A_Now > stopTimer)
                        break
        }
        return (false)
}

Lib_WG_CreateStopTimer(seconds)
{
        stopTime := A_Now
        EnvAdd, stopTime, %seconds%, seconds
        return (stopTime)
}

Lib_WG_SaveMousePosition()
{
        global Lib_WG_mouse_pos_x, Lib_WG_mouse_pos_y
        CoordMode, Mouse, Screen
        MouseGetPos, Lib_WG_mouse_pos_x, Lib_WG_mouse_pos_y
        CoordMode, Mouse, Relative
}

Lib_WG_RestoreMousePosition()
{
        global Lib_WG_mouse_pos_x, Lib_WG_mouse_pos_y
        CoordMode, Mouse, Screen
        MouseMove, Lib_WG_mouse_pos_x, Lib_WG_mouse_pos_y, 0
        CoordMode, Mouse, Relative
}       
        
Lib_WG_LongestListItem(list)
{
        longest = 0
        Loop, Parse, list, |
        {
                If (longest < StrLen(A_LoopField))
                {
                        longest := StrLen(A_loopfield)
                }
        }
        return (longest)
}       

Lib_WG_Beep(tim