library GetWord32;<br>uses<br> SysUtils,<br> Windows,<br> UnitHookDLL in 'UnitHookDLL.pas',<br> QTThunkU in 'QTThunkU.pas',<br> UnitHookType in 'UnitHookType.pas';<br><br>exports<br> OpenGetKeyHook,<br> CloseGetKeyHook;<br>begin<br>end.<br><br><br>unit UnitHookDLL;<br>interface<br>uses Windows, Messages, Dialogs, SysUtils, UnitHookType, Math;<br><br>type<br> THandle16 = Word;<br>function OpenGetKeyHook(sender: HWND; MessageID: WORD): BOOlean; stdcall;<br>function CloseGetKeyHook: BOOLean; stdcall;<br><br>var<br> pShMem: PShareMem;<br> hMappingFile: THandle;<br> FirstProcess: boolean;<br> pFuncCreate, pFuncFree, pFuncCheck: Pointer;<br> hInst16: THandle;<br> MessageHook: HHOOK;<br><br>{$STACKFRAMES On}<br>implementation<br><br>uses QTthunku;<br><br>{执行16位代码下进行取词,修改函数的入口}<br>function SetGDIHook: boolean; stdcall;<br>begin<br> result := false;<br> if pFuncCreate = nil then exit;<br> asm<br> pushad<br> push ebp<br> sub esp,$2c<br> mov edx, pFuncCreate {函数地址}<br> mov ebp,esp<br> add ebp,$2c<br> {利用Thunk执行16位下的函数,函数地址保存在edx中}<br> call QT_Thunk<br> add esp,$2c<br> pop ebp<br> mov byte ptr @result,al<br><br> popad<br> end;<br>end;<br><br>{执行16位代码下取消取词,恢复函数入口}<br><br>function UnSetGDIHook: boolean; stdcall;<br>begin<br> result := false;<br> if pFuncFree = nil then exit;<br> asm<br> {保寄存器的值}<br> pushad<br> push ebp<br> sub esp,$2c<br> mov edx, pFuncFree {函数地址}<br> mov ebp,esp<br> add ebp,$2c<br> {利用Thunk执行16位下的函数,函数地址保存在edx}<br> call QT_Thunk<br> add esp,$2c<br> pop ebp<br> mov byte ptr @result,al<br><br> popad<br> end;<br>end;<br><br>function CheckBuf: boolean; stdcall;<br>var<br> asd1, asd2: pchar;<br>begin<br> result := false;<br> if pFuncCheck = nil then exit;<br> {分配固定的内存,提供与16位代码交换数据}<br> asd1 := GlobalAllocPtr16(GPTR, MAXBUF);<br> {16位指针转换为32位指针}<br> asd2 := Ptr16To32(asd1);<br> asm<br> {保存寄存器的值}<br> pushad<br> push ebp<br> sub esp,$2c<br> push asd1 {第一个参数。最多支持两个参数}<br> {第二个参数}<br> mov edx, pFuncCheck{函数地址}<br> mov ebp,esp<br> add ebp,$2c<br> call QT_Thunk<br> add esp,$2c<br> pop ebp<br> mov byte ptr @result,al<br><br> popad<br> end;<br> if result then<br> begin<br> {拷贝数据到共享内存中}<br> strlcopy(@pShMem^.Text, asd2, MAXBUF);<br> end;<br> {释放16位指针}<br> GlobalFreePtr16(asd1);<br>end;<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> GetMenuItemInfo(menu,i,true,info);<br> GetMenuItemRect(wnd,menu,i,rec);<br> if (rec.Left&lt;=p.X)and(p.X&lt;=rec.Right)and(rec.Top&lt;=p.Y)and(p.Y&lt;=rec.Bottom)then<br> if (info.cch&lt;&gt;0) then<br> begin<br> strlcopy(pShMem^.Text,info.dwTypeData,min(info.cch,MAXBUF));<br> PostMessage(pShMem^.hMainWnd, WM_MOUSEPT, 2, 2);<br> end;<br>// freemem(info.dwTypeData,256);<br>// info.dwTypeData:=nil;<br> if info.hSubMenu&lt;&gt;0 then<br> begin<br> IterateThroughItems(wnd,info.hSubMenu,p,Level+1);<br> end;<br> end;<br>end;<br><br>procedure fOnTimer(theWnd: HWND; msg, idTimer: Cardinal; dwTime: DWORD); stdcall; //CallBack Type<br>var<br> InvalidRect: TRECT;<br> hwndPtIn: HWND;<br> buffer:array[0..255]of char;<br> menu:Hmenu;<br>begin<br> pShmem^.nTimePassed := pShmem^.nTimePassed + 1;<br> if pShmem^.nTimePassed = 10 then<br> begin<br> {获取当前鼠标点的窗口句柄}<br> hwndPtIn := WindowFromPoint(pshmem^.pMouse);<br> {屏幕坐标转换为客户区的坐标}<br> ScreenToClient(hwndPtIn, pshmem^.pMouse);<br> setGDIHook;<br> if(pshmem^.pMouse.x&lt;0)or(pshmem^.pMouse.y&lt;0) then<br> begin<br> Getwindowtext(hwndPtIn,buffer,sizeof(buffer)-1);<br> Setwindowtext(hwndPtIn,buffer);<br> ClientToScreen(hwndPtIn, pshmem^.pMouse);<br> //MenuItemFromPoint(hwndPtIn,GetMenu(hwndPtIn),pshmem^.pMouse);<br> menu:=GetMenu(hwndPtIn);<br> IterateThroughItems(hwndPtIn,menu,pshmem^.pMouse,1);<br>// BringWindowToTop(hwndPtIn);<br>// DrawMenuBar(hwndPtIn);<br> end<br> else begin<br> InvalidRect.left := pshmem^.pMouse.x;<br> InvalidRect.top := pshmem^.pMouse.y;<br> InvalidRect.Right := pshmem^.pMouse.x + 1;<br> InvalidRect.Bottom := pshmem^.pMouse.y + 1;<br> {强迫重画此点}<br> InvalidateRect(hwndPtIn, @InvalidRect, false);<br> end;<br> end<br> else if pShmem^.nTimePassed &gt;= 11 then<br> begin<br> {如果鼠标定留时间超过一定值,即显示数据}<br> pShmem^.nTimePassed := 11;<br> {调用检查缓冲区的数据}<br> if CheckBuf then <br> {消息值为2表示缓冲区有数据}<br> PostMessage(pShMem^.hMainWnd, WM_MOUSEPT, 2, 2);<br> end;<br>end;<br><br>function MouseHookProc(nCode: integer; wPar: WParam; lPar: LParam): lResult; stdcall;<br>var<br> pMouseInf: TMouseHookStruct;<br>begin<br> pShmem^.nTimePassed := 0;<br> UnSetGDIHook; {采用stdcall,所以它里面的变量可以随意}<br> if (nCode &gt;= 0) and ((wPar=WM_MOUSEMOVE)or(wPar=WM_NCMouseMove)) then<br> begin<br> pMouseInf := (PMouseHookStruct(lPar))^;<br> if (pShMem^.pMouse.x &lt;&gt; pMouseInf.pt.x) or<br> (pShMem^.pMouse.y &lt;&gt; 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> {发送鼠标位置消息}<br> PostMessage(pShMem^.hMainWnd, WM_MOUSEPT, 1, 1); {1表示是鼠标消息}<br> end;<br> pShMem^.hHookWnd := pMouseInf.hwnd;<br> end;<br><br> Result := CallNextHookEx(MessageHook, nCode, wPar, lPar);<br>end;<br><br>function OpenGetKeyHook(sender: HWND; MessageID: WORD): BOOLean; stdcall;<br>begin<br> {设置定时器}<br> pShmem^.fTimerID := SetTimer(0, 0, 20, @fOnTimer);<br> {添加鼠标钩子}<br> MessageHook := SetWindowsHookEx(WH_MOUSE, MouseHookProc, HInstance, 0); ;<br> result := true;<br>end;<br><br>function CloseGetKeyHook: BOOLean; stdcall;<br>begin<br> {关闭定时器}<br> KillTimer(0, pShmem^.fTimerID);<br> {取消钩子}<br> UnhookWindowsHookEx(MessageHook);<br> {取消取词}<br> UnSetGDIHook;<br> result := true;<br>end;<br><br>initialization<br> {如果映射文件已经存在则打开}<br> hMappingFile := OpenFileMapping(FILE_MAP_WRITE, False, MappingFileName);<br> if hMappingFile = 0 then<br> begin<br> {创建映射文件}<br> hMappingFile := CreateFileMapping($FFFFFFFF,<br> nil,<br> PAGE_READWRITE, {页面为可读写}<br> 0,<br> SizeOf(TShareMem),<br> PChar(MappingFileName));<br> FirstProcess := true;<br> end<br> else FirstProcess := false;<br> if hMappingFile &lt;&gt; 0 then<br> begin<br> {句柄pShMem指向映射文件地址}<br> pShMem := PShareMem(MapViewOfFile(hMappingFile,<br> FILE_MAP_WRITE,<br> 0,<br> 0,<br> 0));<br> if pShMem = nil then<br> begin<br> CloseHandle(hMappingFile);<br> ShowMessage('不能建立共享内存!');<br> exit;<br> end<br> end;<br> if FirstProcess then<br> begin<br> MessageHook := 0;<br> end;<br> pFuncFree := nil;<br> pFuncCreate := nil;<br> pFuncCheck := nil;<br> pshmem^.nTimePassed := 0;<br> {载入16位DLL,必须用LoadLibrary16}<br> hInst16 := LoadLibrary16('GetWord.DLL');<br> {载入成功}<br> if hInst16 &gt;= 32 then<br> begin<br> {取函数或过程的地址}<br> pFuncCreate := GetProcAddress16(hInst16, 'TextHookCreate');<br> pFuncFree := GetProcAddress16(hInst16, 'TextHookFree');<br> pFuncCheck := GetProcAddress16(hInst16, 'checkbuf');<br> if (pFuncCreate = nil) or (pFuncFree = nil) or (pFuncCheck = nil) then<br> begin<br> pFuncCreate := nil;<br> pFuncFree := nil;<br> pFuncCheck := nil;<br> end;<br> end<br> else begin<br> showmessage('打开16位DLL错误');<br> exit;<br> end;<br>finalization<br> if hInst16 &gt;= 32 then<br> FreeLibrary16(hInst16);<br> UnMapViewOfFile(pShMem);<br> CloseHandle(hMappingFile);<br><br>end.<br><br>unit UnitHookType;<br><br>interface<br><br>uses windows, messages;<br><br>const<br> MaxStringLen = 100;<br> MAXBUF = 100;<br> WM_MOUSEPT = WM_USER + 1138;<br> MappingFileName = 'Mapping File GetWord16';<br><br>type<br> PPointer = ^Pointer;<br> TShareMem = packed record<br> hMainWnd: HWND; {主应用窗口}<br> hHookWnd: HWND; {鼠标所在窗口}<br> pMouse: TPoint; {鼠标信息}<br> fStrMouseQueue: array[0..MaxStringLen] of Char; {鼠标信息串}<br> nTimePassed: integer; {鼠标暂停时间}<br> bCanSpyNow: Boolean; {开始取词}<br> {钩子函数句柄}<br> Text: array[0..MAXBUF] of Char; {返回所取的字符串}<br> fTimerID: Cardinal;<br> end;<br> PShareMem = ^TShareMem;<br><br>implementation<br><br>end.<br><br><br><br>