这是一个SHELL型钩子的DLL文件,用来显示用户打开和关闭的窗口。其中为了保存从调用此DLL的程序传递过来的数据比如调用此DLL的程序的窗口句柄,用一般的方法好像不行,如果从DLL中按数据(句柄)向窗口发送消息,但窗口收不到。我目前是用内存映射文件来保存的,好麻烦,不知有什么更好的办法?另外钩子函数起作用时,所打开的窗口均不能在任务栏上显示出任务按钮,但我用MASM32按同样的思路写却没有同样的问题。请大虾指点更简单的方法。 源程序如下://以下是DLL文件
unit dll; interface uses
Windows, SysUtils, StdCtrls, Messages; function WinProc(nCode: integer; wParam: WPARAM; lParam: LPARAM):LRESULT; stdcall; export;
function InstallHook(hHostWin: HWND): boolean; stdcall; export;//加载钩子
function UninstallHook: boolean; stdcall; export;//卸载钩子
procedure WinHookExit;far;export;
//Procedure DLLMain(hInst: Longint; dwReason: DWord; reserved1: DWord); far;
Procedure DLLMain(dwReason: DWord);far;
Procedure MapMem;
Procedure UnMapMem; var
hhk: hhook;
ProcSaveExit: Pointer;
hObject : THandle;
hwndHost: HWND;
pMem : Pointer;
implementation function WinProc(ncode:integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;export;
const
conWinCreate = 1;
conWinClose = 2;
WM_WININFO = WM_USER + 6; begin
result := 0;
CallNextHookEx(hhk,ncode,wParam,lParam);
case ncode of
HSHELL_WINDOWCREATED:
begin
//messagebeep($FFFFFFFF);
//PostMessage(hwndHost, WM_WININFO, wParam, conWinCreate);
PostMessage(HWND(pMem^), WM_WININFO, wParam, conWinCreate);
end;
HSHELL_WINDOWDESTROYED:
begin
//messagebeep($FFFFFFFF);
//postMessage(hwndHost, WM_WININFO, wParam, conWinClose);
postMessage(HWND(pMem^), WM_WININFO, wParam, conWinClose);
end;
end;
end; function InstallHook(hHostWin:HWND): boolean;
begin
if hhk = 0 then
begin
hhk:=SetWindowsHookEx(WH_SHELL, WinProc, hinstance, 0);
//HWND(pMem)hwndHost := hHostWin;
HWND(pMem^) := hHostWin;
end;
result:= hhk <> 0;
end; function UninstallHook: boolean;
begin
if hhk <> 0 then
begin
if UnHookWindowsHookEx(hhk) then hhk := 0;
end;
result:=hhk=0;
end; procedure WinHookExit;far;
begin
UninstallHook;
ExitProc:=ProcSaveExit;
end;
//Procedure DLLMain(hInst: Longint; dwReason: DWord; reserved1:DWord);
Procedure DLLMain(dwReason: DWord);
begin
Case dwReason of
DLL_PROCESS_ATTACH:
begin
pMem := nil;
hObject := hInstance;//0;
MapMem;//以下的公有数据,如tHWND,tMessageID将直接使用本Buf.
end;
DLL_PROCESS_DETACH: UnMapMem;
DLL_THREAD_ATTACH, DLL_THREAD_DETACH://缺省
end;
//result := TRUE;
end; Procedure UnMapMem;
begin
if Assigned(pMem) then
begin
UnMapViewOfFile(pMem);
pMem := Nil ;
end;
end; Procedure MapMem;
begin
hObject := CreateFileMapping($FFFFFFFF,Nil,Page_ReadWrite,0,$FFFF,
pChar('_IOBuffer'));
if hObject = 0 then
Raise Exception.Create('创建公用数据的Buffer不成功!');
pMem :=MapViewOfFile(hObject,FILE_MAP_WRITE,0,0,SizeOf(hwndHost));
// ;1 ;or ;SizeOf(DataBuf) ;???? ;// 创建SizeOf(DataBuf)的数据区
if not Assigned(pMem) then
begin
UnMapMem;
Raise Exception.Create('创建公用数据的映射关系不成功!') ;
end;
end; end.
//以下调用上面的DLL的应用程序
unit testform; interface uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls,TLHelp32; const
WM_WININFO = WM_USER + 6;
conCreateWin = 1;
conDestroyWin = 2; type
TForm1 = class(TForm)
btnInstallHook: TButton;
lblMessage: TLabel;
procedure btnInstallHookClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
procedure WinMessage(var WinMsg:Tmessage); message WM_WININFO;
public
{ Public declarations }
end; var
Form1: TForm1;
bIntalledHook: boolean = false;
implementation {$R *.DFM} function InstallHook(hClientWin:HWND): boolean; stdcall; external 'shellhook.dll'; function UninstallHook:boolean;stdcall;external 'shellhook.dll'; procedure TForm1.btnInstallHookClick(Sender: TObject);
begin
if bIntalledHook then if UninstallHook then
begin
bIntalledHook := false;
lblMessage.Caption := '';
btnInstallHook.Caption:= 'InstallHook'
end
else
MessageBox(Form1.Handle, 'ErrUNinstallHook','', Mb_OK + MB_ICONERROR) else if InstallHook(Form1.Handle) then
begin
bIntalledHook := true;
btnInstallHook.Caption := 'UninstallHook'
end
else
MessageBox(Form1.Handle, 'ErrInstallHook','', Mb_OK + MB_ICONERROR) end; procedure Tform1.WinMessage(var WinMsg:Tmessage);
var
pWinTitle:Pchar;
TitleLen:Integer;
clp:bool;
WinProcID:DWORD;
fp32:tprocessentry32;
fshandle:thandle;
begin
with lblMessage do
begin
if WinMsg.lParam=1 then
begin
Caption:=' Open ';
sleep(5);
end
else Caption:=' Close ';
GetWindowThreadProcessId(WinMsg.wParam,@WinProcID);
fshandle:=CreateToolhelp32Snapshot(th32cs_snapprocess,0);
fp32.dwsize:=sizeof(fp32);
clp:=process32first(fshandle,fp32);
while (integer(clp)<>0) and (fp32.th32processid<>WinProcId) do
begin
clp:=process32next(fshandle,fp32);
end;
closehandle(fshandle);
TitleLen:=GetWindowTextLength(WinMsg.wParam)+2;
GetMem(pWinTitle,TitleLen);
GetWindowText(WinMsg.wParam,pWinTitle,TitleLen);
Caption:=DateTimeToStr(Now)+Caption+fp32.szexefile+' '+pWinTitle;
if TitleLen > 0 then FreeMem(pWinTitle);
end;
{
ShowWindow(WinMsg.wParam,SW_HIDE);
ShowWindow(WinMsg.wParam,SW_SHOWNORMAL);
SetForegroundWindow(WinMsg.wParam);
}
end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if bIntalledHook then UninstallHook;
end; end.
unit dll; interface uses
Windows, SysUtils, StdCtrls, Messages; function WinProc(nCode: integer; wParam: WPARAM; lParam: LPARAM):LRESULT; stdcall; export;
function InstallHook(hHostWin: HWND): boolean; stdcall; export;//加载钩子
function UninstallHook: boolean; stdcall; export;//卸载钩子
procedure WinHookExit;far;export;
//Procedure DLLMain(hInst: Longint; dwReason: DWord; reserved1: DWord); far;
Procedure DLLMain(dwReason: DWord);far;
Procedure MapMem;
Procedure UnMapMem; var
hhk: hhook;
ProcSaveExit: Pointer;
hObject : THandle;
hwndHost: HWND;
pMem : Pointer;
implementation function WinProc(ncode:integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;export;
const
conWinCreate = 1;
conWinClose = 2;
WM_WININFO = WM_USER + 6; begin
result := 0;
CallNextHookEx(hhk,ncode,wParam,lParam);
case ncode of
HSHELL_WINDOWCREATED:
begin
//messagebeep($FFFFFFFF);
//PostMessage(hwndHost, WM_WININFO, wParam, conWinCreate);
PostMessage(HWND(pMem^), WM_WININFO, wParam, conWinCreate);
end;
HSHELL_WINDOWDESTROYED:
begin
//messagebeep($FFFFFFFF);
//postMessage(hwndHost, WM_WININFO, wParam, conWinClose);
postMessage(HWND(pMem^), WM_WININFO, wParam, conWinClose);
end;
end;
end; function InstallHook(hHostWin:HWND): boolean;
begin
if hhk = 0 then
begin
hhk:=SetWindowsHookEx(WH_SHELL, WinProc, hinstance, 0);
//HWND(pMem)hwndHost := hHostWin;
HWND(pMem^) := hHostWin;
end;
result:= hhk <> 0;
end; function UninstallHook: boolean;
begin
if hhk <> 0 then
begin
if UnHookWindowsHookEx(hhk) then hhk := 0;
end;
result:=hhk=0;
end; procedure WinHookExit;far;
begin
UninstallHook;
ExitProc:=ProcSaveExit;
end;
//Procedure DLLMain(hInst: Longint; dwReason: DWord; reserved1:DWord);
Procedure DLLMain(dwReason: DWord);
begin
Case dwReason of
DLL_PROCESS_ATTACH:
begin
pMem := nil;
hObject := hInstance;//0;
MapMem;//以下的公有数据,如tHWND,tMessageID将直接使用本Buf.
end;
DLL_PROCESS_DETACH: UnMapMem;
DLL_THREAD_ATTACH, DLL_THREAD_DETACH://缺省
end;
//result := TRUE;
end; Procedure UnMapMem;
begin
if Assigned(pMem) then
begin
UnMapViewOfFile(pMem);
pMem := Nil ;
end;
end; Procedure MapMem;
begin
hObject := CreateFileMapping($FFFFFFFF,Nil,Page_ReadWrite,0,$FFFF,
pChar('_IOBuffer'));
if hObject = 0 then
Raise Exception.Create('创建公用数据的Buffer不成功!');
pMem :=MapViewOfFile(hObject,FILE_MAP_WRITE,0,0,SizeOf(hwndHost));
// ;1 ;or ;SizeOf(DataBuf) ;???? ;// 创建SizeOf(DataBuf)的数据区
if not Assigned(pMem) then
begin
UnMapMem;
Raise Exception.Create('创建公用数据的映射关系不成功!') ;
end;
end; end.
//以下调用上面的DLL的应用程序
unit testform; interface uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls,TLHelp32; const
WM_WININFO = WM_USER + 6;
conCreateWin = 1;
conDestroyWin = 2; type
TForm1 = class(TForm)
btnInstallHook: TButton;
lblMessage: TLabel;
procedure btnInstallHookClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
procedure WinMessage(var WinMsg:Tmessage); message WM_WININFO;
public
{ Public declarations }
end; var
Form1: TForm1;
bIntalledHook: boolean = false;
implementation {$R *.DFM} function InstallHook(hClientWin:HWND): boolean; stdcall; external 'shellhook.dll'; function UninstallHook:boolean;stdcall;external 'shellhook.dll'; procedure TForm1.btnInstallHookClick(Sender: TObject);
begin
if bIntalledHook then if UninstallHook then
begin
bIntalledHook := false;
lblMessage.Caption := '';
btnInstallHook.Caption:= 'InstallHook'
end
else
MessageBox(Form1.Handle, 'ErrUNinstallHook','', Mb_OK + MB_ICONERROR) else if InstallHook(Form1.Handle) then
begin
bIntalledHook := true;
btnInstallHook.Caption := 'UninstallHook'
end
else
MessageBox(Form1.Handle, 'ErrInstallHook','', Mb_OK + MB_ICONERROR) end; procedure Tform1.WinMessage(var WinMsg:Tmessage);
var
pWinTitle:Pchar;
TitleLen:Integer;
clp:bool;
WinProcID:DWORD;
fp32:tprocessentry32;
fshandle:thandle;
begin
with lblMessage do
begin
if WinMsg.lParam=1 then
begin
Caption:=' Open ';
sleep(5);
end
else Caption:=' Close ';
GetWindowThreadProcessId(WinMsg.wParam,@WinProcID);
fshandle:=CreateToolhelp32Snapshot(th32cs_snapprocess,0);
fp32.dwsize:=sizeof(fp32);
clp:=process32first(fshandle,fp32);
while (integer(clp)<>0) and (fp32.th32processid<>WinProcId) do
begin
clp:=process32next(fshandle,fp32);
end;
closehandle(fshandle);
TitleLen:=GetWindowTextLength(WinMsg.wParam)+2;
GetMem(pWinTitle,TitleLen);
GetWindowText(WinMsg.wParam,pWinTitle,TitleLen);
Caption:=DateTimeToStr(Now)+Caption+fp32.szexefile+' '+pWinTitle;
if TitleLen > 0 then FreeMem(pWinTitle);
end;
{
ShowWindow(WinMsg.wParam,SW_HIDE);
ShowWindow(WinMsg.wParam,SW_SHOWNORMAL);
SetForegroundWindow(WinMsg.wParam);
}
end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if bIntalledHook then UninstallHook;
end; end.
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货