转个:<br><br>如有讨论者可以通过huiyugan@263.net甘化新(作者)联系。<br><br>//链接库 GFDict.dll的代码,GFDict.dpr<br>(*******************************************************************************<br>* Copy Right (C) Gan Huaxin 2001, 2002, huiyugan@263.net<br>* A Free Screen Words Capture Library<br>* Dedicated to my GirlFriend Sunny, Happy for ever<br>* <br>* Version Date Modification<br>* 0.1 2001-11-07~09 New, oly a test<br>* Can Get Word, Sometimes occure error<br>* 0.2 2002-05-14~16 Some Bugs Fixed,And<br>*******************************************************************************)<br>library GFDict;<br><br>// {$DEFINE MSG_NOT_SEND}<br>{$DEFINE WIN_NT}<br><br>{$IFNDEF WIN_NT}<br> {$DEFINE WIN_9X}<br>{$ENDIF}<br><br>// {$DEFINE DEBUG}<br><br><br>uses<br> SysUtils,<br> Classes,<br> windows,<br> messages,<br> untTypes;<br><br>const<br> STR_MSGNOTIFY
Char='WM_GANNOTIFY';<br><br>var<br> HMapFile:THandle;<br> CommonData:^TCommonData;<br> idMsg : UINT;<br> hwndServer : HWnd;<br><br>var<br> hWndCover : THandle;<br> LastMousePos : TPoint;<br> LastTime : DWORD;<br> g_CriticalSection : TRTLCriticalSection;<br> m_CriticalSection : TRTLCriticalSection;<br> b_InCS : boolean;<br><br>var<br> hNextHookProc: HHook;<br> hProc : THandle;<br> bFirst : boolean;<br> bDllInstalled : boolean;<br> ThunkCodeArr : array[TThunkFunc] of TThunkCode;<br><br>{$IFDEF DEBUG}<br> procedure GanWarning;<br> begin<br> MessageBeep(0);<br> end;<br>{$ELSE}<br> procedure GanWarning;<br> begin<br> end;<br>{$ENDIF}<br><br>{$DEFINE _NOTIFY_}<br><br>{$IFDEF _NOTIFY_}<br> procedure GanNotify;<br> begin<br> MessageBeep(0);<br> end;<br>{$ELSE}<br> procedure GanNotify;<br> begin<br> end;<br>{$ENDIF}<br><br><br>// about Memory Map file support<br>procedure MapCommonData;<br>var FirstCall: Boolean;<br>begin<br> HMapFile:=OpenFileMapping(FILE_MAP_WRITE, False, 'GanGan_ThunkDict');<br> FirstCall:=(HMapFile = 0);<br> if FirstCall then<br> HMapFile:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,<br> 0,SizeOf(TCommonData),<br> 'GanGan_ThunkDict');<br> CommonData:= MapViewOfFile(HMapFile, FILE_MAP_WRITE, 0, 0, 0);<br> if FirstCall then FillChar(CommonData^, SizeOf(TCommonData), 0);<br>end;<br><br>// -----------------------------------------------------------------------------<br>procedure UnInstallThunkFunc(tfType : TThunkFunc);<br>var<br> nCount : DWORD;<br>begin<br> if not ThunkCodeArr[tfType].bInstalled then exit;<br> if (hProc=0) or (ThunkCodeArr[tfType].addr_sys=nil) then exit;<br> WriteProcessMemory(hProc,<br> ThunkCodeArr[tfType].addr_sys,<br> @(ThunkCodeArr[tfType].codeBak),<br> 5,<br> nCount);<br> ThunkCodeArr[tfType].bInstalled := false;<br>end;<br><br>procedure InstallThunkFunc(tfType : TThunkFunc);<br>var<br> nCount : DWORD;<br>begin<br> if ThunkCodeArr[tfType].bInstalled then exit;<br> if (hProc=0) or (ThunkCodeArr[tfType].addr_sys=nil) then exit;<br> WriteProcessMemory(hProc,<br> ThunkCodeArr[tfType].addr_sys,<br> @(ThunkCodeArr[tfType].codeThunk),<br> 5,<br> nCount);<br> ThunkCodeArr[tfType].bInstalled := True;<br>end;<br><br>procedure UnInstallGanFilter; forward;<br><br>{=================== TextOut ==============================================}<br>function GanTextOutA(DC: HDC; X, Y: Integer; Str: PAnsiChar; Count: Integer): BOOL; stdcall;<br>var<br> tm : TTextMetric;<br> rect : TRect;<br> size : TSize;<br> i, j : integer;<br> posDcOrg : TPoint;<br> posDcOff : TPoint;<br>begin<br>// EnterCriticalSection(g_CriticalSection);<br><br> result := FALSE;<br> UnInstallThunkFunc(tfTextOutA);<br>{$IFNDEF MSG_NOT_SEND}<br>try<br> if (CommonData<>nil) then begin<br> GetDcOrgEx(dc, posDcOrg); // Get The DC offset<br> posDcOff := Point(x,y);<br> LPtoDP(dc, posDcOff, 1);<br><br> Rect.Left := posDcOrg.x + posDcOff.x;<br> Rect.Top := posDcOrg.y + posDcOff.y;<br><br> if BOOL(GetTextAlign(dc) and TA_UPDATECP) then begin<br> GetCurrentPositionEx(dc, @posDcOff);<br> Inc(Rect.Left, posDcOff.x);<br> Inc(Rect.Top, posDcOff.y);<br> end;<br><br> GetTextExtentPointA(DC, Str, Count, size);<br><br> Rect.Right := Rect.Left + size.cx;<br> Rect.Bottom := Rect.Top + size.cy;<br><br> if PtInRect(rect, CommonData.MousePos) then begin // in total area!<br> if StrPos(Str, ' ')<>nil then begin<br> i := 0;<br><br> while (Str
= Char(' ')) and (i<Count) do Inc(i);<br><br> j := i;<br><br> while (i<Count) do begin<br> if Str=Char(' ') then begin<br> Str := Char(0);<br> GetTextExtentPointA(DC, Str, i-1, size);<br> rect.Right := rect.Left + size.cx;<br><br> if PtInRect(rect, CommonData.MousePos) then begin<br> // SendMessage(CommonData.CallBackHandle, idMsg, i, 3);<br> StrCopy(CommonData.BufferA, PChar(@(Str[j])));<br> CommonData^.Rect := Rect;<br> SendMessage(CommonData^.CallBackHandle, idMsg, Integer(tfTextOutA), 0);<br> Str := Char(' ');<br> break;<br> end;<br><br> Str := Char(' ');<br> while (Str = Char(' ')) and (i < Count) do Inc(i);<br> if i=Count then break;<br> j := i;<br> Dec(i);<br> // break;<br> end;<br> inc(i);<br> end;<br> if (i=Count) then begin<br> StrCopy(CommonData.BufferA, PChar(@(Str[j])));<br> CommonData^.Rect := Rect;<br> SendMessage(CommonData^.CallBackHandle, idMsg, Integer(tfTextOutA), 0);<br> end;<br> end else<br> begin<br> StrCopy(CommonData.BufferA, Str);<br> CommonData^.Rect := Rect;<br> SendMessage(CommonData^.CallBackHandle, idMsg, Integer(tfTextOutA), 0);<br> end;<br> end;<br> end;<br> (*<br> StrCopy(CommonData.BufferA, Str);<br> CommonData^.Rect := Rect;<br> SendMessage(CommonData^.CallBackHandle, idMsg, Integer(tfTextOutA), 0);<br> *)<br>except<br> GanWarning;<br> StrCopy(CommonData.BufferA, 'Error in TextOutA');<br> SendMessage(CommonData^.CallBackHandle, idMsg, Integer(tfTextOutA), 0);<br>end;<br>{$ENDIF}<br> TextOutA(DC, X, Y, Str, Count);<br> InstallThunkFunc(tfTextOutA);<br>// UnInstallGanFilter;<br><br>// LeaveCriticalSection(g_CriticalSection);<br>end;<br><br>function GanTextOutW(DC: HDC; X, Y: Integer; Str: PWideChar; Count: Integer): BOOL; stdcall;<br>var<br> tm : TTextMetric;<br> rect : TRect;<br> size : TSize;<br> i, j : integer;<br> wChar : WideChar;<br> posDcOrg, posDcOff : TPoint;<br>begin<br>// EnterCriticalSection(g_CriticalSection);<br><br> result := FALSE;<br> UnInstallThunkFunc(tfTextOutW);<br>{$IFNDEF MSG_NOT_SEND}<br>try<br> if (CommonData<>nil) then begin<br> GetDcOrgEx(dc, posDcOrg);<br> posDcOff := Point(x,y);<br> LPtoDP(dc, posDcOff, 1);<br><br> Rect.Left := posDcOrg.x + posDcOff.x;<br> Rect.Top := posDcOrg.y + posDcOff.y;<br><br> if BOOL(GetTextAlign(dc) and TA_UPDATECP) then begin<br> GetCurrentPositionEx(dc, @posDcOff);<br> Inc(Rect.Left, posDcOff.x);<br> Inc(Rect.Top, posDcOff.y);<br> end;<br><br> GetTextExtentPointW(DC, Str, Count, size);<br><br> rect.Right := rect.Left + size.cx;<br> rect.Bottom := rect.Top + size.cy;<br><br> if PtInRect(rect, CommonData.MousePos) then begin<br> if StrPos(PChar(WideCharToString(Str)), ' ')<>nil then begin<br> i := 0;<br><br> while (Str = WideChar(' ')) and (i<Count) do Inc(i);<br><br> j := i;<br><br> while (i<Count) do begin<br> if Str=WideChar(' ') then begin<br> Str := WideChar(0);<br> GetTextExtentPoint32W(DC, Str, i-1, size);<br> rect.Right := rect.Left + size.cx;<br><br> if PtInRect(rect, CommonData.MousePos) then begin<br> // SendMessage(CommonData.CallBackHandle, idMsg, i, 3);<br> StrCopy(CommonData.BufferA,PChar(WideCharToString(@(Str[j]))));<br> CommonData^.Rect := Rect;<br> SendMessage(CommonData^.CallBackHandle, idMsg, Integer(tfTextOutW), 0);<br> Str := WideChar(' ');<br> break;<br> end;<br><br> Str := WideChar(' ');<br> while (Str = WideChar(' ')) and (i < Count) do Inc(i);<br> if i=Count then break;<br> j := i;<br> Dec(i);<br> // break;<br> end;<br> inc(i);<br> end;<br> if (i=Count) then begin<br> StrCopy(CommonData.BufferA, PChar(WideCharToString(@(Str[j]))));<br> CommonData^.Rect := Rect;<br> SendMessage(CommonData^.CallBackHandle, idMsg, Integer(tfTextOutW), 0);<br> end;<br> end else<br> begin<br> StrCopy(CommonData.BufferA,PChar(WideCharToString(Str)));<br> CommonData^.Rect := Rect;<br> SendMessage(CommonData^.CallBackHandle, idMsg, Integer(tfTextOutW), 0);<br> end;<br> end;<br> end;<br>except<br> GanWarning;<br> StrCopy(CommonData.BufferA, 'Error in TextOutW');<br> SendMessage(CommonData^.CallBackHandle, idMsg, Integer(tfTextOutW), 0);<br>end;<br>{$ENDIF}<br> result := TextOutW(DC, X, Y, Str, Count);<br> InstallThunkFunc(tfTextOutW);<br>// UnInstallGanFilter;<br><br>// LeaveCriticalSection(g_CriticalSection);<br>end;<br><br>{=================== ExtTextOut ============================================}<br>(*<br> 这个函数在UltraEdit里会出错,加上异常处理就没有关系。<br> Bug Fixed 2002-05-13<br>*)<br>function GanExtTextOutA(DC: HDC; X, Y: Integer; Options: Longint;<br> Rect: PRect; Str: PAnsiChar; Count: Longint; Dx: PInteger): BOOL; stdcall;<br>var<br> posDcOrg : TPoint;<br> posDc : TPoint;<br> RectText : TRect;<br> size : TSize;<br>begin<br>// EnterCriticalSection(g_CriticalSection);<br><br> result := FALSE;<br> UnInstallThunkFunc(tfExtTextOutA);<br>{$IFNDEF MSG_NOT_SEND}<br><br> GetDcOrgEx(dc, posDcOrg);<br> posDc := Point(x,y);<br> LPtoDP(dc, posDc, 1);<br><br> RectText.Left := posDc.x + posDcOrg.x;<br> RectText.Top := posDc.y + posDcOrg.y;<br><br> if BOOL(GetTextAlign(dc) and TA_UPDATECP) then begin<br> GetCurrentPositionEx(dc, @posDc);<br> Inc(RectText.Left, posDc.x);<br> Inc(RectText.Top, posDc.y);<br> end;<br><br> GetTextExtentPointA(dc, Str, Count, size); {Get The Length and Height of str}<br> with RectText do begin<br> Right := Left + size.cx;<br> Bottom := Top + Size.cy;<br> end;<br> <br> if (CommonData<>nil) {and false} and PtInRect(RectText, CommonData.MousePos) then begin<br> try<br> StrCopy(CommonData.BufferA, Str);<br> CommonData^.Rect := RectText;<br> except<br> GanWarning;<br> StrCopy(CommonData.BufferA, 'ERROR in ExtTextOutA');<br> end;<br> SendMessage(CommonData^.CallBackHandle, idMsg, Integer(tfExtTextOutA), 0);<br> end;<br>{$ENDIF}<br> result := ExtTextOutA(DC, X, Y, Options, Rect, Str, Count, Dx);<br> InstallThunkFunc(tfExtTextOutA);<br>// UnInstallGanFilter;<br><br>// LeaveCriticalSection(g_CriticalSection);<br>end;<br><br>function GanExtTextOutW(DC: HDC; X, Y: Integer; Options: Longint;<br> Rect: PRect; Str: PWideChar; Count: Longint; Dx: PInteger): BOOL; stdcall;<br>var<br> posDcOrg : TPoint;<br> posDc : TPoint;<br> RectText : TRect;<br> size : TSize;<br>label last;<br>begin<br>// EnterCriticalSection(g_CriticalSection);<br> result := FALSE;<br> UnInstallThunkFunc(tfExtTextOutW);<br>{$IFNDEF MSG_NOT_SEND}<br> if CommonData^.bInSpec then begin<br> (*if (Options and ETO_CLIPPED)=0 then goto last;*)<br> try<br> StrCopy(CommonData.BufferA,PChar(WideCharToString(Str)));<br> CommonData^.Rect := RectText;<br> except<br> GanWarning;<br> StrCopy(CommonData.BufferA, 'ERROR in ExtTextOutW');<br> end;<br> SendMessage(CommonData^.CallBackHandle, idMsg, Integer(tfExtTextOutW), 0);<br> goto last;<br> end;<br><br> GetDcOrgEx(dc, posDcOrg);<br> posDc.x := x;<br> posDc.y := y;<br><br> LPtoDP(dc, posDc, 1);<br><br> RectText.Left := posDc.x + posDcOrg.x;<br> RectText.Top := posDc.y + posDcOrg.y;<br><br><br><br> if BOOL(GetTextAlign(dc) and TA_UPDATECP) then begin<br> GetCurrentPositionEx(dc, @posDc);<br> Inc(RectText.Left, posDc.x);<br> Inc(RectText.Top, posDc.y);<br> end;<br><br> GetTextExtentPointW(dc, Str, Count, size); {Get The Length and Height of str}<br> with RectText do begin<br> Right := Left + size.cx;<br> Bottom := Top + Size.cy;<br> end;<br><br><br><br> if (CommonData<>nil) {and false} and PtInRect(RectText, CommonData.MousePos) then begin<br> {Bug Find 2002-05-13}<br> try<br> StrCopy(CommonData.BufferA,PChar(WideCharToString(Str)));<br> CommonData^.Rect := RectText;<br> except<br> GanWarning;<br> StrCopy(CommonData.BufferA, 'ERROR in ExtTextOutW');<br> end;<br> SendMessage(CommonData^.CallBackHandle, idMsg, Integer(tfExtTextOutW), 0);<br> end;<br>{$ENDIF}<br>last:<br> result := ExtTextOutW(DC, X, Y, Options, Rect, Str, Count, Dx);<br> InstallThunkFunc(tfExtTextOutW);<br>// UnInstallGanFilter;<br><br>// LeaveCriticalSection(g_CriticalSection);<br>end;<br><br>{=================== DrawText ==============================================}<br>function GanDrawTextA(hDC: HDC; lpString: PAnsiChar; nCount: Integer;<br> var lpRect: TRect; uFormat: UINT): Integer; stdcall;<br>var<br> RectSave : TRect;<br> posDcOrg : TPoint;<br>begin<br>// EnterCriticalSection(g_CriticalSection);<br><br> UnInstallThunkFunc(tfDrawTextA);<br>{$IFNDEF MSG_NOT_SEND}<br> if (CommonData<>nil) {and false} then begin<br> GetDcOrgEx(hDc, posDcOrg);<br> RectSave := lpRect;<br> OffsetRect(RectSave, posDcOrg.x, posDcOrg.y);<br><br> if PtInRect(RectSave, CommonData^.MousePos) then begin<br> try<br> StrCopy(CommonData.BufferA, lpString);<br> CommonData^.Rect := lpRect;<br> except<br> GanWarning;<br> end;<br> SendMessage(CommonData^.CallBackHandle, idMsg, Integer(tfDrawTextA), 0);<br> end;<br> end;<br>{$ENDIF}<br> result := DrawTextA(hDC, lpString, nCount, lpRect, uFormat);<br> InstallThunkFunc(tfDrawTextA);<br><br>// UnInstallGanFilter;<br><br>// LeaveCriticalSection(g_CriticalSection);<br>end;<br><br>function GanDrawTextW(hDC: HDC; lpString: PWideChar; nCount: Integer;<br> var lpRect: TRect; uFormat: UINT): Integer; stdcall;<br>var<br> RectSave : TRect;<br> posDcOrg : TPoint;<br>begin<br>// EnterCriticalSection(g_CriticalSection);<br><br> UnInstallThunkFunc(tfDrawTextW);<br>{$IFNDEF MSG_NOT_SEND}<br> if (CommonData<>nil) {and false} then begin<br> GetDcOrgEx(hDc, posDcOrg);<br> RectSave := lpRect;<br> OffsetRect(RectSave, posDcOrg.x, posDcOrg.y);<br><br> if PtInRect(RectSave, CommonData^.MousePos) then begin<br> try<br> StrCopy(CommonData.BufferA,PChar(WideCharToString(lpString)));<br> CommonData^.Rect := lpRect;<br> except<br> GanWarning;<br> end;<br> end;<br> SendMessage(CommonData^.CallBackHandle, idMsg, Integer(tfDrawTextW), 0);<br> end;<br>{$ENDIF}<br> result := DrawTextW(hDC, lpString, nCount, lpRect, uFormat);<br> InstallThunkFunc(tfDrawTextW);<br>// UnInstallGanFilter;<br><br>// LeaveCriticalSection(g_CriticalSection);<br>end;<br><br>procedure InstallGanFilter;<br>var<br> tfType : TThunkFunc;<br>begin<br> if bDllInstalled then exit;<br><br> for tfType := tfTextOutA to {tfExtTextOutW}tfDrawTextW do<br> // for tfType := LOW(TThunkFunc) to TThunkFunc(Ord(HIGH(TThunkFunc))-2) do<br> InstallThunkFunc(tfType);<br><br> bDllInstalled := true;<br>end;<br><br>procedure UnInstallGanFilter;<br>var<br> tfType : TThunkFunc;<br>begin<br> if not bDllInstalled then exit;<br><br> for tfType := tfTextOutA to {tfExtTextOutW}tfDrawTextW do<br> // for tfType := LOW(TThunkFunc) to TThunkFunc(Ord(HIGH(TThunkFunc))-2) do<br> UnInstallThunkFunc(tfType);<br><br> bDllInstalled := false;<br>end;<br><br>{================== =========================================================}<br>function WMCoverGetMinMaxInfo(<br> hWnd : THandle;<br> Msg : LongWord;<br> wParam : WPARAM;<br> lParam : LPARAM):BOOL;stdcall;<br>var<br> info : ^MINMAXINFO;<br>begin<br> result := BOOL(0);<br> info := Pointer(lParam);<br> info^.ptMaxSize.x := GetSystemMetrics(SM_CXFULLSCREEN);<br> info^.ptMaxSize.y := GetSystemMetrics(SM_CYFULLSCREEN);<br> info^.ptMinTrackSize.x := 0;<br> info^.ptMinTrackSize.y := 0;<br> info^.ptMaxTrackSize.x := GetSystemMetrics(SM_CXFULLSCREEN);<br> info^.ptMaxTrackSize.y := GetSystemMetrics(SM_CYFULLSCREEN);<br>end;<br><br>function CoverMainProc(<br> hWnd:LongWord;<br> Message:LongWord;<br> wParam:WPARAM;<br> lParam:LPARAM<br> ):BOOL;stdcall;<br>begin<br> case Message of<br> WM_CLOSE :<br> begin<br> DestroyWindow(hWnd);<br> // PostQuitMessage(0);<br> end;<br> end;<br> result := BOOL(DefWindowProc(hWnd, Message, lParam, lParam));<br>end;<br><br><br>procedure GanGetWordTimer(wnd : HWND; msg, idTimer : Cardinal; dwTime : DWORD);far pascal;<br>begin<br> SendMessage(CommonData^.hWndMouse, idMsg, 1, 0);<br> if (CommonData.BufferA='') then begin<br> SendMessage(CommonData.CallBackHandle, idMsg, 0, 2);<br> end;<br> KillTimer(CommonData^.hWndFloat, 2);<br>end;<br><br>procedure WndCoverTimer(wnd : HWND; msg, idTimer : Cardinal; dwTime : DWORD);far pascal; //CallBack Type<br>var<br> mouseWnd : HWnd;<br> szClass : PChar;<br> strClass : string;<br> iLeft, iWidth : Integer;<br> rect : TRect;<br>begin<br> if (CommonData=nil) or (not CommonData^.bCapture) then begin<br> exit;<br> end;<br><br> mouseWnd := WindowFromPoint(CommonData^.MousePos);<br> if (mouseWnd=CommonData^.CallBackHandle) then begin<br> exit;<br> end;<br> szClass := StrAlloc(256);<br> GetClassName(mouseWnd, szClass, 255);<br> strClass := Strpas(szClass);<br> StrDispose(szClass);<br><br> CommonData^.bInSpec := FALSE;<br><br> if (Pos('Internet Explorer_Server', strClass)>0) then begin<br> GetWindowRect(mouseWnd, rect);<br> iLeft := rect.Left - 4;<br> iWidth := rect.Right - rect.Left + 14;<br> if (CommonData^.MousePos.x - iLeft > 200) then begin<br> iLeft := CommonData^.MousePos.x - 200;<br> iWidth := 210;<br> end;<br> CommonData^.bInSpec := TRUE;<br> end<br> else begin<br> iLeft := CommonData^.MousePos.x - 1;<br> iWidth := 1;<br> end;<br> // InstallGanFilter;<br>(*<br> SetWindowPos(CommonData^.hWndFloat,<br> HWND_TOPMOST,<br> CommonData.MousePos.x, CommonData.MousePos.y, 10, 10,<br> SWP_NOACTIVATE or SWP_SHOWWINDOW);<br> ShowWindow(CommonData^.hWndFloat, SW_HIDE);<br>*)<br> CommonData^.BufferA := '';<br> SetWindowPos(CommonData^.hWndFloat,<br> HWND_TOPMOST,<br> iLeft{CommonData.MousePos.x-1}, CommonData.MousePos.y-1,<br> iWidth, 2,<br> 88{SWP_NOACTIVATE or SWP_NOREDRAW});<br><br> SendMessage(CommonData^.hWndMouse, idMsg, 0, 0);<br><br><br> MoveWindow(CommonData^.hWndFloat, -1, -1, 1, 1, TRUE);<br><br> {<br> SetWindowPos(CommonData^.hWndFloat,<br> HWND_TOPMOST,<br> CommonData.MousePos.x, CommonData.MousePos.y,<br> 120, 1,<br> SWP_NOACTIVATE or SWP_SHOWWINDOW);<br> ShowWindow(CommonData^.hWndFloat, SW_HIDE);<br> }<br> SetTimer(CommonData^.hWndFloat, 2, 300, @GanGetWordTimer);<br>end;<br><br>procedure InitCoverWindow(hInst : LongWord);<br>var<br> WndClass : TWndClass; //Ex;<br>begin<br> with WndClass do begin<br> style := WS_EX_TOPMOST;<br> lpfnWndProc := @CoverMainProc; (*消息处理函数*)<br> hInstance := hInst;<br> hbrBackground := color_btnface + 1;<br> lpszClassname := 'GanFreeDict';<br> hicon := 0;<br> hCursor := 0;<br> cbClsExtra := 0;<br> cbWndExtra := 0;<br> end;<br><br> try<br> if not BOOL(RegisterClass{Ex}(WndClass)) then begin<br> MessageBox(0,<br> PChar(Format('$EEEE, Can not register class CHILD %d',[GetLastError])),<br> 'Register Error',<br> MB_OK);<br> end;<br> except<br> MessageBox(0, 'EXCEPTION', 'Register Class', MB_OK);<br> end;<br><br> hWndCover := CreateWindowEx(WS_EX_TOPMOST or WS_EX_TOOLWINDOW,<br> 'GanFreeDict',<br> '^_^',<br> WS_POPUP or WS_VISIBLE,<br> -1,-1,1,1,<br> 0,<br> 0,<br> hInst, // GetModuleHandle('dll.dll'), // 98 for this, 2000 for 0<br> nil);<br><br> if CommonData<>nil then begin<br> CommonData^.hWndFloat := hWndCover;<br> end;<br> SetTimer(hWndCover, 1, 450, @WndCoverTimer);<br><br>end;<br>(******************************************************************************)<br>function GanServerProc(<br> hWnd:LongWord;<br> Message:LongWord;<br> wParam:WPARAM;<br> lParam:LPARAM<br> ):BOOL;stdcall;<br>begin<br> if (Message=idMsg) then begin<br> if (wParam = 0) then begin<br> InstallGanFilter;<br> end<br> else begin<br> UnInstallGanFilter;<br> end;<br> end;<br> case Message of<br> WM_CLOSE :<br> begin<br> DestroyWindow(hWnd);<br> // PostQuitMessage(0);<br> end;<br> end;<br> result := BOOL(DefWindowProc(hWnd, Message, lParam, lParam));<br>end;<br><br><br>procedure InitServerWnd;<br>var<br> WndClass : TWndClass; //Ex;<br>begin<br> with WndClass do begin<br> style := WS_EX_TOPMOST;<br> lpfnWndProc := @GanServerProc; (*消息处理函数*)<br> hInstance := GetModuleHandle('GFDict.dll');<br> hbrBackground := color_btnface + 1;<br> lpszClassname := 'GanServerDict';<br> hicon := 0;<br> hCursor := 0;<br> cbClsExtra := 0;<br> cbWndExtra := 0;<br> end;<br><br> try<br> if not BOOL(RegisterClass{Ex}(WndClass)) then begin<br> MessageBox(0,<br> PChar(Format('Can not register class server %d',[GetLastError])),<br> 'Register Error',<br> MB_OK);<br> end;<br> except<br> MessageBox(0, 'EXCEPTION', 'Register Server Class', MB_OK);<br> end;<br><br> hWndServer := CreateWindowEx(WS_EX_TOPMOST or WS_EX_TOOLWINDOW,<br> 'GanServerDict',<br> 'Gan Server',<br> WS_POPUP or WS_VISIBLE,<br> -1,-1,1,1,<br> 0,<br> 0,<br> 0, //hInst, // GetModuleHandle('dll.dll'), // 98 for this, 2000 for 0<br> nil);<br> if (hWndServer=0) then begin<br> MessageBeep(0);<br> end;<br><br>end;<br>(******************************************************************************)<br><br>procedure InitThunkCode;<br>var<br> tfType : TThunkFunc;<br> hMod : HMODULE;<br> pSysFunc, pThunkFunc : Pointer;<br>begin<br> for tfType := LOW(TThunkFunc) to HIGH(TThunkFunc) do begin<br> // clear to zero<br> FillChar(ThunkCodeArr[tfType], sizeof(TThunkCode), 0);<br><br> // fill it by right value<br> hMod := 0;<br> hMod := GetModuleHandle(PChar(ThunkFuncNameArr[tfType].strMod));<br> if hMod = 0 then continue;<br><br> pSysFunc := nil;<br> pSysFunc := GetProcAddress(hMod,<br> PChar(ThunkFuncNameArr[tfType].strSysProc));<br> if pSysFunc = nil then continue;<br><br> pThunkFunc := nil;<br> pThunkFunc := GetProcAddress(hInstance,<br> PChar(ThunkFuncNameArr[tfType].strThunkProc));<br> if pThunkFunc = nil then continue;<br><br> // now fill it!<br> ThunkCodeArr[tfType].addr_sys := pSysFunc;<br> ThunkCodeArr[tfType].addr_thunk := pThunkFunc;<br><br> ThunkCodeArr[tfType].codeThunk.siJmp := ShortInt($E9); // jmp ____<br> ThunkCodeArr[tfType].codeThunk.dwAddr :=<br> DWORD(pThunkFunc) - DWORD(pSysFunc) - 5;<br><br> ThunkCodeArr[tfType].codeBak.siJmp := PByte(pSysFunc)^;<br> ThunkCodeArr[tfType].codeBak.dwAddr := PDWORD(DWORD(pSysFunc)+1)^;<br> end;<br>end;<br><br>{================== Install Mouse Hook Support ==============================}<br>function MousePosHookHandler(iCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;<br>var<br> pMouse : PMOUSEHOOKSTRUCT;<br> mPoint : TPoint;<br> rect : TRect;<br> bMousePosChg : boolean;<br>begin<br> if iCode < 0 then<br> begin<br> Result := CallNextHookEx(hNextHookProc, iCode, wParam, lParam);<br> end<br> else<br> if (CommonData<>nil) and<br> (CommonData^.bCapture) and<br> (TryEnterCriticalSection(m_CriticalSection))<br> then begin<br><br>{$IFDEF WIN_9X}<br> if bFirst then begin<br> bFirst := false;<br> // InstallGanFilter;<br> InitCoverWindow;<br> end;<br>{$ENDIF}<br><br> pMouse := PMOUSEHOOKSTRUCT(lParam);<br><br> if (CommonData<>nil) then begin<br> CommonData.MousePos := pMouse.pt;<br> CommonData.hWndCapture := pMouse.hWnd;<br> PostMessage(CommonData.CallBackHandle, idMsg, 0, 1);<br> end;<br> if (GetCurrentProcessID <> CommonData^.CallBackProcID) then begin<br> CommonData^.hWndMouse := hWndServer;<br><br> mPoint := pMouse^.pt;<br> ScreenToClient(pMouse^.hwnd, mPoint);<br> if Assigned(CommonData) then<br> CommonData.MousePClient := mPoint;<br> end<br> else begin<br> CommonData^.hWndMouse := 0;<br><br> end;<br>(*<br> if (pMouse.pt.x = LastMousePos.x) and (pMouse.pt.y = LastMousePos.y) then<br> bMousePosChg := false<br> else begin<br> bMousePosChg := true;<br> LastMousePos := pMouse.pt;<br> end;<br> if (wParam = WM_MOUSEMOVE)<br> and true<br>{$IFDEF WIN_9X}<br> and (hWndCover <> 0)<br>{$ENDIF}<br> and bMousePosChg<br> and (not b_InCS)<br> and (GetTickCount - LastTime > G_DELAY_TIME) then<br> begin<br> LastTime := GetTickCount;<br><br> // whether in my window<br> if (CommonData<>nil) and<br> (GetCurrentProcessID = CommonData^.CallBackProcID) then begin<br> result := 0;<br> LeaveCriticalSection(m_CriticalSection);<br> result := CallNextHookEx(hNextHookProc, iCode, wParam, lParam);<br> exit;<br> end;<br> mPoint := pMouse^.pt;<br> ScreenToClient(pMouse^.hwnd, mPoint);<br> if Assigned(CommonData) then<br> CommonData.MousePClient := mPoint;<br><br> rect.TopLeft := mPoint;<br> rect.Right := mPoint.x + 2;<br> rect.Bottom := mPoint.y + 1;<br> // Work for NT 2000 XP<br>{$IFDEF WIN_NT}<br> InstallGanFilter;<br><br> if Assigned(CommonData) then<br> CommonData.BufferA := '';<br><br> InvalidateRect(pMouse^.hWnd, @rect, TRUE);<br> if (mPoint.X<0) or (mPoint.Y<0) then<br> SendMessage(pMouse.hwnd, WM_NCPAINT, 1, 0)<br> else<br> SendMessage(pMouse.hwnd, WM_PAINT, 0, 0);<br><br> UninstallGanFilter;<br> if Assigned(CommonData) and (CommonData.BufferA='') then begin<br> SendMessage(CommonData.CallBackHandle, idMsg, 0, 2);<br> end;<br>{$ENDIF}<br> // flowing work on 98<br>{$IFDEF WIN_9X}<br> if (hWndCover <> 0) then begin<br> SetWindowPos(hWndCover, 0, pMouse.pt.X, pMouse.pt.Y, 4, 1,<br> SWP_NOZORDER or SWP_NOACTIVATE);<br> ShowWindow(hWndCover, SW_SHOW);<br><br>// EnterCriticalSection(m_CriticalSection);<br><br> InstallGanFilter;<br> ShowWindow(hWndCover, SW_HIDE);<br><br>// LeaveCriticalSection(m_CriticalSection);<br> end;<br>{$ENDIF}<br> end;<br>*)<br> LeaveCriticalSection(m_CriticalSection);<br> Result := CallNextHookEx(hNextHookProc, iCode, wParam, lParam);<br> end<br> else begin<br> Result := CallNextHookEx(hNextHookProc, iCode, wParam, lParam);<br> end;<br>end;<br><br>function EnableMouseHook(hld:hwnd; ProcessID : DWORD; hInst:THandle): BOOL; export;<br>begin<br> Result := False;<br> if hNextHookProc <> 0 then Exit;<br><br> hNextHookProc := SetWindowsHookEx(WH_MOUSE, MousePosHookHandler,Hinstance, 0);<br>// GetWindowThreadProcessID(hWnd, nil));<br><br> InitCoverWindow(hInst);<br> if CommonData <> nil then begin<br> CommonData^.CallBackHandle := hld;<br> CommonData^.CallBackProcID := ProcessID;<br> end;<br> Result :=hNextHookProc <> 0 ;<br>end;<br><br>function DisableMouseHook: BOOL; export;<br>begin<br>try<br> if hNextHookProc <> 0 then<br> begin<br> KillTimer(CommonData^.hWndFloat, 1);<br> KillTimer(CommonData^.hWndFloat, 2);<br> SendMessage(CommonData^.hWndFloat, WM_CLOSE, 0, 0);<br> CommonData^.hWndFloat := 0;<br><br> UnInstallGanFilter;<br> UnhookWindowshookEx(hNextHookProc);<br> hNextHookProc := 0;<br> end;<br> Result := hNextHookProc = 0;<br>except<br> MessageBeep(0);<br>end;<br>end;<br><br>function SetCaptureFlag(bSet:BOOL):BOOL; export;<br>begin<br> if CommonData<>nil then begin<br> result := TRUE;<br> CommonData^.bCapture := bSet;<br> end<br> else begin<br> result := FALSE;<br> end;<br>end;<br><br>procedure DllMain(dwReason : DWORD);<br>begin<br> case dwReason of<br> DLL_PROCESS_ATTACH :<br> begin<br> // InstallGanFilter;<br> // InitCoverWindow;<br> end;<br> DLL_PROCESS_DETACH :<br> begin<br> if (hWndServer <> 0) then begin<br> SendMessage(hWndServer, WM_CLOSE, 0, 0);<br> hWndServer := 0;<br> try<br> UnRegisterClass('GanServerDict', hInstance);<br> except<br> MessageBeep(0);<br> end;<br> end;<br> UnInstallGanFilter;<br> if CommonData<>nil then begin<br> try<br> UnMapViewOfFile(CommonData);<br> CommonData := nil;<br> CloseHandle(HMapFile);<br> HMapFile := 0;<br> except<br> MessageBox(0,<br> 'Error when free MapViewFile',<br> 'FreeDict Error',<br> MB_OK);<br> end;<br> end;<br>(*<br> if (hWndCover <> 0) then begin<br> try<br> DestroyWindow(hWndCover);<br> hWndCover := 0;<br> if (UnRegisterClass('GanFreeDict', hInstance)) then<br> {MessageBox(0,<br> 'Success to Unregister _GanFreeDict_ Class',<br> 'Success',<br> MB_OK);}<br> except<br> MessageBox(0,<br> 'Error when Destroy window and UnRegisterClass',<br> 'FreeDict Error',<br> MB_OK);<br> end;<br> end;<br>*)<br><br> if hProc<>0 then begin<br> try<br> CloseHandle(hProc);<br> hProc := 0;<br> except<br> MessageBox(0,<br> 'Error when CloseHandle',<br> 'FreeDict Error',<br> MB_OK);<br> end;<br> end;<br><br> DeleteCriticalSection(g_CriticalSection);<br> DeleteCriticalSection(m_CriticalSection);<br> end;<br> DLL_THREAD_ATTACH :<br> begin<br> end;<br> DLL_THREAD_DETACH :<br> begin<br> end;<br> end;<br>end;<br><br>exports<br> EnableMouseHook,<br> DisableMouseHook,<br> GanTextOutA,<br> GanTextOutW,<br> GanExtTextOutA,<br> GanExtTextOutW,<br> GanDrawTextA,<br> GanDrawTextW,<br> SetCaptureFlag;<br><br>begin<br> InitializeCriticalSection(g_CriticalSection);<br> InitializeCriticalSection(m_CriticalSection);<br> b_InCS := false;<br> hNextHookProc := 0;<br> hProc := 0;<br> bFirst := true;<br> bDllInstalled := false;<br> hWndCover := 0;<br> hWndServer := 0;<br> CommonData := nil;<br> HMapFile := 0;<br> LastTime := 0;<br> FillChar(LastMousePos, sizeof(TPoint), 0);<br> idMsg := RegisterWindowMessage(STR_MSGNOTIFY);<br><br> MapCommonData;<br><br> hProc := OpenProcess(PROCESS_ALL_ACCESS,<br> FALSE,<br> GetCurrentProcessID());<br> InitThunkCode;<br> InitServerWnd;<br> // InitCoverWindow;<br><br> // DisableThreadLibraryCalls(hInstance);<br><br> DLLProc := @DLLMain;<br> DLLMain(DLL_PROCESS_ATTACH);<br>end.<br><br><br><br><br>(*******************************************************************************<br>* Copy Right (C) Gan Huaxin 2001, 2002, huiyugan@263.net<br>* A Free Screen Words Capture Library<br>* Dedicated to my GirlFriend Sunny, Happy for ever<br>* <br>* Version Date Modification<br>* 0.1 2001-11-07~09 New, oly a test<br>* Can Get Word, Sometimes occure error<br>* 0.2 2002-05-14~16 Some Bugs Fixed,And<br>*******************************************************************************)<br>unit untTypes;<br><br>interface<br><br>uses<br> Windows;<br><br>type<br> TCommonData = record<br> bCapture : BOOL;<br> bInSpec : BOOL;<br> CallBackHandle:HWnd;<br> CallBackProcID : DWORD;<br> hWndFloat : HWnd; (*浮动窗口的句柄*)<br> hWndMouse : HWnd; (*鼠标所在窗口server的句柄*)<br> hWndCapture : HWnd; (*当前鼠标所在的窗口*)<br> MousePos : TPoint; (*当前鼠标屏幕坐标*)<br> MousePClient : TPoint; (*鼠标所在窗口的坐标*)<br> Rect : TRect;<br> case integer of<br> 0 : (BufferA : array [0..1023] of Char);<br> 1 : (BufferW : array [0..511] of WideChar);<br> end;<br><br><br> PCommonData = ^TCommonData;<br><br> TCode5 = packed record<br> siJmp : ShortInt;<br> dwAddr : DWORD;<br> end;<br><br> TThunkFunc = (tfTextOutA, tfTextOutW,<br> tfExtTextOutA, tfExtTextOutW,<br> tfDrawTextA, tfDrawTextW);<br><br> TThunkFuncName = packed record<br> strMod : string; // 系统模块名称<br> strSysProc : string; // 系统DLL中的名字<br> strThunkProc : string; // 你替换的函数的名字,必须在DLL的引出表中<br> end;<br><br> TThunkCode = packed record<br> codeBak : TCode5; // 系统函数的代码的前5个字节<br> codeThunk : TCode5; // 跳转到你的代码的5个字节<br> addr_sys : Pointer; // 系统函数的地址<br> addr_thunk : Pointer; // 替换函数的地址<br> bInstalled : boolean; // 安装了吗?<br> end;<br><br>const<br> G_DELAY_TIME = 100;<br><br>const<br> ThunkFuncNameArr : array[TThunkFunc] of TThunkFuncName = (<br> (strMod : 'gdi32.dll'; strSysProc : 'TextOutA'; strThunkProc : 'GanTextOutA'),<br> (strMod : 'gdi32.dll'; strSysProc : 'TextOutW'; strThunkProc : 'GanTextOutW'),<br> (strMod : 'gdi32.dll'; strSysProc : 'ExtTextOutA'; strThunkProc : 'GanExtTextOutA'),<br> (strMod : 'gdi32.dll'; strSysProc : 'ExtTextOutW'; strThunkProc : 'GanExtTextOutW'),<br> (strMod : 'user32.dll'; strSysProc : 'DrawTextA'; strThunkProc : 'GanDrawTextA'),<br> (strMod : 'user32.dll'; strSysProc : 'DrawTextW'; strThunkProc : 'GanDrawTextW')<br> );<br><br><br>implementation<br><br>end.<br><br><br><br>//单元untMain.pas的代码,窗体设置见下<br>(*******************************************************************************<br>* Copy Right (C) Gan Huaxin 2001, 2002, huiyugan@263.net<br>* A Free Screen Words Capture Library<br>* Dedicated to my GirlFriend Sunny, Happy for ever<br>*<br>* Version Date Modification<br>* 0.1 2001-11-07~09 New, oly a test<br>* Can Get Word, Sometimes occure error<br>* 0.2 2002-05-14~16 Some Bugs Fixed,And<br>*******************************************************************************)<br>unit untMain;<br><br>interface<br><br>uses<br> Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,<br> StdCtrls, untTypes;<br><br>type<br> TfrmGanDict = class(TForm)<br> btnLoad: TButton;<br> btnUnLoad: TButton;<br> lblHwnd: TLabel;<br> btnAbout: TButton;<br> lblMousePos: TLabel;<br> memoThunk: TMemo;<br> lblFontWidth: TLabel;<br> lblRect: TLabel;<br> procedure btnLoadClick(Sender: TObject);<br> procedure btnUnLoadClick(Sender: TObject);<br> procedure FormDestroy(Sender: TObject);<br> procedure FormCreate(Sender: TObject);<br> private<br> { Private declarations }<br> public<br> { Public declarations }<br> procedure WndProc(var Mess: TMessage); override;<br> end;<br><br>var<br> frmGanDict: TfrmGanDict;<br><br>implementation<br><br>uses untAbout;<br><br>{$R *.DFM}<br><br>var<br> HMapFile:THandle;<br> CommonData:^TCommonData;<br><br><br>const<br> STR_MSGNOTIFYchar='WM_GANNOTIFY';<br>var<br> idMsg : UINT;<br><br>function EnableMouseHook(hld:hwnd; ProcessID : DWORD; hInst : THandle): BOOL; external 'GFDict.dll';<br>function DisableMouseHook: BOOL; external 'GFDict.dll';<br>function SetCaptureFlag(bFlag:BOOL): BOOL; external 'GFDict.dll';<br><br>procedure MapCommonData;<br>var FirstCall: Boolean;<br>begin<br> HMapFile:=OpenFileMapping(FILE_MAP_WRITE, False, 'GanGan_ThunkDict');<br> FirstCall:=(HMapFile = 0);<br> if FirstCall then<br> HMapFile:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,<br> 0,SizeOf(TCommonData),<br> 'GanGan_ThunkDict');<br> CommonData:= MapViewOfFile(HMapFile, FILE_MAP_WRITE, 0, 0, 0);<br> if FirstCall then FillChar(CommonData^, SizeOf(TCommonData), 0);<br>end;<br><br>procedure TfrmGanDict.btnLoadClick(Sender: TObject);<br>begin<br> if not EnableMouseHook(handle, GetCurrentProcessID, Application.Handle) then<br> ShowMessage('ERROR')<br> else<br> SetCaptureFlag(TRUE);<br>end;<br><br>procedure TfrmGanDict.btnUnLoadClick(Sender: TObject);<br>begin<br> DisableMouseHook;<br>end;<br><br>procedure TfrmGanDict.FormDestroy(Sender: TObject);<br>begin<br> DisableMouseHook;<br> if CommonData<>nil then begin<br> UnMapViewOfFile(CommonData);<br> CommonData := nil;<br> CloseHandle(HMapFile);<br> HMapFile := 0;<br> end;<br>end;<br><br>procedure TfrmGanDict.FormCreate(Sender: TObject);<br>begin<br> idMsg := RegisterWindowMessage(STR_MSGNOTIFY);<br> CommonData := nil;<br> MapCommonData;<br> SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0,<br> SWP_NOSIZE or SWP_NOMOVE);<br>end;<br><br>const<br> StrProcNames : array[0..5] of String =<br> ('TextOutA',<br> 'TextOutW',<br> 'ExtTextOutA',<br> 'ExtTextOutW',<br> 'DrawTextA',<br> 'DrawTextW');<br>procedure TfrmGanDict.WndProc(var Mess: TMessage);<br>begin<br> case Mess.LParam of<br> 0:<br> begin<br> if (mess.msg = idMsg) then begin<br> if (Mess.wParam >=0) and (Mess.WParam <= 5) then begin<br> lblHwnd.Caption := StrProcNames[mess.wParam]; //Format('Handle : 0x%X', [mess.wParam]);<br> if CommonData <> nil then with CommonData^ do begin<br> memoThunk.Text := CommonData.BufferA;<br> lblRect.Caption := Format('Client X:%d, Y:%d, Rect[%d,%d,%d,%d]',<br> [MousePClient.x, MousePClient.y,<br> Rect.Left, Rect.Top, Rect.Right, Rect.Bottom]);<br> // lblThunkText.Caption := CommonData.BufferA;<br> end<br> end else<br> lblHwnd.Caption := 'UnKnow Message';<br> end;<br> end;<br> 1:<br> begin<br> if CommonData<>nil then with CommonData^ do<br> lblMousePos.Caption := Format('Mouse Pos X : %d, Y : %d',<br> [MousePos.X,<br> MousePos.Y]);<br> end;<br> 2:<br> begin<br> memoThunk.Text := '---';<br> end;<br> 3:<br> begin<br> lblFontWidth.Caption := Format('Font Width : %d', [mess.wParam]);<br> end;<br> end;<br> inherited;<br>end;<br><br>end.