simplified WinEvents

Post your working scripts, libraries and tools
User avatar
KuroiLight
Posts: 327
Joined: 12 Apr 2015, 20:24
GitHub: KuroiLight

simplified WinEvents

10 Jan 2018, 20:54

I tried to simplify SetWinEventHook as much as I could for ease of usage. May expand it later.
You can set a WinEvent hook for any of the available events without the min/max range requirement.
You can add events to a callbacks hook after initial usage and remove events from the hook without removing all of them.

To Add an event hook use:
HookEvent(functionname, events, pid := "0", flags := "0")
functionname is a string name of the function, processId filter and dwflags optional, events must be an array of event constants (listed in WinEvents.ahk)
the function specified by function name must have the definition like: WinEventProc(hHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime)
To remove an event hook use:
UnHookEvent(functionname, events)
params same as above

WinEvents.ahk:

Code: Select all

;Event Library
;Version: 1.0
;Author: KuroiLight/klomb
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;https://msdn.microsoft.com/en-us/library/windows/desktop/dd373640(v=vs.85).aspx
;dwFlags: Flag values that specify the location of the hook function and of the events to be skipped.
global WINEVENT_OUTOFCONTEXT := 0x0000
     , WINEVENT_SKIPOWNTHREAD := 0x0001
     , WINEVENT_SKIPOWNPROCESS := 0x0002
     , WINEVENT_INCONTEXT := 0x0004

;https://msdn.microsoft.com/en-us/library/windows/desktop/dd318066(v=vs.85).aspx
;eventMin/eventMax: Specifies the event constant for the lowest/highest event value in the range of events that are handled by the hook function.
;0x00000001-0x7FFFFFFF
global EVENT_OBJECT_ACCELERATORCHANGE := 0x8012
     , EVENT_OBJECT_CLOAKED := 0x8017
     , EVENT_OBJECT_CONTENTSCROLLED := 0x8015
     , EVENT_OBJECT_CREATE := 0x8000
     , EVENT_OBJECT_DEFACTIONCHANGE := 0x8011
     , EVENT_OBJECT_DESCRIPTIONCHANGE := 0x800D
     , EVENT_OBJECT_DESTROY := 0x8001
     , EVENT_OBJECT_DRAGSTART := 0x8021
     , EVENT_OBJECT_DRAGCANCEL := 0x8022
     , EVENT_OBJECT_DRAGCOMPLETE := 0x8023
     , EVENT_OBJECT_DRAGENTER := 0x8024
     , EVENT_OBJECT_DRAGLEAVE := 0x8025
     , EVENT_OBJECT_DRAGDROPPED := 0x8026
     , EVENT_OBJECT_END := 0x80FF
     , EVENT_OBJECT_FOCUS := 0x8005
     , EVENT_OBJECT_HELPCHANGE := 0x8010
     , EVENT_OBJECT_HIDE := 0x8003
     , EVENT_OBJECT_HOSTEDOBJECTSINVALIDATED := 0x8020
     , EVENT_OBJECT_IME_HIDE := 0x8028
     , EVENT_OBJECT_IME_SHOW := 0x8027
     , EVENT_OBJECT_IME_CHANGE := 0x8029
     , EVENT_OBJECT_INVOKED := 0x8013
     , EVENT_OBJECT_LIVEREGIONCHANGED := 0x8019
     , EVENT_OBJECT_LOCATIONCHANGE := 0x800B
     , EVENT_OBJECT_NAMECHANGE := 0x800C
     , EVENT_OBJECT_PARENTCHANGE := 0x800F
     , EVENT_OBJECT_REORDER := 0x8004
     , EVENT_OBJECT_SELECTION := 0x8006
     , EVENT_OBJECT_SELECTIONADD := 0x8007
     , EVENT_OBJECT_SELECTIONREMOVE := 0x8008
     , EVENT_OBJECT_SELECTIONWITHIN := 0x8009
     , EVENT_OBJECT_SHOW := 0x8002
     , EVENT_OBJECT_STATECHANGE := 0x800A
     , EVENT_OBJECT_TEXTEDIT_CONVERSIONTARGETCHANGED := 0x8030
     , EVENT_OBJECT_TEXTSELECTIONCHANGED := 0x8014
     , EVENT_OBJECT_UNCLOAKED := 0x8018
     , EVENT_OBJECT_VALUECHANGE := 0x800E
     , EVENT_SYSTEM_ALERT := 0x0002
     , EVENT_SYSTEM_ARRANGMENTPREVIEW := 0x8016
     , EVENT_SYSTEM_CAPTUREEND := 0x0009
     , EVENT_SYSTEM_CAPTURESTART := 0x0008
     , EVENT_SYSTEM_CONTEXTHELPEND := 0x000D
     , EVENT_SYSTEM_CONTEXTHELPSTART := 0x000C
     , EVENT_SYSTEM_DESKTOPSWITCH := 0x0020
     , EVENT_SYSTEM_DIALOGEND := 0x0011
     , EVENT_SYSTEM_DIALOGSTART := 0x0010
     , EVENT_SYSTEM_DRAGDROPEND := 0x000F
     , EVENT_SYSTEM_DRAGDROPSTART := 0x000E
     , EVENT_SYSTEM_END := 0x00FF
     , EVENT_SYSTEM_FOREGROUND := 0x0003
     , EVENT_SYSTEM_MENUPOPUPEND := 0x0007
     , EVENT_SYSTEM_MENUPOPUPSTART := 0x0006
     , EVENT_SYSTEM_MENUEND := 0x0005
     , EVENT_SYSTEM_MENUSTART := 0x0004
     , EVENT_SYSTEM_MINIMIZEEND := 0x0017
     , EVENT_SYSTEM_MINIMIZESTART := 0x0016
     , EVENT_SYSTEM_MOVESIZEEND := 0x000B
     , EVENT_SYSTEM_MOVESIZESTART := 0x000A
     , EVENT_SYSTEM_SCROLLINGEND := 0x0013
     , EVENT_SYSTEM_SCROLLINGSTART := 0x0012
     , EVENT_SYSTEM_SOUND := 0x0001
     , EVENT_SYSTEM_SWITCHEND := 0x0015
     , EVENT_SYSTEM_SWITCHSTART := 0x0014

/*
    ;C callback definition
    void CALLBACK WinEventProc(
       HWINEVENTHOOK hWinEventHook,
       DWORD         event,
       HWND          hwnd,
       LONG          idObject,
       LONG          idChild,
       DWORD         dwEventThread,
       DWORD         dwmsEventTime
    );
    ;AHK callback definition
    WinEventProc(hHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime)
*/

EventHookTable := {}, _hHookTable := {}

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

HookEvent(functionname, events, pid := "0", flags := "0") {
    global EventHookTable
    
    for i, event_id in events {
        if(!EventHookTable[event_id])
            EventHookTable[event_id] := Array() 
        if(CreateWinEventHook(functionname, event_id, pid, flags))
            EventHookTable[event_id].Push(functionname)
    }
}

UnHookEvent(functionname, events) {
    global EventHookTable

    for i, event_id in events {
        if(EventHookTable[event_id]) {
            for i2, v2 in EventHookTable[event_id] {
                if(v2 == functionname) {
                    DeleteWinEventHook(functionname, event_id)
                    EventHookTable[event_id].RemoveAt(i2)
                }
            }
            if(EventHookTable[event_id].Length() == 0)
                EventHookTable.Delete(event_id)
        }
    }
}

CreateWinEventHook(functionname, event, pids := "0", dwflags := "0") {
    global _hHookTable

    cb := RegisterCallback(functionname)
    DeleteWinEventHook(functionname, event)
    DllCall("CoInitialize", UInt, 0)
    if(hHook := DllCall("SetWinEventHook", UInt, event, UInt, event, UInt, 0, UInt, cb, UInt, pids, UInt, 0, UInt, dwflags))
        _hHookTable[functionname . "_" . event] := hHook

    return (hHook != 0)
}

DeleteWinEventHook(functionname, event) {
    global _hHookTable
    
    hHook := _hHookTable.Delete(functionname . "_" . event)

    return (hHook != 0 ? DllCall("UnhookWinEvent", UInt, hHook) : false)
}
Eample Usage:

Code: Select all

#Include .\WinEvents.ahk

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

HookEvent("WinEventProc", [EVENT_OBJECT_HIDE,EVENT_OBJECT_SHOW])
HookEvent("WinEventProc", [EVENT_OBJECT_FOCUS]) ;add another event to be passed to this function.
Sleep, 10000
UnHookEvent("WinEventProc", [EVENT_OBJECT_HIDE]) ; only remove the events that you want.
ExitApp, 0

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
return

WinEventProc(hHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime) {
    DetectHiddenWindows, On
    WinGet, pid, PID, ahk_id %hwnd%
    WinGet, pname, ProcessName, ahk_pid %pid%

    FileAppend, % "WinEventProc: " . hHook . ", " . event . ", " . hwnd . ", " . idObject . ", " . idChild . ", " . dwEventThread . ", " . dwmsEventTime . "`n", *
    FileAppend, % "`t" . pname . "`n", *
    return 0
}
Last edited by KuroiLight on 10 Jan 2018, 20:58, edited 2 times in total.
Windows 10, Ryzen 1600, 16GB G.Skill DDR4, 8GB RX 480 | [MyScripts][MySublimeSettings] [Unlicense][MIT License]
01/24/18
[/color]
guest3456
Posts: 2419
Joined: 09 Oct 2013, 10:31

Re: simplified WinEvents

10 Jan 2018, 20:56

haven't tried it, but looks like nice work

AHKStudent
Posts: 308
Joined: 05 May 2018, 12:23

Re: simplified WinEvents

22 May 2018, 21:53

KuroiLight wrote:I tried to simplify SetWinEventHook as much as I could for ease of usage. May expand it later.
You can set a WinEvent hook for any of the available events without the min/max range requirement.
You can add events to a callbacks hook after initial usage and remove events from the hook without removing all of them.

To Add an event hook use:
HookEvent(functionname, events, pid := "0", flags := "0")
functionname is a string name of the function, processId filter and dwflags optional, events must be an array of event constants (listed in WinEvents.ahk)
the function specified by function name must have the definition like: WinEventProc(hHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime)
To remove an event hook use:
UnHookEvent(functionname, events)
params same as above

WinEvents.ahk:

Code: Select all

;Event Library
;Version: 1.0
;Author: KuroiLight/klomb
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;https://msdn.microsoft.com/en-us/library/windows/desktop/dd373640(v=vs.85).aspx
;dwFlags: Flag values that specify the location of the hook function and of the events to be skipped.
global WINEVENT_OUTOFCONTEXT := 0x0000
     , WINEVENT_SKIPOWNTHREAD := 0x0001
     , WINEVENT_SKIPOWNPROCESS := 0x0002
     , WINEVENT_INCONTEXT := 0x0004

;https://msdn.microsoft.com/en-us/library/windows/desktop/dd318066(v=vs.85).aspx
;eventMin/eventMax: Specifies the event constant for the lowest/highest event value in the range of events that are handled by the hook function.
;0x00000001-0x7FFFFFFF
global EVENT_OBJECT_ACCELERATORCHANGE := 0x8012
     , EVENT_OBJECT_CLOAKED := 0x8017
     , EVENT_OBJECT_CONTENTSCROLLED := 0x8015
     , EVENT_OBJECT_CREATE := 0x8000
     , EVENT_OBJECT_DEFACTIONCHANGE := 0x8011
     , EVENT_OBJECT_DESCRIPTIONCHANGE := 0x800D
     , EVENT_OBJECT_DESTROY := 0x8001
     , EVENT_OBJECT_DRAGSTART := 0x8021
     , EVENT_OBJECT_DRAGCANCEL := 0x8022
     , EVENT_OBJECT_DRAGCOMPLETE := 0x8023
     , EVENT_OBJECT_DRAGENTER := 0x8024
     , EVENT_OBJECT_DRAGLEAVE := 0x8025
     , EVENT_OBJECT_DRAGDROPPED := 0x8026
     , EVENT_OBJECT_END := 0x80FF
     , EVENT_OBJECT_FOCUS := 0x8005
     , EVENT_OBJECT_HELPCHANGE := 0x8010
     , EVENT_OBJECT_HIDE := 0x8003
     , EVENT_OBJECT_HOSTEDOBJECTSINVALIDATED := 0x8020
     , EVENT_OBJECT_IME_HIDE := 0x8028
     , EVENT_OBJECT_IME_SHOW := 0x8027
     , EVENT_OBJECT_IME_CHANGE := 0x8029
     , EVENT_OBJECT_INVOKED := 0x8013
     , EVENT_OBJECT_LIVEREGIONCHANGED := 0x8019
     , EVENT_OBJECT_LOCATIONCHANGE := 0x800B
     , EVENT_OBJECT_NAMECHANGE := 0x800C
     , EVENT_OBJECT_PARENTCHANGE := 0x800F
     , EVENT_OBJECT_REORDER := 0x8004
     , EVENT_OBJECT_SELECTION := 0x8006
     , EVENT_OBJECT_SELECTIONADD := 0x8007
     , EVENT_OBJECT_SELECTIONREMOVE := 0x8008
     , EVENT_OBJECT_SELECTIONWITHIN := 0x8009
     , EVENT_OBJECT_SHOW := 0x8002
     , EVENT_OBJECT_STATECHANGE := 0x800A
     , EVENT_OBJECT_TEXTEDIT_CONVERSIONTARGETCHANGED := 0x8030
     , EVENT_OBJECT_TEXTSELECTIONCHANGED := 0x8014
     , EVENT_OBJECT_UNCLOAKED := 0x8018
     , EVENT_OBJECT_VALUECHANGE := 0x800E
     , EVENT_SYSTEM_ALERT := 0x0002
     , EVENT_SYSTEM_ARRANGMENTPREVIEW := 0x8016
     , EVENT_SYSTEM_CAPTUREEND := 0x0009
     , EVENT_SYSTEM_CAPTURESTART := 0x0008
     , EVENT_SYSTEM_CONTEXTHELPEND := 0x000D
     , EVENT_SYSTEM_CONTEXTHELPSTART := 0x000C
     , EVENT_SYSTEM_DESKTOPSWITCH := 0x0020
     , EVENT_SYSTEM_DIALOGEND := 0x0011
     , EVENT_SYSTEM_DIALOGSTART := 0x0010
     , EVENT_SYSTEM_DRAGDROPEND := 0x000F
     , EVENT_SYSTEM_DRAGDROPSTART := 0x000E
     , EVENT_SYSTEM_END := 0x00FF
     , EVENT_SYSTEM_FOREGROUND := 0x0003
     , EVENT_SYSTEM_MENUPOPUPEND := 0x0007
     , EVENT_SYSTEM_MENUPOPUPSTART := 0x0006
     , EVENT_SYSTEM_MENUEND := 0x0005
     , EVENT_SYSTEM_MENUSTART := 0x0004
     , EVENT_SYSTEM_MINIMIZEEND := 0x0017
     , EVENT_SYSTEM_MINIMIZESTART := 0x0016
     , EVENT_SYSTEM_MOVESIZEEND := 0x000B
     , EVENT_SYSTEM_MOVESIZESTART := 0x000A
     , EVENT_SYSTEM_SCROLLINGEND := 0x0013
     , EVENT_SYSTEM_SCROLLINGSTART := 0x0012
     , EVENT_SYSTEM_SOUND := 0x0001
     , EVENT_SYSTEM_SWITCHEND := 0x0015
     , EVENT_SYSTEM_SWITCHSTART := 0x0014

/*
    ;C callback definition
    void CALLBACK WinEventProc(
       HWINEVENTHOOK hWinEventHook,
       DWORD         event,
       HWND          hwnd,
       LONG          idObject,
       LONG          idChild,
       DWORD         dwEventThread,
       DWORD         dwmsEventTime
    );
    ;AHK callback definition
    WinEventProc(hHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime)
*/

EventHookTable := {}, _hHookTable := {}

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

HookEvent(functionname, events, pid := "0", flags := "0") {
    global EventHookTable
    
    for i, event_id in events {
        if(!EventHookTable[event_id])
            EventHookTable[event_id] := Array() 
        if(CreateWinEventHook(functionname, event_id, pid, flags))
            EventHookTable[event_id].Push(functionname)
    }
}

UnHookEvent(functionname, events) {
    global EventHookTable

    for i, event_id in events {
        if(EventHookTable[event_id]) {
            for i2, v2 in EventHookTable[event_id] {
                if(v2 == functionname) {
                    DeleteWinEventHook(functionname, event_id)
                    EventHookTable[event_id].RemoveAt(i2)
                }
            }
            if(EventHookTable[event_id].Length() == 0)
                EventHookTable.Delete(event_id)
        }
    }
}

CreateWinEventHook(functionname, event, pids := "0", dwflags := "0") {
    global _hHookTable

    cb := RegisterCallback(functionname)
    DeleteWinEventHook(functionname, event)
    DllCall("CoInitialize", UInt, 0)
    if(hHook := DllCall("SetWinEventHook", UInt, event, UInt, event, UInt, 0, UInt, cb, UInt, pids, UInt, 0, UInt, dwflags))
        _hHookTable[functionname . "_" . event] := hHook

    return (hHook != 0)
}

DeleteWinEventHook(functionname, event) {
    global _hHookTable
    
    hHook := _hHookTable.Delete(functionname . "_" . event)

    return (hHook != 0 ? DllCall("UnhookWinEvent", UInt, hHook) : false)
}
Eample Usage:

Code: Select all

#Include .\WinEvents.ahk

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

HookEvent("WinEventProc", [EVENT_OBJECT_HIDE,EVENT_OBJECT_SHOW])
HookEvent("WinEventProc", [EVENT_OBJECT_FOCUS]) ;add another event to be passed to this function.
Sleep, 10000
UnHookEvent("WinEventProc", [EVENT_OBJECT_HIDE]) ; only remove the events that you want.
ExitApp, 0

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
return

WinEventProc(hHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime) {
    DetectHiddenWindows, On
    WinGet, pid, PID, ahk_id %hwnd%
    WinGet, pname, ProcessName, ahk_pid %pid%

    FileAppend, % "WinEventProc: " . hHook . ", " . event . ", " . hwnd . ", " . idObject . ", " . idChild . ", " . dwEventThread . ", " . dwmsEventTime . "`n", *
    FileAppend, % "`t" . pname . "`n", *
    return 0
}
Is there a way to use this script to detect anytime WM_GETTEXT is called and to report back the process that called it?

Thank you
User avatar
KuroiLight
Posts: 327
Joined: 12 Apr 2015, 20:24
GitHub: KuroiLight

Re: simplified WinEvents

23 May 2018, 23:12

AHKStudent wrote:
Is there a way to use this script to detect anytime WM_GETTEXT is called and to report back the process that called it?

Thank you
been a while since I touched this, but as far as I know not unless the WM_GETTEXT message is being sent to the process that is running this code.
Windows 10, Ryzen 1600, 16GB G.Skill DDR4, 8GB RX 480 | [MyScripts][MySublimeSettings] [Unlicense][MIT License]
01/24/18
[/color]

Return to “Scripts and Functions”

Who is online

Users browsing this forum: No registered users and 27 guests