如何利用HOOK技术实现对键盘监控以及重新封装键盘按键消息? ( 积分: 100 )

  • 主题发起人 主题发起人 david_sale
  • 开始时间 开始时间
D

david_sale

Unregistered / Unconfirmed
GUEST, unregistred user!
富翁里很多帖子提到可用SetwindowshookEX将 WH_KEYBORD设定钩子函数,代码放入一个DLL中得以监控到系统的所有键盘输入,但我希望将按键的键值改变,然后再传回系统处理,如我下例中希望将按1的键值全部改成输出2的键值,但不能成功。请大家指教<br><br>代码如下:<br><br>function keyboardhook(icode:integer;wparam:wparam;lparam:lparam):lresult;stdcall;export;<br>begin<br>if icode&lt;0 then<br> &nbsp;result:=CallNextHookEx(oldhook,icode,wparam,lparam);<br> &nbsp;exit;<br>else<br> &nbsp;begin<br> &nbsp;if wparam=49 then &nbsp; //按键为1时改变键值为2<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp;wparam:=50;<br> &nbsp; &nbsp;result:=CallNextHookEx(oldhook,icode,wparam,lparam);<br> &nbsp; &nbsp;end;<br> &nbsp; &nbsp;<br> //showmessage(inttostr(wparam)+' &nbsp;'+ IntToHex(lparam,8));<br> //result:=CallNextHookEx(oldhook,icode,wparam,lparam);<br> &nbsp;end;<br>end;<br><br>function setkeyhook:bool;export;//加载钩子<br>begin<br>if oldhook=0 then<br> &nbsp; oldhook:=SetWindowsHookEx(WH_KEYBOARD,keyboardhook,HInstance,0);<br>result:=oldhook&lt;&gt;0;<br>end;<br><br>function endkeyhook:bool;export;<br>begin<br>if oldhook&lt;&gt;0 then unhookwindowshookex(oldhook);<br>oldhook:=0;<br>result:=oldhook=0;<br>end;
 
富翁里很多帖子提到可用SetwindowshookEX将 WH_KEYBORD设定钩子函数,代码放入一个DLL中得以监控到系统的所有键盘输入,但我希望将按键的键值改变,然后再传回系统处理,如我下例中希望将按1的键值全部改成输出2的键值,但不能成功。请大家指教<br><br>代码如下:<br><br>function keyboardhook(icode:integer;wparam:wparam;lparam:lparam):lresult;stdcall;export;<br>begin<br>if icode&lt;0 then<br> &nbsp;result:=CallNextHookEx(oldhook,icode,wparam,lparam);<br> &nbsp;exit;<br>else<br> &nbsp;begin<br> &nbsp;if wparam=49 then &nbsp; //按键为1时改变键值为2<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp;wparam:=50;<br> &nbsp; &nbsp;result:=CallNextHookEx(oldhook,icode,wparam,lparam);<br> &nbsp; &nbsp;end;<br> &nbsp; &nbsp;<br> //showmessage(inttostr(wparam)+' &nbsp;'+ IntToHex(lparam,8));<br> //result:=CallNextHookEx(oldhook,icode,wparam,lparam);<br> &nbsp;end;<br>end;<br><br>function setkeyhook:bool;export;//加载钩子<br>begin<br>if oldhook=0 then<br> &nbsp; oldhook:=SetWindowsHookEx(WH_KEYBOARD,keyboardhook,HInstance,0);<br>result:=oldhook&lt;&gt;0;<br>end;<br><br>function endkeyhook:bool;export;<br>begin<br>if oldhook&lt;&gt;0 then unhookwindowshookex(oldhook);<br>oldhook:=0;<br>result:=oldhook=0;<br>end;
 
waiting.........
 
富翁们都出来回答一下好吗?
 
你hook到的时候是已经按键完成之后了吧...
 
是啊,已经HOOK到键值wparam和lparam了,但是我不知道如何改变,再向下传递出去。
 
用 WH_GETMESSAGE 钩子可以修改, 具体请看 http://www.2ccc.com/article.asp?articleid=1503
 
我的最终目的是写一个键盘自定义工具,可以自定义键盘上各个键或组合键,如可以让F1键打出B,让D键打出f,用Shift+Enter打出Tab等等。<br>就如软件Key Transformation V5.261 http://key.softboy.net<br>希望有兴趣研究的朋友,加我QQ:23800585
 
刘麻子 贴的代码果然不错<br>if MSG(Pointer(LParam)^).wParam=49 then &nbsp; //按键为1时改变键值为2<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp;MSG(Pointer(LParam)^).wParam:=50;<br> &nbsp; &nbsp;result:=CallNextHookEx(oldhook,icode,wparam,lparam);<br> &nbsp; &nbsp;end;<br>这样就可以把1改成2了
 
谢谢刘麻子和huangyiiiiii的参与,代码我修正一下<br>当我有一组键值需要对应的情况下,而且是未知有多少个键要对应的时候,我用了一个TstringList来从外部读入一个文本文件,格式为:<br>49=50 <br>50=51<br>51=52<br>也就是从这个表中查出将来输出的键值。增加了两个输出函数loadkey,freekey分别用于读入外部文件和清理TstringList对象,但我发现总不能执行findkey函数?<br>var<br>Keylist:TstringList;<br><br>function findkey(inkey:integer;var outKey:integer):bool;stdcall;export; &nbsp;//查找输出键<br>var<br>ta,tb:string;<br>begin<br>ta:=''''+inttostr(inkey)+'''';<br>tb:=keylist.values[ta]; &nbsp;//返回键值<br>//showmessage(keylist.Text+' &nbsp; '+tb);<br>if tb&lt;&gt;'' then<br> &nbsp;begin<br> &nbsp;outKey:=StrToInt(tb);<br> &nbsp;result:=true;<br> &nbsp;end<br>else<br> &nbsp;result:=false;<br>end;<br><br>function freekey:bool;export;//清除对应库内存<br>begin<br>//showmessage(keylist.Text);<br>if Assigned(keylist) then<br> &nbsp; begin<br> &nbsp; keylist.Free;<br> &nbsp; result:=true;<br> &nbsp; end<br>else<br>result:=false;<br>end;<br><br>function loadkey(inKeyname:string):bool;stdcall;export;//装键值对应库<br>begin<br>keylist:=TStringList.Create;<br>if not FileExists(inKeyname) then<br> &nbsp; begin<br> &nbsp; result:=false;<br> &nbsp; exit;<br> &nbsp; end;<br>keylist.LoadFromFile(inKeyname);<br>//showmessage(keylist.Text);<br>result:=true;<br>end;<br><br>function keyboardhook(icode:integer;wparam:wparam;lparam:lparam):lresult;stdcall;export;<br>var<br>ta,tb:string;<br>tc:integer;<br>begin<br>if (pmsg(lparam).message= WM_KEYDOWN) or (pmsg(lparam).message= WM_KEYUP) then<br> &nbsp; begin<br> &nbsp; if findkey(pmsg(lparam).wParam,tc) then &nbsp; //从TstringList中查找是否要变换值<br> &nbsp; &nbsp; begin<br> &nbsp; &nbsp; wparam:=tc;<br> &nbsp; &nbsp; pmsg(lparam).wParam:=tc;<br> &nbsp; &nbsp; end;<br> &nbsp; end;<br>result:=CallNextHookEx(oldhook,icode,wparam,lparam);<br>end;
 
借个 地方问下 呵呵 楼主不介意吧 &nbsp;呵呵<br>我顺着楼主的想法试着做了下 &nbsp;出了个问题<br>我在dll里定义了个全局 TStringList的变量<br>在HookOn(strs:TStringList)里接受主程序里传来的 引用 并赋给dll里的全局变量<br>然后还有个GetKey会使用这个引用 &nbsp; <br>但是发现 在 HookOn 里面调用GetKey 能正确执行 &nbsp;但是在HookCallBack里调用GetKey时单步执行到GetKey里面时确发现 那个引用是nil<br><br>这是怎么回事啊 &nbsp; 是不是因为HookCallBack是由操作系统调用 有些不一样啊<br>谁能解释一下 &nbsp; &nbsp; &nbsp; 谢谢拉
 
huangyiiiiii的意思是想在主程序中实现TStringList对象的创建,然后将对象的指针传入DLL让里面的函数引用? <br>我查了有关资料:由于钩子是安装到系统里的,钩子的运行是在操作系统里面,因此这个钩子不能使用你的程序所定义的任何全局变量!利用共享内存技术,利用 API 函数 CreateFileMapping() 可创建共享内存,这个内存可以在任何运行的程序中使用,也就是说任何运行的 .EXE、.DLL 和其他程序都可以使用这块内存,也就是如果把TStringList的数据放到这块内存中,在HOOK里也就能访问到这块数据。<br><br>我是在DLL文件中创建TStringList对象,在HookCallBack中也能引用在findkey中也能引用,但是很奇怪在HookCallBack中调用了findkey后,只能捕获一次,以后就不能对WM_KEYDOWN和WM_KEYUP消息捕获了,百思不得其解?我想是不是也是这个共享内存的原因?<br><br>function keyboardhook(icode:integer;wparam:wparam;lparam:lparam):lresult;stdcall;export;<br>var<br>tc:integer;<br>begin<br>if (pmsg(lparam).message= WM_KEYDOWN) or (pmsg(lparam).message= WM_KEYUP) then<br> &nbsp; begin<br> &nbsp; showmessage('in key');<br> &nbsp; if findkey(pmsg(lparam).wParam,tc) then &nbsp; //去掉这行就可以每次都可以捕获消息<br> &nbsp; &nbsp; &nbsp;pmsg(lparam).wParam:=tc;<br> &nbsp; end;<br>result:=CallNextHookEx(oldhook,icode,wparam,lparam);<br>end;<br><br>huangyiiiiii可以告诉我的你的QQ或UC号吗?
 
我也被搞糊涂了 &nbsp; 我在dll里定义了个全局变量FileName &nbsp; &nbsp;HookOn里面硬编码一个值<br>回掉函数里面把他ShowMessage出来 &nbsp; &nbsp;好象只有在扑获自己的键盘消息的时候能显示正确的只 &nbsp; 其他窗口都显示空
 
完全解决,接受答案了
 
友情提示: 接受答案的时候不能发言, 不然俺们就拿不到分分的, 拜托楼主重新操作一次罢, 阿门~
 
多人接受答案了。
 
后退
顶部