Dll工程(續(xù))
UnitHookDll.pas
//-----------------------------------------------------------------------------------
unit UnitHookDll;
interface
uses
Windows, SysUtils, Classes, math, messages, dialogs,
UnitNt2000Hook,
UnitHookType;
const
COLOR1=255;
COLOR2=0;
COLOR3=255;
Trap=true; //True陷阱式,F(xiàn)alse表示改引入表式
procedure StartHook; stdcall; {開始取詞}//安裝鉤子
procedure StopHook; stdcall; {停止取詞}//卸載鉤子
function NewBeginPaint(Wnd: HWND; var lpPaint: TPaintStruct): HDC; stdcall;
function NewCreateCompatibleDC(DC: HDC): HDC; stdcall;
function NewTextOutA(theDC: HDC; nXStart, nYStart: integer; str: pchar; count: integer): bool; stdcall;
function NewTextOutW(theDC: HDC; nXStart, nYStart: integer; str: pWidechar; count: integer): bool; stdcall;
function NewExtTextOutA(theDC: HDC; nXStart, nYStart: integer; toOptions:Longint;
rect: PRect; Str: PAnsiChar; Count: Longint; Dx: PInteger): BOOL; stdcall;
function NewExtTextOutW(theDC: HDC; nXStart, nYStart: integer; toOptions:
Longint; rect: PRect;
Str: Pwidechar; Count: Longint; Dx: PInteger): BOOL; stdcall;
function NewDrawTextA(theDC: HDC; lpString: PAnsiChar; nCount: Integer;
var lpRect: TRect; uFormat: UINT): Integer; stdcall;
function NewDrawTextW(theDC: HDC; lpString: PWideChar; nCount: Integer;
var lpRect: TRect; uFormat: UINT): Integer; stdcall;
implementation
var
MouseHook: THandle;
pShMem: PShareMem;
hMappingFile: THandle;
FirstProcess:boolean;{是否是第一個進(jìn)程}
Hook: array[fBeginPaint..fDrawTextW] of THookClass;{API HOOK類}
i:integer;
{自定義的BeginPaint}
function NewBeginPaint(Wnd: HWND; var lpPaint: TPaintStruct): HDC; stdcall;
type
TBeginPaint=function (Wnd: HWND; var lpPaint: TPaintStruct): HDC; stdcall;
begin
Hook[fBeginPaint].Restore;
result:=TBeginPaint(Hook[fBeginPaint].OldFunction)(Wnd,lpPaint);
if Wnd=pshmem^.hHookWnd then{如果是當(dāng)前鼠標(biāo)的窗口句柄}
begin
pshmem^.DCMouse:=result;{記錄它的返回值}
end
else pshmem^.DCMouse:=0;
Hook[fBeginPaint].Change;
end;
{自定義的GetWindowDC}
function NewGetWindowDC(Wnd: HWND): HDC; stdcall;
type
TGetWindowDC=function (Wnd: HWND): HDC; stdcall;
begin
Hook[fGetWindowDC].Restore;
result:=TGetWindowDC(Hook[fGetWindowDC].OldFunction)(Wnd);
if Wnd=pshmem^.hHookWnd then{如果是當(dāng)前鼠標(biāo)的窗口句柄}
begin
pshmem^.DCMouse:=result;{記錄它的返回值}
end
else pshmem^.DCMouse:=0;
Hook[fGetWindowDC].Change;
end;
{自定義的GetDC}
function NewGetDC(Wnd: HWND): HDC; stdcall;
type
TGetDC=function (Wnd: HWND): HDC; stdcall;
begin
Hook[fGetDC].Restore;
result:=TGetDC(Hook[fGetDC].OldFunction)(Wnd);
if Wnd=pshmem^.hHookWnd then{如果是當(dāng)前鼠標(biāo)的窗口句柄}
begin
pshmem^.DCMouse:=result;{記錄它的返回值}
end
else pshmem^.DCMouse:=0;
Hook[fGetDC].Change;
end;
{自定義的CreateCompatibleDC}
function NewCreateCompatibleDC(DC: HDC): HDC; stdcall;
type
TCreateCompatibleDC=function (DC: HDC): HDC; stdcall;
begin
Hook[fCreateCompatibleDC].Restore;
result:=TCreateCompatibleDC(Hook[fCreateCompatibleDC].OldFunction)(DC);
if DC=pshmem^.DCMouse then{如果是當(dāng)前鼠標(biāo)的窗口HDC}
begin
pshmem^.DCCompatible:=result;{記錄它的返回值}
end
else pshmem^.DCCompatible:=0;
Hook[fCreateCompatibleDC].Change;
end;
//-------------------------------------------------------
function NewTextOutA(theDC: HDC; nXStart, nYStart: integer; str: pchar; count: integer): bool;
stdcall;
type
TTextOutA=function (theDC: HDC; nXStart, nYStart: integer; str: pchar; count: integer): bool;stdcall;
var
dwBytes: DWORD;
poOri, poDC, poText, poMouse: TPoint;
Size: TSize;
Rec:TRect;
faint:boolean;
begin
Hook[fTextOutA].Restore;{暫停截取API,恢復(fù)被截的函數(shù)}
try
if pShMem^.bCanSpyNow then{是否開始取詞}
begin
GetDCOrgEx(theDC, poOri);{HDC的坐標(biāo)}//用屏幕坐標(biāo)定義窗口客戶區(qū)起點位置
poDC.x := nXStart;{顯示的相對坐標(biāo)}
poDC.y := nYStart;
if(poOri.X=0)and(poOri.Y=0)then{如果HDC的坐標(biāo)為(0,0)}
begin
if (theDC=pShmem^.DCCompatible)then
faint:=false{精確匹配,就是指定的內(nèi)存HDC}
else faint:=true;{模糊匹配,"可能"是內(nèi)存HDC}
{取鼠標(biāo)當(dāng)前處的窗口(等效于Delphi的控件)坐標(biāo)}
GetWindowRect(pShMem^.hHookWnd,Rec);
poOri.X:=Rec.Left;{把窗口坐標(biāo)作為HDC的坐標(biāo)}
poOri.Y:=Rec.Top;
end
else begin{如果是普通HDC}
{局部邏輯坐標(biāo)轉(zhuǎn)化為設(shè)備相關(guān)坐標(biāo)}
LPToDP(theDC, poDC, 1);
faint:=false;{精確匹配,是普通HDC}
end;
{計算顯示文字的屏幕坐標(biāo)}
poText.x := poDC.x + poOri.x;
poText.y := poDC.y + poOri.y;
{獲取當(dāng)前鼠標(biāo)的坐標(biāo)}
GetCursorPos(poMouse);
{如果對齊屬性是居中}
if (GetTextAlign(theDC) and TA_UPDATECP) <> 0 then
begin
GetCurrentPositionEx(theDC, @poOri);
poText.x := poText.x + poOri.x;
poText.y := poText.y + poOri.y;
end;
{顯示文字的長和寬}
GetTextExtentPoint(theDC, Str, Count, Size);
{鼠標(biāo)是否在文本的范圍內(nèi)}
if (poMouse.x >= poText.x) and (poMouse.x <= poText.x + Size.cx)
and (poMouse.y >= poText.y) and (poMouse.y <= poText.y + Size.cy)
then
begin
{最多取MaxStringLen個字節(jié)}
dwBytes := min(Count, MaxStringLen);
{拷貝字符串}
CopyMemory(@(pShMem^.Text), Str, dwBytes);//截獲的字符在這里了...
{以空字符結(jié)束}
pShMem^.Text[dwBytes] := Chr(0);
{發(fā)送WM_MOUSEPT成功取詞的消息給主程序}
postMessage(pShMem^.hProcWnd, WM_MOUSEPT, fTextOutA, 2);
{如果輸出的不是Tab鍵,而且是精確匹配的}
if (string(pShMem^.Text)<>#3)and(not faint) then
pShMem^.bCanSpyNow := False;{取詞結(jié)束}
end;
end;
finally
{調(diào)用被截的函數(shù)}
result := TTextOutA(Hook[fTextOutA].OldFunction)(theDC, nXStart,
nYStart, str, count);
end;
Hook[fTextOutA].Change;{重新截取API}
end;
function NewTextOutW(theDC: HDC; nXStart, nYStart: integer; str: pWidechar; count: integer): bool; stdcall;
type
TTextOutW=function (theDC: HDC; nXStart, nYStart: integer; str: pWidechar; count: integer): bool; stdcall;
var
dwBytes: DWORD;
poOri, poDC, poText, poMouse: TPoint;
Size: TSize;
Rec:TRect;
faint:boolean;
begin
Hook[fTextOutW].Restore;{暫停截取API,恢復(fù)被截的函數(shù)}
// SetTextColor(thedc,RGB(COLOR1,COLOR2,COLOR3));
try
if pShMem^.bCanSpyNow then{是否開始取詞}
begin
GetDCOrgEx(theDC, poOri);{HDC的坐標(biāo)}
poDC.x := nXStart;{顯示的相對坐標(biāo)}
poDC.y := nYStart;
if(poOri.X=0)and(poOri.Y=0)then{如果HDC的坐標(biāo)為(0,0)}
begin
if (theDC=pShmem^.DCCompatible)then
faint:=false{精確匹配,就是指定的內(nèi)存HDC}
else faint:=true;{模糊匹配,"可能"是內(nèi)存HDC}
{取鼠標(biāo)當(dāng)前處的窗口(等效于Delphi的控件)坐標(biāo)}
GetWindowRect(pShMem^.hHookWnd,Rec);
poOri.X:=Rec.Left;{把窗口坐標(biāo)作為HDC的坐標(biāo)}
poOri.Y:=Rec.Top;
end
else begin{如果是普通HDC}
{局部邏輯坐標(biāo)轉(zhuǎn)化為設(shè)備相關(guān)坐標(biāo)}
LPToDP(theDC, poDC, 1);
faint:=false;{精確匹配,是普通HDC}
end;
{計算顯示文字的屏幕坐標(biāo)}
poText.x := poDC.x + poOri.x;
poText.y := poDC.y + poOri.y;
{獲取當(dāng)前鼠標(biāo)的坐標(biāo)}
GetCursorPos(poMouse);
{如果對齊屬性是居中}
if (GetTextAlign(theDC) and TA_UPDATECP) <> 0 then
begin
GetCurrentPositionEx(theDC, @poOri);
poText.x := poText.x + poOri.x;
poText.y := poText.y + poOri.y;
end;
{顯示文字的長和寬}
GetTextExtentPointW(theDC, Str, Count, Size);
{鼠標(biāo)是否在文本的范圍內(nèi)}
if (poMouse.x >= poText.x) and (poMouse.x <= poText.x + Size.cx)
and (poMouse.y >= poText.y) and (poMouse.y <= poText.y + Size.cy)
then
begin
{最多取MaxStringLen個字節(jié)}
dwBytes := min(Count*2, MaxStringLen);
{拷貝字符串}
CopyMemory(@(pShMem^.Text), Pchar(WideCharToString(Str)), dwBytes);//截獲的字符在這里了...
{以空字符結(jié)束}
pShMem^.Text[dwBytes] := Chr(0);
{發(fā)送WM_MOUSEPT成功取詞的消息給主程序}
postMessage(pShMem^.hProcWnd, WM_MOUSEPT, fTextOutW, 2);
{如果輸出的不是Tab鍵,而且是精確匹配的}
if (string(pShMem^.Text)<>#3)and(not faint) then
pShMem^.bCanSpyNow := False;{取詞結(jié)束}
end;
end;
finally
{調(diào)用被截的函數(shù)}
result := TTextOutW(Hook[fTextOutW].OldFunction)(theDC, nXStart, nYStart, str, Count);
end;
Hook[fTextOutW].Change;{重新截取API}
end;
function NewExtTextOutA(theDC: HDC; nXStart, nYStart: integer; toOptions:Longint;
rect: PRect; Str: PAnsiChar; Count: Longint; Dx: PInteger): BOOL; stdcall;
type
TExtTextOutA=function (theDC: HDC; nXStart, nYStart: integer; toOptions:Longint;
rect: PRect; Str: PAnsiChar; Count: Longint; Dx: PInteger): BOOL; stdcall;
var
dwBytes: DWORD;
poOri, poDC, poText, poMouse: TPoint;
Size: TSize;
Rec:TRect;
faint:boolean;
begin
Hook[fExtTextOutA].Restore;{暫停截取API,恢復(fù)被截的函數(shù)}
// SetTextColor(thedc,RGB(COLOR1,COLOR2,COLOR3));
try
if pShMem^.bCanSpyNow then{是否開始取詞}
begin
GetDCOrgEx(theDC, poOri);{HDC的坐標(biāo)}
poDC.x := nXStart;{顯示的相對坐標(biāo)}
poDC.y := nYStart;
if(poOri.X=0)and(poOri.Y=0)then{如果HDC的坐標(biāo)為(0,0)}
begin
if (theDC=pShmem^.DCCompatible)then
faint:=false{精確匹配,就是指定的內(nèi)存HDC}
else faint:=true;{模糊匹配,"可能"是內(nèi)存HDC}
{取鼠標(biāo)當(dāng)前處的窗口(等效于Delphi的控件)坐標(biāo)}
GetWindowRect(pShMem^.hHookWnd,Rec);
poOri.X:=Rec.Left;{把窗口坐標(biāo)作為HDC的坐標(biāo)}
poOri.Y:=Rec.Top;
end
else begin{如果是普通HDC}
{局部邏輯坐標(biāo)轉(zhuǎn)化為設(shè)備相關(guān)坐標(biāo)}
LPToDP(theDC, poDC, 1);
faint:=false;{精確匹配,是普通HDC}
end;
{計算顯示文字的屏幕坐標(biāo)}
poText.x := poDC.x + poOri.x;
poText.y := poDC.y + poOri.y;
{獲取當(dāng)前鼠標(biāo)的坐標(biāo)}
GetCursorPos(poMouse);
{如果對齊屬性是居中}
if (GetTextAlign(theDC) and TA_UPDATECP) <> 0 then
begin
GetCurrentPositionEx(theDC, @poOri);
poText.x := poText.x + poOri.x;
poText.y := poText.y + poOri.y;
end;
{顯示文字的長和寬}
GetTextExtentPoint(theDC, Str, Count, Size);
{鼠標(biāo)是否在文本的范圍內(nèi)}
if (poMouse.x >= poText.x) and (poMouse.x <= poText.x + Size.cx)
and (poMouse.y >= poText.y) and (poMouse.y <= poText.y + Size.cy)
then
begin
{最多取MaxStringLen個字節(jié)}
dwBytes := min(Count, MaxStringLen);
{拷貝字符串}
CopyMemory(@(pShMem^.Text), Str, dwBytes);
{以空字符結(jié)束}
pShMem^.Text[dwBytes] := Chr(0);
{發(fā)送WM_MOUSEPT成功取詞的消息給主程序}
postMessage(pShMem^.hProcWnd, WM_MOUSEPT, fExtTextOutA, 2);
{如果輸出的不是Tab鍵,而且是精確匹配的}
if (string(pShMem^.Text)<>#3)and(not faint) then
pShMem^.bCanSpyNow := False;{取詞結(jié)束}
end;
end;
finally
{調(diào)用被截的函數(shù)}
result := TExtTextOutA(Hook[fExtTextOutA].OldFunction)(theDC, nXStart, nYStart, toOptions, rect, Str,
Count, Dx);
end;
Hook[fExtTextOutA].Change;{重新截取API}
end;
Dll工程(續(xù)2)
UnitHookDll.pas (2)
//-----------------------------------------------------------------------------------
主窗體單元UnitMain.pas
unit UnitMain;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls,UnitHookType, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
procedure Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
private
procedure getMouseInfo(var theMess:TMessage); message WM_MOUSEPT;{處理WM_MOUSEPT}
private
hMapObj : THandle;
pShMem : PShareMem;
fWndClosed:boolean;{是否正在退出主程序}
{ Private declarations }
public
{ Public declarations }
end;
// {未公開的函數(shù),實現(xiàn)隱浮窗口}
// procedure SwitchToThisWindow(wnd:Hwnd;Switch:BOOL);stdcall;external 'user32.dll';
procedure StartHook; stdcall; external 'GetWordDll.DLL';
procedure StopHook; stdcall; external 'GetWordDll.DLL';
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
if button1.caption='取詞' then
begin
StartHook;
button1.caption:='停止';
end
else begin
StopHook;
button1.caption:='取詞';
end;
end;
const
StrProcNames : array[fTextOutA..fDrawTextW] of String =
('來自TextOutA',
'來自TextOutW',
'來自ExtTextOutA',
'來自ExtTextOutW',
'來自DrawTextA',
'來自菜單(來自DrawTextW)'
);
procedure TForm1.getMouseInfo(var theMess : TMessage);
begin
if fWndClosed then
Exit;
//if theMess.Msg=WM_MOUSEPT then showmessage('fff');
if theMess.LParam = 1 then{顯示鼠標(biāo)位置}
edit1.Text := 'X:' + IntToStr(pShMem^.pMouse.x) + ' ' +
'Y:' + IntToStr(pShMem^.pMouse.y) + ' ' +
'HWND:0x' + IntToHex(pShMem^.hHookWnd, 8) + ' ' +
pShMem^.fStrMouseQueue
else if theMess.LParam = 2 then
begin
edit2.Text := pShMem^.Text;
if (theMess.WParam>=4)and(theMess.WParam<=9) then
edit3.Text :=StrProcNames[theMess.Wparam-4];
end;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
fWndClosed := True;{正在退出主程序}
if button1.caption<>'取詞' then
Button1Click(sender);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
SetForegroundWindow(self.Handle);{實現(xiàn)隱浮窗口}
hMapObj := OpenFileMapping(FILE_MAP_WRITE,{獲取完全訪問映射文件}
False,{不可繼承的}
LPCTSTR(MappingFileName));{映射文件名字}
if hMapObj = 0 then
begin
ShowMessage('不能定位內(nèi)存映射文件塊!');
Halt;
end;
pShMem := MapViewOfFile(hMapObj,FILE_MAP_WRITE,0,0,0);
if pShMem = nil then
begin
ShowMessage('映射文件錯誤'+ IntToStr(GetLastError));
CloseHandle(hMapObj);
Halt;
end;
FillChar(pShMem^, SizeOf(TShareMem), 0);
pShMem^.hProcWnd := Self.Handle;
fWndClosed:=false;
end;
end.