全局键盘(鼠标)钩子的dll问题(刚才忘记分数了)

rollrock1987 2008-08-19 04:04:09
想写一个全局的 键盘(鼠标)钩子,用来判断键盘或者鼠标已经空闲了多少时间即:鼠标和键盘没有输入。在写的过程中遇到了如下问题:
我用两种方法写的两个dll 其中一个是可以成功实现键盘(鼠标)钩子的,还有一个只能钩到对话框上的鼠标和键盘消息(因为我的测试程序的是一个对话框程序)
先看下成功的这个dll:这个dll 没有用头文件 对导出函数(就是在测试程序里面要用的函数,应该是这样叫的吧)进行声明。而是用了一个def文件
#include "stdafx.h"

#define DLLEXPORT __declspec(dllexport)

#pragma data_seg (".MouseKeyHook")
HHOOK g_hHookKbd = NULL;
HHOOK g_hHookMouse = NULL;
DWORD g_dwLastInputTick = 0;

#pragma data_seg ()

HINSTANCE hInst =NULL;

BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch( ul_reason_for_call )
{
case DLL_PROCESS_ATTACH:
hInst=(HINSTANCE)hModule;
break;

}
return TRUE;
}

DLLEXPORT DWORD GetLastMouseKeyTime()
{
return g_dwLastInputTick;
}


LRESULT CALLBACK MyKbdHook(int code, WPARAM wParam, LPARAM lParam)
{
if (code==HC_ACTION)
{
g_dwLastInputTick = GetTickCount();
}
return ::CallNextHookEx(g_hHookKbd, code, wParam, lParam);
}

LRESULT CALLBACK MyMouseHook(int code, WPARAM wParam, LPARAM lParam)
{
if (code==HC_ACTION) {
g_dwLastInputTick = GetTickCount();
}
return ::CallNextHookEx(g_hHookMouse, code, wParam, lParam);
}

DLLEXPORT BOOL InitHook()
{
if (g_hHookKbd == NULL) {

g_hHookKbd = SetWindowsHookEx(WH_KEYBOARD, MyKbdHook, hInst, 0);
g_hHookMouse = SetWindowsHookEx(WH_MOUSE, MyMouseHook, hInst, 0);
g_dwLastInputTick = GetTickCount(); // init count
}

return TRUE;
}

DLLEXPORT void UninstallHook()
{
BOOL bRet1 = UnhookWindowsHookEx(g_hHookKbd);
BOOL bRet2 = UnhookWindowsHookEx(g_hHookMouse);
}
下面是 .DEF文件:
LIBRARY "MouseKeyHook"
DESCRIPTION 'MouseKeyHook DLL by Paul DiLascia'
SECTIONS .MouseKeyHook READ WRITE SHARED
用这个dll来测试的话 可以得到我想要的结果。
/////////////////////////////////////////////////////////////
第二个dll没有用def文件,而是用一个头文件将导出函数声明了一下代码如下:
#include <windows.h>
#include "IdleUI.h"

#pragma data_seg (".IdleUI") // you must define as SHARED in .def
HHOOK g_hHookKbd = NULL; // one instance for all processes
HHOOK g_hHookMouse = NULL; // one instance for all processes
DWORD g_dwLastInputTick = 0; // tick time of last input event
#pragma data_seg ()

HINSTANCE hInst =NULL;

BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
switch( ul_reason_for_call )
{
case DLL_PROCESS_ATTACH:
hInst=(HINSTANCE)hModule;
break;

}
return TRUE;
}

DWORD GetLastMouseKeyTime()
{
return g_dwLastInputTick;
}

LRESULT CALLBACK MyKbdHook(int code, WPARAM wParam, LPARAM lParam)
{
if (code==HC_ACTION) {
g_dwLastInputTick = GetTickCount();
}
return ::CallNextHookEx(g_hHookKbd, code, wParam, lParam);
}

LRESULT CALLBACK MyMouseHook(int code, WPARAM wParam, LPARAM lParam)
{
if (code==HC_ACTION) {
g_dwLastInputTick = GetTickCount();
}
return ::CallNextHookEx(g_hHookMouse, code, wParam, lParam);
}


BOOL InitHook()
{
if (g_hHookKbd == NULL) {

g_hHookKbd = SetWindowsHookEx(WH_KEYBOARD, MyKbdHook, hInst, 0);
g_hHookMouse = SetWindowsHookEx(WH_MOUSE, MyMouseHook, hInst, 0);
g_dwLastInputTick = GetTickCount(); // init count
}

return TRUE;
}

void UninstallHook()
{
BOOL bRet1 = UnhookWindowsHookEx(g_hHookKbd);
BOOL bRet2 = UnhookWindowsHookEx(g_hHookMouse);

}

以下是头文件:
IdleUI.h

#define DLLEXPORT __declspec(dllexport)
DLLEXPORT DWORD GetLastMouseKeyTime();
DLLEXPORT BOOL InitHook();
DLLEXPORT void UninstallHook();

我用同一个对话框程序来测试这两个dll
部分代码:
.cpp
#pragma comment(lib,"MouseKeyHook.lib")
_declspec(dllimport) DWORD GetLastMouseKeyTime();
_declspec(dllimport) BOOL InitHook();
_declspec(dllimport) void UninstallHook();

BOOL CTestHookDlg::OnInitDialog()
{....
InitHook();
SetTimer(1,1000,0);
.....
}

void CTestHookDlg::OnTimer(UINT nIDEvent)
{
CString s;
DWORD nsec = (GetTickCount()-GetLastMouseKeyTime())/1000;
s.Format("鼠标键盘已空闲 %d 秒.",nsec);
((CButton*)(GetDlgItem(IDC_STATIC)))->SetWindowText(s);

CDialog::OnTimer(nIDEvent);
}

void CTestHookDlg::OnDestroy()
{
CDialog::OnDestroy();

UninstallHook();
}

第一个dll可以成功时间我的目的。
第二个dll就有点奇怪了,只有当鼠标在我的测试对话框的上面移动的时候,会有响应,当鼠标在测试对话框外面移动的时候 时间就一秒一秒的上去了(键盘也一样)
请问这个是怎么回事啊??我估摸着是是不是和.def文件有关啊??难道全局钩子一定要用.def文件吗?不可以用头文件将导出函数声明吗??


还有一个问题: 用我所谓的成功的dll  有时候测试根本没有反映,就是说我鼠标和键盘一动不动,他照样显示的是 “鼠标键盘已空闲 0 秒”
我是第一次弄这个东西,还望各位大虾多帮帮忙。
...全文
255 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
cnzdgs 2008-08-21
  • 打赏
  • 举报
回复
看了你上面的代码,基本上没问题了,只有一点GetDlgItem强制转换为CButton*是不对的,但这样也没有影响。不知道你所说的不稳定具体是什么情况,鼠标在放着不动的时候有时也是会有鼠标移动的,另外有些鼠标有时放在那里指针会自动向某一方向移动,估计你现在遇到的是这类状况,你可以把鼠标拔掉试试。
rollrock1987 2008-08-21
  • 打赏
  • 举报
回复
恩 好的 只要代码没问题就可以了 至于是系统啊 鼠标的问题 我想我们也是没有办法的 给分了

不过有点奇怪啊。。。怎么就您一个人在回帖啊 其他人呢??是都不懂呢 还是大家都奥运去了啊 好像有点冷清
cnzdgs 2008-08-20
  • 打赏
  • 举报
回复
第1个问题是在DLL中使用共享数据的方法,有两种方式,一种是用def,另一种是用#pragma。至于书中有没有介绍我就不清楚了。
第2个问题你先把控件ID改掉再看。
rollrock1987 2008-08-20
  • 打赏
  • 举报
回复
十分感谢 "cnzdgs" 第一个问题已经解决了,50分肯定是你的了 呵呵 。有些东西 我怎么在书上找不到呢。我看了介绍dll和hook的书,好像没有说全局钩子不用def文件的话一定要在dll文件里面加上#pragma comment(linker, "/SECTION:.MouseKeyHook,RWS")的啊



还是第二个问题:请问"cnzdgs" 您说的 ID 不要用IDC_STATIC 是不是我所描述的第二个问题?? 我觉得 这个不应该是ID 的问题 因为我改了ID 但是也是有时候行,有时候不行的。难道是钩子没有安装成功还是什么呢??为什么有时候行,有时候不行呢?? 这个就是稳定性问题了,和别的应用程序或者什么有关系么?? 谁帮我解决下啊 谢谢了
rollrock1987 2008-08-20
  • 打赏
  • 举报
回复
还是第二个问题 改了ID 没用 现象仍旧出现
up
cnzdgs 2008-08-19
  • 打赏
  • 举报
回复
#pragma comment(linker, "/SECTION:.MouseKeyHook,RWS")要加在DLL项目的某个文件里面,EXE项目不用加。
控件ID不要用IDC_STATIC,随便改一下就可以。
rollrock1987 2008-08-19
  • 打赏
  • 举报
回复
这么多分 怎么没有要呀 不要分的也可以回帖帮帮我
rollrock1987 2008-08-19
  • 打赏
  • 举报
回复
请问楼上朋友:在我的那个只有 头文件(导出函数的声明文件)没有def文件的dll里面,需要加一个#pragma comment(linker, "/SECTION:.MouseKeyHook,RWS")就能正确了是吗??那这个应该是加在 测试文件里面的吧???
就是不明白啊,一个全局的钩子怎么好像变成了线程钩子了啊??(只能钩住特定窗口的消息)


还有一问:用我所谓的成功的dll, 有时候测试根本没有反映,就是说我鼠标和键盘一动不动,他照样显示的是 “鼠标键盘已空闲 0 秒” 请问这个是怎么回事呢??谢谢
cnzdgs 2008-08-19
  • 打赏
  • 举报
回复
如果没有def,需要加一行代码来替代SECTIONS .MouseKeyHook READ WRITE SHARED:
#pragma comment(linker, "/SECTION:.MouseKeyHook,RWS")

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧