VC中调用系统全局的钩子实现(附注释)

//开辟一个跨进程使用的共享区,因钩子回调函数会自动载入系统的各个应用程序
//因此,回调函数内使用的全局变量均应放入此区域内
//win2000好像 忽略此区域,我没有试验
#pragma data_seg(".webmote")
HWND hWndTarget=NULL;
HHOOK hook=NULL;
HHOOK hookb=NULL;
#pragma data_seg()
#pragma comment(linker, "/section:.webmote,rws")

HINSTANCE hInst=NULL;
UINT UWM_MOUSEMINTOR;
UINT UWM_KBMINTOR;

static LRESULT CALLBACK msghook(UINT nCode, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK kbhook(UINT nCode, WPARAM wParam, LPARAM lParam);

//每一个引用此DLL的程序会自动调用此函数
//因此如果想随DLL清楚钩子的话,请加上调用程序的验证,以防止多个调用此DLL的程序互相影响
//如果需要被多个应用程序用,可能需要维护一个链表,benDLL仅供一个实例调用
BOOL APIENTRY DllMain( HINSTANCE hInstance,
                      DWORD  Reason,
                      LPVOID Reserved
     )
{
switch(Reason)
   { /* reason */
    case DLL_PROCESS_ATTACH:
        hInst = hInstance;
       UWM_MOUSEMINTOR = RegisterWindowMessage(UWM_MOUSEMINTOR_MSG);
       UWM_KBMINTOR=     RegisterWindowMessage(UWM_KBMINTOR_MSG);
       break;
    case DLL_PROCESS_DETACH:
    clearMyHook();    
    //hWndTarget=NULL;
    //hook=NULL;
    //hookb=NULL;
    break;
   } /* reason */
   return TRUE;
}


/****************************************************************************
*                                 setMyHook
* Inputs:
*       hWndParent ,window handle of target post message
* Result: BOOL
*       TRUE if successful
* FALSE if error
* Effect:
*       Sets the hook
****************************************************************************/

BOOL LIBSPEC setMyHook(HWND hWnd)
{
    if(hook != NULL || hookb!=NULL)
 return FALSE; // already hooked!
 //
 // 安装鼠标钩子
 // 安装一个全局钩子,线程ID指定0,安装特定线程得监控程序,指定为
 //  ::GetWindowThreadProcessId(hWndTargetProcess,NULL)
 //  
 hWndTarget=hWnd;
    hook = ::SetWindowsHookEx(WH_MOUSE, //鼠标钩子
      (HOOKPROC)msghook,
      hInst,
   0); //::GetWindowThreadProcessId(hWndTargetProcess,NULL)
 hookb=::SetWindowsHookEx(WH_KEYBOARD, //键盘钩子
      (HOOKPROC)kbhook,
      hInst,
   0);
   if(!(hook == NULL || hookb==NULL))
{ /* success */
  return TRUE;
}
else
{  
 clearMyHook();
 return FALSE;
}  
} // setMyHook

BOOL LIBSPEC clearMyHook()
{
  //检测是否同一个线程关闭本hook得
 DWORD dwStart= ::GetWindowThreadProcessId(hWndTarget,NULL);  
 DWORD dwEnd=::GetCurrentThreadId();
  if(dwEnd!=dwStart)return FALSE; //不是调用线程不能关闭
  BOOL bResult=FALSE;
 if(hook==NULL || hookb==NULL)
 {
 if(hookb!=NULL)
 {
  ::UnhookWindowsHookEx(hookb);
  hookb=NULL;
 }
 if(hook!=NULL)
 {
  ::UnhookWindowsHookEx(hook);
  hook=NULL;
 }
 hWndTarget=NULL;
 return bResult;
 }
 else
 {
 bResult=::UnhookWindowsHookEx(hookb);
 BOOL unhooked =::UnhookWindowsHookEx(hook);
 hookb=NULL;
 hook=NULL;
 hWndTarget=NULL;
 return bResult && unhooked;
 }
 
} // clearMyHook

static LRESULT CALLBACK msghook(UINT nCode, WPARAM wParam, LPARAM lParam)
{
    if(nCode < 0)
{ /* pass it on */
 ::CallNextHookEx(hook, nCode, wParam, lParam);
 return 0;
} /* pass it on */
 if(nCode!=HC_NOREMOVE)
 {
   if(wParam==WM_LBUTTONDBLCLK || wParam==WM_LBUTTONDOWN ||
   wParam==WM_RBUTTONDOWN || wParam==WM_MBUTTONDOWN ||
   wParam==WM_NCLBUTTONDBLCLK || wParam==WM_NCLBUTTONDOWN ||
   wParam==WM_NCRBUTTONDOWN || wParam==WM_NCMBUTTONDOWN )
  {
  //LPMOUSEHOOKSTRUCT msg = (LPMOUSEHOOKSTRUCT)lParam;
   ::PostMessage(hWndTarget, UWM_MOUSEMINTOR, wParam, lParam);
  }
 }

    return ::CallNextHookEx(hook, nCode, wParam, lParam);
} // msghook

static LRESULT CALLBACK kbhook(UINT nCode, WPARAM wParam, LPARAM lParam)
{
    if(nCode < 0)
{ /* pass it on */
 ::CallNextHookEx(hookb, nCode, wParam, lParam);
 return 0;
} /* pass it on */
  if(nCode!=HC_NOREMOVE && (lParam>>31)==0) //keydown
 {
 //LPMOUSEHOOKSTRUCT msg = (LPMOUSEHOOKSTRUCT)lParam;
  ::PostMessage(hWndTarget, UWM_KBMINTOR, wParam, lParam);
 }

    return ::CallNextHookEx(hookb, nCode, wParam, lParam);
} // kb hook 
 

你可能感兴趣的:(VC中调用系统全局的钩子实现(附注释))