?
Solved

Windows global Hooks

Posted on 2001-08-10
3
Medium Priority
?
1,500 Views
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;
HOOKPROC ProcHook;
HINSTANCE hdll;
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
(ProcAdd)(msg);
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rect) ;
sprintf(szStartMsg,"%s",msg);
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){    
     sprintf(msg,szHook);
}//end getMyInt


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


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

   }else if (nCode==HC_ACTION){
      PMOUSEHOOKSTRUCT=(MOUSEHOOKSTRUCT *)lParam;

      //capture the WM_MOUSEMOVE          
      if (wParam==WM_MOUSEMOVE){
         memset(szHook,0,1024);

         //place the hwnd, x and y data in the szHook variable
         sprintf(szHook,"hwnd=[%u], x=[%i],y=[%i]",
             PMOUSEHOOKSTRUCT->hwnd,
             PMOUSEHOOKSTRUCT->pt.x,
             PMOUSEHOOKSTRUCT->pt.y);
      }//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 santos@traxxinc.net or just post a message here.

Any help would be appreciated...

Thanks
Vorlon
0
Comment
Question by:vorlon
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
3 Comments
 
LVL 5

Accepted Solution

by:
robpitt earned 400 total points
ID: 6373295
There are numerous samples of using SetWindowsHookEx with a dll. I suggest searching msdn.microsoft.com 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:
http://website.lineone.net/~codebox/focuslog.zip


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.

Rob
0
 
LVL 20

Expert Comment

by:Madshi
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.
0
 
LVL 2

Author Comment

by:vorlon
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...
Vorlon
0

Featured Post

NFR key for Veeam Agent for Linux

Veeam is happy to provide a free NFR license for one year.  It allows for the non‑production use and valid for five workstations and two servers. Veeam Agent for Linux is a simple backup tool for your Linux installations, both on‑premises and in the public cloud.

Question has a verified solution.

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

This article shows how to make a Windows 7 gadget that accepts files dropped from the Windows Explorer.  It also illustrates how to give your gadget a non-rectangular shape and how to add some nifty visual effects to text displayed in a your gadget.…
This article shows how to make a Windows 7 gadget that extends its U/I with a flyout panel -- a window that pops out next to the gadget.  The example gadget shows several additional techniques:  How to automatically resize a gadget or flyout panel t…
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. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
This tutorial will teach you the special effect of super speed similar to the fictional character Wally West aka "The Flash" After Shake : http://www.videocopilot.net/presets/after_shake/ All lightning effects with instructions : http://www.mediaf…

800 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