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