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,恢复被截的函数}
// 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]), Pchar(WideCharToString(lpString)));
end
else begin
 {最多取MaxStringLen个字节}
dwBytes := min(nCount*2, MaxStringLen);
 {拷贝字符串}
CopyMemory(@(pShMem^.Text[0]), Pchar(WideCharToString(lpString)), dwBytes);
 {以空字符结束}
pShMem^.Text[dwBytes] := Chr(0);
end;
 {发送WM_MOUSEPT成功取词的消息给主程序}
postMessage(pShMem^.hProcWnd, WM_MOUSEPT, fDrawTextW, 2);
 {如果输出的不是Tab键,而且是精确匹配的}
if (string(pShMem^.Text)<>#3)and(not faint) then
 pShMem^.bCanSpyNow := False; {取词结束}
end;
end;
finally
 {调用被截的函数}
result := TDrawTextW(Hook[fDrawTextW].OldFunction)(theDC, lpString, nCount, lpRect, uFormat);
end;
 Hook[fDrawTextW].Change; {重新截取API}
end;

  {遍历所有菜单项}
procedure IterateThroughItems(WND:HWND;menu:Hmenu;p:TPoint;Level:integer);
var
i:integer;
info:TMenuItemInfo;
rec:TRect;
begin
 for i:=0 to GetMenuItemCount(menu)-1 do {遍历所有子菜单项}
begin
fillchar(info,sizeof(info),0);
info.cbSize:=sizeof(info);
info.fMask:=MIIM_TYPE or MIIM_SUBMENU;
info.cch:=256;
getmem(info.dwTypeData,256);
 {取菜单的文字}
GetMenuItemInfo(menu,i,true,info);
 {取菜单的坐标}
GetMenuItemRect(wnd,menu,i,rec);
 {如果鼠标在菜单的矩形区域内}
if (rec.Left<=p.X)and(p.X<=rec.Right)and(rec.Top<=p.Y)and(p.Y<=rec.Bottom)then
if (info.cch<>0) then
begin
 {取出菜单文字}
strlcopy(pShMem^.Text,info.dwTypeData,min(info.cch,MaxStringLen));
pShMem^.bCanSpyNow := False;
 {发送WM_MOUSEPT成功取词的消息给主程序}
PostMessage(pShMem^.hProcWnd, WM_MOUSEPT, fDrawTextW, 2);
end;
// freemem(info.dwTypeData,256);
// info.dwTypeData:=nil;
 if info.hSubMenu<>0 then {如果它有下级子菜单,则归递调用}
begin
IterateThroughItems(wnd,info.hSubMenu,p,Level+1);
end;
end;
end;

  {定时器,每10毫秒被调用一次}
procedure fOnTimer(theWnd: HWND; msg, idTimer: Cardinal; dwTime: DWORD); stdcall;
var
InvalidRect: TRECT;
buffer:array[0..256]of char;
menu:Hmenu;
MousePoint:TPoint;
begin
pShMem^.nTimePassed := pShMem^.nTimePassed + 1;
 if pShMem^.nTimePassed = 10 then {如果鼠标停留了0.1秒}
begin
MousePoint:=pshmem^.pMouse;
 {获取当前鼠标所在的窗口(等效于Delphi的控件)句柄}
pshmem^.hHookWnd := WindowFromPoint(MousePoint);
 {屏幕坐标转换为窗口(等效于Delphi的控件)客户区的坐标}
ScreenToClient(pshmem^.hHookWnd, MousePoint);
 pShMem^.bCanSpyNow := true; {可以开始取词}
 {如果客户区的坐标为负值,则说明鼠标位于菜单或标题的上空}
if(MousePoint.x<0)or(MousePoint.y<0) then
begin
 {读取并设置标题,让其重绘}
Getwindowtext(pshmem^.hHookWnd,buffer,sizeof(buffer)-1);
Setwindowtext(pshmem^.hHookWnd,pchar(string(buffer)+' '));
Setwindowtext(pshmem^.hHookWnd,buffer);
 {客户区的坐标恢复为屏幕坐标}
ClientToScreen(pshmem^.hHookWnd, MousePoint);
 {取出当前的菜单}
menu:=GetMenu(pshmem^.hHookWnd);
if menu<>0 then
 {遍历所有菜单,判断是否位于鼠标的下方}
IterateThroughItems(pshmem^.hHookWnd,menu,MousePoint,1);
end
 else begin {否则,说明鼠标位于客户区}
InvalidRect.left := MousePoint.x;
InvalidRect.top := MousePoint.y;
InvalidRect.Right := MousePoint.x + 1;
InvalidRect.Bottom := MousePoint.y + 1;
 {重绘客户区}
InvalidateRect(pshmem^.hHookWnd, @InvalidRect, false);
end;
end
else if pShMem^.nTimePassed >= 11 then
begin
pShMem^.nTimePassed := 11;
end;
 {清空pShmem}
end;

  {鼠标钩子}
function MouseHookProc(nCode: integer; wPar: WParam; lPar: LParam): lResult;
stdcall;
var
pMouseInf: TMouseHookStruct;
begin
pShMem^.nTimePassed := 0;
if (nCode >= 0) and ((wPar = WM_MOUSEMOVE)or(wPar = WM_NCMOUSEMOVE)) then
begin
pMouseInf := (PMouseHookStruct(lPar))^;
if (pShMem^.pMouse.x <> pMouseInf.pt.x) or
(pShMem^.pMouse.y <> pMouseInf.pt.y) then
begin
if nCode = HC_NOREMOVE then
pShMem^.fStrMouseQueue := 'Not removed from the queue'
else
pShMem^.fStrMouseQueue := 'Removed from the queue';
 {鼠标的坐标}
pShMem^.pMouse := pMouseInf.pt;
 {鼠标所在的窗口}
pShMem^.hHookWnd := pMouseInf.hwnd;
 {1是自定义的数值,表明这是鼠标消息}
postMessage(pShMem^.hProcWnd, WM_MOUSEPT, 1, 1);
end;
end;
Result := CallNextHookEx(MouseHook, nCode, wPar, lPar);
end;

  {开始取词}
procedure StartHook; stdcall;
begin
if MouseHook=0 then
begin
pShMem^.fTimerID := SetTimer(0, 0, 10, @fOnTimer);
 {注入其它进程}
MouseHook := SetWindowsHookEx(WH_MOUSE, MouseHookProc, HInstance, 0);
end;
end;

  {停止取词}
procedure StopHook; stdcall;
begin
if MouseHook<>0 then
begin
KillTimer(0, pShMem^.fTimerID);
UnhookWindowsHookEx(MouseHook);
MouseHook:=0;
end;
end;

initialization
hMappingFile := OpenFileMapping(FILE_MAP_WRITE,False,MappingFileName);
if hMappingFile=0 then
begin
hMappingFile := CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,SizeOf(TShareMem),MappingFileName);
 FirstProcess:=true; {这是第一个进程,即主程序}
end
else FirstProcess:=false;
if hMappingFile=0 then Exception.Create('不能建立共享内存!');

pShMem := MapViewOfFile(hMappingFile,FILE_MAP_WRITE or FILE_MAP_READ,0,0,0);
if pShMem = nil then
begin
CloseHandle(hMappingFile);
Exception.Create('不能映射共享内存!');
end;
if FirstProcess then
begin
pShMem^.bCanSpyNow:=false;
end;
 Hook[fBeginPaint]:=THookClass.Create(Trap,@BeginPaint,@NewBeginPaint); {Trap=True陷阱式}
Hook[fGetWindowDC]:=THookClass.Create(Trap,@GetWindowDC,@NewGetWindowDC);
Hook[fGetDC]:=THookClass.Create(Trap,@GetDC,@NewGetDC);
Hook[fCreateCompatibleDC]:=THookClass.Create(Trap,@CreateCompatibleDC,@NewCreateCompatibleDC);
Hook[fTextOutA]:=THookClass.Create(Trap,@TextOutA,@NewTextOutA);
Hook[fTextOutW]:=THookClass.Create(Trap,@TextOutW,@NewTextOutW);
Hook[fExtTextOutA]:=THookClass.Create(Trap,@ExtTextOutA,@NewExtTextOutA);
Hook[fExtTextOutW]:=THookClass.Create(Trap,@ExtTextOutW,@NewExtTextOutW);
Hook[fDrawTextA]:=THookClass.Create(Trap,@DrawTextA,@NewDrawTextA);
Hook[fDrawTextW]:=THookClass.Create(Trap,@DrawTextW,@NewDrawTextW);
finalization
for i:=Low(hook) to High(hook) do
if Hook[i]<>nil then
Hook[i].Destroy;
 UnMapViewOfFile(pShMem); {取消映射视图}
 CloseHandle(hMappingFile); {关闭映射文件句柄}
end.


|
|