Windows global Hooks

Posted on 2001-08-10
Last Modified: 2013-12-03
Hi all,

Need help with Windows Hooks...

I'm trying to insert a global Mouse Hook into the system chain. But it's not working working according to plan. It almost looks like it's active only on my current application.

I have the main application that inserts the hook by calling SetWindowsHookEx. The hook procedure itself resides in a DLL. Right now I have the hook procedure simply intercept the WM_MOUSEMOVE message globaly accross all applications. When a message is intercepted, I display the window handle (hwnd) and x/y positions of the mouse associated with the message on my main application (exe) by simply calling the DrawText function within my WM_PAINT. The problem is that the message is only being displayed when the hook intercepts WM_MOUSEMOVE messages for my application ONLY instead of all of the windows on the system.

Here's what I have:
In my main application (.exe) I have:

//global declarations
typedef void (*MYPROC) (LPTSTR msg);
MYPROC  ProcAdd;
char szStartMsg[1024];

//in my WM_CREATE message
//ProcAdd - getMyMsg is called to get a string from the DLL
//ProcHook - myMouseHook is the MouseProc hook function
hdll=LoadLibrary((LPCTSTR)szAppDll);//load the library
if (hdll!=NULL){
    (ProcAdd) = ((MYPROC)  GetProcAddress(hdll,(LPCSTR)"getMyMsg"));
    (ProcHook)= ((HOOKPROC)GetProcAddress(hdll,(LPCSTR)"myMouseHook"));

//install the hook GLOBALLY
hhook = SetWindowsHookEx(WH_MOUSE,ProcHook,hdll,0);

//in my WM_PAINT message
//call getMyMsg to get a string from the dll and place it in msg
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rect) ;
DrawText (hdc, szStartMsg, -1, &rect,DT_SINGLELINE) ;
EndPaint (hwnd, &ps) ;

Then, in my DLL the ProcAdd (getMymsg) function is defined as:
extern "C" void getMyMsg(LPTSTR msg){    
}//end getMyInt

And, my MouseProc hook function (myMouseHook) is defined as:
extern "C" LRESULT CALLBACK myMouseHook(int nCode, WPARAM wParam, LPARAM lParam){

   if (nCode < 0){ // do not process the message
      return CallNextHookEx(hhook, nCode, wParam, lParam);

   }else if (nCode==HC_ACTION){

      //capture the WM_MOUSEMOVE          
      if (wParam==WM_MOUSEMOVE){

         //place the hwnd, x and y data in the szHook variable
         sprintf(szHook,"hwnd=[%u], x=[%i],y=[%i]",
      }//end if wParam
   }//end if (nCode)
   return CallNextHookEx(hhook, nCode, wParam, lParam);
}//end myMouseHook

szHook is being written to in the hook function.
Then szHook is returned to the calling app through a call to getMyMsg.
Therefore, each time the application receives a WM_PAINT message, it should
display the current mouse position and window handle of the window in which
the mouse resides over...

In the main app, I have a 1 second timer enabled to force a WM_PAINT and
therefore repaint the window...

Like I said above, the application does display the mouse position and
window handle every second as long as I move the mouse over my main application. As
soon as I move the mouse over another application, my app doesn't display the message
even though it's being repainted.

If you need additional info, e-mail me at or just post a message here.

Any help would be appreciated...

Question by:vorlon

Accepted Solution

robpitt earned 100 total points
ID: 6373295
There are numerous samples of using SetWindowsHookEx with a dll. I suggest searching for "SetWindowsHookEx DLL" and reading some of the documents found.

Here is a sample of my own which deals with WH_CBT though you could adapt it to any hook type:

The key point is that the hHook value returned by SetWindowsHook() needs to be propagated to all other instances of the hook DLL as loaded by other processes. The easiest way to do this is via a shared data segment. Any other data that needs to be accesible to all instances of the DLL must also be shared between DLL instances.

LVL 20

Expert Comment

ID: 6373560
Rob is absolutely right (of course). Just a little additional explanation:

When doing global hooks, your dll is not only loaded into your own process, but a copy of your dll is loaded into each and every GUI processes system wide (that is the reason why the callback function has to be in a dll). But the global variables of the dll are only correctly initialized in the copy of the dll, which is loaded into your own application. Furthermore you're only calling the "getMyMsg" function of the copy of the dll, that is loaded in your own application. All the other dlls have their own "szHook" buffers.

The solution is to put at least the szHook and the hHook variable into a shared segment, so that they are shared between all loaded copies of your dll. Please don't ask me about how the syntax for shared segments is in C++ (I'm a Delphi programmer), but I guess, you'll find enough examples with it on the net...

Regards, Madshi.

Author Comment

ID: 6374174
Thanks guys...

It totally escaped me what Madshi said:
"When doing global hooks, your dll is not only loaded into your own process, but a copy of your dll is
loaded into each and every GUI processes system wide (that is the reason why the callback function has
to be in a dll). "

Once I shared the memory (easy), it all worked...

Since Rob was the first one to suggest a shared memory correction, you get the points...

Thanks both of you...

Featured Post

Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
How To Display a Conditional Image in a Microsoft Access Report 23 95
wordpress limitations 4 115
Post a good COM tutorial 1 54
What namespace do I need to import? 2 28
As more and more people are shifting to the latest .Net frameworks, the windows presentation framework is gaining importance by the day. Many people are now turning to WPF controls to provide a rich user experience. I have been using WPF controls fo…
For a while now I'v been searching for a circular progress control, much like the one you get when first starting your Silverlight application. I found a couple that were written in WPF and there were a few written in Silverlight, but all appeared o…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA.…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

776 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question