simplified WinEvents

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
KuroiLight
Posts: 327
Joined: 12 Apr 2015, 20:24
Contact:

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: 3454
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: 1472
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
Contact:

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]
Archimede
Posts: 464
Joined: 25 Nov 2021, 09:49
Location: Switzerland / Italy

Re: simplified WinEvents

26 Nov 2022, 12:13

Hallo.
I am testing your functions, that seem very interesting and useful.
I think you made a very complicate and very useful work.
I downloaded WinEvents.ahk; I am documenting all ( the constants and th functions ): are you interested I will send you the documented script?

I need to know the meaning of some things.
About the UDF functionn must be declared like the first argument on HookEvent( ... ): that UDF function mud be defined with 7 arguments: what is the meaning of any one?
What is hHook ( Handle to an event hook function ): how I can handle it by AutoHotKey functions?
What is hWnd ( Handle to the window that generates the event ): how I can handle it by AutoHotKey functions?
What is idObject ( Identifies the object associated with the event ): how I can handle it by AutoHotKey functions?
What is idChild ( Identifies whether the event was triggered by an object or a child element of the object ): how I can handle it by AutoHotKey functions?
What is dwEventThread ( I no found any description about it ): what is and how I can handle it by AutoHotKey functions?
What is dwmsEventTime ( Specifies the time, in milliseconds, that the event was generated ): what time? the absolute time or the time calculated starting from a time?

I think all these information can be useful for everyone; I am makink the documentation of your work: if you like I will send it at the end.
Thank you very much
User avatar
andymbody
Posts: 867
Joined: 02 Jul 2017, 23:47

Re: simplified WinEvents

01 Mar 2024, 14:25

Thank you!

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: Basi, nitsik and 149 guests