奇怪,WH_CBT钩子勾不住其他程序的事件 ( 积分: 50 )

墨剑

Unregistered / Unconfirmed
GUEST, unregistred user!
我时这样用的.
procedure TForm1.FormCreate(Sender: TObject);
begin
HkEdees:=SetWindowsHookEx(WH_CBT, @GetSysMsgProc, Hinstance, 0);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
UnHookWindowsHookEx(HkEdees);
end;
function GetSysMsgProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
{在此处设了断点,外部程序启动,关闭都没有触发,怎么回事?????}
Result:= CallNextHookEx(0, nCode, wParam, lParam);
end;

是不是xp不行呢?
比如我用键盘钩子
HkEdees:=SetWindowsHookEx(WH_KEYBOARD, @GetSysMsgProc, Hinstance, 0);
也勾不住在其他程序中的按键.但是如果改成:
HkEdees:=SetWindowsHookEx(13, @GetSysMsgProc, Hinstance, 0);
就能钩子其他程序中的按键了..
这到底是怎么回事呢? 难道windows定义的不对么? 希望做过这块的高手看看
 
哦,自己明白了,WH_CBT是系统勾子,要放到dll中才起作用
 
没想到也是白费功夫,放在dll中一样勾不住其他程序的窗口创建,撤销事件.
有谁知道原因呢?
或者能不能给我一个成功的勾子的例子?
 
为什么不直接Hook GetMessage ?
 
白兄,Hook GetMessage 是什么意思?能说的详细一点吗?
 
就是 WH_GETMESSAGE, 放进 dll 中可以注入全部进程。
然后就可以得到所有 Windows 标准事件了。
 
需要注意些什么呢? 我用WH_CBT还能勾子本程序的事件,用WH_GetMessage反而什么也没勾住
 
不可能什么都没勾住吧,应该有大量事件才对吧?你可以参考那个著名的键盘钩子例子,换城WH_GETMESSAGE就是了。
 
我就是照着键盘勾子来写的,只改动勾子的类型和消息类型的判断
 
那换台机器看看,或者把代码都贴上来。
 
程序很简单,帮忙看看

library edeeHook;

uses
SysUtils,
Classes,Windows,Messages,ShellApi;
type
TCallBackFun=procedure(ThreadId:integer);
TCBTHook = Record
IsRun : Boolean;
Hook:HHook;
CallBackFun : TCallBackFun;
end;

var
MyCBTHook :TCBTHook;

{$R *.RES}


function gethookinfo(code:integer;wp:WPARAM;lp:LPARAM):LResult;stdcall;
var
OperID:Integer;
begin

if code<0 then
begin
result:= CallNextHookEx(MyCBTHook.Hook,code,wp,lp);
exit;
end;

OperID:=0;
{此处省略消息的判断}

OperID:=wp;
if OperID<>0 then
MyCBTHook.callbackfun(OperID);
result:= CallNextHookEx(MyCBTHook.Hook,code,wp,lp);

end;

procedure InstallCBTHook(CallBackF:TCallBackFun);stdcall;
begin
if Not MyCBTHook.IsRun then
begin
MyCBTHook.Hook:=SetWindowsHookex(WH_CBT,GetHookInfo,HInstance,0);
MyCBTHook.CallBackFun := CallBackF;
MyCBTHook.IsRun :=True;
end;
end;

procedure UninstallCBThook(); stdcall;
begin
if MyCBTHook.IsRun then
begin
UnHookWindowsHookEx(MyCBTHook.Hook);
MyCBTHook.CallBackFun := Nil;
MyCBTHook.IsRun :=not MyCBTHook.IsRun ;
end;
end;

Procedure DLLEntryPoint(dwReason:DWord);
begin
case dwReason of
DLL_PROCESS_ATTACH: MyCBTHook.isrun:=false;
DLL_PROCESS_DETACH:;
DLL_THREAD_ATTACH:;
DLL_THREAD_DETACH:;
end;
end;

Exports
InstallCBTHook,
UninstallCBThook;
begin
DLLProc := @DLLEntryPoint;
DLLEntryPoint(DLL_PROCESS_ATTACH);
end.

/************以下是调用程序***************************/
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;
type
TCallBackFun=procedure(ThreadId:integer);
type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private

{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
NCount:Integer;
implementation
procedure InstallCBTHook(CallBackF:TCallBackFun);stdcall;external 'edeeHook.dll';
procedure UninstallCBThook();stdcall;external 'edeeHook.dll';
{$R *.DFM}


procedure ShowTreadId(ThreadId: Integer);
begin
inc(NCount);
if NCount>5000 then Application.Terminate;
TForm1(Application.MainForm).Memo1.Lines.Insert(0,inttostr(TForm1(Application.MainForm).Memo1.lines.Count)+':'+inttostr(ThreadId));
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
NCount:=0;
InstallCBTHook(ShowTreadId);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
UninstallCBThook;
end;

end.
 
看上去没问题
你在 gethookinfo 中加上
OutputDebugString(PChar(InttoStr(wp)));
然后运行的时候找 dbgview 来看看
 
死机了一回. 然后怎么弄也不知道怎样用debugview来看,不要笑哦
 
你打开dbgview就自然能看到。
 

Similar threads

I
回复
0
查看
562
import
I
I
回复
0
查看
724
import
I
I
回复
0
查看
640
import
I
I
回复
0
查看
639
import
I
顶部