AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

SteamLab 0.8.3.1 a - Take control of Steam!
Goto page 1, 2, 3, 4, 5, 6, 7  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
bmcclure



Joined: 24 Nov 2007
Posts: 446

PostPosted: Wed Dec 05, 2007 4:08 am    Post subject: SteamLab 0.8.3.1 a - Take control of Steam! Reply with quote

SteamLab
Version: 0.8.3.1 a
Homepage: SteamLab Wiki
SteamLab.exe
-or-
SteamLab.zip - Includes full AHK code (new Lib.zip required, below)



This is a helper application I am writing for Steam. It is currently in an Alpha state, and if anyone else here loves Steam as much as I do, I'm hoping for some feedback on its usefulness and maybe some enhancement suggestions.

Notice: This script requires a number of non-standard functions be in the standard lib directory if you use the AHK version I will always post my latest Lib directory here when I release a new version of the script:
Lib.zip
The Exe version does not have this limitation.

Current Features:

-Completely matches Steam UI
-Most functions available on a custom dock attached to the Steam window
-Automates download/install of Steam (optionally GameShadow, CrosuS)
-Manages game updates (work in progress)
-Manages CD keys
-Manages script backups and Steam settings/shortcuts backups
-Auto-restores deleted Steam shortcuts files (never lose your games again!)
-Lock your Steam window (protect that VAC status!)
-Customizable hotkeys for Steam Dock and volume control (GUI to come!)

The Dock:

More screenshots in posts to follow

Instructions
For the Exe version, simple place it in a new directory, and it will extract all the required components when you run SteamLab.exe.

For the Zip version, unzip all of the contents (keeping the folders) into a new folder, and the rest will be extracted upon first run of SteamLab.ahk.

If you enjoy SteamLab, I suggest you remove Steam from your startup programs and add SteamLab instead (it will run Steam automatically)

See the following posts for a full list of current and planned features, known issues, and some of my custom functions and code.
_________________
-Ben

SteamLab
SteamLab Wiki

[Broken] - My industrial music [on GarageBand]


Last edited by bmcclure on Sun Jan 13, 2008 7:48 am; edited 11 times in total
Back to top
View user's profile Send private message
bmcclure



Joined: 24 Nov 2007
Posts: 446

PostPosted: Wed Dec 05, 2007 4:09 am    Post subject: SteamLab - Features Reply with quote

First and foremost, a special thanks to these developers for their wonderful functions, code bits, and forum assistance. Each of you has made this much simpler than it probably should be Smile
-majkinetor
-Titan
-Skan
-corrupt

Note: This script will install Steam when you run it, if it is not installed already. It will also optionally install GameShadow and CrosuS.

Current Features:
-Matches Steam's UI and window behavior
-An optional dock on the Steam window for common functions
-Lock the Steam window and require a password to open it
-Key Manager - manage all of your offline CD keys!
-Backup Manager - backup and restore script settings, keys, Steam settings, Non-Steam shortcuts, and more!
-OSD notifications with custom font

Default Hotkeys
-Shift+Home - Toggle Steam Dock
-Shift+PgUp - Increase Volume
-Shift+PgDn - Decrease Volume
-Shift+End - Toggle Mute
Note: Edit cfg/hotkeys.ini to change or remove the hotkeys.

Known Issues:
-Added: Dock buttons don't fit if you use the smaller Games List window in Steam
-Some XP machines display edges around the buttons, I cannot figure this out. It doesn't happen on Vista on my machine but it happens on my XP laptop.
-OSD attempts to color the font background like the window behind it, but with complex images this almost never works out and white jaggies can be seen around the OSD text.
-Auto-paste in the Key Manager is not implemented. No matter which option you select, the entire key will simply be copied to the clipboard.

Planned/In Development:
-Implement Key Manager auto-paste functions
-Screenshot Manager - A universal hotkey for taking screenshots in all games, and a custom GUI for managing them
-Full hotkeys - Customizable hotkeys to access all functions
-Mouse Gestures
-Custom backups
-Custom scheduler for backups, updates, and more
-Automatically set CPU affinity and thread priority for selected games
-Allow multiple SteamWin tabs on one gui window (current max is one tab)
_________________
-Ben

SteamLab
SteamLab Wiki

[Broken] - My industrial music [on GarageBand]


Last edited by bmcclure on Tue Dec 18, 2007 6:37 am; edited 13 times in total
Back to top
View user's profile Send private message
bmcclure



Joined: 24 Nov 2007
Posts: 446

PostPosted: Wed Dec 05, 2007 4:11 am    Post subject: SteamLab - Screenshots Reply with quote

Screenshots

Steam Dock:



Tray Menu:


Settings:


Key Manager:



Backup Manager:

_________________
-Ben

SteamLab
SteamLab Wiki

[Broken] - My industrial music [on GarageBand]


Last edited by bmcclure on Tue Dec 11, 2007 3:54 am; edited 1 time in total
Back to top
View user's profile Send private message
bmcclure



Joined: 24 Nov 2007
Posts: 446

PostPosted: Wed Dec 05, 2007 4:16 am    Post subject: SteamLab - Code and Functions Reply with quote

This is where I will post some of my custom code and functions for reference, and hopefully to get enhancement suggestions.

Note: I am constantly adding comments to this code, and will add the comments here as I create them.

SteamWin() - Updated 12/16/2007
Functions for creating custom Steam-like windows and window controls
(Note: See the Gui code for examples)
Code:
; These functions will attempt to make your GUIs match Steam's default UI
; Requires: AddGraphicButton(), AHKArray

SW_Create(pTitle,pWidth,pHeight,pGuiNum="",pImgDir="") {
; This will create the controls for a window with a fake titlebar and Steam's colors. This will NOT show the window.
; Parameters:
;   pTitle: The window's title
;   pWidth/pHeight: The window's dimensions in px
;   pGuiNum: The window's Gui Num (should not already exist, defaults to script's current default)
;   pImgDir: The directory containing the subdirectories of bitmaps ("res\gui" if not specified)
; Returns:
;   0 if the command failed, or the SteamWin (The number of this window for use in other SteamWin functions)
; Example: thisSteamWin := SW_Create("Title",640,480,15)
   local curNum, GUiCloseLnk
   If Not SteamWin
      SteamWin := 0
   If Not pImgDir
      pImgDir := "res\gui"
   SteamWin++ ; This can be referenced as a default by all functions that use it
   SteamWin%SteamWin%Title := pTitle
   SteamWin%SteamWin%H := SteamWin%SteamWin%Height := pHeight
   SteamWin%SteamWin%W := SteamWin%SteamWin%Width := pWidth
   SteamWin%SteamWin%GuiNum := CurrentGuiNum := pGuiNum
   SteamWin%SteamWin%ImgDir := pImgDir
   If pGuiNum {
      Gui, %pGuiNum%:Default ; GuiNum must be default for the image buttons to work
      Gui, %pGUiNum%:+LabelSteamWin%SteamWin%
   }
   Gui, Destroy ; Just in case there was another GUI with this number (hope it was saved, heh)
   Gui, Color, 686A65, 5E5E5E ; Actual window background will be (464646)
   Gui, -Caption ; Get rid of default title bar
   Gui, Add, Picture, x0 y0 vSW%SteamWin%Bg w%pWidth% h%pHeight% 0x4000000, %pImgDir%\bg\Window.bmp ; Window background
   tbWidth := pWidth - 32
   Gui, Add, Picture, x0 y0 w%tbWidth% h20 vSW%SteamWin%Titlebar gTitlebarClick, %pImgDir%\bg\Titlebar.bmp ; Titlebar
   Gui, Add, Picture, x+0 yp+0 w32 h20 vSW%SteamWin%TitlebarRight, %pImgDir%\bg\Titlebar.bmp ; Titlebar
   Gui, Font, S8 CWhite, Tahoma
   Gui, Add, Text, x5 y3 +Backgroundtrans vSW%SteamWin%Title, %pTitle%
   If SW%SteamWin%TitlebarMin_hwnd
      SW%SteamWin%TitlebarMin_hwnd := ""
   If SW%SteamWin%TitlebarClose_hwnd
      SW%SteamWin%TitlebarClose_hwnd := ""
   LoadImage_AGB(SW%SteamWin%TitlebarMinb1, pImgDir . "\btn\TitlebarMin.bmp", 15, 15)
   LoadImage_AGB(SW%SteamWin%TitlebarMinb1_ro, pImgDir . "\btn\TitlebarMin_RO.bmp", 15, 15)
   LoadImage_AGB(SW%SteamWin%TitlebarCloseb1, pImgDir . "\btn\TitlebarClose.bmp", 15, 15)
   LoadImage_AGB(SW%SteamWin%TitlebarCloseb1_ro, pImgDir . "\btn\TitlebarClose_RO.bmp", 15, 15)
   SW%SteamWin%TitlebarMin_bH := SW%SteamWin%TitlebarMin_bW := 15
   SW%SteamWin%TitlebarMin_bO := "x" . pWidth - 32 . " y3"
   SW%SteamWin%TitlebarMin_bG := "SWGuiMin"
   SW%SteamWin%TitlebarClose_bH := SW%SteamWin%TitlebarClose_bW := 15
   SW%SteamWin%TitlebarClose_bO := "x" . pWidth - 16 . " y3"
   GuiCloseLnk := IsLabel(pGuiNum . "GuiClose") ? pGuiNum : "SW"
   SW%SteamWin%TitlebarClose_bG := GuiCloseLnk . "GuiClose"
   AddGraphicButton("SW" . SteamWin . "TitlebarMin", SW%SteamWin%TitlebarMinb1, "x" . pWidth - 32 . " y3 w15 h15 gSWGuiMin", 15, 15) ; Steam's minimize (-) button
   AddGraphicButton("SW" . SteamWin . "TitlebarClose", SW%SteamWin%TitlebarCloseb1, "x" . pWidth - 16 . " y3 w15 h15 g" . GuiCloseLnk . "GuiClose", 15, 15) ; Steam's close (x) button
   
   ActiveCloseButtons .= "SW" . SteamWin . "TitlebarMin|SW" . SteamWin . "TitlebarClose|"
   
   Return %SteamWin%
}

SWGuiMin:
   WinMinimize
Return
   
SWGuiClose:
   WinGet, thisID,ID,A
   DllCall("AnimateWindow","UInt",thisID,"Int",500,"UInt","0x90000") ; Fade the window out
   WinClose, ahk_id %thisID%
Return

SW_AddButton(pVar, pLabel="", pName = "", pExt="", pOptions = "", pSteamWin = "") {
; Adds a Steam-like graphical button to the specified Steam window
; Parameters:
;   pVar: The variable name to assign to the button
;   pLabel: The label to jump to when the button is clicked. Defaults to pVar
;   pName: The filename (without .bmp) of the button to load. This is usually (not always) the text of the button.
;   pExt: The extension of the button file (Default: .bmp)
;   pOptions: Button options (excluding 'h' and 'w'), such as x and y coordinates for the button
;   pSteamWin: The SteamWin to make the changes to. Defaults to %SteamWin% (the last created window)
   local thisGuiNum, thisImgDir, thisHandle, thisBitmap, thisW, thisH
   If Not pSteamWin {
      If SteamWin
         pSteamWin := SteamWin
      Else Return 0 ; Current SteamWin unknown
   }
   If Not pName
      pName := "OK" ; Default to an OK button
   If Not pExt
      pExt := ".bmp"
   If Not pLabel
      pLabel := pVar ; If no label is specified, use the variable name as a label
   thisGuiNum := SteamWin%pSteamWin%GuiNum
   thisImgDir := SteamWin%pSteamWin%ImgDir
   If Not FileExist(thisImgDir . "\btn\" . pName . pExt)
      Return 0 ; The button file doesn't exist
   
   ; Check if a rollover button should be used
   ROImage := 0
   If FileExist(thisImgDir . "\btn\" . pName . "_RO" . pExt) {
      ROImage := thisImgDir . "\btn\" . pName . "_RO" . pExt
   }
   If thisGuiNum
      Gui, %thisGuiNum%:Default ; If there's a GUI num, make it the default
      ; Load the image file and get its dimensions
   If Not GDIplus_Start() { ; false means command worked
      If Not GDIplus_LoadBitmap(thisBitmap, thisImgDir . "\btn\" . pName . pExt) { ; False means command worked
         GDIplus_GetImageDimension(thisBitmap, thisW, thisH)
         GDIplus_DisposeImage(thisBitmap)
      } Else Gosub, GDIplusError
      GDIplus_Stop()
   } Else Gosub, GDIplusError
   LoadImage_AGB(%pVar%b1, thisImgDir . "\btn\" . pName . pExt, thisH, thisW)
   If ROImage
      LoadImage_AGB(%pVar%b1_ro, ROImage, thisH, thisW)
   Else
      LoadImage_AGB(%pVar%b1_ro, thisImgDir . "\btn\" . pName . pExt, thisH, thisW)
      
   If %pVar%_hwnd
      %pVar%_hwnd := ""
   %pVar%_bH := thisH
   %pVar%_bW := thisW
   %pVar%_bO := pOptions
   %pVar%_bG := pLabel
   ActiveButtons .= pVar . "|"
   AddGraphicButton(pVar, %pVar%b1, pOptions . " w" . thisW . " h" . thisH . " g" . pLabel, thisH, thisW)
   Return 1
   GDIplusError:
      If (#GDIplus_lastError != "") {
         msgbox, 16, GDI+ Error,
         ( LTrim
         There was an error in the GDI+ Wrapper. If the problem continues`, please contact support.
         The following information may be helpful in diagnosing the problem:
         Function Call: %#GDIplus_lastError%
         )
      }
   Return
}

SW_AddTextButton(pVar, pLabel="", pName = "", pSize="", pBg="", pOptions = "", pSteamWin = "") {
; Adds a Steam-like graphical button to the specified Steam window with a graphical text label on it
   local thisGuiNum, thisImgDir, thisHandle, thisBitmap, thisW, thisH
   If Not pSteamWin {
      If SteamWin
         pSteamWin := SteamWin
      Else Return 0 ; Current SteamWin unknown
   }
   If Not pName
      pName := "OK" ; Default to an OK button
   
   If Not pBg
      pBg := "Bg"
   ; Calculate button size required, if not specified
   If Not pSize {
      thisSize := GetTextSize(pName, "S8", "Tahoma")
      pSize := (thisSize > 53) ? 3 : 2
   }
   If Not pLabel
      pLabel := pVar ; If no label is specified, use the variable name as a label
   thisGuiNum := SteamWin%pSteamWin%GuiNum
   thisImgDir := SteamWin%pSteamWin%ImgDir
   
   ; Check if button already generated
   FileCreateDir,%thisImgDir%\tmp\btn
   thisFile1 := thisImgDir . "\tmp\btn\" . pName . "_" . pSize . ".bmp"
   If Not FileExist(thisFile1) { ; generate the button
      TextToImage(thisImgDir . "\btn\Button_" . pSize . "_" . pBg . ".png",pName,thisFile1,"XP=12 YP=7 Height=8.5 Align=Left|Top Weight=100 TextColour=FFFFFF Quality=3", "Tahoma")
   }
   ; Check if rollover already generated
   thisFile2 := thisImgDir . "\tmp\btn\" . pName . "_" . pSize . "_ro.bmp"
   If Not FileExist(thisFile2) { ; generate the button
      TextToImage(thisImgDir . "\btn\Button_" . pSize . "_" . pBg . ".png",pName,thisFile2,"XP=12 YP=7 Height=8.5 Align=Left|Top Weight=100 TextColour=C4B550 Quality=3", "Tahoma")
   }
   If thisGuiNum
      Gui, %thisGuiNum%:Default ; If there's a GUI num, make it the default
      ; Load the image file and get its dimensions
   If Not GDIplus_Start() { ; false means command worked
      If Not GDIplus_LoadBitmap(thisBitmap, thisFile1) { ; False means command worked
         GDIplus_GetImageDimension(thisBitmap, thisW, thisH)
         GDIplus_DisposeImage(thisBitmap)
      } Else Gosub, GDIplusError2
      GDIplus_Stop()
   } Else Gosub, GDIplusError2
   LoadImage_AGB(%pVar%b1, thisFile1, thisH, thisW)
   LoadImage_AGB(%pVar%b1_ro, thisFile2, thisH, thisW)
      
   If %pVar%_hwnd
      %pVar%_hwnd := ""
   %pVar%_bH := thisH
   %pVar%_bW := thisW
   %pVar%_bO := pOptions
   %pVar%_bG := pLabel
   ActiveButtons .= pVar . "|"
   ;Gui,  Add, Picture, w%thisW% h%thisH% g%pLabel% %pOptions% v%pVar%, %thisFile2%
   AddGraphicButton(pVar, %pVar%b1, pOptions . " w" . thisW . " h" . thisH . " g" . pLabel, thisH, thisW)
   Return 1
   GDIplusError2:
      If (#GDIplus_lastError != "") {
         msgbox, 16, GDI+ Error,
         ( LTrim
         GDI+ Wrapper Error:
         Function Call: %#GDIplus_lastError%
         )
      }
   Return
}

BtnMouseLeave(wParam, lParam, msg, hwnd)
{
  Global
  theseButtons := ActiveButtons . "|" . ActiveDockButtons
  Loop, Parse, theseButtons,|
  {
     If (hwnd = %A_LoopField%_hwnd)
        AddGraphicButton(A_LoopField, %A_LoopField%b1, %A_LoopField%_bO . " w" . %A_LoopField%_bW . " h" . %A_LoopField%_bH . " g" . %A_LoopField%_bG,%A_LoopField%_bH,%A_LoopField%_bW)
  }
}
BtnMouseMove(wParam, lParam, msg, hwnd)
{
   Global
   Static _LastButtonData = true
   theseButtons := ActiveButtons . "|" . ActiveDockButtons
   Loop, Parse, theseButtons,|
      If (hwnd = %A_LoopField%_hwnd)
         If (_LastButtonData != %A_LoopField%_hwnd)
            AddGraphicButton(A_LoopField, %A_LoopField%b1_ro, %A_LoopField%_bO . " w" . %A_LoopField%_bW . " h" . %A_LoopField%_bH . " g" . %A_LoopField%_bG,%A_LoopField%_bH,%A_LoopField%_bW)
   _LastButtonData := hwnd
   Return
}

SW_AddTabControl(pVar, pLabel="", pName="", pWidth="", pHeight="", pPos="", pAfterTabs="", pSteamWin="") {
   ; pVar: variable for the tab control (sub-vars will be created for the individual components)
   ; pLabel: label to run when a tab is clicked (pName is appended to this label for each tab), defaults to none
   ; pName: The name of the first tab to create (separate multiple tabs with a pipe, like Tab1|Tab2)
   ; pWidth/pHeight: The w and h coordinates for the entire tab control
   ; pPos: The x/y positioning options for the top left of the tab control
   ; pSteamWin: implied if not specified
   local thisGuiNum, thisImgDir, thisTab
   If Not pSteamWin {
      If SteamWin
         pSteamWin := SteamWin
      Else Return 0 ; Current SteamWin unknown
   }
   If Not pWidth
      pWidth := SteamWin%pSteamWin%W
   If Not pHeight
      pHeight := SteamWin%pSteamWin%H
   If Not SteamWin%pSteamWin%TabNum
      SteamWin%pSteamWin%TabNum := 0 ; sets the last tab number so that you can leave that param blank
   SteamWin%pSteamWin%TabControl := pVar
   SteamWin%pSteamWin%TabNum++
   thisTab := SteamWin%pSteamWin%TabNum
   If Not pName
      pName := "Tab" . SteamWin%pSteamWin%TabNum ; If not specified, make Tab name generic
   If Not pLabel
      pLabel := "SW_TabClick"
   thisGuiNum := SteamWin%pSteamWin%GuiNum
   thisImgDir := SteamWin%pSteamWin%ImgDir
   If thisGuiNum
      Gui, %thisGuiNum%:Default
   thisX := thisY := thisOptions := ""
   If pPos {
      Loop,  Parse, pPos, %A_Space%
      {
         If (SubStr(A_LoopField,1,1) = "x") {
            thisX := A_LoopField
         } Else If (SubStr(A_LoopField,1,1) = "y") {
            thisY := A_LoopField
         } Else {
            thisOptions .= " " . A_LoopField
         }
      }
   }
   ;SteamWin%pSteamWin%TabControl%thisTab%
   Gui, Add, Picture, v%pVar%1Left w11 h22 %thisX% %thisY%,res\gui\tab\Tab_Left.bmp
   Gui, Add, Picture, v%pVar%1Top w78 h2 x+0 yp+0,res\gui\tab\Tab_Top.bmp
   newX := "x" . (SubStr(thisX,2) + 11)
   Gui, Add, Picture, v%pVar%1Bg w78 h20 %newX% y+0,res\gui\tab\Tab.bmp
   Gui, Font, S8 CC4B550
   Gui, Add, Text,v%pVar%1 +Backgroundtrans xp+0 yp+2 g%pLabel% %thisOptions%,%pName%
   Gui, Font, S8 CWhite
   Gui, Add, Picture, v%pVar%1Right w9 h22 x+0 yp-4,res\gui\tab\Tab_Right.bmp
   GuiControlGet, namePos, Pos, %pVar%1
   newWidth := namePosW + 16
   GuiControl, Move, %pVar%1Bg, w%newWidth%
   pBHeight := pHeight - 21
   Gui, Add, Picture, v%pVar%Bg w%pWidth% h%pBHeight% %thisX% y+0 Section,res\gui\bg\Tab.bmp
   %pVar%_LastTab := %pVar%1
   %pVar% := thisTab
   Return thisTab
   SW_TabClick:
      thisTab := A_GuiControl
      tabControl := SubStr(thisTab,1,StrLen(thisTab) - 1)
      If Not %tabControl%_LastTab
         %tabControl%_LastTab := tabControl . "1"
      lastTab := %tabControl%_LastTab
      lastTabControl := SubStr(lastTab,1,StrLen(lastTab) - 1)
      
      ; Change pprevious tab's images to off, and this tab's to on
      GuiControl, +CFFFFFF,%lastTab%
      GuiControl, ,%lastTab%Left, res\gui\tab\Tab_Left_off.bmp
      GuiControl, ,%lastTab%Top, res\gui\tab\Tab_Top_off.bmp
      GuiControl, ,%lastTab%Bg, res\gui\tab\Tab_off.bmp
      GuiControl, ,%lastTab%Right, res\gui\tab\Tab_Right_off.bmp
      GuiControl, +CC4B550,%thisTab%
      GuiControl, ,%thisTab%Left, res\gui\tab\Tab_Left.bmp
      GuiControl, ,%thisTab%Top, res\gui\tab\Tab_Top.bmp
      GuiControl, ,%thisTab%Bg, res\gui\tab\Tab.bmp
      GuiControl, ,%thisTab%Right, res\gui\tab\Tab_Right.bmp
      lastControls := %lastTab%_Controls
      thisControls := %thisTab%_Controls
      Loop,Parse,lastControls,`,
      {
         GuiControl, Hide, %A_LoopField%
      }
      Loop,Parse,thisControls,`,
      {
         GuiControl, Show, %A_LoopField%
      }
      %tabControl%_LastTab := thisTab
      ; Get the var of the tab which was clicked
      ; Tab clicked can be referenced by: A_GuiControl
      
      ; Jump to user specified pLabel
      ; Change the contents of the tab control based on the tab clicked
   Return
}

SW_AddTab(pVar, pName, pTabNum="", pOptions="", pSteamWin="") {
   local lastTabNum, thisPos, newX, thisGuiNum
   If Not pSteamWin {
      If SteamWin
         pSteamWin := SteamWin
      Else Return 0 ; Current SteamWin unknown
   }
   If Not pOptions
      pOptions := "gSW_TabClick"
   thisGuiNum := SteamWin%pSteamWin%GuiNum
   If thisGuiNum
      Gui, %thisGuiNum%:Default
   
   If Not pVar . "1"
      Return 0 ; No tabs to add on to
   If Not pTabNum {
      Loop {
         If %pVar%%A_Index%
            pTabNum := A_Index + 1
         Else Break
      }
   }
   If %pVar%%pTabNum% {
      GuiControlGet, thisPos, Pos, %pVar%%pTabNum%
      ; Shift other tabs to the right one, then add the new one in place of the old
   } Else {
         lastTabNum := pTabNum - 1
         GuiControlGet, lastPosEnd, Pos, %pVar%%lastTabNum%Right
         thisPosLeftX := lastPosEndX + lastPosEndW
         thisPosLeftY := lastPosEndY
         Gui, Add, Picture, v%pVar%%pTabNum%Left w11 h22 x%thisPosLeftX% y%thisPosLeftY%,res\gui\tab\Tab_Left_off.bmp
         Gui, Add, Picture, v%pVar%%pTabNum%Top w78 h2 x+0 yp+0,res\gui\tab\Tab_Top_off.bmp
         newX := thisPosLeftX + 11
         Gui, Add, Picture, v%pVar%%pTabNum%Bg w78 h20 x%newX% y+0,res\gui\tab\Tab_off.bmp
         Gui, Font, S8 CFFFFFF
         Gui, Add, Text,v%pVar%%pTabNum% +Backgroundtrans xp+0 yp+2 %pOptions%,%pName%
         Gui, Font, S8 CWhite
         Gui, Add, Picture, v%pVar%%pTabNum%Right w9 h22 x+0 yp-4,res\gui\tab\Tab_Right_off.bmp
         SW_UpdateTab(pVar, pTabNum, pName)
   }
   If (pTabNum > %pVar%)
      %pVar% := pTabNum
   GuiControlGet, %pVar%_hwnd, Hwnd, %pVar%
   SetTimer,SW_MouseOverTab,250
   Return
   SW_MouseOverTab:
      MouseGetPos,,,thisWinID, thisControl
      Loop,%SteamWin%
      {
         If (thisWinID = SteamWin%A_Index%WinID) {
            thisTabControl := SteamWin%A_Index%TabControl
            GuiControlGet, thisControl, Hwnd, %thisControl%

            If (SubStr(thisControl,1,StrLen(thisTabControl)) = thisTabControl) {

               If (SubStr(thisControl,StrLen(thisControl)-5) = "Right") {
                  thisControl := SubStr(thisControl,1,StrLen(thisControl)-5)
               } Else If (SubStr(thisControl,StrLen(thisControl)-4) = "Left") {
                  thisControl := SubStr(thisControl,1,StrLen(thisControl)-4)
               } Else If (SubStr(thisControl,StrLen(thisControl)-3) = "Top") {
                  thisControl := SubStr(thisControl,1,StrLen(thisControl)-3)
               } Else If (SubStr(thisControl,StrLen(thisControl)-2) = "Bg") {
                  thisControl := SubStr(thisControl,1,StrLen(thisControl)-2)
               }
               GuiControl, +cC4B550, %thisControl%
            } Else {
               ;Turn non-active tabs back to white
            }
            Break
         }
      }
   Return
}

SW_UpdateTab(pVar, pTabNum, pNewName, pSteamWin="") {
   local thisGui, thisSize, thisFactor
   If Not pSteamWin {
      If SteamWin
         pSteamWin := SteamWin
      Else Return 0 ; Current SteamWin unknown
   }
   GuiControlGet, LastSz, Pos, %pVar%%pTabNum%
   prevSize := LastSzW
   thisSize := GetTextSize(pNewName, "S8", "Tahoma")
   GuiControl, Move, %pVar%%pTabNum%, w%thisSize%
   GuiControl,,%pVar%%pTabNum%,%pNewName%
   GuiControlGet, namePos, Pos, %pVar%%pTabNum%
   GuiControl, Move, %pVar%%pTabNum%Bg, w%namePosW%
   GuiControl, Move, %pVar%%pTabNum%Top, w%namePosW%
   GuiControl, Move, %pVar%%pTabNum%Right,% "x" . namePosX + namePosW
   Difference := thisSize - prevSize
   If (pTabNum < %pVar%)
   Loop,% %pVar% {
      If (A_Index > pTabNum) {
         ; Move %pVar%%A_Index% over to the right
         ; Get x position of previous tab's right side, add 9
         GuiControlGet,curLeftPos, Pos, %pVar%%A_Index%Left
         GuiControlGet,curRightPos, Pos, %pVar%%A_Index%Right
         newLeftX := curLeftPosX + Difference
         newRightX := curRightPosX + Difference
         GuiControl, Move, %pVar%%A_Index%Left, x%newLeftX%
         GuiControl, Move, %pVar%%A_Index%Top, % "x" . newLeftX + 11
         GuiControl, Move, %pVar%%A_Index%Bg, % "x" . newLeftX + 11
         GuiControl, Move, %pVar%%A_Index%, % "x" . newLeftX + 11
         GuiControl, Move, %pVar%%A_Index%Right, x%newRightX%
      }
   }
}

SW_AddSeparator(pWidth, pPos="", pSteamWin="") {
   local thisGui
   If Not pSteamWin {
      If SteamWin
         pSteamWin := SteamWin
      Else Return 0 ; Current SteamWin unknown
   }
   Gui, %thisGui%Add, Picture, w%pWidth% %pPos% h2,res\gui\bg\Separator.bmp
   Return 1
}

SW_AddRadio(pV="", pText="", pPos="", pW="", pH="", pSteamWin="") {
   local thisGui
   If Not pSteamWin {
      If SteamWin
         pSteamWin := SteamWin
      Else Return 0 ; Current SteamWin unknown
   }
   If SteamWin%SteamWin%GuiNum
      thisGui := SteamWin%SteamWin%GuiNum . ":"
   If Not pPos
      pPos := "xp+0 y+0"
   If pV
      pV = v%pV%
   If pW
      pW = w%pW%
   If pH
      pH = h%pH%
   Gui, %thisGui%Add, Radio, %pW% %pH% %pV% %pPos% 0x8000, %pText%
   Return 1
}

SW_AddCheckbox(pV="", pText="", pChecked=0, pPos="", pW="", pH="", pSteamWin="") {
   local thisGui
   If Not pSteamWin {
      If SteamWin
         pSteamWin := SteamWin
      Else Return 0 ; Current SteamWin unknown
   }
   If SteamWin%SteamWin%GuiNum
      thisGui := SteamWin%SteamWin%GuiNum . ":"
   If Not pPos
      pPos := "xp+0 y+0"
   If pV
      pV = v%pV%
   If pW
      pW = w%pW%
   If pH
      pH = h%pH%
   Gui, %thisGui%Add, Checkbox, %pW% %pH% %pV% %pPos% Checked%pChecked% 0x8000, %pText%
   Return 1
}

SW_AnimateWin(pHwnd, pSw) {
   If (pSw = 5) { ;show
      DllCall("AnimateWindow","UInt",pHwnd,"Int",500,"UInt","0xa0000") ; Fade in
      
   } Else { ; hide
      DllCall("AnimateWindow","UInt",pHwnd,"Int",500,"UInt","0x90000") ; Fade out
      
   }
}

SW_Show(pSteamWin="") {
   local thisH, thisW, thisTitle, thisGui
   If Not pSteamWin {
      If SteamWin
         pSteamWin := SteamWin
      Else Return 0 ; Current SteamWin unknown
   }
   thisTitle := SteamWin%pSteamWin%Title
   thisH := SteamWin%pSteamWin%H
   thisW := SteamWin%pSteamWin%W
   If SteamWin%pSteamWin%GuiNum
      thisGui := SteamWin%pSteamWin%GuiNum . ":"
   Gui, %thisGui%Show, h%thisH% w%thisW% Hide, %thisTitle%
   Gui, %thisGui%+LastFound
   WinMove, ,,,,%thisW%, %thisH%
   DetectHiddenWindows, On
   SteamWin%pSteamWin%WinID := WinGet("ID",thisTitle)
   DllCall("AnimateWindow","UInt",SteamWin%pSteamWin%WinID,"Int",500,"UInt","0xa0000")
   SetTimer, SWIsActive, 100
   OnMessage(0x200, "BtnMouseMove")
   OnMessage(0x2A3, "BtnMouseLeave")
   OnMessage(0x202, "BtnMouseLeave")
   OnMessage(0x201, "WM_LBUTTONDOWN")
   OnMessage(0x84, "WM_NCHITTEST")
   OnMessage(0x83, "WM_NCCALCSIZE")
   OnMessage(0x86, "WM_NCACTIVATE")
   Return 1
   
   TitlebarClick:
      PostMessage, 0xA1, 2,,, A
   Return
}

SWIsActive:
   OneExists := 0
   Loop %SteamWin%
   {
      curGuiNum := SteamWin%A_Index%GuiNum ? SteamWin%A_Index%GuiNum . ":" : ""
      Gui, %curGuiNum%Default
      DetectHiddenWindows, Off
      IfWinExist,% "ahk_id" . SteamWin%A_Index%WinID
      {
         OneExists := 1
         IfWinActive,% "ahk_id" . SteamWin%A_Index%WinID
         {
            NewFontColor%A_Index% = White
            ro := "" ; show the standard image
         } Else {
            NewFontColor%A_Index% = C0C0C0
            ro :="_ro" ; show the rollover image
         }
         If (NewFontColor%A_Index% != LastFontColor%A_Index%) {
            NewFontColor := NewFontColor%A_Index%
            Gui, Font, c%NewFontColor%
            thisTitleBar := "SW" . A_Index . "Titlebar"
            thisTitle := "SW" . A_Index . "Title"
            thisT := SteamWin%A_Index%Title
            GuiControl, Font, %thisTitle%
            GuiControl, ,%thisTitle%, %thisT%
            Gui, Font, cWhite
            LastFontColor%A_Index% = %NewFontColor%
            ; Update the titlebar buttons
            AddGraphicButton("SW" . A_Index . "TitlebarMin", SW%A_Index%TitlebarMinb1%ro%, "x" . pWidth - 32 . " y3 w15 h15 gSWGuiMin", 15, 15) ; Steam's minimize (-) button
            AddGraphicButton("SW" . A_Index . "TitlebarClose", SW%A_Index%TitlebarCloseb1%ro%, "x" . pWidth - 16 . " y3 w15 h15 g" . SW%A_Index%TitlebarClose_bG, 15, 15) ; Steam's close (x) button
         }
      }
   }
   ;If Dock_Enabled = 1
   ;   OneExists := 1
   If Not OneExists {
      SetTimer, SWIsActive, Off
      If !Dock_Enabled {
         OnMessage(0x200, "")
         OnMessage(0x2A3, "")
         OnMessage(0x202, "")
      }
      OnMessage(0x201, "")
      OnMessage(0x84, "")
      OnMessage(0x83, "") ; WM_NCCALCSIZE
      OnMessage(0x86, "") ; WM_NCACTIVATE
   }
Return

; Allow moving the GUI by dragging any point in its client area.
WM_LBUTTONDOWN()
{
    if A_Gui
        PostMessage, 0xA1, 2 ; WM_NCLBUTTONDOWN
}

; Sizes the client area to fill the entire window.
WM_NCCALCSIZE()
{
    if A_Gui
        return 0
}

; Prevents a border from being drawn when the window is activated.
WM_NCACTIVATE()
{
    if A_Gui
        return 1
}


; Redefine where the sizing borders are.  This is necessary since
; returning 0 for WM_NCCALCSIZE effectively gives borders zero size.
WM_NCHITTEST(wParam, lParam)
{
    static border_size = 6
   
    if !A_Gui
        return
   
    WinGetPos, gX, gY, gW, gH
   
    x := lParam<<48>>48, y := lParam<<32>>48
   
    hit_left    := x <  gX+border_size
    hit_right   := x >= gX+gW-border_size
    hit_top     := y <  gY+border_size
    hit_bottom  := y >= gY+gH-border_size
   
    if hit_top
    {
        if hit_left
            return 0xD
        else if hit_right
            return 0xE
        else
            return 0xC
    }
    else if hit_bottom
    {
        if hit_left
            return 0x10
        else if hit_right
            return 0x11
        else
            return 0xF
    }
    else if hit_left
        return 0xA
    else if hit_right
        return 0xB
   
    ; else let default hit-testing be done
}


Program Management functions
Check if a program is installed, download and install a program, run a program, get the path of a program...
Code:
;======================
;= Program Management =
;======================
IsInstalled(pRegKey = "", pPath = "") {
   ;Reg syntax: RootKey\Path\[Key] (keep ending slash to use default value)
   PathFromReg :=""
   If pRegKey {
      If (SubStr(pRegKey,0) != "\") { ; If the last character of the reg key is not a \
         ValName := SubStr(pRegKey,InStr(pRegKey,"\",1,0)+1) ; Extract the value from the string
         pRegKey := SubStr(pRegKey,1,InStr(pRegKey,"\",1,0)) ; Extract the key path from the string
      }
      RegPath := SubStr(pRegKey,InStr(pRegKey,"\",1)+1,InStr(pRegKey,"\",1,0)-1)
      RegRootKey := SubStr(pRegKey,1,InStr(pRegKey,"\",1,1)-1)
      RegResult := RegRead(RegRootKey,RegPath,ValName)
      PathFromReg := StringReplace(RegResult,"/","\",1)
      if (PathFromReg) and (SubStr(PathFromReg,0) != "\")
         PathFromReg .= "\" ; Add a slash to the end of the reg path
   }
   If pPath and (SubStr(pPath,0) != "\")
      pPath .= "\" ; Add a slash
   If PathFromReg and pPath and (PathFromReg = pPath)
      Return SubStr(PathFromReg,1,StrLen(PathFromReg)-1)
   If PathFromReg {
      If FileExist(PathFromReg . "*")
         Return SubStr(PathFromReg,1,StrLen(PathFromReg)-1)
      Else Return 0
   } Else If pPath {
      If FileExist(pPath . "*")
         Return SubStr(pPath,1,StrLen(pPath)-1)
      Else Return 0
   }
   Return 0
}

Install(pAppName, pInstaller = "setup.exe", pDownloadUrl = "", pRegKey = "", pInstallerDir = "installers", pPrompt = 0, pProgress = 1, pSilentInstall = 0) {
   Global ProgressBar, ProgressN, KB
   DeleteInstaller := 0
   If Not InStr(FileExist(pInstallerDir), "D")
      FileCreateDir,%pInstallerDir%
   If Not FileExist(pInstallerDir . "\" . pInstaller) {
      If pDownloadUrl {
         If Not ConnectedToInternet()
            Return 0
         If pProgress {
            Progress, M h80 w500, %pDownloadUrl%, .
            OnMessage(0x1100, "SetCounter")
            Download(pDownloadUrl,pInstallerDir . "\" . pInstaller,0x1100)
            Progress, Off
         } Else
            Download(pDownloadUrl,pInstallerDir . "\" . pInstaller)
         DeleteInstaller := 1
      } Else Return 0
   }
   If FileExist(pInstallerDir . "\" . pInstaller) {
      RunWait,%pInstallerDir%\%pInstaller%
      ; Change above to Run, and use this section to monitor the installation process and ascertain the install dir
      NewInstallPath := pRegKey ? IsInstalled(pRegKey) : FileSelectFolder("",0,"Please select the new install path")
   }
   If DeleteInstaller
      FileDelete,%pInstallerDir%\%pInstaller%
   Return NewInstallPath
}

RunApp(pExe,pPath="",pName="",pRegKey="") {
   Process,Exist,%pExe%
   If Not ErrorLevel {
      Installed := 1
      If Not pPath and Not FileExist(pExe)
         pPath := FileSelectFolder("",0,"Please select the folder for" . pExe)
      If Not FileExist(pPath . "\" . pExe)
         Installed := 0
      If pRegKey and not IsInstalled(pRegKey)
         Installed := 0
      If Installed {
         OSD("Starting " . pName)
         Run,%pExe%,%pPath%
         Process,Exist,%pExe%
      } Else OSD("Error: " . pName . " Not Found")
   }
   Return ErrorLevel
}

SetAppPath(pName, pPath = "", pIniFile = "", pIniHeader = "", pIniSetting = "") {
   global ConfigFile
   If Not pPath and pIniFile and pIniHeader and pIniSetting
      IniRead,%pPath%,%pIniFile%,%pIniHeader%,%pIniSetting%,%A_SPACE%
   If Not pPath
      pPath := FileSelectFolder("",0,"Please select your" . pName . "path if available")
   If pPath and pIniFile and pIniHeader and pIniSetting {
      IniWrite,%pPath%,%pIniFile%,%pIniHeader%,%pIniSetting%
      Return pPath
   } Else Return 0
}


Switch()
Switch and Case functions, kind of like a partially-working Switch/Case in other programming languages, on steroids.
Code:
;=========================
;= Switch/Case functions =
;=========================
; DESCRIPTION:
; Checks a list of values against a defined variable and does something upon a match.
; Processing of Case() statements stops after the first match for any Switch().
; Case() accepts wildcards in values, allows multiple values and chained actions.
; Actions can be run immediately upon match, or after the Switch is closed.
;
; Warning: Do NOT under any circumstances use any variables starting with "_Switch"
;          in your script! Do not change any of the _Switch variables manually. Just
;          call these functions instead to keep the vars synced. You have been warned...
;
; USAGE:
; Switch("myVar")               ; Opens the switch
; Case("Value","Action")      ; Checks Value against %MyVar% and runs Action on match
; Case(...)                ; If it did not match, continue checking other cases
; Case("", "Action")         ; Optional, a catch-all if there were no matches before
; Switch("myVar",0)          ; Closes the switch (Switch() also closes current switch)
;
; Note: Easily check if a match was found in an open Switch() by closing it in an If statement:
; If Switch() {
;    ... (switch had a match)
; } Else {
;   ... (switch didn't have a match)
; }
;
; RETURN VALUES
; Switch(): 1 - opened
;           [Value] - closed with match, returns the matching value
;           0 - closed without a match, or failed
;
; Case(): [Value] - Case() matched and returns the matching value
;         0 - No match, or no Switch() open
;
; VALUE/ACTION SYNTAX
; Case() is fairly robust. There are many ways to specify values and actions.
;
; VALUES (Don't forget the quotes!)
; - "Value[|Value2[|...]]" - Check for one or more values (separator: |)
; - "*Value" - Check for a string ending with "Value" (wildcard: *)
; - "Val*ue" - Check for a string starting with "Val" and ending with "ue"
; - "Value**" - Check for "Value*" (two *'s override the wildcard and display one)
; - "Value1||Value2" - Check for the string "Value1|Value2" (two |'s override "or" functionality)
;
; ACTIONS (Don't forget the quotes!)
; - "Label1[|Label2[|...]]" - Jump to one or any number of sub labels in your script (separator: |)
; - "Path\To\File.ahk", "[Parameters]" - Directly run an AHK or EXE file, optionally with parameters
;                       ^(Even if there are no parameters you must use empty quotes to load a file)
;             ^(If this is .ahk and the script is compiled, it will first check for File.exe)
; - "*Label" - Upon a match, wait to jump to Label until the Switch() is closed. (* at beginning)
;    ^(This works for running scripts/exe's, too)
; - "**Label" - Upon a match jump to *Label (two *'s override the "wait" functionality)
;
; NOTES
; Programs and labels can be chained together in the same Action
; You can jump to a label with another Switch() in it as long is uses a different variable name
; You can start another Switch() and come back to the first by re-calling Switch() for the first variable
; You can start a new Switch() with the same name of a closed Switch() since it no longer exists
; You can enter any code you'd like in-between Switch()'s and Case()'s, it will not interfere
;
; USAGE EXAMPLE
; Create a menu where all objects forward to a single gLabel containing
; a Switch() for the option clicked and a Case() for each option

Switch(pVar="",pEnabled=1) {
   local thisSwitch, thisMatch, thisAction, thisWait, thisWaitParams
   thisSwitch := pVar ? pVar : _SwitchOpen
   If Not thisSwitch
      Return 0
   thisMatch := _Switch%thisSwitch%_Match ; The matching value, or blank if no match
   thisWait := _Switch%thisSwitch%_Wait ; 1 to run the action upon closing of the switch, blank if the action ran immediately
   thisWaitParams := _Switch%thisSwitch%_Params ; The params to run if the action is a file
   If Not pVar or Not pEnabled { ; Evaluate then close the switch
      If thisWait ; Run the action now
         _Switch_Action(thisAction,thisParams)
      ; free the globals from oppression
      _Switch%thisSwitch% := _Switch%thisSwitch%_Val := _Switch%thisSwitch%_Match := _Switch%thisSwitch%_Action := _Switch%thisSwitch%_ActionParams := _Switch%thisSwitch%_Wait := _Switch%thisSwitch%_WaitParams := _SwitchOpen := "" ; This officially closes the switch
      Return thisMatch ; Return the matching value (true), or blank (false) if there was no match
   }
   ; Open the switch
   If (pEnabled != 2) {
      _Switch%thisSwitch%_Match := _Switch%thisSwitch%_Action := _Switch%thisSwitch%_ActionParams := _Switch%thisSwitch%_Wait := _Switch%thisSwitch%_WaitParams := ""
      _Switch%pVar%_Val := %pVar% ; Keep the % signs, we want to use thisSwitch's value
   }
   _Switch%pVar% := _SwitchOpen := pVar ; This officially opens the switch
   Return 1
}

Case(pVal="", pAction="", pArgs="[[none]]"){
   local thisFile, thisMatches, thisRegEx, thisLoopIndex, thisParams, thisVal
   If Not _SwitchOpen or _Switch%_SwitchOpen%_Match ; No switch open
      Return 0
   ; Switch is open, there has not been a match yet
   If pVal {
      pVal := StringReplace(pVal, "||", "^<>^<>^<>^", "All")
      Loop, Parse, pVal, |
      {
         thisVal := StringReplace(A_LoopField, "^<>^<>^<>^", "|", "All")
         If InStr(thisVal, "*") { ; Match as regex instead
            thisRegEx := StringReplace(thisVal, "\", "\\", "All")
            thisRegEx := StringReplace(thisRegEx, ".", "\.", "All")
            thisRegEx := StringReplace(thisRegEx, "**", "^<>^<>^<>^", "All")
            thisRegEx := StringReplace(thisRegEx, "*", ".*", "All")
            thisRegEx := StringReplace(thisRegEx, "^<>^<>^<>^", "*", "All")
            thisRegEx := StringReplace(thisRegEx, "?", "\?", "All")
            thisRegEx := StringReplace(thisRegEx, "+", "\+", "All")
            thisRegEx := StringReplace(thisRegEx, "[", "\[", "All")
            thisRegEx := StringReplace(thisRegEx, "{", "\{", "All")
            thisRegEx := StringReplace(thisRegEx, "|", "\|", "All")
            thisRegEx := StringReplace(thisRegEx, "(", "\(", "All")
            thisRegEx := StringReplace(thisRegEx, ")", "\)", "All")
            thisRegEx := StringReplace(thisRegEx, "^", "\^", "All")
            thisRegEx := StringReplace(thisRegEx, "$", "\$", "All")
            RegExMatch(_Switch%_SwitchOpen%_Val,"i)" . thisRegEx,thisMatches) ; thisMatches will be blank if no match
         } Else {
            If (thisVal = _Switch%_SwitchOpen%_Val) { ; Match!
               thisMatches := thisVal
            } Else thisMatches := 0
         }
      }
   } Else thisMatches := 1 ; Treat as a catch-all
   If thisMatches { ; set globals and process action(s)
      _Switch%_SwitchOpen%_Match := thisMatches
      If pArgs != "[[none]]"
         _Switch%_SwitchOpen%_Type := 1
      Else
         _Switch%_SwitchOpen%_Type := ""
      _Switch%_SwitchOpen%_Params := pArgs
      pAction := StringReplace(pAction, "||", "^<>^<>^<>^", "All")
      Loop, Parse, pAction, |
      {
         thisLoopIndex := A_Index
         pParams := StringReplace(pParams, "||", "^<>^<>^<>^", "All")
         Loop, Parse, pParams, |
         {
            If (A_Index = thisLoopIndex) {
               thisParams := A_LoopField
               Break
            }
         }
         If (SubStr(A_LoopField,1,1) = "*") { ; Queue the action to run when the switch closes
            If _Switch%_SwitchOpen%_Wait
               _Switch%_SwitchOpen%_Wait .= "|"
            _Switch%_SwitchOpen%_Wait .= SubStr(A_LoopField,2)
            If _Switch%_SwitchOpen%_WaitParams
               _Switch%_SwitchOpen%_WaitParams .= "|"
            _Switch%_SwitchOpen%_WaitParams .= thisParams
         } Else { ; Queue the action to run momentarily
            If _Switch%_SwitchOpen%_Action
               _Switch%_SwitchOpen%_Action .= "|"
            _Switch%_SwitchOpen%_Action .= A_LoopField
            If _Switch%_SwitchOpen%_ActionParams
               _Switch%_SwitchOpen%_ActionParams .= "|"
            _Switch%_SwitchOpen%_ActionParams .= thisParams
         }
      }
      If _Switch%_SwitchOpen%_Action ; Run the actions now
         _Switch_Action(_Switch%_SwitchOpen%_Action,_Switch%_SwitchOpen%_ActionParams)
      Return 1
   } Else Return 0
}

_Switch_Action(pAction,pParams="") {
   global
   thisActionNum := 0
   Loop, Parse, pAction, |
   {
      thisAction := StringReplace(A_LoopField, "^<>^<>^<>^", "||", "All")
      thisLoopIndex := A_Index
      Loop, Parse, pParams, |
         If (A_Index = thisLoopIndex)
            thisParams := A_LoopField
      If thisParams { ; Run the file
         If (SubStr(thisAction,StrLen(thisAction)-3) = "ahk") {
            If A_IsCompiled { ; check if an exe exists for the action instead
               If FileExist(SubStr(thisAction,1,StrLen(thisAction)-3) . ".exe")
                  thisExeInstead := 1
            } Else
               If Not A_AhkPath ; check if an exe exists for the action instead
                  If FileExist(SubStr(thisAction,1,StrLen(thisAction)-3) . ".exe")
                     thisExeInstead := 1
            If thisExeInstead {
               thisAction := SubStr(thisAction,1,StrLen(thisAction)-3) . ".exe"
               Run, %thisAction% %thisParams%
            } Else Run, AutoHotKey.exe %thisAction% %thisParams%,%A_AhkPath%
         } Else Run, %thisAction% %thisParams%
      } Else If IsLabel(thisAction) ; Go to the label
         GoSub,%thisAction%
      thisActionNum++
   }
   Return thisActionNum
}


Third-Party functions used:
If I miss an author's name, please let me know whose function it is!
-Dock() - majkinetor
-MMenu() - majkinetor
-AHKArray() - olegbl
-execute()
-GDIPlusWrapper
-xpath() - Titan
-AHK functions - Titan
-RC4txt2hex()/RC4hex2txt()
-ElapsedTime()
-StringMod()
-HttpQueryInfo()
-ConnectedToInternet()
-Let()/Assign()/Clear()
-AddGraphicButton()/LoadImage_AGB()
-Anchor() - Titan
_________________
-Ben

SteamLab
SteamLab Wiki

[Broken] - My industrial music [on GarageBand]


Last edited by bmcclure on Tue Dec 18, 2007 6:38 am; edited 3 times in total
Back to top
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 3615
Location: Belgrade

PostPosted: Wed Dec 05, 2007 9:45 am    Post subject: Reply with quote

I don't use steam, but this looks really nice
Also, thx for useful functions.
_________________
Back to top
View user's profile Send private message MSN Messenger
corrupt



Joined: 29 Dec 2004
Posts: 2391

PostPosted: Thu Dec 06, 2007 2:35 am    Post subject: Reply with quote

I'm not a big fan of Steam but do use it for a few games. I'll take it for a spin soon. Thanks Smile
Back to top
View user's profile Send private message Visit poster's website
bmcclure



Joined: 24 Nov 2007
Posts: 446

PostPosted: Thu Dec 06, 2007 7:12 am    Post subject: Reply with quote

I love Steam Smile My Steam library has grown to over a hundred games now I believe, not including all of the Non-Steam games that I launch through Steam in order to get the Friends functionality in-game.

Sometimes Steam, for no apparent reason, tends to wipe out my shortcuts file so I have to manually add the Non-Steam games all over again, set their names and custom icons, etc. Performing this action multiple times is what prompted me to start SteamLab (which, at the time, I referred to as the appropriately-named SteamShortcuts).

corrupt, your response made me consider the fact that not everyone who might find the rest of the functions useful likes Steam as much as I do. Do you think there would be any value in simply offering to disable Steam functionality upon first launch so that it can be used stand-alone? Even though I specifically made it to help me manage Steam, most of the things it can do aren't Steam-specific.

I hope you like the functionality the script has so far, and welcome any comments or suggestions you have.
_________________
-Ben

SteamLab
SteamLab Wiki

[Broken] - My industrial music [on GarageBand]
Back to top
View user's profile Send private message
bmcclure



Joined: 24 Nov 2007
Posts: 446

PostPosted: Thu Dec 06, 2007 9:08 am    Post subject: SteamLab 0.5.0.4 a Released Reply with quote

Minor release.

New Features:
-Titlebar Close and Minimize buttons now dim when the window is inactive

Bug fixes:
-Dock now works properly upon closing and re-opening the dock, or exiting and re-opening the Steam window.

Known Issues:
-Dock doesn't always properly set its window order when it re-opens unless it is clicked on.
_________________
-Ben

SteamLab
SteamLab Wiki

[Broken] - My industrial music [on GarageBand]
Back to top
View user's profile Send private message
bmcclure



Joined: 24 Nov 2007
Posts: 446

PostPosted: Fri Dec 07, 2007 6:11 pm    Post subject: New Release Coming Reply with quote

Edit: Released
_________________
-Ben

SteamLab
SteamLab Wiki

[Broken] - My industrial music [on GarageBand]


Last edited by bmcclure on Sat Dec 08, 2007 8:31 pm; edited 1 time in total
Back to top
View user's profile Send private message
bmcclure



Joined: 24 Nov 2007
Posts: 446

PostPosted: Sat Dec 08, 2007 8:28 pm    Post subject: SteamLab 0.8.1.5 Released Reply with quote

Fixes:
-Backup files now stack up properly by date so they are not overwritten
-Much improved dock functionality. Everything works as expected

New features:
-Windows now resizable
-Multiple tabs now supported per window (just like Steam)


Known Issues:
-Not all windows resize properly yet
-Not all tabs have functionality yet
-Dock rollovers don't work if moving down from top or bottom of dock window (fixed in next version)

Coming Up:
-Universal volume control hotkeys (works in vista too without UAC!)
-Compressed Game backups (back up your profiles/saves/configs)
-Manual backups - Specify a file, allow SteamLab to back it up for you.
-Scheduled backups (standard files and the new game zips)
-Dock buttons to include rollover effect
-Screenshot Manager / universal screenshot hotkey
_________________
-Ben

SteamLab
SteamLab Wiki

[Broken] - My industrial music [on GarageBand]


Last edited by bmcclure on Mon Dec 10, 2007 6:28 pm; edited 1 time in total
Back to top
View user's profile Send private message
Superfraggle



Joined: 02 Nov 2004
Posts: 773
Location: London, UK

PostPosted: Sun Dec 09, 2007 6:12 pm    Post subject: Reply with quote

This does look nice, I'll try it when I get my internet back.
_________________
Steve F AKA Superfraggle

http://r.yuwie.com/superfraggle
Back to top
View user's profile Send private message MSN Messenger
bmcclure



Joined: 24 Nov 2007
Posts: 446

PostPosted: Tue Dec 11, 2007 3:45 am    Post subject: New Version About to be Released Reply with quote

New version posted
_________________
-Ben

SteamLab
SteamLab Wiki

[Broken] - My industrial music [on GarageBand]


Last edited by bmcclure on Tue Dec 11, 2007 4:59 am; edited 2 times in total
Back to top
View user's profile Send private message
bmcclure



Joined: 24 Nov 2007
Posts: 446

PostPosted: Tue Dec 11, 2007 4:36 am    Post subject: Reply with quote

Can I get somebody who uses Steam and runs Windows XP to test this for me? If you don't have Steam, the script should download/install it for you, if you don't mind Smile

On my laptop running XP, my graphical buttons show up with ugly default button edges. On my main machine running Vista however, the buttons show up properly, as in my screenshots.

I cannot figure this out, as essentially my script uses AddGraphicButton() which I believe is not supposed to leave button edges.
_________________
-Ben

SteamLab
SteamLab Wiki

[Broken] - My industrial music [on GarageBand]
Back to top
View user's profile Send private message
hermes as guest
Guest





PostPosted: Tue Dec 11, 2007 4:45 am    Post subject: Reply with quote

Crashed upon trying to run under windows xp (using the exe version)



Looks like you failed to include some function :/
Back to top
bmcclure



Joined: 24 Nov 2007
Posts: 446

PostPosted: Tue Dec 11, 2007 4:50 am    Post subject: Reply with quote

Thanks for the report.

I must have posted a bad Exe.

I'll get a new version compiled and posted. If you wouldn't mind, could you test it again after I re-post? Thanks!
_________________
-Ben

SteamLab
SteamLab Wiki

[Broken] - My industrial music [on GarageBand]
Back to top
View user's profile Send private message
Display posts from previous: