//开辟一个跨进程使用的共享区,因钩子回调函数会自动载入系统的各个应用程序
//因此,回调函数内使用的全局变量均应放入此区域内
//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