Last active
May 14, 2022 14:51
-
-
Save zero-plusplus/88b4407e3a939233315a1e2e2fffd464 to your computer and use it in GitHub Desktop.
This class provides methods to register/unregister window change event.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @author zero-plusplus (https://github.com/zero-plusplus) | |
* @licence MIT | |
* @link https://gist.github.com/zero-plusplus/88b4407e3a939233315a1e2e2fffd464 | |
*/ | |
/** | |
* Provides a way to register or unregister window change event. | |
* @example | |
* ; Always change to pseudo full screen when notepad is active | |
* WindowChangeEvent.register(Func("eventCallback")) | |
* | |
* eventCallback(windowInfo) { | |
* if (windowInfo.exe == "notepad.exe") { | |
* WinMove, A, , 0, 0, %A_ScreenWidth%, %A_ScreenHeight% | |
* } | |
* } | |
* @example | |
* ; If you are debugging with SciTE4AutoHotkey or Visual Studio Code, you should be careful that the editor freezes when the window change event is called by [WinActivate](https://www.autohotkey.com/docs/commands/WinActivate.htm). | |
* ; To avoid this, you must temporarily unregister before WinActivate. | |
* | |
* event := WindowChangeEvent.register(Func("eventCallback")) | |
* event.unregister() | |
* WinActivate, ahk_exe notepad.exe | |
* event.register() | |
* | |
* eventCallback(windowInfo) { | |
* } | |
*/ | |
class WindowChangeEvent { | |
/** | |
* `true` if a callback is registered for the window change event, `false` otherwise. | |
* @type {boolean} | |
*/ | |
isRegistered[] { | |
get { | |
return 0 < this.id | |
} | |
} | |
/** | |
* @param {(windowInfo: WindowChangeEvent.ActiveWindowInfo) => void} callback - Callable object called on window change. | |
*/ | |
__NEW(callback := "") { | |
this.id := 0 | |
if (!IsObject(callback)) { | |
throw Exception("``callback`` must be a Func, BoundFunc, or user-defined function.") | |
} | |
this.callback := callback | |
} | |
/** | |
* Registers a callback to the window change event. | |
* @static | |
* @param {(windowInfo: WindowChangeEvent.ActiveWindowInfo) => void} callback - Callable object called on window change. | |
* @return {WindowChangeEvent} | |
*/ | |
/** | |
* Registers a pre-specified callback to the window change event. | |
* @chainable | |
*/ | |
register(callback := "") { | |
; https://docs.microsoft.com/en-us/windows/win32/winauto/event-constants | |
static EVENT_SYSTEM_FOREGROUND := 0x00000003 | |
; static method | |
if (this == WindowChangeEvent) { | |
return new WindowChangeEvent(callback).register() | |
} | |
; instance method | |
; https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwineventhook | |
this.id := DllCall( "SetWinEventHook" | |
, "UInt", eventMin := EVENT_SYSTEM_FOREGROUND | |
, "UInt", eventMax := EVENT_SYSTEM_FOREGROUND | |
, "UInt", hmodWinEventProc := 0 | |
, "UInt", pfnWinEventProc := RegisterCallback(Func("WindowChangeEvent._callbackWrapper"), "", , &(this.callback)) | |
, "UInt", idProcess := 0 | |
, "UInt", idThread := 0 | |
, "UInt", dwFlags := 0 ) | |
return this | |
} | |
/** | |
* Unregisters a registered callback. | |
* @chainable | |
*/ | |
unregister() { | |
if (DllCall("UnhookWinEvent", "UInt", this.id)) { | |
this.id := 0 | |
} | |
return this | |
} | |
/** | |
* @private | |
* @static | |
*/ | |
_callbackWrapper() { | |
callback := Object(A_EventInfo) | |
%callback%(WindowChangeEvent.ActiveWindowInfo) | |
} | |
/** | |
* Provides properties to get information about the active window. | |
*/ | |
class ActiveWindowInfo { | |
/** | |
* Returns the title of the active window. | |
* @static | |
* @type {string} | |
*/ | |
title { | |
get { | |
WinGetTitle, title, A | |
return title | |
} | |
} | |
/** | |
* Returns the window class of the active window. | |
* @static | |
* @type {string} | |
*/ | |
class { | |
get { | |
WinGetClass, winClass, A | |
return winClass | |
} | |
} | |
/** | |
* It is the same as the `class` property except that it is prefixed with `"ahk_class "`. | |
* @static | |
* @type {string} | |
*/ | |
ahk_class { | |
get { | |
return "ahk_class " . this.class | |
} | |
} | |
/** | |
* Returns the window id (hwnd) of the active window. | |
* @static | |
* @type {string} | |
*/ | |
id { | |
get { | |
WinGet, id, ID, A | |
return id | |
} | |
} | |
/** | |
* It is the same as the `id` property except that it is prefixed with `"ahk_id "`. | |
* @static | |
* @type {string} | |
*/ | |
ahk_id { | |
get { | |
return "ahk_id " . this.id | |
} | |
} | |
/** | |
* Returns the process id of the active window. | |
* @static | |
* @type {string} | |
*/ | |
pid { | |
get { | |
WinGet, pid, PID, A | |
return pid | |
} | |
} | |
/** | |
* It is the same as the `pid` property except that it is prefixed with `"ahk_pid "`. | |
* @static | |
* @type {string} | |
*/ | |
ahk_pid { | |
get { | |
return "ahk_pid " . this.pid | |
} | |
} | |
/** | |
* Returns the process name of the active window. | |
* @static | |
* @type {string} | |
*/ | |
exe { | |
get { | |
WinGet, processName, ProcessName, A | |
return processName | |
} | |
} | |
/** | |
* It is the same as the `exe` property except that it is prefixed with `"ahk_exe "`. | |
* @static | |
* @type {string} | |
*/ | |
ahk_exe { | |
get { | |
return "ahk_exe " . this.exe | |
} | |
} | |
/** | |
* Returns the window text of the active window. | |
* @static | |
* @type {string} | |
*/ | |
text { | |
get { | |
WinGetText, text, A | |
return text | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @author zero-plusplus (https://github.com/zero-plusplus) | |
* @licence MIT | |
* @link https://gist.github.com/zero-plusplus/88b4407e3a939233315a1e2e2fffd464 | |
*/ | |
/** | |
* Provides a way to register or unregister window change event. | |
* @example | |
* ; Always change to pseudo full screen when notepad is active | |
* WindowChangeEvent.register(eventCallback) | |
* | |
* eventCallback(windowInfo) { | |
* if (windowInfo.exe == "notepad.exe") { | |
* WinMove(0, 0, A_ScreenWidth, A_ScreenHeight, "A") | |
* } | |
* } | |
* @example | |
* ; If you are debugging with SciTE4AutoHotkey or Visual Studio Code, you should be careful that the editor freezes when the window change event is called by [WinActivate](https://www.autohotkey.com/docs/commands/WinActivate.htm). | |
* ; To avoid this, you must temporarily unregister before WinActivate. | |
* | |
* event := WindowChangeEvent.register(eventCallback) | |
* event.unregister() | |
* WinActivate("ahk_exe notepad.exe") | |
* event.register() | |
* | |
* eventCallback(windowInfo) { | |
* } | |
*/ | |
class WindowChangeEvent { | |
/** | |
* `true` if a callback is registered for the window change event, `false` otherwise. | |
* @type {boolean} | |
*/ | |
isRegistered { | |
get { | |
return 0 < this.id | |
} | |
} | |
/** | |
* @param {(windowInfo: WindowChangeEvent.ActiveWindowInfo) => void} callback - Callable object called on window change. | |
*/ | |
__NEW(callback := "") { | |
this.id := 0 | |
if (!IsObject(callback)) { | |
throw Error("``callback`` must be a Func, BoundFunc, or user-defined function.") | |
} | |
this.callback := callback | |
} | |
/** | |
* Registers a callback to the window change event. | |
* @static | |
* @param {(windowInfo: WindowChangeEvent.ActiveWindowInfo) => void} callback - Callable object called on window change. | |
* @return {WindowChangeEvent} | |
*/ | |
static register(callback) { | |
return WindowChangeEvent(callback).register() | |
} | |
/** | |
* Registers a pre-specified callback to the window change event. | |
* @chainable | |
*/ | |
register() { | |
; https://docs.microsoft.com/en-us/windows/win32/winauto/event-constants | |
static EVENT_SYSTEM_FOREGROUND := 0x00000003 | |
; https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwineventhook | |
this.id := DllCall( | |
"SetWinEventHook", | |
"UInt", eventMin := EVENT_SYSTEM_FOREGROUND, | |
"UInt", eventMax := EVENT_SYSTEM_FOREGROUND, | |
"UInt", hmodWinEventProc := 0, | |
"UInt", pfnWinEventProc := CallbackCreate(ObjBindMethod(WindowChangeEvent, "_callbackWrapper", this.callback)), | |
"UInt", idProcess := 0, | |
"UInt", idThread := 0, | |
"UInt", dwFlags := 0 | |
) | |
return this | |
} | |
/** | |
* Unregisters a registered callback. | |
* @chainable | |
*/ | |
unregister() { | |
if (DllCall("UnhookWinEvent", "UInt", this.id)) { | |
this.id := 0 | |
} | |
return this | |
} | |
/** | |
* @private | |
* @static | |
*/ | |
static _callbackWrapper(callback) { | |
callback(WindowChangeEvent.ActiveWindowInfo) | |
} | |
/** | |
* Provides properties to get information about the active window. | |
*/ | |
class ActiveWindowInfo { | |
/** | |
* Returns the title of the active window. | |
* @static | |
* @type {string} | |
*/ | |
static title { | |
get { | |
title := WinGetTitle("A") | |
return title | |
} | |
} | |
/** | |
* Returns the window class of the active window. | |
* @static | |
* @type {string} | |
*/ | |
static class { | |
get { | |
winClass := WinGetClass("A") | |
return winClass | |
} | |
} | |
/** | |
* It is the same as the `class` property except that it is prefixed with `"ahk_class "`. | |
* @static | |
* @type {string} | |
*/ | |
static ahk_class { | |
get { | |
return "ahk_class " . this.class | |
} | |
} | |
/** | |
* Returns the window id (hwnd) of the active window. | |
* @static | |
* @type {string} | |
*/ | |
static id { | |
get { | |
id := WinGetId("A") | |
return id | |
} | |
} | |
/** | |
* It is the same as the `id` property except that it is prefixed with `"ahk_id "`. | |
* @static | |
* @type {string} | |
*/ | |
static ahk_id { | |
get { | |
return "ahk_id " . this.id | |
} | |
} | |
/** | |
* Returns the process id of the active window. | |
* @static | |
* @type {string} | |
*/ | |
static pid { | |
get { | |
pid := WinGetPid("A") | |
return pid | |
} | |
} | |
/** | |
* It is the same as the `pid` property except that it is prefixed with `"ahk_pid "`. | |
* @static | |
* @type {string} | |
*/ | |
static ahk_pid { | |
get { | |
return "ahk_pid " . this.pid | |
} | |
} | |
/** | |
* Returns the process name of the active window. | |
* @static | |
* @type {string} | |
*/ | |
static exe { | |
get { | |
processName := WinGetProcessName("A") | |
return processName | |
} | |
} | |
/** | |
* It is the same as the `exe` property except that it is prefixed with `"ahk_exe "`. | |
* @static | |
* @type {string} | |
*/ | |
static ahk_exe { | |
get { | |
return "ahk_exe " . this.exe | |
} | |
} | |
/** | |
* Returns the window text of the active window. | |
* @static | |
* @type {string} | |
*/ | |
static text { | |
get { | |
text := WinGetText("A") | |
return text | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment