WinEventHook example...
#1
Posted 20 May 2007 - 08:49 AM
ie. window creation/deletion, menu navigation, alt-tab, selection changes, scrolling, window activation, foreground, etc., by using the SetWinEventHook function as found here: http://msdn2.microso...y/ms696160.aspx
The SendMessage function is used to inform the script, where lParam points to the hook callback function parameters on stack.
http://www.autohotke...ineventhook.rar
I first tried CBT hooks but overall things were flaky and unreliable...
I am also writing a multiple generic callback DLL, but the code is in such a mess as I tried to integrate a CBT hook into the same DLL, that I'm not going to post it now. It is mostly untested and needs fixing...
JGR
#2
Posted 20 May 2007 - 09:03 AM
Many Thanks!.
I downloaded and tried and the script prompts a missing "GetDeRefInteger()"
Please look into it.
PS: Wow! The DLL is just 2.52KB and can be easily included in an uncompiled script!
#3
Posted 20 May 2007 - 09:10 AM
InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; The caller must ensure that pDest has sufficient capacity. To preserve any existing contents in pDest,
; only pSize number of bytes starting at pOffset are altered in it.
{
Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data.
DllCall("RtlFillMemory", UInt, &pDest + pOffset + A_Index-1, UInt, 1, UChar, pInteger >> 8*(A_Index-1) & 0xFF)
}
ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4)
; pSource is a string (buffer) whose memory area contains a raw/binary integer at pOffset.
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned.
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int).
; pSource must be ByRef to avoid corruption during the formal-to-actual copying process
; (since pSource might contain valid data beyond its first binary zero).
{
Loop %pSize% ; Build the integer by adding up its bytes.
result += *(&pSource + pOffset + A_Index-1) << 8*(A_Index-1)
if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
return result ; Signed vs. unsigned doesn't matter in these cases.
; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
return -(0xFFFFFFFF - result + 1)
}
GetDeRefInteger(pSource, pIsSigned = false, pSize = 4)
; pSource is an integer pointer to a raw/binary integer
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned.
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int).
{
Loop %pSize% ; Build the integer by adding up its bytes.
result += *(pSource + A_Index-1) << 8*(A_Index-1)
if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
return result ; Signed vs. unsigned doesn't matter in these cases.
; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
return -(0xFFFFFFFF - result + 1)
}
SetDeRefInteger(pInteger, pDest, pSize = 4)
; The caller must ensure that *pDest has sufficient capacity and that pDest is a valid dereferencable integer pointer.
; To preserve any existing contents at *pDest, only pSize number of bytes are altered.
{
Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data.
DllCall("RtlFillMemory", UInt, pDest + A_Index-1, UInt, 1, UChar, pInteger >> 8*(A_Index-1) & 0xFF)
}
#4
Posted 20 May 2007 - 02:35 PM
So, does CBT hook works OK or not ?
#5
Posted 20 May 2007 - 03:29 PM
The fact that the DLL is spread across multiple contexts introduces lots of headaches. I even needed to use a mutex...
I'm not going to continue working on the CBT hook, as it is too much of a pain, and didn't work well anyway... (A dodgy AHK script could bring the system to its knees quite easily)
JGR
#6
Posted 20 May 2007 - 03:49 PM
If it works correctly in those half its OK.
You can test your hook if you set your dll to be loaded in all processes via 1 registry key (cant recall the name atm). That is one of the ways and it is limited as dll is loaded in all processes on next start up.
Good idea.I am also writing a multiple generic callback DLL, but the code is in such a mess as I tried to integrate a CBT hook into the same DLL
#7
Posted 20 May 2007 - 04:02 PM
The callback DLL is done now and is here (with hooks un-integrated): http://www.autohotke...pic.php?t=19370
I'll post the hook dll (it should work with any of the windows hooks). Code to use it is clearly commented out in the archive in the first post.
I won't be making any more changes to it...
http://www.autohotke...JGR/cbthook.rar
JGR
#8
Posted 20 May 2007 - 04:10 PM
Thx again.
#9
Supercalifragilistic
Posted 20 May 2007 - 04:31 PM
But I'm a noob in hooking. I know what the hooking process is supposed to do, but ... what is the purpose of your prog ?
I seen that AppsKey and End stops the hooking process, but I didn't seen what it does.
How your prog works ? What does it do ?
Is there a working example ?
What are the events which are hooked ?
More explanations, please....
#10
Posted 20 May 2007 - 04:43 PM
To see it you will need a debug viewer like this one, or just change the code to something more obvious, like FileWrite. (Don't try messagebox, you'll regret it).
It doesn't actually do anything useful at the moment per se, the idea is that you write the functional bit yourselves.
As for how it works: See here. The callback function is in the dll, and sends AHK a message, with a pointer to the parameters of the callback in lParam.
My advice, is that you read carefully about hooking before trying to use it. As if you're not careful, your system will take a *huge* performance hit/hanging.
#11
Supercalifragilistic
Posted 20 May 2007 - 06:55 PM
#12
Posted 21 May 2007 - 07:33 AM
I never heard until today for the first one.
BTW, you should probably create better example with more clear hook unloading. Currently if you don't press a hotkey that says nothing, hook never gets unloaded.
#13
Posted 21 May 2007 - 07:38 AM
#14
Posted 21 May 2007 - 09:12 AM
DetectHiddenWindows, On
event := 0x00008000 ;EVENT_OBJECT_CREATE
hwnd:=WinExist("ahk_pid " . DllCall("GetCurrentProcessId","Uint"))
msg := 0x550
hook_dll = wineventhook\wineventhook.dll
hHookModule := API_LoadLibrary(hook_dll)
hHook := Hook(hwnd, msg, event, event, "HookHandler")
return
!e:
Msgbox % "Unhook: " Unhook(hHook,msg)
return
HookHandler(wParam, lParam, msg, hwnd) {
msgbox Hello from hook
}
Hook(comm_hwnd, comm_msg, s_event, e_event, function, wparam=0) {
global hook_dll
r := DllCall(hook_dll "\reghook", "UInt", comm_hwnd, "UInt", COMM_MSG, "UInt", s_event, "UInt", e_event, "UInt", wparam)
if !r
return 0
OnMessage(COMM_MSG, function)
return r
}
Unhook(handle, com_msg) {
OnMessage(com_msg)
return DllCall("UnhookWinEvent", "UInt", handle)
}
API_LoadLibrary( dll ) {
return DllCall("LoadLibrary", "str", dll)
}
#15
new_noobie
Posted 21 May 2007 - 09:22 AM
have access to my XP box right now, so I tried the "EnumWindows.ahk" script
included in JGR's archive and corrupt's post in this thread, and they both
produce a message box with no output (well corrupt's shows Output1 and
Output2 without and data).
I did look at the msdn link given in the "WinEventHook example..." thread in
this forum and it says that SetWinEventHook is supported in win98 and later.
The box I tried the examples on is win98se. Can anyone show me what might be
needed to get it to work?
@JGR, can the dll be made to function on win9x if it does not now?
thx




