You can use this on multiple windows and each will get a different background color.
By default you can use the Ctrl+Shift+W hotkey to change the current window background color.
On Windows 10 the effect will only be visible as a border color unless the app has a transparent background (e.g Settings)
ChangeWindowColor.ahk is the main script to launch.
You need both the following files in the same folder (pick the Dock.ahk file depending on your OS).
ChangeWindowColor.ahk
Code: Select all
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
#SingleInstance Force
Enabled := ComObjError(false)
#include %A_ScriptDir%\Dock.ahk
GuiArray := Object()
Colors := ["0xD95319", "0xEDB120", "0x7E2F8E", "0x77AC30"]
return
; Ctrl+Shift+W
; Change background color of current window
^+w::
WinGet, id, ID, A
SetBackgroudColor(id)
return
SetBackgroudColor(CurrHwnd)
{
global Colors, GuiArray
WinGetTitle, CurrTitle, ahk_id %CurrHwnd%
GuiName := "GUI" CurrHwnd+0
if (GuiArray.HasKey(GuiName))
{
GuiArray[GuiName] := ""
GuiArray.Delete(GuiName)
Gui, %GuiName%:Destroy
Return
}
Gui, %GuiName%:New, +hwndGuihwnd
Gui, %GuiName%:+ToolWindow
Gui, %GuiName%:Color, % Colors[1]
Colors.Push(Colors[1])
Colors.RemoveAt(1)
WinSet, Transparent, 0, % "ahk_id " Guihwnd
Gui, %GuiName%:Show, xCenter yCenter, %CurrTitle%, class DockGui
WinSet, Style, -0xC00000, % "ahk_id " Guihwnd
exDock := new Dock(CurrHwnd,Guihwnd)
exDock.Position("Title")
exDock.CloseCallback := Func("CloseCallback").Bind(GuiName)
GuiArray[GuiName] := exDock
WinActivate, % "ahk_id " . CurrHwnd
WinSet, Transparent, 255, % "ahk_id " . Guihwnd
Return
}
CloseCallback(GuiName)
{
Gui, %GuiName%:Destroy
}
Dock.ahk for Windows 7
Code: Select all
/*
Class Dock
Attach a window to another
Author
Marco Gavelli
Original Author
Soft (visionary1 ???)
version
0.1 (2017.04.20)
0.2 (2017.05.06)
0.2.1 (2017.05.07)
0.2.1.1 bug fixed (2017.05.09)
0.2.2 testing multiple docks... (2017.05.09)
License
WTFPL (http wtfpl.net /) Broken Link for safety
Dev env
Windows 10 pro x64
AutoHotKey H v1.1.25.01 32bit
To Do...
Multiple Dock, group windows...
thanks to
Helgef for overall coding advices
*/
class Dock
{
static EVENT_OBJECT_LOCATIONCHANGE := 0x800B
, EVENT_OBJECT_FOCUS := 0x8005, EVENT_OBJECT_DESTROY := 0x8001
, EVENT_MIN := 0x00000001, EVENT_MAX := 0x7FFFFFFF ;for debug
, EVENT_SYSTEM_MINIMIZESTART := 0x0016
, EVENT_SYSTEM_MINIMIZEEND := 0x0017
, EVENT_SYSTEM_FOREGROUND := 0x0003
, EVENT_OBJECT_HIDE := 0x8003
, EVENT_OBJECT_SHOW := 0x8002
/*
Instance := new Dock(Host hwnd, Client hwnd, [Callback], [CloseCallback])
Host hwnd
hwnd of a Host window
Client hwnd
hwnd of a window that follows Host window (window that'll be attached to a Host window)
[Callback]
a func object, or a bound func object
if omitted, default EventsHandler will be used, which is hard-coded in 'Dock.EventsHandler'
To construct your own events handler, I advise you to see Dock.EventsHandler first
[CloseCallback]
a func object, or a bound func object
called when Host window is destroyed, see 'Dock Example.ahk' for practical usuage
*/
__New(Host, Client, Callback := "", CloseCallback := "")
{
this.hwnd := []
this.hwnd.Host := Host
this.hwnd.Client := Client
; WinSet, ExStyle, +0x80, % "ahk_id " this.hwnd.Client
this.Bound := []
this.Callback := IsObject(Callback) ? Callback : ObjBindMethod(Dock.EventsHandler, "Calls")
this.CloseCallback := IsFunc(CloseCallback) || IsObject(CloseCallback) ? CloseCallback
/*
lpfnWinEventProc
*/
this.hookProcAdr := RegisterCallback("_DockHookProcAdr",,, &this)
/*
idProcess
*/
WinGet, idProcess, PID, % "ahk_id " . this.hwnd.Host
;idProcess := 0
/*
idThread
*/
idThread := DllCall("GetWindowThreadProcessId", "Ptr", this.hwnd.Host, "Int", 0)
;idThread := 0
; DllCall("CoInitialize", "Int", 0)
this.Hook := DllCall("SetWinEventHook"
, "UInt", Dock.EVENT_SYSTEM_FOREGROUND ;eventMin
, "UInt", Dock.EVENT_OBJECT_LOCATIONCHANGE ;eventMax
, "Ptr", 0 ;hmodWinEventProc
, "Ptr", this.hookProcAdr ;lpfnWinEventProc
, "UInt", idProcess ;idProcess
, "UInt", idThread ;idThread
, "UInt", 0) ;dwFlags
this.enable := 1
}
/*
Instance.Unhook()
unhooks Dock and frees memory
*/
Unhook()
{
DllCall("UnhookWinEvent", "Ptr", this.Hook)
; DllCall("CoUninitialize")
DllCall("GlobalFree", "Ptr", this.hookProcAdr)
this.Hook := ""
this.hookProcAdr := ""
this.Callback := ""
; WinSet, ExStyle, -0x80, % "ahk_id " this.hwnd.Client
}
__Delete()
{
this.Delete("Bound")
If (this.Hook)
this.Unhook()
this.CloseCallback := ""
}
/*
provisional
*/
Add(hwnd, pos := "")
{
static last_hwnd := 0
this.Bound.Push( new this( !NumGet(&this.Bound, 4*A_PtrSize) ? this.hwnd.Client : last_hwnd, hwnd ) )
If pos Contains Top,Bottom,R,Right,L,Left
this.Bound[NumGet(&this.Bound, 4*A_PtrSize)].Position(pos)
last_hwnd := hwnd
}
/*
Instance.Position(pos)
pos - sets position to dock client window
Top - sets to Top side of the host window
Bottom - sets to bottom side of the host window
R or Right - right side
L or Left - left side
*/
Position(pos)
{
this.pos := pos
Return this.EventsHandler.EVENT_OBJECT_LOCATIONCHANGE(this, "host")
}
/*
Default EventsHandler
*/
class EventsHandler extends Dock.HelperFunc
{
Calls(self, hWinEventHook, event, hwnd)
{
Critical
If (hwnd = self.hwnd.Host)
{
Return this.Host(self, event)
}
If (hwnd = self.hwnd.Client)
{
Return this.Client(self, event)
}
}
Host(self, event)
{
If (event = Dock.EVENT_OBJECT_HIDE)
{
WinHide, % "ahk_id " self.hwnd.Client
}
If (event = Dock.EVENT_OBJECT_SHOW)
{
WinShow, % "ahk_id " self.hwnd.Client
}
If (event = Dock.EVENT_SYSTEM_MINIMIZESTART)
{
self.enable := 0
}
If (event = Dock.EVENT_SYSTEM_MINIMIZEEND)
{
Sleep, 500 ; Wait animation
WinSet, Transparent, 0, % "ahk_id " self.hwnd.Client
this.EVENT_OBJECT_LOCATIONCHANGE(self, "host")
this.EVENT_SYSTEM_FOREGROUND(self.hwnd.Client)
this.EVENT_SYSTEM_FOREGROUND(self.hwnd.Host)
WinSet, Transparent, 255, % "ahk_id " self.hwnd.Client
self.enable := 1
}
If (event = Dock.EVENT_SYSTEM_FOREGROUND AND self.enable)
{
WinSet, Transparent, 0, % "ahk_id " self.hwnd.Client
this.EVENT_SYSTEM_FOREGROUND(self.hwnd.Client)
this.EVENT_SYSTEM_FOREGROUND(self.hwnd.Host)
this.EVENT_SYSTEM_FOREGROUND(self.hwnd.Host) ; why??
WinSet, Transparent, 255, % "ahk_id " self.hwnd.Client
Return ""
}
If (event = Dock.EVENT_OBJECT_LOCATIONCHANGE AND self.enable)
{
Return this.EVENT_OBJECT_LOCATIONCHANGE(self, "host")
}
If (event = Dock.EVENT_OBJECT_DESTROY)
{
self.Unhook()
If (IsFunc(self.CloseCallback) || IsObject(self.CloseCallback))
Return self.CloseCallback()
}
}
Client(self, event)
{
If (event = Dock.EVENT_SYSTEM_FOREGROUND)
{
}
If (event = Dock.EVENT_OBJECT_LOCATIONCHANGE)
{
}
}
/*
Called when host window got focus
without this, client window can't be showed (can't set to top)
*/
EVENT_SYSTEM_FOREGROUND(hwnd)
{
Return this.WinSetTop(hwnd)
}
/*
Called when host window is moved
*/
EVENT_OBJECT_LOCATIONCHANGE(self, via)
{
Host := this.WinGetPos(self.hwnd.Host)
Client := this.WinGetPos(self.hwnd.Client)
If InStr(self.pos, "Title")
{
; SysGet, BorderWidth, 5
If (via = "host")
{
Return this.MoveWindow(self.hwnd.Client ;hwnd
, Host.x ;x
, Host.y ;y
, Host.w ;width
, Host.h) ;height
}
If (via = "client")
{
}
}
If InStr(self.pos, "Top")
{
If (via = "host")
{
Return this.MoveWindow(self.hwnd.Client ;hwnd
, Host.x ;x
, Host.y - Client.h ;y
, Client.w ;width
, Client.h) ;height
}
If (via = "client")
{
Return this.MoveWindow(self.hwnd.Host ;hwnd
, Client.x ;x
, Client.y + Client.h ;y
, Host.w ;width
, Host.h) ;height
}
}
If InStr(self.pos, "Bottom")
{
If (via = "host")
{
Return this.MoveWindow(self.hwnd.Client ;hwnd
, Host.x ;x
, Host.y + Host.h ;y
, Client.w ;width
, Client.h) ;height
}
If (via = "client")
{
Return this.MoveWindow(self.hwnd.Host ;hwnd
, Client.x ;x
, Client.y - Host.h ;y
, Host.w ;width
, Host.h) ;height
}
}
If InStr(self.pos, "R")
{
If (via = "host")
{
Return this.MoveWindow(self.hwnd.Client ;hwnd
, Host.x + Host.w ;x
, Host.y ;y
, Client.w ;width
, Client.h) ;height
}
If (via = "client")
{
Return this.MoveWindow(self.hwnd.Host ;hwnd
, Client.x - Host.w ;x
, Client.y ;y
, Host.w ;width
, Host.h) ;height
}
}
If InStr(self.pos, "L")
{
If (via = "host")
{
Return this.MoveWindow(self.hwnd.Client ;hwnd
, Host.x - Client.w ;x
, Host.y ;y
, Client.w ;width
, Client.h) ;height
}
If (via = "client")
{
Return this.MoveWindow(self.hwnd.Host ;hwnd
, Client.x + Client.w ;x
, Client.y ;y
, Host.w ;width
, Host.h) ;height
}
}
}
}
class HelperFunc
{
WinGetPos(hwnd)
{
WinGetPos, hX, hY, hW, hH, % "ahk_id " . hwnd
Return {x: hX, y: hY, w: hW, h: hH}
}
WinSetTop(hwnd)
{
WinSet, AlwaysOnTop, On, % "ahk_id " . hwnd
WinSet, AlwaysOnTop, Off, % "ahk_id " . hwnd
}
MoveWindow(hwnd, x, y, w, h)
{
DllCall("MoveWindow", "Ptr", hwnd, "Int", x, "Int", y, "Int", w, "Int", h, "Int", 1)
tmp := 0 "-" 0 " W" w " H" h " R12-12"
WinSet, Region, %tmp%, % "ahk_id " hwnd
Return ""
}
Run(Target)
{
Try Run, % Target,,, OutputVarPID
Catch,
Throw, "Couldn't run " Target
WinWait, % "ahk_pid " OutputVarPID
Return WinExist("ahk_pid " OutputVarPID)
}
}
}
_DockHookProcAdr(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime)
{
this := Object(A_EventInfo)
this.Callback.Call(this, hWinEventHook, event, hwnd)
}
Dock.ahk for Windows 10
Code: Select all
/*
Class Dock
Attach a window to another
Author
Marco Gavelli
Original Author
Soft (visionary1 ???)
version
0.1 (2017.04.20)
0.2 (2017.05.06)
0.2.1 (2017.05.07)
0.2.1.1 bug fixed (2017.05.09)
0.2.2 testing multiple docks... (2017.05.09)
License
WTFPL (http wtfpl.net /) Broken Link for safety
Dev env
Windows 10 pro x64
AutoHotKey H v1.1.25.01 32bit
To Do...
Multiple Dock, group windows...
thanks to
Helgef for overall coding advices
*/
class Dock
{
static EVENT_OBJECT_LOCATIONCHANGE := 0x800B
, EVENT_OBJECT_FOCUS := 0x8005, EVENT_OBJECT_DESTROY := 0x8001
, EVENT_MIN := 0x00000001, EVENT_MAX := 0x7FFFFFFF ;for debug
, EVENT_SYSTEM_MINIMIZESTART := 0x0016
, EVENT_SYSTEM_MINIMIZEEND := 0x0017
, EVENT_SYSTEM_FOREGROUND := 0x0003
, EVENT_OBJECT_HIDE := 0x8003
, EVENT_OBJECT_SHOW := 0x8002
/*
Instance := new Dock(Host hwnd, Client hwnd, [Callback], [CloseCallback])
Host hwnd
hwnd of a Host window
Client hwnd
hwnd of a window that follows Host window (window that'll be attached to a Host window)
[Callback]
a func object, or a bound func object
if omitted, default EventsHandler will be used, which is hard-coded in 'Dock.EventsHandler'
To construct your own events handler, I advise you to see Dock.EventsHandler first
[CloseCallback]
a func object, or a bound func object
called when Host window is destroyed, see 'Dock Example.ahk' for practical usuage
*/
__New(Host, Client, Callback := "", CloseCallback := "")
{
this.hwnd := []
this.hwnd.Host := Host
this.hwnd.Client := Client
; WinSet, ExStyle, +0x80, % "ahk_id " this.hwnd.Client
this.Bound := []
this.Callback := IsObject(Callback) ? Callback : ObjBindMethod(Dock.EventsHandler, "Calls")
this.CloseCallback := IsFunc(CloseCallback) || IsObject(CloseCallback) ? CloseCallback
/*
lpfnWinEventProc
*/
this.hookProcAdr := RegisterCallback("_DockHookProcAdr",,, &this)
/*
idProcess
*/
WinGet, idProcess, PID, % "ahk_id " . this.hwnd.Host
;idProcess := 0
/*
idThread
*/
idThread := DllCall("GetWindowThreadProcessId", "Ptr", this.hwnd.Host, "Int", 0)
;idThread := 0
; DllCall("CoInitialize", "Int", 0)
this.Hook := DllCall("SetWinEventHook"
, "UInt", Dock.EVENT_SYSTEM_FOREGROUND ;eventMin
, "UInt", Dock.EVENT_OBJECT_LOCATIONCHANGE ;eventMax
, "Ptr", 0 ;hmodWinEventProc
, "Ptr", this.hookProcAdr ;lpfnWinEventProc
, "UInt", idProcess ;idProcess
, "UInt", idThread ;idThread
, "UInt", 0) ;dwFlags
this.enable := 1
}
/*
Instance.Unhook()
unhooks Dock and frees memory
*/
Unhook()
{
DllCall("UnhookWinEvent", "Ptr", this.Hook)
; DllCall("CoUninitialize")
DllCall("GlobalFree", "Ptr", this.hookProcAdr)
this.Hook := ""
this.hookProcAdr := ""
this.Callback := ""
; WinSet, ExStyle, -0x80, % "ahk_id " this.hwnd.Client
}
__Delete()
{
this.Delete("Bound")
If (this.Hook)
this.Unhook()
this.CloseCallback := ""
}
/*
provisional
*/
Add(hwnd, pos := "")
{
static last_hwnd := 0
this.Bound.Push( new this( !NumGet(&this.Bound, 4*A_PtrSize) ? this.hwnd.Client : last_hwnd, hwnd ) )
If pos Contains Top,Bottom,R,Right,L,Left
this.Bound[NumGet(&this.Bound, 4*A_PtrSize)].Position(pos)
last_hwnd := hwnd
}
/*
Instance.Position(pos)
pos - sets position to dock client window
Top - sets to Top side of the host window
Bottom - sets to bottom side of the host window
R or Right - right side
L or Left - left side
*/
Position(pos)
{
this.pos := pos
Return this.EventsHandler.EVENT_OBJECT_LOCATIONCHANGE(this, "host")
}
/*
Default EventsHandler
*/
class EventsHandler extends Dock.HelperFunc
{
Calls(self, hWinEventHook, event, hwnd)
{
Critical
If (hwnd = self.hwnd.Host)
{
Return this.Host(self, event)
}
If (hwnd = self.hwnd.Client)
{
Return this.Client(self, event)
}
}
Host(self, event)
{
If (event = Dock.EVENT_OBJECT_HIDE)
{
WinHide, % "ahk_id " self.hwnd.Client
}
If (event = Dock.EVENT_OBJECT_SHOW)
{
WinShow, % "ahk_id " self.hwnd.Client
}
If (event = Dock.EVENT_SYSTEM_MINIMIZESTART)
{
self.enable := 0
}
If (event = Dock.EVENT_SYSTEM_MINIMIZEEND)
{
Sleep, 500 ; Wait animation
WinSet, Transparent, 0, % "ahk_id " self.hwnd.Client
this.EVENT_OBJECT_LOCATIONCHANGE(self, "host")
this.EVENT_SYSTEM_FOREGROUND(self.hwnd.Client)
this.EVENT_SYSTEM_FOREGROUND(self.hwnd.Host)
WinSet, Transparent, 255, % "ahk_id " self.hwnd.Client
self.enable := 1
}
If (event = Dock.EVENT_SYSTEM_FOREGROUND AND self.enable)
{
WinSet, Transparent, 0, % "ahk_id " self.hwnd.Client
this.EVENT_SYSTEM_FOREGROUND(self.hwnd.Client)
this.EVENT_SYSTEM_FOREGROUND(self.hwnd.Host)
this.EVENT_SYSTEM_FOREGROUND(self.hwnd.Host) ; why??
WinSet, Transparent, 255, % "ahk_id " self.hwnd.Client
Return ""
}
If (event = Dock.EVENT_OBJECT_LOCATIONCHANGE AND self.enable)
{
Return this.EVENT_OBJECT_LOCATIONCHANGE(self, "host")
}
If (event = Dock.EVENT_OBJECT_DESTROY)
{
self.Unhook()
If (IsFunc(self.CloseCallback) || IsObject(self.CloseCallback))
Return self.CloseCallback()
}
}
Client(self, event)
{
If (event = Dock.EVENT_SYSTEM_FOREGROUND)
{
}
If (event = Dock.EVENT_OBJECT_LOCATIONCHANGE)
{
}
}
/*
Called when host window got focus
without this, client window can't be showed (can't set to top)
*/
EVENT_SYSTEM_FOREGROUND(hwnd)
{
Return this.WinSetTop(hwnd)
}
/*
Called when host window is moved
*/
EVENT_OBJECT_LOCATIONCHANGE(self, via)
{
Host := this.WinGetPos(self.hwnd.Host)
Client := this.WinGetPos(self.hwnd.Client)
If InStr(self.pos, "Title")
{
; SysGet, BorderWidth, 5
If (via = "host")
{
Return this.MoveWindow(self.hwnd.Client ;hwnd
, Host.x+6 ;x
, Host.y-2 ;y
, Host.w-10 ;width
, Host.h-2) ;height
}
If (via = "client")
{
}
}
If InStr(self.pos, "Top")
{
If (via = "host")
{
Return this.MoveWindow(self.hwnd.Client ;hwnd
, Host.x ;x
, Host.y - Client.h ;y
, Client.w ;width
, Client.h) ;height
}
If (via = "client")
{
Return this.MoveWindow(self.hwnd.Host ;hwnd
, Client.x ;x
, Client.y + Client.h ;y
, Host.w ;width
, Host.h) ;height
}
}
If InStr(self.pos, "Bottom")
{
If (via = "host")
{
Return this.MoveWindow(self.hwnd.Client ;hwnd
, Host.x ;x
, Host.y + Host.h ;y
, Client.w ;width
, Client.h) ;height
}
If (via = "client")
{
Return this.MoveWindow(self.hwnd.Host ;hwnd
, Client.x ;x
, Client.y - Host.h ;y
, Host.w ;width
, Host.h) ;height
}
}
If InStr(self.pos, "R")
{
If (via = "host")
{
Return this.MoveWindow(self.hwnd.Client ;hwnd
, Host.x + Host.w ;x
, Host.y ;y
, Client.w ;width
, Client.h) ;height
}
If (via = "client")
{
Return this.MoveWindow(self.hwnd.Host ;hwnd
, Client.x - Host.w ;x
, Client.y ;y
, Host.w ;width
, Host.h) ;height
}
}
If InStr(self.pos, "L")
{
If (via = "host")
{
Return this.MoveWindow(self.hwnd.Client ;hwnd
, Host.x - Client.w ;x
, Host.y ;y
, Client.w ;width
, Client.h) ;height
}
If (via = "client")
{
Return this.MoveWindow(self.hwnd.Host ;hwnd
, Client.x + Client.w ;x
, Client.y ;y
, Host.w ;width
, Host.h) ;height
}
}
}
}
class HelperFunc
{
WinGetPos(hwnd)
{
WinGetPos, hX, hY, hW, hH, % "ahk_id " . hwnd
Return {x: hX, y: hY, w: hW, h: hH}
}
WinSetTop(hwnd)
{
WinSet, AlwaysOnTop, On, % "ahk_id " . hwnd
WinSet, AlwaysOnTop, Off, % "ahk_id " . hwnd
}
MoveWindow(hwnd, x, y, w, h)
{
DllCall("MoveWindow", "Ptr", hwnd, "Int", x, "Int", y, "Int", w, "Int", h, "Int", 1)
tmp := 0 "-" 0 " W" w " H" h " R0-0"
WinSet, Region, %tmp%, % "ahk_id " hwnd
Return ""
}
Run(Target)
{
Try Run, % Target,,, OutputVarPID
Catch,
Throw, "Couldn't run " Target
WinWait, % "ahk_pid " OutputVarPID
Return WinExist("ahk_pid " OutputVarPID)
}
}
}
_DockHookProcAdr(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime)
{
this := Object(A_EventInfo)
this.Callback.Call(this, hWinEventHook, event, hwnd)
}
[Updated 07/03/2020]
Added Windows 10 version
[Updated 09/03/2020]
Handle windows hiding
Credits:
Original Dock.ahk is from:
https://www.autohotkey.com/boards/viewtopic.php?f=6&t=30912
Tested on Windows 7 with Aero Theme and Windows 10