unit UnitHookType;
interface
uses windows, messages;
const
MaxStringLen = 100; WM_MOUSEPT = WM_USER + 1138; MappingFileName = 'GetWord32 for 9x NT 2000'; fBeginPaint=0; fGetWindowDC=1; fGetDC=2; fCreateCompatibleDC=3; fTextOutA=4; fTextOutW=5; fExtTextOutA=6; fExtTextOutW=7; fDrawTextA=8; fDrawTextW=9; type PPointer = ^Pointer; TShareMem = packed record hProcWnd: HWND; {主应用窗口句柄} hHookWnd: HWND; {鼠标所在窗口} pMouse: TPoint; {鼠标信息} DCMouse,DCCompatible: HDC; fTimerID: integer; fStrMouseQueue: array[0..MaxStringLen] of Char; {鼠标信息串} nTimePassed: integer; {鼠标停留的时间} bCanSpyNow: Boolean; {开始取词} Text: array[0..MaxStringLen] of Char; {字符串} end; PShareMem = ^TShareMem; implementation
end.
//================================================== unit UnitHookDll; interface
uses Windows, SysUtils, Classes, math, messages, dialogs, UnitNt2000Hook,
UnitHookType; const
COLOR1=255; COLOR2=0; COLOR3=255; Trap=true; //True陷阱式,False表示改引入表式 procedure StartHook; stdcall; {开始取词}
procedure StopHook; stdcall; {停止取词} implementation
var
MouseHook: THandle; pShMem: PShareMem; hMappingFile: THandle; FirstProcess:boolean;{是否是第一个进程} 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{如果是当前鼠标的窗口句柄} 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{如果是当前鼠标的窗口句柄} 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{如果是当前鼠标的窗口句柄} 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{如果是当前鼠标的窗口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,恢复被截的函数} try if pShMem^.bCanSpyNow then{是否开始取词} begin GetDCOrgEx(theDC, poOri);{HDC的坐标} poDC.x := nXStart;{显示的相对坐标} poDC.y := nYStart; if(poOri.X=0)and(poOri.Y=0)then{如果HDC的坐标为(0,0)} begin if (theDC=pShmem^.DCCompatible)then faint:=false{精确匹配,就是指定的内存HDC} else faint:=true;{模糊匹配,"可能"是内存HDC} {取鼠标当前处的窗口(等效于Delphi的控件)坐标} GetWindowRect(pShMem^.hHookWnd,Rec); poOri.X:=Rec.Left;{把窗口坐标作为HDC的坐标} poOri.Y:=Rec.Top; end else begin{如果是普通HDC} {局部逻辑坐标转化为设备相关坐标} LPToDP(theDC, poDC, 1); faint:=false;{精确匹配,是普通HDC} end; {计算显示文字的屏幕坐标} poText.x := poDC.x + poOri.x; poText.y := poDC.y + poOri.y; {获取当前鼠标的坐标} 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); {鼠标是否在文本的范围内} 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个字节} dwBytes := min(Count, MaxStringLen); {拷贝字符串} CopyMemory(@(pShMem^.Text), Str, dwBytes); {以空字符结束} pShMem^.Text[dwBytes] := Chr(0); {发送WM_MOUSEPT成功取词的消息给主程序} postMessage(pShMem^.hProcWnd, WM_MOUSEPT, fTextOutA, 2); {如果输出的不是Tab键,而且是精确匹配的} if (string(pShMem^.Text)<>#3)and(not faint) then pShMem^.bCanSpyNow := False;{取词结束} end; end; finally {调用被截的函数} 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,恢复被截的函数} // SetTextColor(thedc,RGB(COLOR1,COLOR2,COLOR3)); try if pShMem^.bCanSpyNow then{是否开始取词} begin GetDCOrgEx(theDC, poOri);{HDC的坐标} poDC.x := nXStart;{显示的相对坐标} poDC.y := nYStart; if(poOri.X=0)and(poOri.Y=0)then{如果HDC的坐标为(0,0)} begin if (theDC=pShmem^.DCCompatible)then faint:=false{精确匹配,就是指定的内存HDC} else faint:=true;{模糊匹配,"可能"是内存HDC} {取鼠标当前处的窗口(等效于Delphi的控件)坐标} GetWindowRect(pShMem^.hHookWnd,Rec); poOri.X:=Rec.Left;{把窗口坐标作为HDC的坐标} poOri.Y:=Rec.Top; end else begin{如果是普通HDC} {局部逻辑坐标转化为设备相关坐标} LPToDP(theDC, poDC, 1); faint:=false;{精确匹配,是普通HDC} end; {计算显示文字的屏幕坐标} poText.x := poDC.x + poOri.x; poText.y := poDC.y + poOri.y; {获取当前鼠标的坐标} 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); {鼠标是否在文本的范围内} 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个字节} dwBytes := min(Count*2, MaxStringLen); {拷贝字符串} CopyMemory(@(pShMem^.Text), Pchar(WideCharToString(Str)), dwBytes); {以空字符结束} pShMem^.Text[dwBytes] := Chr(0); {发送WM_MOUSEPT成功取词的消息给主程序} postMessage(pShMem^.hProcWnd, WM_MOUSEPT, fTextOutW, 2); {如果输出的不是Tab键,而且是精确匹配的} if (string(pShMem^.Text)<>#3)and(not faint) then pShMem^.bCanSpyNow := False;{取词结束} end; end; finally {调用被截的函数} 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,恢复被截的函数} // SetTextColor(thedc,RGB(COLOR1,COLOR2,COLOR3)); try if pShMem^.bCanSpyNow then{是否开始取词} begin GetDCOrgEx(theDC, poOri);{HDC的坐标} poDC.x := nXStart;{显示的相对坐标} poDC.y := nYStart; if(poOri.X=0)and(poOri.Y=0)then{如果HDC的坐标为(0,0)} begin if (theDC=pShmem^.DCCompatible)then faint:=false{精确匹配,就是指定的内存HDC} else faint:=true;{模糊匹配,"可能"是内存HDC} {取鼠标当前处的窗口(等效于Delphi的控件)坐标} GetWindowRect(pShMem^.hHookWnd,Rec); poOri.X:=Rec.Left;{把窗口坐标作为HDC的坐标} poOri.Y:=Rec.Top; end else begin{如果是普通HDC} {局部逻辑坐标转化为设备相关坐标} LPToDP(theDC, poDC, 1); faint:=false;{精确匹配,是普通HDC} end; {计算显示文字的屏幕坐标} poText.x := poDC.x + poOri.x; poText.y := poDC.y + poOri.y; {获取当前鼠标的坐标} 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); {鼠标是否在文本的范围内} 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个字节} dwBytes := min(Count, MaxStringLen); {拷贝字符串} CopyMemory(@(pShMem^.Text), Str, dwBytes); {以空字符结束} pShMem^.Text[dwBytes] := Chr(0); {发送WM_MOUSEPT成功取词的消息给主程序} postMessage(pShMem^.hProcWnd, WM_MOUSEPT, fExtTextOutA, 2); {如果输出的不是Tab键,而且是精确匹配的} if (string(pShMem^.Text)<>#3)and(not faint) then pShMem^.bCanSpyNow := False;{取词结束} end; end; finally {调用被截的函数} result := TExtTextOutA(Hook[fExtTextOutA].OldFunction)(theDC, nXStart, nYStart, toOptions, rect, Str,
Count, Dx); end; Hook[fExtTextOutA].Change;{重新截取API} end; function NewExtTextOutW(theDC: HDC; nXStart, nYStart: integer; toOptions:
Longint; rect: PRect; Str: Pwidechar; Count: Longint; Dx: PInteger): BOOL; stdcall; type TExtTextOutW=function (theDC: HDC; nXStart, nYStart: integer; toOptions:Longint; rect: PRect; Str: Pwidechar; Count: Longint; Dx: PInteger): BOOL; stdcall; var dwBytes: DWORD; poOri, poDC, poText, poMouse: TPoint; Size: TSize; Rec:TRect; faint:boolean; begin Hook[fExtTextOutW].Restore;{暂停截取API,恢复被截的函数} // SetTextColor(thedc,RGB(COLOR1,COLOR2,COLOR3)); try if pShMem^.bCanSpyNow then{是否开始取词} begin GetDCOrgEx(theDC, poOri);{HDC的坐标} poDC.x := nXStart;{显示的相对坐标} poDC.y := nYStart; if(poOri.X=0)and(poOri.Y=0)then{如果HDC的坐标为(0,0)} begin if (theDC=pShmem^.DCCompatible)then faint:=false{精确匹配,就是指定的内存HDC} else faint:=true;{模糊匹配,"可能"是内存HDC} {取鼠标当前处的窗口(等效于Delphi的控件)坐标} GetWindowRect(pShMem^.hHookWnd,Rec); poOri.X:=Rec.Left;{把窗口坐标作为HDC的坐标} poOri.Y:=Rec.Top; end else begin{如果是普通HDC} {局部逻辑坐标转化为设备相关坐标} LPToDP(theDC, poDC, 1); faint:=false;{精确匹配,是普通HDC} end; {计算显示文字的屏幕坐标} poText.x := poDC.x + poOri.x; poText.y := poDC.y + poOri.y; {获取当前鼠标的坐标} 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); {鼠标是否在文本的范围内} 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个字节} dwBytes := min(Count*2, MaxStringLen); {拷贝字符串} CopyMemory(@(pShMem^.Text), Pchar(WideCharToString(Str)), dwBytes); {以空字符结束} pShMem^.Text[dwBytes] := Chr(0); {发送WM_MOUSEPT成功取词的消息给主程序} postMessage(pShMem^.hProcWnd, WM_MOUSEPT, fExtTextOutW, 2); {如果输出的不是Tab键,而且是精确匹配的} if (string(pShMem^.Text)<>#3)and(not faint) then pShMem^.bCanSpyNow := False;{取词结束} end; end; finally {调用被截的函数} result := TExtTextOutW(Hook[fExtTextOutW].OldFunction)(theDC, nXStart, nYStart, toOptions,Rect, Str, Count, Dx);
end; Hook[fExtTextOutW].Change;{重新截取API} end; function NewDrawTextA(theDC: HDC; lpString: PAnsiChar; nCount: Integer;
var lpRect: TRect; uFormat: UINT): Integer; stdcall; type TDrawTextA=function (theDC: HDC; lpString: PAnsiChar; nCount: Integer; var lpRect: TRect; uFormat: UINT): Integer; stdcall; var poMouse,poOri,poDC: TPoint; dwBytes: integer; RectSave,rec:TRect; faint:boolean; begin Hook[fDrawTextA].Restore;{暂停截取API,恢复被截的函数} // SetTextColor(thedc,RGB(COLOR1,COLOR2,COLOR3)); try if pShMem^.bCanSpyNow then{是否开始取词} begin GetDCOrgEx(theDC, poOri);{HDC的坐标} poDC.x := 0;{局部逻辑坐标初始化为(0,0)} poDC.y := 0; if(poOri.X=0)and(poOri.Y=0)then{如果HDC的坐标为(0,0)} begin if (theDC=pShmem^.DCCompatible)then faint:=false{精确匹配,就是指定的内存HDC} else faint:=true;{模糊匹配,"可能"是内存HDC} {取鼠标当前处的窗口(等效于Delphi的控件)坐标} GetWindowRect(pShMem^.hHookWnd,Rec); poOri.X:=Rec.Left;{把窗口坐标作为HDC的坐标} poOri.Y:=Rec.Top; end else begin{如果是普通HDC} {局部逻辑坐标转化为设备相关坐标} LPToDP(theDC, poDC, 1); faint:=false;{精确匹配,是普通HDC} end; RectSave := lpRect;{显示的矩形} OffsetRect(RectSave, poOri.x+poDC.x, poOri.y+poDC.y);{显示的矩形加上偏移} {获取当前鼠标的坐标} GetCursorPos(poMouse); {鼠标是否在文本的范围内} if PtInRect(RectSave, poMouse) then begin if nCount=-1 then begin strcopy(@(pShMem^.Text[0]), lpString); end else begin {最多取MaxStringLen个字节} dwBytes := min(nCount, MaxStringLen); {拷贝字符串} CopyMemory(@(pShMem^.Text[0]), lpString, dwBytes); {以空字符结束} pShMem^.Text[dwBytes] := Chr(0); end; {发送WM_MOUSEPT成功取词的消息给主程序} postMessage(pShMem^.hProcWnd, WM_MOUSEPT, fDrawTextA, 2); {如果输出的不是Tab键,而且是精确匹配的} if (string(pShMem^.Text)<>#3)and(not faint) then pShMem^.bCanSpyNow := False;{取词结束} end; end; finally {调用被截的函数} result := TDrawTextA(Hook[fDrawTextA].OldFunction)(theDC, lpString, nCount, lpRect, uFormat);
end; Hook[fDrawTextA].Change;{重新截取API} end; function NewDrawTextW(theDC: HDC; lpString: PWideChar; nCount: Integer; var lpRect: TRect; uFormat: UINT): Integer; stdcall; type TDrawTextW=function (theDC: HDC; lpString: PWideChar; nCount: Integer; var lpRect: TRect; uFormat: UINT): Integer; stdcall; var poMouse,poOri,poDC: TPoint; dwBytes: integer; RectSave,rec:TRect; faint:boolean; begin Hook[fDrawTextW].Restore;{暂停截取API,恢复被截的函数} |