自己写的一个截获鼠标消息的全局钩子,但是只对本程序窗口有用,对其它窗口都没有响应,请DFW中的高手们进来看看,谢谢了! ( 积分: 37 )

  • 主题发起人 LearningAug
  • 开始时间
L

LearningAug

Unregistered / Unconfirmed
GUEST, unregistred user!
//DLL代码…………………………………………………………………………………………

library Project1;

uses
SysUtils,
Classes, Windows, messages, shellapi, Dialogs;

type
Tcallbackfun = procedure;//回调函数
Tmousehook = record
isrun: boolean;
hook: hhook;
callbackfun: Tcallbackfun;
end;

var
mymousehook: Tmousehook;

{$R *.res}

//钩子函数

function gethookinfo(code: integer; wp: WPARAM; lp: LPARAM): LResult; stdcall;
begin
if code < 0 then
begin
result := CallNextHookEx(mymousehook.hook, code, wp, lp);
exit;
end;
case wp of
WM_LBUTTONDOWN:
begin
mymousehook.callbackfun;//调用回调函数
end;
end;

result := CallNextHookEx(mymousehook.hook, code, wp, lp);
end;

//安装钩子

procedure installmousehook(callbackF: Tcallbackfun); stdcall;
begin
if not mymousehook.isrun then
begin

mymousehook.hook := setwindowshookex(WH_MOUSE, @gethookinfo, HInstance,0);//全局钩子

mymousehook.callbackfun := callbackf;

mymousehook.isrun := not mymousehook.isrun;
end;
end;

//卸载钩子

procedure uninstallmousehook(); stdcall;
begin
if mymousehook.isrun then
begin
UnHookWindowsHookEx(mymousehook.hook);
mymousehook.callbackfun := nil;
mymousehook.isrun := not mymousehook.isrun;
end;
end;

//DLL入口函数

procedure DLLEntryPoint(dwReason: DWord);

begin
case dwReason of
DLL_PROCESS_ATTACH:
begin
mymousehook.isrun := false;
end;
DLL_PROCESS_DETACH: ;
DLL_THREAD_ATTACH: ;
DLL_THREAD_DETACH: ;
end;
end;

exports
installmousehook,
uninstallmousehook;

begin
DLLProc := @DLLEntryPoint;
DLLEntryPoint(DLL_PROCESS_ATTACH);
end.

//应用程序代码……………………………………………………………………………………

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
Tcallbackfun = procedure;
type
TForm1 = class(TForm)
Button1: TButton;

procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

procedure installmousehook(callbackF: Tcallbackfun); stdcall; external
'Project1.dll';

procedure uninstallmousehook(); stdcall; external 'Project1.dll';
{$R *.dfm}

procedure addinfo;
begin

form1.Visible := true ;
ShowWindow(Application.Handle, SW_SHOWNORMAL);
form1.width:= form1.width +1;
end;

//安装钩子

procedure TForm1.Button1Click(Sender: TObject);
begin
installmousehook(addinfo);
end;

//卸装钩子

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

end.

我想达到的目的:在任何窗口中,只要点击鼠标左键,form1的宽度都会增加1。但是现在我只有在form1上单击鼠标左键才有效,一旦form1最小化后,在其它地方点击鼠标左键,都没有响应,请问是不是我的全局钩子有问题?我应该怎么修改呢?谢谢了!!
 

我爱PASCAL

Unregistered / Unconfirmed
GUEST, unregistred user!
由于不大懂dll,所以我编的那个钩子没有dll
就两个函数搞定,真的很简单,全局都有反应的。
 

白河愁

Unregistered / Unconfirmed
GUEST, unregistred user!
mymousehook.hook := setwindowshookex(WH_MOUSE, @gethookinfo, HInstance,0);//全局钩子

MyMouseHook.hook := setWindowsHookEx(WH_MOUSE, proc, hinst, 0);

为什么要做两次?
 
L

LearningAug

Unregistered / Unconfirmed
GUEST, unregistred user!
TO 白河愁:

不好意思,我写错了哈。只需要这一句:
mymousehook.hook := setwindowshookex(WH_MOUSE, @gethookinfo, HInstance,0);//全局钩子,下面的:MyMouseHook.hook := setWindowsHookEx(WH_MOUSE, proc, hinst, 0);不要,我已经修改了帖子,谢谢!

请问为什么我的全局钩子不起作用呢?
 
Y

ysp娃娃

Unregistered / Unconfirmed
GUEST, unregistred user!
不知道 是不是你要的

library MouseHook;

uses
windows,Messages,SysUtils,
Dialogs;

{$R *.res}
var
MyHook:HHook;
TargetWinHandle:Hwnd;
WinRect:TRect;
function MouseHookProc(icode:Integer;wparam:WPARAM;lparam:LPARAM):LRESULT;stdcall;
begin
Result:=0;
if icode=HC_ACTION then
begin
if wparam=WM_LBUTTONDOWN then
begin
TargetWinHandle:=FindWindow(nil,Pchar('Form1'));
if TargetWinHandle=0 then Exit;
GetWindowRect(TargetWinHandle,WinRect);
WinRect.Right:= WinRect.Right+1;
MoveWindow(TargetWinHandle,WinRect.Left,WinRect.Top,WinRect.Right-WinRect.Left,
WinRect.Bottom-WinRect.Top,True);
Result:=0;
end;
end

else
Result:= CallNextHookEx(MyHook,icode,wparam,lparam);
end;

function InstallMouseHook:Boolean; export;
begin
MyHook:=0;
MyHook:=SetWindowsHookEx(WH_MOUSE,@MouseHookProc,Hinstance,0);
Result:= (MyHook <> 0);
end;

function UnInstallMouseHook:Boolean; export;
begin
MyHook:=0;
UnHookWindowsHookEx(MyHook);
Result:= (MyHook = 0);
end;

exports
InstallMouseHook,UnInstallMouseHook;

end.


unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation
function InstallMouseHook:boolean;external 'MouseHook.dll' ;
function UnInstallMouseHook:boolean;external 'MouseHook.dll' ;
{$R *.dfm}

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
UnInstallMouseHook;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
InstallMouseHook;
end;

end.
钩子有时候会卸载不掉 最好加上 SendMessage(HWND_BROADCAST,WM_SETTINGCHANGE,0,0); 这一句
 

我爱PASCAL

Unregistered / Unconfirmed
GUEST, unregistred user!
我不明白,为什么钩子都要编成dll
不是有不用dll的吗
 
Y

ysp娃娃

Unregistered / Unconfirmed
GUEST, unregistred user!
全局钩子必须用dll 针对系统的 .针对某个进程的可以不用dll
 
L

LearningAug

Unregistered / Unconfirmed
GUEST, unregistred user!
to ysp娃娃:
谢谢你!你的方法可行。但是你注意到没有,我在DLL中使用了一个回调函数,我想通过这个回调函数和我的程序进行通信。
具体一点,我使用这个全局钩子的目的:当我将程序隐藏到系统托盘的时候,我可以通过点击鼠标右键把隐藏在托盘的程序调出来。所以我用了一个回调函数来实现这个功能,但是我不确定回调函数在全局钩子中是否有效,请问各位还有好的方法吗?小弟不胜感激!!
 
Y

ysp娃娃

Unregistered / Unconfirmed
GUEST, unregistred user!
function MouseHookProc(icode:Integer;wparam:WPARAM;lparam:LPARAM):LRESULT;stdcall;
begin
Result:=0;
if icode=HC_ACTION then
begin
if wparam=WM_LBUTTONDOWN then
begin
TargetWinHandle:=FindWindow(nil,Pchar('"QQ尾巴"专杀工具'));
if TargetWinHandle=0 then Exit;
ShowWindow(TargetWinHandle,SW_SHOWNORMAL);
// GetWindowRect(TargetWinHandle,WinRect);
// WinRect.Right:= WinRect.Right+1;
// MoveWindow(TargetWinHandle,WinRect.Left,WinRect.Top,WinRect.Right-WinRect.Left,
// WinRect.Bottom-WinRect.Top,True);
Result:=0;
end;
end

else
Result:= CallNextHookEx(MyHook,icode,wparam,lparam);
end;
这样行吗?
 
L

LearningAug

Unregistered / Unconfirmed
GUEST, unregistred user!
to ysp娃娃:
这样是可以哈,但是这样不好和我的程序进行通信。比如我在点击鼠标左键的时候,想同时从系统托盘中调出主窗口,然后再修改主窗口中这个Form1内的一个标签的Caption,这样做可能就很难实现了。
有知道用回调函数可以实现这个功能吗?还是非常感谢你的帮助哈!!!
 
Y

ysp娃娃

Unregistered / Unconfirmed
GUEST, unregistred user!
回调函数我用的不多,我觉得用内存映象文件或全局原子 能实现. 要不你用WM_COPYDATA 这个消息 这个简单.
我靠 赚你得分还真难
 

我爱PASCAL

Unregistered / Unconfirmed
GUEST, unregistred user!
我这个没用dll还是响应全局的消息的, 只不过监视程序要在运行中,
编成dll后是不是可不起动程序,自动随window起动,随时监控?
 
L

LearningAug

Unregistered / Unconfirmed
GUEST, unregistred user!
我其实就这个要求,见红色的字:
function MouseHookProc(icode:Integer;wparam:WPARAM;lparam:LPARAM):LRESULT;stdcall;
begin
Result:=0;
if icode=HC_ACTION then
begin
if wparam=WM_LBUTTONDOWN then
begin
[red]// 能够直接像下面这样操作程序中form1的对象就可以了,我是把这些写在一
//回调函数中的,但是只有当窗口存在的时候才能捕获此消息,窗口不存在就不
//能捕获此消息
form1.Button1.Caption:='XXX';
form1.Color:=clRed;[/red]

Result:=0;
end;
end

else
Result:= CallNextHookEx(MyHook,icode,wparam,lparam);
end;
 
L

LearningAug

Unregistered / Unconfirmed
GUEST, unregistred user!
请问我该怎么做呢?
 

白河愁

Unregistered / Unconfirmed
GUEST, unregistred user!
form1.Button1.Caption:='XXX';
form1.Color:=clRed;[/red]

你把这些改成 MESSAGEBOX(GETACTIVEWINDOW,'1','1',0);
看看
 
L

LearningAug

Unregistered / Unconfirmed
GUEST, unregistred user!
to 白河愁:
改成这个后可以全局上响应了。但是我是想修改form1中的各种属性啊
 
Y

ysp娃娃

Unregistered / Unconfirmed
GUEST, unregistred user!
这个楼主消失的时间更长
 
顶部