屏幕取词源码<br><br>unit UnitHookDll;<br><br>interface<br><br>uses Windows, SysUtils, Classes, math, messages, dialogs, UnitNt2000Hook,<br> UnitHookType;<br><br>const<br> COLOR1=255;<br> COLOR2=0;<br> COLOR3=255;<br> Trap=true; //True陷阱式,False表示改引入表式<br><br> procedure StartHook; stdcall; {开始取词}<br> procedure StopHook; stdcall; {停止取词}<br><br>implementation<br><br>var<br> MouseHook: THandle;<br> pShMem: PShareMem;<br> hMappingFile: THandle;<br> FirstProcess:boolean;{是否是第一个进程}<br> Hook: array[fBeginPaint..fDrawTextW] of THookClass;{API HOOK类}<br> i:integer;<br><br>{自定义的BeginPaint}<br>function NewBeginPaint(Wnd: HWND; var lpPaint: TPaintStruct): HDC; stdcall;<br>type<br> TBeginPaint=function (Wnd: HWND; var lpPaint: TPaintStruct): HDC; stdcall;<br>begin<br> Hook[fBeginPaint].Restore;<br> result:=TBeginPaint(Hook[fBeginPaint].OldFunction)(Wnd,lpPaint);<br> if Wnd=pshmem^.hHookWnd then{如果是当前鼠标的窗口句柄}<br> begin<br> pshmem^.DCMouse:=result;{记录它的返回值}<br> end<br> else pshmem^.DCMouse:=0;<br> Hook[fBeginPaint].Change;<br>end;<br><br>{自定义的GetWindowDC}<br>function NewGetWindowDC(Wnd: HWND): HDC; stdcall;<br>type<br> TGetWindowDC=function (Wnd: HWND): HDC; stdcall;<br>begin<br> Hook[fGetWindowDC].Restore;<br> result:=TGetWindowDC(Hook[fGetWindowDC].OldFunction)(Wnd);<br> if Wnd=pshmem^.hHookWnd then{如果是当前鼠标的窗口句柄}<br> begin<br> pshmem^.DCMouse:=result;{记录它的返回值}<br> end<br> else pshmem^.DCMouse:=0; <br> Hook[fGetWindowDC].Change;<br>end;<br><br>{自定义的GetDC}<br>function NewGetDC(Wnd: HWND): HDC; stdcall;<br>type<br> TGetDC=function (Wnd: HWND): HDC; stdcall;<br>begin<br> Hook[fGetDC].Restore;<br> result:=TGetDC(Hook[fGetDC].OldFunction)(Wnd);<br> if Wnd=pshmem^.hHookWnd then{如果是当前鼠标的窗口句柄}<br> begin<br> pshmem^.DCMouse:=result;{记录它的返回值}<br> end<br> else pshmem^.DCMouse:=0;<br> Hook[fGetDC].Change;<br>end;<br><br>{自定义的CreateCompatibleDC}<br>function NewCreateCompatibleDC(DC: HDC): HDC; stdcall;<br>type<br> TCreateCompatibleDC=function (DC: HDC): HDC; stdcall;<br>begin<br> Hook[fCreateCompatibleDC].Restore;<br> result:=TCreateCompatibleDC(Hook[fCreateCompatibleDC].OldFunction)(DC);<br> if DC=pshmem^.DCMouse then{如果是当前鼠标的窗口HDC}<br> begin<br> pshmem^.DCCompatible:=result;{记录它的返回值}<br> end<br> else pshmem^.DCCompatible:=0;<br> Hook[fCreateCompatibleDC].Change;<br>end;<br><br>function NewTextOutA(theDC: HDC; nXStart, nYStart: integer; str: pchar; count: integer): bool;<br> stdcall;<br>type<br> TTextOutA=function (theDC: HDC; nXStart, nYStart: integer; str: pchar; count: integer): bool;stdcall;<br>var<br> dwBytes: DWORD;<br> poOri, poDC, poText, poMouse: TPoint;<br> Size: TSize;<br> Rec:TRect;<br> faint:boolean;<br>begin<br> Hook[fTextOutA].Restore;{暂停截取API,恢复被截的函数}<br> try<br> if pShMem^.bCanSpyNow then{是否开始取词}<br> begin<br> GetDCOrgEx(theDC, poOri);{HDC的坐标}<br> poDC.x := nXStart;{显示的相对坐标}<br> poDC.y := nYStart;<br> if(poOri.X=0)and(poOri.Y=0)then{如果HDC的坐标为(0,0)}<br> begin<br> if (theDC=pShmem^.DCCompatible)then<br> faint:=false{精确匹配,就是指定的内存HDC}<br> else faint:=true;{模糊匹配,"可能"是内存HDC}<br> {取鼠标当前处的窗口(等效于Delphi的控件)坐标}<br> GetWindowRect(pShMem^.hHookWnd,Rec);<br> poOri.X:=Rec.Left;{把窗口坐标作为HDC的坐标}<br> poOri.Y:=Rec.Top;<br> end<br> else begin{如果是普通HDC}<br> {局部逻辑坐标转化为设备相关坐标}<br> LPToDP(theDC, poDC, 1);<br> faint:=false;{精确匹配,是普通HDC}<br> end;<br> {计算显示文字的屏幕坐标}<br> poText.x := poDC.x + poOri.x;<br> poText.y := poDC.y + poOri.y;<br> {获取当前鼠标的坐标}<br> GetCursorPos(poMouse);<br> {如果对齐属性是居中}<br> if (GetTextAlign(theDC) and TA_UPDATECP) <> 0 then<br> begin<br> GetCurrentPositionEx(theDC, @poOri);<br> poText.x := poText.x + poOri.x;<br> poText.y := poText.y + poOri.y;<br> end;<br> {显示文字的长和宽}<br> GetTextExtentPoint(theDC, Str, Count, Size);<br> {鼠标是否在文本的范围内}<br> if (poMouse.x >= poText.x) and (poMouse.x <= poText.x + Size.cx)<br> and (poMouse.y >= poText.y) and (poMouse.y <= poText.y + Size.cy)<br> then<br> begin<br> {最多取MaxStringLen个字节}<br> dwBytes := min(Count, MaxStringLen);<br> {拷贝字符串}<br> CopyMemory(@(pShMem^.Text), Str, dwBytes);<br> {以空字符结束}<br> pShMem^.Text[dwBytes] := Chr(0);<br> {发送WM_MOUSEPT成功取词的消息给主程序}<br> postMessage(pShMem^.hProcWnd, WM_MOUSEPT, fTextOutA, 2);<br> {如果输出的不是Tab键,而且是精确匹配的}<br> if (string(pShMem^.Text)<>#3)and(not faint) then<br> pShMem^.bCanSpyNow := False;{取词结束}<br> end;<br> end;<br> finally<br> {调用被截的函数}<br> result := TTextOutA(Hook[fTextOutA].OldFunction)(theDC, nXStart,<br> nYStart, str, count);<br> end;<br> Hook[fTextOutA].Change;{重新截取API}<br>end;<br><br><br>function NewTextOutW(theDC: HDC; nXStart, nYStart: integer; str: pWidechar; count: integer): bool; stdcall;<br>type<br> TTextOutW=function (theDC: HDC; nXStart, nYStart: integer; str: pWidechar; count: integer): bool; stdcall;<br>var<br> dwBytes: DWORD;<br> poOri, poDC, poText, poMouse: TPoint;<br> Size: TSize;<br> Rec:TRect;<br> faint:boolean;<br>begin<br> Hook[fTextOutW].Restore;{暂停截取API,恢复被截的函数}<br>// SetTextColor(thedc,RGB(COLOR1,COLOR2,COLOR3));<br> try<br> if pShMem^.bCanSpyNow then{是否开始取词}<br> begin<br> GetDCOrgEx(theDC, poOri);{HDC的坐标}<br> poDC.x := nXStart;{显示的相对坐标}<br> poDC.y := nYStart;<br> if(poOri.X=0)and(poOri.Y=0)then{如果HDC的坐标为(0,0)}<br> begin<br> if (theDC=pShmem^.DCCompatible)then<br> faint:=false{精确匹配,就是指定的内存HDC}<br> else faint:=true;{模糊匹配,"可能"是内存HDC}<br> {取鼠标当前处的窗口(等效于Delphi的控件)坐标}<br> GetWindowRect(pShMem^.hHookWnd,Rec);<br> poOri.X:=Rec.Left;{把窗口坐标作为HDC的坐标}<br> poOri.Y:=Rec.Top;<br> end<br> else begin{如果是普通HDC}<br> {局部逻辑坐标转化为设备相关坐标}<br> LPToDP(theDC, poDC, 1);<br> faint:=false;{精确匹配,是普通HDC}<br> end;<br> {计算显示文字的屏幕坐标}<br> poText.x := poDC.x + poOri.x;<br> poText.y := poDC.y + poOri.y;<br> {获取当前鼠标的坐标}<br> GetCursorPos(poMouse);<br> {如果对齐属性是居中}<br> if (GetTextAlign(theDC) and TA_UPDATECP) <> 0 then<br> begin<br> GetCurrentPositionEx(theDC, @poOri);<br> poText.x := poText.x + poOri.x;<br> poText.y := poText.y + poOri.y;<br> end;<br> {显示文字的长和宽}<br> GetTextExtentPointW(theDC, Str, Count, Size);<br> {鼠标是否在文本的范围内}<br> if (poMouse.x >= poText.x) and (poMouse.x <= poText.x + Size.cx)<br> and (poMouse.y >= poText.y) and (poMouse.y <= poText.y + Size.cy)<br> then<br> begin<br> {最多取MaxStringLen个字节}<br> dwBytes := min(Count*2, MaxStringLen);<br> {拷贝字符串}<br> CopyMemory(@(pShMem^.Text), Pchar(WideCharToString(Str)), dwBytes);<br> {以空字符结束}<br> pShMem^.Text[dwBytes] := Chr(0);<br> {发送WM_MOUSEPT成功取词的消息给主程序}<br> postMessage(pShMem^.hProcWnd, WM_MOUSEPT, fTextOutW, 2);<br> {如果输出的不是Tab键,而且是精确匹配的}<br> if (string(pShMem^.Text)<>#3)and(not faint) then<br> pShMem^.bCanSpyNow := False;{取词结束}<br> end;<br> end;<br> finally<br> {调用被截的函数}<br> result := TTextOutW(Hook[fTextOutW].OldFunction)(theDC, nXStart, nYStart, str, Count);<br> end;<br> Hook[fTextOutW].Change;{重新截取API}<br>end;<br><br>function NewExtTextOutA(theDC: HDC; nXStart, nYStart: integer; toOptions:Longint;<br> rect: PRect; Str: PAnsiChar; Count: Longint; Dx: PInteger): BOOL; stdcall;<br>type<br> TExtTextOutA=function (theDC: HDC; nXStart, nYStart: integer; toOptions:Longint;<br> rect: PRect; Str: PAnsiChar; Count: Longint; Dx: PInteger): BOOL; stdcall;<br>var<br> dwBytes: DWORD;<br> poOri, poDC, poText, poMouse: TPoint;<br> Size: TSize;<br> Rec:TRect;<br> faint:boolean;<br>begin<br> Hook[fExtTextOutA].Restore;{暂停截取API,恢复被截的函数}<br>// SetTextColor(thedc,RGB(COLOR1,COLOR2,COLOR3));<br> try<br> if pShMem^.bCanSpyNow then{是否开始取词}<br> begin<br> GetDCOrgEx(theDC, poOri);{HDC的坐标}<br> poDC.x := nXStart;{显示的相对坐标}<br> poDC.y := nYStart;<br> if(poOri.X=0)and(poOri.Y=0)then{如果HDC的坐标为(0,0)}<br> begin<br> if (theDC=pShmem^.DCCompatible)then<br> faint:=false{精确匹配,就是指定的内存HDC}<br> else faint:=true;{模糊匹配,"可能"是内存HDC}<br> {取鼠标当前处的窗口(等效于Delphi的控件)坐标}<br> GetWindowRect(pShMem^.hHookWnd,Rec);<br> poOri.X:=Rec.Left;{把窗口坐标作为HDC的坐标}<br> poOri.Y:=Rec.Top;<br> end<br> else begin{如果是普通HDC}<br> {局部逻辑坐标转化为设备相关坐标}<br> LPToDP(theDC, poDC, 1);<br> faint:=false;{精确匹配,是普通HDC}<br> end;<br> {计算显示文字的屏幕坐标}<br> poText.x := poDC.x + poOri.x;<br> poText.y := poDC.y + poOri.y;<br> {获取当前鼠标的坐标}<br> GetCursorPos(poMouse);<br> {如果对齐属性是居中}<br> if (GetTextAlign(theDC) and TA_UPDATECP) <> 0 then<br> begin<br> GetCurrentPositionEx(theDC, @poOri);<br> poText.x := poText.x + poOri.x;<br> poText.y := poText.y + poOri.y;<br> end;<br> {显示文字的长和宽}<br> GetTextExtentPoint(theDC, Str, Count, Size);<br> {鼠标是否在文本的范围内}<br> if (poMouse.x >= poText.x) and (poMouse.x <= poText.x + Size.cx)<br> and (poMouse.y >= poText.y) and (poMouse.y <= poText.y + Size.cy)<br> then<br> begin<br> {最多取MaxStringLen个字节}<br> dwBytes := min(Count, MaxStringLen);<br> {拷贝字符串}<br> CopyMemory(@(pShMem^.Text), Str, dwBytes);<br> {以空字符结束}<br> pShMem^.Text[dwBytes] := Chr(0);<br> {发送WM_MOUSEPT成功取词的消息给主程序}<br> postMessage(pShMem^.hProcWnd, WM_MOUSEPT, fExtTextOutA, 2);<br> {如果输出的不是Tab键,而且是精确匹配的}<br> if (string(pShMem^.Text)<>#3)and(not faint) then<br> pShMem^.bCanSpyNow := False;{取词结束}<br> end;<br> end;<br> finally<br> {调用被截的函数}<br> result := TExtTextOutA(Hook[fExtTextOutA].OldFunction)(theDC, nXStart, nYStart, toOptions, rect, Str,<br> Count, Dx);<br> end;<br> Hook[fExtTextOutA].Change;{重新截取API}<br>end;<br><br>function NewExtTextOutW(theDC: HDC; nXStart, nYStart: integer; toOptions:<br> Longint; rect: PRect;<br> Str: Pwidechar; Count: Longint; Dx: PInteger): BOOL; stdcall;<br>type<br> TExtTextOutW=function (theDC: HDC; nXStart, nYStart: integer; toOptions:Longint;<br> rect: PRect; Str: Pwidechar; Count: Longint; Dx: PInteger): BOOL; stdcall;<br>var<br> dwBytes: DWORD;<br> poOri, poDC, poText, poMouse: TPoint;<br> Size: TSize;<br> Rec:TRect;<br> faint:boolean; <br>begin<br> Hook[fExtTextOutW].Restore;{暂停截取API,恢复被截的函数}<br>// SetTextColor(thedc,RGB(COLOR1,COLOR2,COLOR3));<br> try<br> if pShMem^.bCanSpyNow then{是否开始取词}<br> begin<br> GetDCOrgEx(theDC, poOri);{HDC的坐标}<br> poDC.x := nXStart;{显示的相对坐标}<br> poDC.y := nYStart;<br> if(poOri.X=0)and(poOri.Y=0)then{如果HDC的坐标为(0,0)}<br> begin<br> if (theDC=pShmem^.DCCompatible)then<br> faint:=false{精确匹配,就是指定的内存HDC}<br> else faint:=true;{模糊匹配,"可能"是内存HDC}<br> {取鼠标当前处的窗口(等效于Delphi的控件)坐标}<br> GetWindowRect(pShMem^.hHookWnd,Rec);<br> poOri.X:=Rec.Left;{把窗口坐标作为HDC的坐标}<br> poOri.Y:=Rec.Top;<br> end<br> else begin{如果是普通HDC}<br> {局部逻辑坐标转化为设备相关坐标}<br> LPToDP(theDC, poDC, 1);<br> faint:=false;{精确匹配,是普通HDC}<br> end;<br> {计算显示文字的屏幕坐标}<br> poText.x := poDC.x + poOri.x;<br> poText.y := poDC.y + poOri.y;<br> {获取当前鼠标的坐标}<br> GetCursorPos(poMouse);<br> {如果对齐属性是居中}<br> if (GetTextAlign(theDC) and TA_UPDATECP) <> 0 then<br> begin<br> GetCurrentPositionEx(theDC, @poOri);<br> poText.x := poText.x + poOri.x;<br> poText.y := poText.y + poOri.y;<br> end;<br> {显示文字的长和宽}<br> GetTextExtentPointW(theDC, Str, Count, Size);<br> {鼠标是否在文本的范围内}<br> if (poMouse.x >= poText.x) and (poMouse.x <= poText.x + Size.cx)<br> and (poMouse.y >= poText.y) and (poMouse.y <= poText.y + Size.cy)<br> then<br> begin<br> {最多取MaxStringLen个字节}<br> dwBytes := min(Count*2, MaxStringLen);<br> {拷贝字符串}<br> CopyMemory(@(pShMem^.Text), Pchar(WideCharToString(Str)), dwBytes);<br> {以空字符结束}<br> pShMem^.Text[dwBytes] := Chr(0);<br> {发送WM_MOUSEPT成功取词的消息给主程序}<br> postMessage(pShMem^.hProcWnd, WM_MOUSEPT, fExtTextOutW, 2);<br> {如果输出的不是Tab键,而且是精确匹配的}<br> if (string(pShMem^.Text)<>#3)and(not faint) then<br> pShMem^.bCanSpyNow := False;{取词结束}<br> end;<br> end;<br> finally<br> {调用被截的函数}<br> result := TExtTextOutW(Hook[fExtTextOutW].OldFunction)(theDC, nXStart, nYStart, toOptions,Rect, Str, Count, Dx);<br> end;<br> Hook[fExtTextOutW].Change;{重新截取API}<br>end;<br><br>function NewDrawTextA(theDC: HDC; lpString: PAnsiChar; nCount: Integer;<br> var lpRect: TRect; uFormat: UINT): Integer; stdcall;<br>type<br> TDrawTextA=function (theDC: HDC; lpString: PAnsiChar; nCount: Integer;<br> var lpRect: TRect; uFormat: UINT): Integer; stdcall;<br>var<br> poMouse,poOri,poDC: TPoint;<br> dwBytes: integer;<br> RectSave,rec:TRect;<br> faint:boolean; <br>begin<br> Hook[fDrawTextA].Restore;{暂停截取API,恢复被截的函数}<br>// SetTextColor(thedc,RGB(COLOR1,COLOR2,COLOR3));<br> try<br> if pShMem^.bCanSpyNow then{是否开始取词}<br> begin<br> GetDCOrgEx(theDC, poOri);{HDC的坐标}<br> poDC.x := 0;{局部逻辑坐标初始化为(0,0)}<br> poDC.y := 0;<br> if(poOri.X=0)and(poOri.Y=0)then{如果HDC的坐标为(0,0)}<br> begin<br> if (theDC=pShmem^.DCCompatible)then<br> faint:=false{精确匹配,就是指定的内存HDC}<br> else faint:=true;{模糊匹配,"可能"是内存HDC}<br> {取鼠标当前处的窗口(等效于Delphi的控件)坐标}<br> GetWindowRect(pShMem^.hHookWnd,Rec);<br> poOri.X:=Rec.Left;{把窗口坐标作为HDC的坐标}<br> poOri.Y:=Rec.Top;<br> end<br> else begin{如果是普通HDC}<br> {局部逻辑坐标转化为设备相关坐标}<br> LPToDP(theDC, poDC, 1);<br> faint:=false;{精确匹配,是普通HDC}<br> end;<br> RectSave := lpRect;{显示的矩形}<br> OffsetRect(RectSave, poOri.x+poDC.x, poOri.y+poDC.y);{显示的矩形加上偏移}<br> {获取当前鼠标的坐标}<br> GetCursorPos(poMouse);<br> {鼠标是否在文本的范围内}<br> if PtInRect(RectSave, poMouse) then<br> begin<br> if nCount=-1 then<br> begin<br> strcopy(@(pShMem^.Text[0]), lpString);<br> end<br> else begin<br> {最多取MaxStringLen个字节}<br> dwBytes := min(nCount, MaxStringLen);<br> {拷贝字符串}<br> CopyMemory(@(pShMem^.Text[0]), lpString, dwBytes);<br> {以空字符结束}<br> pShMem^.Text[dwBytes] := Chr(0);<br> end;<br> {发送WM_MOUSEPT成功取词的消息给主程序}<br> postMessage(pShMem^.hProcWnd, WM_MOUSEPT, fDrawTextA, 2);<br> {如果输出的不是Tab键,而且是精确匹配的}<br> if (string(pShMem^.Text)<>#3)and(not faint) then<br> pShMem^.bCanSpyNow := False;{取词结束}<br> end;<br> end;<br> finally<br> {调用被截的函数}<br> result := TDrawTextA(Hook[fDrawTextA].OldFunction)(theDC, lpString, nCount, lpRect, uFormat);<br> end;<br> Hook[fDrawTextA].Change;{重新截取API}<br>end;<br><br>function NewDrawTextW(theDC: HDC; lpString: PWideChar; nCount: Integer;<br> var lpRect: TRect; uFormat: UINT): Integer; stdcall;<br>type<br> TDrawTextW=function (theDC: HDC; lpString: PWideChar; nCount: Integer;<br> var lpRect: TRect; uFormat: UINT): Integer; stdcall;<br>var<br> poMouse,poOri,poDC: TPoint;<br> dwBytes: integer;<br> RectSave,rec:TRect;<br> faint:boolean;<br>begin<br> Hook[fDrawTextW].Restore;{暂停截取API,恢复被截的函数}<br>// SetTextColor(thedc,RGB(COLOR1,COLOR2,COLOR3));<br> try<br> if pShMem^.bCanSpyNow then{是否开始取词}<br> begin<br> GetDCOrgEx(theDC, poOri);{HDC的坐标}<br> poDC.x := 0;{局部逻辑坐标初始化为(0,0)}<br> poDC.y := 0;<br> if(poOri.X=0)and(poOri.Y=0)then{如果HDC的坐标为(0,0)}<br> begin<br> if (theDC=pShmem^.DCCompatible)then<br> faint:=false{精确匹配,就是指定的内存HDC}<br> else faint:=true;{模糊匹配,"可能"是内存HDC}<br> {取鼠标当前处的窗口(等效于Delphi的控件)坐标}<br> GetWindowRect(pShMem^.hHookWnd,Rec);<br> poOri.X:=Rec.Left;{把窗口坐标作为HDC的坐标}<br> poOri.Y:=Rec.Top;<br> end<br> else begin{如果是普通HDC}<br> {局部逻辑坐标转化为设备相关坐标}<br> LPToDP(theDC, poDC, 1);<br> faint:=false;{精确匹配,是普通HDC}<br> end;<br> RectSave := lpRect;{显示的矩形}<br> OffsetRect(RectSave, poOri.x+poDC.x, poOri.y+poDC.y);{显示的矩形加上偏移}<br> {获取当前鼠标的坐标}<br> GetCursorPos(poMouse);<br> {鼠标是否在文本的范围内}<br> if PtInRect(RectSave, poMouse) then<br> begin<br> if nCount=-1 then<br> begin<br> strcopy(@(pShMem^.Text[0]), Pchar(WideCharToString(lpString)));<br> end<br> else begin<br> {最多取MaxStringLen个字节}<br> dwBytes := min(nCount*2, MaxStringLen);<br> {拷贝字符串}<br> CopyMemory(@(pShMem^.Text[0]), Pchar(WideCharToString(lpString)), dwBytes);<br> {以空字符结束}<br> pShMem^.Text[dwBytes] := Chr(0);<br> end;<br> {发送WM_MOUSEPT成功取词的消息给主程序}<br> postMessage(pShMem^.hProcWnd, WM_MOUSEPT, fDrawTextW, 2);<br> {如果输出的不是Tab键,而且是精确匹配的}<br> if (string(pShMem^.Text)<>#3)and(not faint) then<br> pShMem^.bCanSpyNow := False;{取词结束}<br> end;<br> end;<br> finally<br> {调用被截的函数}<br> result := TDrawTextW(Hook[fDrawTextW].OldFunction)(theDC, lpString, nCount, lpRect, uFormat);<br> end;<br> Hook[fDrawTextW].Change;{重新截取API}<br>end;<br><br>{遍历所有菜单项}<br>procedure IterateThroughItems(WND:HWND;menu:Hmenu;p:TPoint;Level:integer);<br>var<br> i:integer;<br> info:TMenuItemInfo;<br> rec:TRect;<br>begin<br> for i:=0 to GetMenuItemCount(menu)-1 do {遍历所有子菜单项}<br> begin<br> fillchar(info,sizeof(info),0);<br> info.cbSize:=sizeof(info);<br> info.fMask:=MIIM_TYPE or MIIM_SUBMENU;<br> info.cch:=256;<br> getmem(info.dwTypeData,256);<br> {取菜单的文字}<br> GetMenuItemInfo(menu,i,true,info);<br> {取菜单的坐标}<br> GetMenuItemRect(wnd,menu,i,rec);<br> {如果鼠标在菜单的矩形区域内}<br> if (rec.Left<=p.X)and(p.X<=rec.Right)and(rec.Top<=p.Y)and(p.Y<=rec.Bottom)then<br> if (info.cch<>0) then<br> begin<br> {取出菜单文字}<br> strlcopy(pShMem^.Text,info.dwTypeData,min(info.cch,MaxStringLen));<br> pShMem^.bCanSpyNow := False;<br> {发送WM_MOUSEPT成功取词的消息给主程序}<br> PostMessage(pShMem^.hProcWnd, WM_MOUSEPT, fDrawTextW, 2);<br> end;<br>// freemem(info.dwTypeData,256);<br>// info.dwTypeData:=nil;<br> if info.hSubMenu<>0 then {如果它有下级子菜单,则归递调用}<br> begin<br> IterateThroughItems(wnd,info.hSubMenu,p,Level+1);<br> end;<br> end;<br>end;<br><br>{定时器,每10毫秒被调用一次}<br>procedure fOnTimer(theWnd: HWND; msg, idTimer: Cardinal; dwTime: DWORD); stdcall;<br>var<br> InvalidRect: TRECT;<br> buffer:array[0..256]of char;<br> menu:Hmenu;<br> MousePoint:TPoint;<br>begin<br> pShMem^.nTimePassed := pShMem^.nTimePassed + 1;<br> if pShMem^.nTimePassed = 10 then {如果鼠标停留了0.1秒}<br> begin<br> MousePoint:=pshmem^.pMouse;<br> {获取当前鼠标所在的窗口(等效于Delphi的控件)句柄}<br> pshmem^.hHookWnd := WindowFromPoint(MousePoint);<br> {屏幕坐标转换为窗口(等效于Delphi的控件)客户区的坐标}<br> ScreenToClient(pshmem^.hHookWnd, MousePoint);<br> pShMem^.bCanSpyNow := true;{可以开始取词}<br> {如果客户区的坐标为负值,则说明鼠标位于菜单或标题的上空}<br> if(MousePoint.x<0)or(MousePoint.y<0) then<br> begin<br> {读取并设置标题,让其重绘}<br> Getwindowtext(pshmem^.hHookWnd,buffer,sizeof(buffer)-1);<br> Setwindowtext(pshmem^.hHookWnd,pchar(string(buffer)+' '));<br> Setwindowtext(pshmem^.hHookWnd,buffer);<br> {客户区的坐标恢复为屏幕坐标}<br> ClientToScreen(pshmem^.hHookWnd, MousePoint);<br> {取出当前的菜单}<br> menu:=GetMenu(pshmem^.hHookWnd);<br> if menu<>0 then<br> {遍历所有菜单,判断是否位于鼠标的下方}<br> IterateThroughItems(pshmem^.hHookWnd,menu,MousePoint,1);<br> end<br> else begin{否则,说明鼠标位于客户区}<br> InvalidRect.left := MousePoint.x;<br> InvalidRect.top := MousePoint.y;<br> InvalidRect.Right := MousePoint.x + 1;<br> InvalidRect.Bottom := MousePoint.y + 1;<br> {重绘客户区}<br> InvalidateRect(pshmem^.hHookWnd, @InvalidRect, false);<br> end;<br> end<br> else if pShMem^.nTimePassed >= 11 then<br> begin<br> pShMem^.nTimePassed := 11;<br> end;<br> {清空pShmem}<br>end;<br><br>{鼠标钩子}<br>function MouseHookProc(nCode: integer; wPar: WParam; lPar: LParam): lResult;<br> stdcall;<br>var<br> pMouseInf: TMouseHookStruct;<br>begin<br> pShMem^.nTimePassed := 0;<br> if (nCode >= 0) and ((wPar = WM_MOUSEMOVE)or(wPar = WM_NCMOUSEMOVE)) then<br> begin<br> pMouseInf := (PMouseHookStruct(lPar))^;<br> if (pShMem^.pMouse.x <> pMouseInf.pt.x) or<br> (pShMem^.pMouse.y <> pMouseInf.pt.y) then<br> begin<br> if nCode = HC_NOREMOVE then<br> pShMem^.fStrMouseQueue := 'Not removed from the queue'<br> else<br> pShMem^.fStrMouseQueue := 'Removed from the queue';<br> {鼠标的坐标}<br> pShMem^.pMouse := pMouseInf.pt;<br> {鼠标所在的窗口}<br> pShMem^.hHookWnd := pMouseInf.hwnd;<br> {1是自定义的数值,表明这是鼠标消息}<br> postMessage(pShMem^.hProcWnd, WM_MOUSEPT, 1, 1);<br> end;<br> end;<br> Result := CallNextHookEx(MouseHook, nCode, wPar, lPar);<br>end;<br><br>{开始取词}<br>procedure StartHook; stdcall;<br>begin<br> if MouseHook=0 then<br> begin<br> pShMem^.fTimerID := SetTimer(0, 0, 10, @fOnTimer);<br> {注入其它进程}<br> MouseHook := SetWindowsHookEx(WH_MOUSE, MouseHookProc, HInstance, 0);<br> end;<br>end;<br><br>{停止取词}<br>procedure StopHook; stdcall;<br>begin<br> if MouseHook<>0 then<br> begin<br> KillTimer(0, pShMem^.fTimerID);<br> UnhookWindowsHookEx(MouseHook);<br> MouseHook:=0;<br> end;<br>end;<br><br>initialization<br> hMappingFile := OpenFileMapping(FILE_MAP_WRITE,False,MappingFileName);<br> if hMappingFile=0 then<br> begin<br> hMappingFile := CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,SizeOf(TShareMem),MappingFileName);<br> FirstProcess:=true; {这是第一个进程,即主程序}<br> end<br> else FirstProcess:=false;<br> if hMappingFile=0 then Exception.Create('不能建立共享内存!');<br><br> pShMem := MapViewOfFile(hMappingFile,FILE_MAP_WRITE or FILE_MAP_READ,0,0,0);<br> if pShMem = nil then<br> begin<br> CloseHandle(hMappingFile);<br> Exception.Create('不能映射共享内存!');<br> end;<br> if FirstProcess then<br> begin<br> pShMem^.bCanSpyNow:=false;<br> end;<br> Hook[fBeginPaint]:=THookClass.Create(Trap,@BeginPaint,@NewBeginPaint);{Trap=True陷阱式}<br> Hook[fGetWindowDC]:=THookClass.Create(Trap,@GetWindowDC,@NewGetWindowDC);<br> Hook[fGetDC]:=THookClass.Create(Trap,@GetDC,@NewGetDC);<br> Hook[fCreateCompatibleDC]:=THookClass.Create(Trap,@CreateCompatibleDC,@NewCreateCompatibleDC);<br> Hook[fTextOutA]:=THookClass.Create(Trap,@TextOutA,@NewTextOutA);<br> Hook[fTextOutW]:=THookClass.Create(Trap,@TextOutW,@NewTextOutW);<br> Hook[fExtTextOutA]:=THookClass.Create(Trap,@ExtTextOutA,@NewExtTextOutA);<br> Hook[fExtTextOutW]:=THookClass.Create(Trap,@ExtTextOutW,@NewExtTextOutW);<br> Hook[fDrawTextA]:=THookClass.Create(Trap,@DrawTextA,@NewDrawTextA);<br> Hook[fDrawTextW]:=THookClass.Create(Trap,@DrawTextW,@NewDrawTextW); <br>finalization<br> for i:=Low(hook) to High(hook) do<br> if Hook<>nil then<br> Hook.Destroy;<br> UnMapViewOfFile(pShMem); {取消映射视图}<br> CloseHandle(hMappingFile); {关闭映射文件句柄}<br>end.