Window hooking?
Window hooking?
Anyone know how to perform window hooking so I know when a third-party
window is opening? I'd like to make the Windows Calculator always open in
the center of the Desktop, but not move it after it's opened.
window is opening? I'd like to make the Windows Calculator always open in
the center of the Desktop, but not move it after it's opened.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
"PureBasic won't be object oriented, period" - Fred.
-
- User
- Posts: 41
- Joined: Fri Aug 22, 2003 7:10 pm
- Location: 76 (FRANCE)
- Contact:
Try there : http://www.codeproject.com/system/hooksys.asp
Re: Window hooking?
Thanks Heis, but I'm still confused over this.
If you look at http://tinyurl.com/5dzq7 there's an example of how to position
a MessageBox before it's displayed (click the "Listing 1" link in the article);
however I've not been successful in converting it to PureBasic. Anyone able
to offer any advice? Thanks.
If you look at http://tinyurl.com/5dzq7 there's an example of how to position
a MessageBox before it's displayed (click the "Listing 1" link in the article);
however I've not been successful in converting it to PureBasic. Anyone able
to offer any advice? Thanks.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
"PureBasic won't be object oriented, period" - Fred.
-
- User
- Posts: 41
- Joined: Fri Aug 22, 2003 7:10 pm
- Location: 76 (FRANCE)
- Contact:
This code should get you started:
Hook dll:
Program:
For your calculator problem, this should work well, because #WM_CREATE
is send after the window is created, but before it is displayed.
So if you move it from inside the hook procedure, it should work, and also
look good
Hook dll:
Code: Select all
; This is the hook procedure. It must be compiled to a dll.
; Every process on which this hook is installed will load
; this dll and execute the procedure.
;
; Even though you also load this dll from the program that installes
; the hook, you have to keep in mind that this code is mostly excecuted
; inside a foreign process, not the one of your program.
;
; For this example, all the code does is catch a #WM_CREATE message
; and broadcast our own message, so the original program can read
; it. Usually, whatever task needs to be done can be done right here
; inside the procedure, so that extra message is not needed.
;
Global CreateMessage.l
ProcedureDLL AttachProcess(Instance)
CreateMessage = RegisterWindowMessage_("MyHook_Window_Created")
EndProcedure
; This is the hook procedure
; The parameters depend on what type of hook you install.
; This is a hook which is called before the window procedure of the
; process is called.
;
ProcedureDLL MyHookProcedure(nCode.l, wParam.l, *lParam.CWPSTRUCT)
; Just catch this one message.
If *lParam\message = #WM_CREATE
PostMessage_(#HWND_BROADCAST, CreateMessage, *lParam\hwnd, 0)
EndIf
; This is very important to allow multiple hooks to work side by side.
ProcedureReturn CallNextHookEx_(@MyHookProcedure(), nCode, wParam, *lParam)
EndProcedure
Code: Select all
; This is the program that installes the hook.
; Note: it also needs to load the hook dll, even if it itself is not hooked.
; little gui stuff
Enumeration
#GADGET_List
#GADGET_Start
#GADGET_Stop
EndEnumeration
#Hook_Path = "b:\test.dll" ; the hook dll
#LIBRARY_Hook = 0 ; PB id for our dll.
If OpenWindow(0, 0, 0, 400, 400, #PB_Window_SystemMenu|#PB_Window_Screencentered, "Hook example")
If CreateGadgetList(WindowID())
ListViewGadget(#GADGET_List, 5, 5, 390, 365)
ButtonGadget(#GADGET_Start, 5, 375, 120, 20, "Install Hook")
ButtonGadget(#GADGET_Stop, 130, 375, 120, 20, "Remove Hook")
EndIf
DisableGadget(#GADGET_Stop, 1)
CreateMessage = RegisterWindowMessage_("MyHook_Window_Created")
Repeat
Event = WaitWindowEvent()
; here we received our create message..
;
If Event = CreateMessage
hwnd = EventwParam()
Name$ = Space(500)
GetWindowText_(hwnd, @Name$, 500)
AddGadgetItem(#GADGET_List, -1, "WM_CREATE: "+RSet(Hex(hwnd), 8, "0")+" -> "+Name$)
SetGadgetState(#GADGET_List, CountGadgetItems(#GADGET_List)-1)
ElseIf Event = #PB_EventCloseWindow
Quit = 1
ElseIf Event = #PB_EventGadget
Select EventGadgetID()
Case #GADGET_Start
; This code installes the hook.
If OpenLibrary(#LIBRARY_Hook, #Hook_Path)
dllInstance = LibraryID(#LIBRARY_Hook)
dllFunction = IsFunction(#LIBRARY_Hook, "MyHookProcedure")
; If you set the last parameter to a threadid, only this thread will get
; hooked. Like this, every thread is hooked.
HookID = SetWindowsHookEx_(#WH_CALLWNDPROC, dllFunction, dllInstance, #NULL)
If HookID
DisableGadget(#GADGET_Start, 1)
DisableGadget(#GADGET_Stop, 0)
AddGadgetItem(#GADGET_List, -1, "=====> Hook installed")
SetGadgetState(#GADGET_List, CountGadgetItems(#GADGET_List)-1)
EndIf
EndIf
Case #GADGET_Stop
; This removes the hook.. quite simple.
If HookID
UnhookWindowsHookEx_(HookID)
CloseLibrary(#LIBRARY_Hook)
DisableGadget(#GADGET_Start, 0)
DisableGadget(#GADGET_Stop, 1)
AddGadgetItem(#GADGET_List, -1, "=====> Hook removed")
SetGadgetState(#GADGET_List, CountGadgetItems(#GADGET_List)-1)
HookID = 0
EndIf
EndSelect
EndIf
Until Quit
EndIf
; unhook if not allready done.
If HookID
UnhookWindowsHookEx_(HookID)
CloseLibrary(#LIBRARY_Hook)
EndIf
End
is send after the window is created, but before it is displayed.
So if you move it from inside the hook procedure, it should work, and also
look good
quidquid Latine dictum sit altum videtur
Thanks Freak, I'll have a play later on... but I thought it would be a lot simpler
than using a DLL? I'd prefer a standalone exe solution, like that Visual Basic
example uses... if VB can do it, surely PureBasic can? Here's what I've been
testing, but it fails and even crashes my PC sometimes:
than using a DLL? I'd prefer a standalone exe solution, like that Visual Basic
example uses... if VB can do it, surely PureBasic can? Here's what I've been
testing, but it fails and even crashes my PC sometimes:
Code: Select all
; WARNING: Running this *might* crash your PC!
Procedure WindowHook(uMsg,wParam,lParam)
If uMsg=#HCBT_ACTIVATE
AddGadgetItem(0,-1,Str(wParam)) ; Show window handle that just opened?
UnhookWindowsHookEx_(hHook)
EndIf
ProcedureReturn #FALSE
EndProcedure
If OpenWindow(1,300,250,400,200,#PB_Window_SystemMenu,"test")
CreateGadgetList(WindowID())
ListViewGadget(0,0,0,400,200)
hHook=SetWindowsHookEx_(#WH_CBT,@WindowHook(),GetModuleHandle_(0),GetCurrentThreadId_())
Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf
Last edited by PB on Sun Jan 30, 2005 8:45 pm, edited 1 time in total.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
"PureBasic won't be object oriented, period" - Fred.
Well, according to the documentation, you need to have the code located
in a dll if you want the hook to be system wide or on a thread which is not
your own.
And since you want it to work on the calculator, it won't help to hook your
own process.
btw, in your example, you should set the 3rd parameter to 0 instead of
GetModuleHandle_(0). This should only be a instance handle if the code IS
inside a dll, otheweise it should be 0.
in a dll if you want the hook to be system wide or on a thread which is not
your own.
And since you want it to work on the calculator, it won't help to hook your
own process.
btw, in your example, you should set the 3rd parameter to 0 instead of
GetModuleHandle_(0). This should only be a instance handle if the code IS
inside a dll, otheweise it should be 0.
quidquid Latine dictum sit altum videtur
> according to the documentation, you need to have the code located
> in a dll if you want the hook to be system wide
Ah, I see. No wonder you used a DLL then! I'll play with your code then.
Many thanks for your help on this. Hopefully I can get it doing what I want.
> in a dll if you want the hook to be system wide
Ah, I see. No wonder you used a DLL then! I'll play with your code then.
Many thanks for your help on this. Hopefully I can get it doing what I want.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
"PureBasic won't be object oriented, period" - Fred.
Hum, it seems to work fine here.
Did you put the code to move the window in the dll or the main app?
If you put it in the app, the window is of course allready drawn by the time
that the communication from dll to app is done.
But you don't need to do it from the app, this was only for my example,
you should do it from the dll.
Here's the code:
Compile it to a dll and use the above app code to set/remove the hook.
Works fine here.
Did you put the code to move the window in the dll or the main app?
If you put it in the app, the window is of course allready drawn by the time
that the communication from dll to app is done.
But you don't need to do it from the app, this was only for my example,
you should do it from the dll.
Here's the code:
Code: Select all
ProcedureDLL MyHookProcedure(nCode.l, wParam.l, *lParam.CWPSTRUCT)
; Just catch this one message.
If *lParam\message = #WM_CREATE
; only check toplevel windows
If GetWindowLong_(*lParam\hwnd, #GWL_STYLE) & #WS_CHILD = 0
Name$ = Space(1000)
; since this dll is executed by the hooked programm, this call will
; return the calculator executable name
;
GetModuleFileName_(0, @Name$, 1000)
If LCase(GetFilePart(Name$)) = "calc.exe"
; get the window size and move it.
GetWindowRect_(*lParam\hwnd, @Size.RECT)
w = Size\right - Size\left
h = Size\bottom - Size\top
x = (GetSystemMetrics_(#SM_CXSCREEN)-w)/2
y = (GetSystemMetrics_(#SM_CYSCREEN)-h)/2
MoveWindow_(*lParam\hwnd, x, y, w, h, #False)
EndIf
EndIf
EndIf
; This is very important to allow multiple hooks to work side by side.
ProcedureReturn CallNextHookEx_(@MyHookProcedure(), nCode, wParam, *lParam)
EndProcedure
Works fine here.
quidquid Latine dictum sit altum videtur
Enumeration??
Enumeration does not appear to be a valid command.
It's not listed in the online command index either.
I'm running 3.10 - Ebay special
It's not listed in the online command index either.
I'm running 3.10 - Ebay special
Re: Enumeration??
> Enumeration does not appear to be a valid command
It was introduced in v3.80: http://www.purebasic.com/news36.php3
> It's not listed in the online command index either
See: http://www.purebasic.com/documentation/ ... tions.html
I'm running 3.10 - Ebay special
There's your problem. E-mail support@purebasic.com and talk to them.
It was introduced in v3.80: http://www.purebasic.com/news36.php3
> It's not listed in the online command index either
See: http://www.purebasic.com/documentation/ ... tions.html
I'm running 3.10 - Ebay special
There's your problem. E-mail support@purebasic.com and talk to them.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
"PureBasic won't be object oriented, period" - Fred.