全局钩子的问题(200分)

  • 主题发起人 主题发起人 ITBlueCollar
  • 开始时间 开始时间
I

ITBlueCollar

Unregistered / Unconfirmed
GUEST, unregistred user!
写一个程序的时候想用钩子,在用的时候出现一个的问题:<br>用键盘全局钩子没什么问题,但是用WH_CBT或者WH_CALLWNDPROC,WH_SHELL 全局钩子的时候<br>却只能拦截到这个程序本身的消息,不能拦截到其他程序的消息。一个测试程序如下:<br><br>{用于测试全局钩子的Dll文件}<br>library ProjectDllTest;<br>uses<br>&nbsp; SysUtils,<br>&nbsp; Windows,<br>&nbsp; Classes,<br>&nbsp; IniFiles,<br>&nbsp; Messages;<br><br>{$R *.res}<br><br>var<br>&nbsp; KeyboardHook: HHOOK;<br>&nbsp; CBTHandle: HHOOK;<br>&nbsp; IniTest: TIniFile;<br><br>//---------------- keyboard hook -------------------------------<br>{<br>键盘全局钩子消息处理测试函数:<br>}<br>function KeyboardProc(nCode: Integer;wParam: WPARAM; lParam: LPARAM): LRESULT;stdcall;<br>begin<br>&nbsp; if(HC_ACTION = nCode) then<br>&nbsp; begin<br>&nbsp; &nbsp; //如果按下F8,则弹出对话框<br>&nbsp; &nbsp; if(VK_F8 = wParam) then<br>&nbsp; &nbsp; &nbsp; MessageBox(0,'virtual key : F8','get a virtual key',MB_OK);<br>&nbsp; end;<br>&nbsp; Result := CallNextHookEx(KeyboardHook,nCode,wParam,lParam);<br>end;<br><br>// 设置全局键盘钩子<br>function EnableKeyboardHook(): Boolean; stdcall; export;<br>begin<br>&nbsp; KeyboardHook := SetWindowsHookEx(WH_KEYBOARD,@KeyboardProc,hInstance,0);<br>&nbsp; if( KeyboardHook &lt;&gt; 0) then Result := True<br>&nbsp; else Result := False;<br>end;<br><br>// 取消全局键盘钩子<br>function DisableKeyboardHook(): Boolean; stdcall; export;<br>begin<br>&nbsp; if( KeyboardHook &lt;&gt; 0) then<br>&nbsp; begin<br>&nbsp; &nbsp; UnhookWindowsHookEx(KeyboardHook);<br>&nbsp; &nbsp; Result := True;<br>&nbsp; end<br>&nbsp; else Result := False;<br>end;<br><br><br>//--------------------------- CBT Hook test ---------------------------<br>// CBT(computer-based training )全局钩子测试函数<br>function CBTProc(nCode: Integer;wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;<br>begin<br>&nbsp; if( HCBT_CREATEWND = nCode) then<br>&nbsp; begin<br>&nbsp; &nbsp; // 如果消息为 HCBT_CREATEWND,则将该窗口的句柄记录到 log 文件中<br>&nbsp; &nbsp; if(IniTest &lt;&gt; nil) then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; IniTest.WriteString('HCBT_CREATEWND',IntToHex(wParam,2),'Created');<br>&nbsp; &nbsp; end;<br>&nbsp; end<br>&nbsp; else if(HCBT_DESTROYWND = nCode) then<br>&nbsp; begin<br>&nbsp; &nbsp; &nbsp; // 如果消息为 HCBT_DESTROYWND,则将该窗口的句柄记录到 log 文件中<br>&nbsp; &nbsp; if(IniTest &lt;&gt; nil) then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; IniTest.WriteString('HCBT_DESTROYWND',IntToHex(wParam,2),'Destroy');<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>&nbsp; Result := CallNextHookEx(CBTHandle,nCode,wParam,lParam);<br>end;<br><br>// 设置CBT全局钩子<br>function EnableCBTHook(): Boolean; stdcall; export;<br>begin<br>&nbsp; CBTHandle := SetWindowsHookEx(WH_CBT,@CBTProc,hInstance,0);<br>&nbsp; // 用于记录消息的 log文件<br>&nbsp; IniTest := TIniFile.Create('f:/log.ini');<br>&nbsp; if( IniTest &lt;&gt; nil) then IniTest.WriteString('Enable CBT Hook','Start','OK');<br>&nbsp; if( CBTHandle = 0) then Result := False<br>&nbsp; else Result := True;<br>end;<br><br>//取消 CBT全局钩子<br>function DisableCBTHook(): Boolean; stdcall; export;<br>begin<br>&nbsp; if( IniTest &lt;&gt; nil) then<br>&nbsp; begin<br>&nbsp; &nbsp; IniTest.WriteString('Enable CBT Hook','Finish','OK');<br>&nbsp; &nbsp; IniTest.Destroy;<br>&nbsp; &nbsp; IniTest := nil;<br>&nbsp; end;<br>&nbsp; if( CBTHandle &lt;&gt; 0) then UnhookWindowsHookEx(CBTHandle);<br>&nbsp; Result := True;<br>end;<br><br>exports<br>&nbsp; EnableKeyboardHook, DisableKeyboardHook, EnableCBTHook,DisableCBTHook ;<br>end.<br><br>//----------------------------------------------------------------------------<br>{用于测试的窗体文件}<br>unit Unit1;<br><br>interface<br><br>uses<br>&nbsp; Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,<br>&nbsp; Dialogs, StdCtrls;<br><br>type<br>&nbsp; TForm1 = class(TForm)<br>&nbsp; &nbsp; BtbEnableKeyboardHook: TButton;<br>&nbsp; &nbsp; BtnDisableKeyboardHook: TButton;<br>&nbsp; &nbsp; BtnEnableCBTHook: TButton;<br>&nbsp; &nbsp; BtnDisableCBTHook: TButton;<br>&nbsp; &nbsp; procedure BtbEnableKeyboardHookClick(Sender: TObject);<br>&nbsp; &nbsp; procedure BtnDisableKeyboardHookClick(Sender: TObject);<br>&nbsp; &nbsp; procedure BtnEnableCBTHookClick(Sender: TObject);<br>&nbsp; &nbsp; procedure BtnDisableCBTHookClick(Sender: TObject);<br>&nbsp; private<br>&nbsp; &nbsp; { Private declarations }<br>&nbsp; public<br>&nbsp; &nbsp; { Public declarations }<br>&nbsp; end;<br><br>var<br>&nbsp; Form1: TForm1;<br><br>function EnableKeyboardHook: Boolean; stdcall; external 'ProjectDllTest.dll';<br>function DisableKeyboardHook: Boolean; stdcall; external 'ProjectDllTest.dll';<br>function EnableCBTHook: Boolean; stdcall; external 'ProjectDllTest.dll';<br>function DisableCBTHook: Boolean; stdcall; external 'ProjectDllTest.dll';<br><br>implementation<br><br>{$R *.dfm}<br><br>procedure TForm1.BtbEnableKeyboardHookClick(Sender: TObject);<br>begin<br>&nbsp; EnableKeyboardHook();<br>end;<br><br>procedure TForm1.BtnDisableKeyboardHookClick(Sender: TObject);<br>begin<br>&nbsp; DisableKeyboardHook();<br>end;<br><br>procedure TForm1.BtnEnableCBTHookClick(Sender: TObject);<br>begin<br>&nbsp; EnableCBTHook();<br>end;<br><br>procedure TForm1.BtnDisableCBTHookClick(Sender: TObject);<br>begin<br>&nbsp; DisableCBTHook();<br>end;<br>procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);<br>begin<br>&nbsp; DisableCBTHook();<br>end;<br><br>end.<br><br>运行程序发现,启用键盘钩子按下F8,会弹出两个MessageBox(KeyDown,KeyUp各一个),<br>因此键盘钩子可以正常使用,<br>但是启用CBT钩子之后,CBT钩子却只收到该程序本身的消息,比如在窗口上弹出系统菜<br>单,这个菜单将会被记录到log中,但是在这个程序外创建的窗口就没有任何信息,这是<br>为什么???<br>高手指点指点,多谢!
 
是否因为IniTest非整个系统的全局变量的问题??你先试试 MessageBox是否有反应??
 
没写过WH_CBT的,只写过WH_SHELL,我想应该是一样的吧。你用RegisterWindowMessage在前台应用程序和勾子DLL中注册一个消息,WH_CBT收到HCBT_CREATEWND(其中wParam参数就是其它将要建立的应用程序的句柄)就把wParam SendMessage到你的前台应用程序中。有了句柄就好办了 [:D]
 
http://www.delphibbs.com/delphibbs/dispq.asp?lid=2601403
 
WH_CALLWNDPROC 安装一个钩子函数,用于在消息发送到目标窗口过程前将其截取。<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;该类型可以是一个系统级别的钩子或者线程级别的钩子。<br><br>WH_CBT &nbsp;安装一个钩子函数,用于接收提供电脑辅助训练功能的钩子通知.<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;该类型只能是一个系统级别的钩子
 
后退
顶部