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,恢复被截的函数}
posted on 2009-07-24 09:47  yxbsmx  阅读(635)  评论(0编辑  收藏  举报