mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-27 15:24:05 +00:00
Win32-specific mouseover dll sources added, taken directly from StarDict
codebase with minimal modifications.
This commit is contained in:
parent
1a5a4daa52
commit
18b355cda3
244
src/mouseover_win32/GetWord.c
Normal file
244
src/mouseover_win32/GetWord.c
Normal file
|
@ -0,0 +1,244 @@
|
|||
#include "GetWord.h"
|
||||
#include "TextOutHook.h"
|
||||
|
||||
TKnownWndClass GetWindowType(HWND WND, const char* WNDClass)
|
||||
{
|
||||
const char* StrKnownClasses[] = {
|
||||
"RICHEDIT20A",
|
||||
"RICHEDIT20W",
|
||||
"RICHEDIT",
|
||||
"EDIT",
|
||||
"INTERNET EXPLORER_SERVER",
|
||||
"CONSOLEWINDOWCLASS", // NT
|
||||
"TTYGRAB", // 9x
|
||||
};
|
||||
TKnownWndClass KnownClasses[] = {
|
||||
kwcRichEdit,
|
||||
kwcRichEdit,
|
||||
kwcRichEdit,
|
||||
kwcMultiLineEdit,
|
||||
kwcInternetExplorer_Server,
|
||||
kwcConsole,
|
||||
kwcConsole,
|
||||
};
|
||||
int i;
|
||||
for (i=0; i<7; i++) {
|
||||
if (_stricmp(WNDClass, StrKnownClasses[i])==0)
|
||||
break;
|
||||
}
|
||||
if (i<7) {
|
||||
if (KnownClasses[i] == kwcMultiLineEdit) {
|
||||
if ((GetWindowLong(WND, GWL_STYLE) & ES_MULTILINE) == 0)
|
||||
return kwcSingleLineEdit;
|
||||
}
|
||||
return KnownClasses[i];
|
||||
} else
|
||||
return kwcUnknown;
|
||||
}
|
||||
|
||||
static char* ExtractWordFromRichEditPos(HWND WND, POINT Pt, int *BeginPos)
|
||||
{
|
||||
return ExtractFromEverything(WND, Pt, BeginPos);
|
||||
}
|
||||
/*
|
||||
typedef struct TEditParams {
|
||||
HWND WND;
|
||||
POINT Pt;
|
||||
char Buffer[256];
|
||||
} TEditParams;
|
||||
|
||||
static int ExtractWordFromEditPosPack(TEditParams *params)
|
||||
{
|
||||
int Result = 0;
|
||||
int BegPos;
|
||||
BegPos = SendMessage(params->WND, EM_CHARFROMPOS, 0, params->Pt.x | params->Pt.y << 16);
|
||||
if (BegPos == -1)
|
||||
return Result;
|
||||
int MaxLength;
|
||||
MaxLength = SendMessage(params->WND, EM_LINELENGTH, BegPos & 0xFFFF, 0);
|
||||
if (MaxLength <= 0)
|
||||
return Result;
|
||||
char *Buf;
|
||||
Buf = GlobalAlloc(GMEM_FIXED, MaxLength + 1);
|
||||
if (Buf) {
|
||||
*Buf = MaxLength;
|
||||
MaxLength = SendMessage(params->WND, EM_GETLINE, BegPos >> 16, (int)Buf);
|
||||
Buf[MaxLength] = '\0';
|
||||
BegPos = (BegPos & 0xFFFF) - SendMessage(params->WND, EM_LINEINDEX, BegPos >> 16, 0) - 1;
|
||||
int EndPos;
|
||||
EndPos = BegPos;
|
||||
while ((BegPos >= 0) && IsCharAlpha(Buf[BegPos]))
|
||||
BegPos--;
|
||||
while ((EndPos < MaxLength) && IsCharAlpha(Buf[EndPos]))
|
||||
EndPos++;
|
||||
MaxLength = EndPos - BegPos - 1;
|
||||
if (MaxLength >= 0) {
|
||||
if (255 >= MaxLength) {
|
||||
Buf[EndPos] = '\0';
|
||||
lstrcpy(params->Buffer, Buf + BegPos + 1);
|
||||
Result = MaxLength;
|
||||
}
|
||||
}
|
||||
GlobalFree(Buf);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
*/
|
||||
static char* ExtractWordFromEditPos(HWND hEdit, POINT Pt, int *BeginPos)
|
||||
{
|
||||
return ExtractFromEverything(hEdit, Pt, BeginPos);
|
||||
/* TEditParams *TP;
|
||||
TP = malloc(sizeof(TEditParams));
|
||||
TP->WND = hEdit;
|
||||
TP->Pt = Pt;
|
||||
TP->Buffer[0] = '\0';
|
||||
ScreenToClient(hEdit, &(TP->Pt));
|
||||
int MaxLength;
|
||||
MaxLength = ExtractWordFromEditPosPack(TP);
|
||||
char *Result;
|
||||
if (MaxLength>0) {
|
||||
Result = strdup(TP->Buffer);
|
||||
} else {
|
||||
Result = NULL;
|
||||
}
|
||||
free(TP);
|
||||
return Result;
|
||||
*/
|
||||
}
|
||||
|
||||
static char* ExtractWordFromIE(HWND WND, POINT Pt, int *BeginPos)
|
||||
{
|
||||
return ExtractFromEverything(WND, Pt, BeginPos);
|
||||
}
|
||||
|
||||
typedef struct TConsoleParams {
|
||||
HWND WND;
|
||||
POINT Pt;
|
||||
RECT ClientRect;
|
||||
char Buffer[256];
|
||||
} TConsoleParams;
|
||||
|
||||
static int GetWordFromConsolePack(TConsoleParams *params)
|
||||
{
|
||||
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (hStdOut != INVALID_HANDLE_VALUE) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
if (GetConsoleScreenBufferInfo(hStdOut, &csbi)) {
|
||||
COORD CurPos;
|
||||
CurPos.X = csbi.srWindow.Left + (SHORT)(params->Pt.x * (csbi.srWindow.Right - csbi.srWindow.Left + 1) / params->ClientRect.right);
|
||||
CurPos.Y = csbi.srWindow.Top + (SHORT)(params->Pt.y * (csbi.srWindow.Bottom - csbi.srWindow.Top + 1) / params->ClientRect.bottom);
|
||||
if ((CurPos.X >= 0) && (CurPos.X <= csbi.dwSize.X - 1) && (CurPos.Y >= 0) && (CurPos.Y <= csbi.dwSize.Y - 1)) {
|
||||
int BegPos;
|
||||
char *Buf;
|
||||
|
||||
BegPos = CurPos.X;
|
||||
CurPos.X = 0;
|
||||
Buf = GlobalAlloc(GMEM_FIXED, csbi.dwSize.X + 1);
|
||||
if (Buf) {
|
||||
DWORD ActualRead;
|
||||
if ((ReadConsoleOutputCharacter(hStdOut, Buf, csbi.dwSize.X, CurPos, &ActualRead)) && (ActualRead == csbi.dwSize.X)) {
|
||||
int WordLen;
|
||||
|
||||
OemToCharBuff(Buf, Buf, csbi.dwSize.X);
|
||||
if (csbi.dwSize.X > 255)
|
||||
WordLen = 255;
|
||||
else
|
||||
WordLen = csbi.dwSize.X;
|
||||
strncpy(params->Buffer, Buf, WordLen);
|
||||
GlobalFree(Buf);
|
||||
return WordLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static void GetWordFromConsolePackEnd() {}
|
||||
|
||||
static BOOL RemoteExecute(HANDLE hProcess, void *RemoteThread, size_t RemoteSize, void *Data, int DataSize, DWORD *dwReturn)
|
||||
{
|
||||
void *pRemoteThread = VirtualAllocEx(hProcess, NULL, RemoteSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||
void *pData;
|
||||
HANDLE hThread;
|
||||
|
||||
if (!pRemoteThread)
|
||||
return FALSE;
|
||||
if (!WriteProcessMemory(hProcess, pRemoteThread, RemoteThread, RemoteSize, 0)) {
|
||||
VirtualFreeEx(hProcess, pRemoteThread, RemoteSize, MEM_RELEASE);
|
||||
return FALSE;
|
||||
}
|
||||
pData = VirtualAllocEx(hProcess, NULL, DataSize, MEM_COMMIT, PAGE_READWRITE);
|
||||
if (!pData) {
|
||||
VirtualFreeEx(hProcess, pRemoteThread, RemoteSize, MEM_RELEASE);
|
||||
return FALSE;
|
||||
}
|
||||
if (!WriteProcessMemory(hProcess, pData, Data, DataSize, 0)) {
|
||||
VirtualFreeEx(hProcess, pRemoteThread, RemoteSize, MEM_RELEASE);
|
||||
VirtualFreeEx(hProcess, pData, DataSize, MEM_RELEASE);
|
||||
return FALSE;
|
||||
}
|
||||
// Bug: I don't know why the next line will fail in Windows XP, so get word from cmd.exe can't work presently.
|
||||
hThread = CreateRemoteThread(hProcess, 0, 0, (LPTHREAD_START_ROUTINE)pRemoteThread, pData, 0, 0);
|
||||
WaitForSingleObject(hThread, INFINITE);
|
||||
GetExitCodeThread(hThread, dwReturn);
|
||||
ReadProcessMemory(hProcess, pData, Data, DataSize, 0);
|
||||
VirtualFreeEx(hProcess, pRemoteThread, RemoteSize, MEM_RELEASE);
|
||||
VirtualFreeEx(hProcess, pData, DataSize, MEM_RELEASE);
|
||||
if (hThread) {
|
||||
CloseHandle(hThread);
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static char* GetWordFromConsole(HWND WND, POINT Pt, int *BeginPos)
|
||||
{
|
||||
TConsoleParams *TP;
|
||||
DWORD pid;
|
||||
DWORD MaxWordSize;
|
||||
char *Result;
|
||||
|
||||
TP = malloc(sizeof(TConsoleParams));
|
||||
TP->WND = WND;
|
||||
TP->Pt = Pt;
|
||||
ScreenToClient(WND, &(TP->Pt));
|
||||
GetClientRect(WND, &(TP->ClientRect));
|
||||
|
||||
GetWindowThreadProcessId(GetParent(WND), &pid);
|
||||
|
||||
if (pid != GetCurrentProcessId()) {
|
||||
// The next line will fail in Win2k, but OK in Windows XP.
|
||||
HANDLE ph = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, pid);
|
||||
if (ph) {
|
||||
if (!RemoteExecute(ph, GetWordFromConsolePack, (size_t)GetWordFromConsolePackEnd - (size_t)GetWordFromConsolePack, TP, sizeof(TConsoleParams), &MaxWordSize))
|
||||
MaxWordSize = 0;
|
||||
CloseHandle(ph);
|
||||
}
|
||||
} else {
|
||||
MaxWordSize = GetWordFromConsolePack(TP);
|
||||
}
|
||||
|
||||
if (MaxWordSize > 0) {
|
||||
Result = _strdup(TP->Buffer);
|
||||
} else {
|
||||
Result = NULL;
|
||||
}
|
||||
free(TP);
|
||||
return Result;
|
||||
}
|
||||
|
||||
char* TryGetWordFromAnyWindow(TKnownWndClass WndType, HWND WND, POINT Pt, int *BeginPos)
|
||||
{
|
||||
typedef char* (*GetWordFunction_t)(HWND, POINT, int*);
|
||||
const GetWordFunction_t GetWordFunction[]= {
|
||||
ExtractFromEverything,
|
||||
ExtractWordFromRichEditPos,
|
||||
ExtractWordFromEditPos,
|
||||
ExtractWordFromEditPos,
|
||||
ExtractWordFromIE,
|
||||
GetWordFromConsole,
|
||||
};
|
||||
return GetWordFunction[WndType](WND, Pt, BeginPos);
|
||||
}
|
18
src/mouseover_win32/GetWord.h
Normal file
18
src/mouseover_win32/GetWord.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef _GetWord_H_
|
||||
#define _GetWord_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
typedef enum TKnownWndClass {
|
||||
kwcUnknown,
|
||||
kwcRichEdit,
|
||||
kwcMultiLineEdit,
|
||||
kwcSingleLineEdit,
|
||||
kwcInternetExplorer_Server,
|
||||
kwcConsole,
|
||||
} TKnownWndClass;
|
||||
|
||||
TKnownWndClass GetWindowType(HWND WND, const char* WNDClass);
|
||||
char* TryGetWordFromAnyWindow(TKnownWndClass WndType, HWND WND, POINT Pt, int *BeginPos);
|
||||
|
||||
#endif
|
122
src/mouseover_win32/HookImportFunction.c
Normal file
122
src/mouseover_win32/HookImportFunction.c
Normal file
|
@ -0,0 +1,122 @@
|
|||
#include "HookImportFunction.h"
|
||||
#include <tlhelp32.h>
|
||||
|
||||
|
||||
// These code come from: http://dev.csdn.net/article/2/2786.shtm
|
||||
// I fixed a bug in it and improved it to hook all the modules of a program.
|
||||
|
||||
#define MakePtr(cast, ptr, AddValue) (cast)((size_t)(ptr)+(size_t)(AddValue))
|
||||
|
||||
static PIMAGE_IMPORT_DESCRIPTOR GetNamedImportDescriptor(HMODULE hModule, LPCSTR szImportModule)
|
||||
{
|
||||
PIMAGE_DOS_HEADER pDOSHeader;
|
||||
PIMAGE_NT_HEADERS pNTHeader;
|
||||
PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
|
||||
|
||||
if ((szImportModule == NULL) || (hModule == NULL))
|
||||
return NULL;
|
||||
pDOSHeader = (PIMAGE_DOS_HEADER) hModule;
|
||||
if (IsBadReadPtr(pDOSHeader, sizeof(IMAGE_DOS_HEADER)) || (pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE)) {
|
||||
return NULL;
|
||||
}
|
||||
pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDOSHeader, pDOSHeader->e_lfanew);
|
||||
if (IsBadReadPtr(pNTHeader, sizeof(IMAGE_NT_HEADERS)) || (pNTHeader->Signature != IMAGE_NT_SIGNATURE))
|
||||
return NULL;
|
||||
if (pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0)
|
||||
return NULL;
|
||||
pImportDesc = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, pDOSHeader, pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
|
||||
while (pImportDesc->Name) {
|
||||
PSTR szCurrMod = MakePtr(PSTR, pDOSHeader, pImportDesc->Name);
|
||||
if (_stricmp(szCurrMod, szImportModule) == 0)
|
||||
break;
|
||||
pImportDesc++;
|
||||
}
|
||||
if (pImportDesc->Name == (DWORD)0)
|
||||
return NULL;
|
||||
return pImportDesc;
|
||||
}
|
||||
|
||||
static BOOL IsNT()
|
||||
{
|
||||
OSVERSIONINFO stOSVI;
|
||||
BOOL bRet;
|
||||
|
||||
memset(&stOSVI, 0, sizeof(OSVERSIONINFO));
|
||||
stOSVI.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
bRet = GetVersionEx(&stOSVI);
|
||||
if (FALSE == bRet) return FALSE;
|
||||
return (VER_PLATFORM_WIN32_NT == stOSVI.dwPlatformId);
|
||||
}
|
||||
|
||||
static BOOL HookImportFunction(HMODULE hModule, LPCSTR szImportModule, LPCSTR szFunc, PROC paHookFuncs, PROC* paOrigFuncs)
|
||||
{
|
||||
PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
|
||||
PIMAGE_THUNK_DATA pOrigThunk;
|
||||
PIMAGE_THUNK_DATA pRealThunk;
|
||||
|
||||
if (!IsNT() && ((size_t)hModule >= 0x80000000))
|
||||
return FALSE;
|
||||
pImportDesc = GetNamedImportDescriptor(hModule, szImportModule);
|
||||
if (pImportDesc == NULL)
|
||||
return FALSE;
|
||||
pOrigThunk = MakePtr(PIMAGE_THUNK_DATA, hModule, pImportDesc->OriginalFirstThunk);
|
||||
pRealThunk = MakePtr(PIMAGE_THUNK_DATA, hModule, pImportDesc->FirstThunk);
|
||||
while (pOrigThunk->u1.Function) {
|
||||
if (IMAGE_ORDINAL_FLAG != (pOrigThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)) {
|
||||
PIMAGE_IMPORT_BY_NAME pByName = MakePtr(PIMAGE_IMPORT_BY_NAME, hModule, pOrigThunk->u1.AddressOfData);
|
||||
BOOL bDoHook;
|
||||
// When hook EditPlus, read pByName->Name[0] will case this dll terminate, so call IsBadReadPtr() here.
|
||||
if (IsBadReadPtr(pByName, sizeof(IMAGE_IMPORT_BY_NAME))) {
|
||||
pOrigThunk++;
|
||||
pRealThunk++;
|
||||
continue;
|
||||
}
|
||||
if ('\0' == pByName->Name[0]) {
|
||||
pOrigThunk++;
|
||||
pRealThunk++;
|
||||
continue;
|
||||
}
|
||||
bDoHook = FALSE;
|
||||
if ((szFunc[0] == pByName->Name[0]) && (_strcmpi(szFunc, (char*)pByName->Name) == 0)) {
|
||||
if (paHookFuncs)
|
||||
bDoHook = TRUE;
|
||||
}
|
||||
if (bDoHook) {
|
||||
MEMORY_BASIC_INFORMATION mbi_thunk;
|
||||
DWORD dwOldProtect;
|
||||
|
||||
VirtualQuery(pRealThunk, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION));
|
||||
VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, PAGE_READWRITE, &mbi_thunk.Protect);
|
||||
if (paOrigFuncs)
|
||||
*paOrigFuncs = (PROC)pRealThunk->u1.Function;
|
||||
pRealThunk->u1.Function = (DWORD)paHookFuncs;
|
||||
|
||||
VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, mbi_thunk.Protect, &dwOldProtect);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
pOrigThunk++;
|
||||
pRealThunk++;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL HookAPI(LPCSTR szImportModule, LPCSTR szFunc, PROC paHookFuncs, PROC* paOrigFuncs)
|
||||
{
|
||||
HANDLE hSnapshot;
|
||||
MODULEENTRY32 me = {sizeof(MODULEENTRY32)};
|
||||
BOOL bOk;
|
||||
|
||||
if ((szImportModule == NULL) || (szFunc == NULL)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,0);
|
||||
|
||||
bOk = Module32First(hSnapshot,&me);
|
||||
while (bOk) {
|
||||
HookImportFunction(me.hModule, szImportModule, szFunc, paHookFuncs, paOrigFuncs);
|
||||
bOk = Module32Next(hSnapshot,&me);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
9
src/mouseover_win32/HookImportFunction.h
Normal file
9
src/mouseover_win32/HookImportFunction.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef _HookImportFunction_H_
|
||||
#define _HookImportFunction_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
BOOL HookAPI(LPCSTR szImportModule, LPCSTR szFunc, PROC paHookFuncs, PROC* paOrigFuncs);
|
||||
|
||||
#endif
|
29
src/mouseover_win32/Makefile
Normal file
29
src/mouseover_win32/Makefile
Normal file
|
@ -0,0 +1,29 @@
|
|||
GCC:=i586-mingw32msvc-gcc -W -Wall
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: GdTextOutHook.dll libGdTextOutHook.a GdTextOutSpy.dll libGdTextOutSpy.a
|
||||
|
||||
clean:
|
||||
rm -f *.o *.a *.dll
|
||||
|
||||
TextOutHook.o: TextOutHook.c
|
||||
$(GCC) -DBUILDING_DLL -c $<
|
||||
|
||||
HookImportFunction.o: HookImportFunction.c
|
||||
$(GCC) -c $<
|
||||
|
||||
GetWord.o: GetWord.c
|
||||
$(GCC) -c $<
|
||||
|
||||
GdTextOutHook.dll libGdTextOutHook.a: TextOutHook.o HookImportFunction.o GetWord.o
|
||||
$(GCC) -shared -o GdTextOutHook.dll $^ -lgdi32 -Wl,--out-implib,libGdTextOutHook.a
|
||||
|
||||
TextOutSpy.o: TextOutSpy.c
|
||||
$(GCC) -DBUILDING_DLL -c $<
|
||||
|
||||
ThTypes.o: ThTypes.c
|
||||
$(GCC) -c $<
|
||||
|
||||
GdTextOutSpy.dll libGdTextOutSpy.a: TextOutSpy.o ThTypes.o
|
||||
$(GCC) -shared -o GdTextOutSpy.dll $^ -lgdi32 -Wl,--out-implib,libGdTextOutSpy.a
|
395
src/mouseover_win32/TextOutHook.c
Normal file
395
src/mouseover_win32/TextOutHook.c
Normal file
|
@ -0,0 +1,395 @@
|
|||
#include "TextOutHook.h"
|
||||
#include "GetWord.h"
|
||||
#include "HookImportFunction.h"
|
||||
|
||||
|
||||
typedef BOOL (WINAPI *TextOutANextHook_t)(HDC hdc, int nXStart, int nYStart, LPCSTR lpszString,int cbString);
|
||||
TextOutANextHook_t TextOutANextHook = NULL;
|
||||
typedef BOOL (WINAPI *TextOutWNextHook_t)(HDC hdc, int nXStart, int nYStart, LPCWSTR lpszString,int cbString);
|
||||
TextOutWNextHook_t TextOutWNextHook = NULL;
|
||||
typedef BOOL (WINAPI *ExtTextOutANextHook_t)(HDC hdc, int nXStart, int nYStart, UINT fuOptions, CONST RECT *lprc, LPCSTR lpszString, UINT cbString, CONST INT *lpDx);
|
||||
ExtTextOutANextHook_t ExtTextOutANextHook = NULL;
|
||||
typedef BOOL (WINAPI *ExtTextOutWNextHook_t)(HDC hdc, int nXStart, int nYStart, UINT fuOptions, CONST RECT *lprc, LPCWSTR lpszString, UINT cbString, CONST INT *lpDx);
|
||||
ExtTextOutWNextHook_t ExtTextOutWNextHook = NULL;
|
||||
|
||||
typedef struct TEverythingParams {
|
||||
HWND WND;
|
||||
POINT Pt;
|
||||
int Active;
|
||||
int WordLen;
|
||||
int Unicode;
|
||||
int BeginPos;
|
||||
char MatchedWordA[256];
|
||||
wchar_t MatchedWordW[256];
|
||||
} TEverythingParams;
|
||||
|
||||
TEverythingParams *CurParams = NULL;
|
||||
|
||||
static void ConvertToMatchedWordA(TEverythingParams *TP)
|
||||
{
|
||||
if (TP->WordLen>0) {
|
||||
int BeginPos;
|
||||
if (!TP->Unicode) {
|
||||
BeginPos = TP->BeginPos;
|
||||
if (BeginPos) {
|
||||
TP->BeginPos = MultiByteToWideChar(CP_ACP, 0, TP->MatchedWordA, BeginPos, TP->MatchedWordW, sizeof(TP->MatchedWordW)/sizeof(TP->MatchedWordW[0]) - 1);
|
||||
if (TP->BeginPos == 0) {
|
||||
TP->WordLen=0;
|
||||
TP->MatchedWordA[0] = '\0';
|
||||
return;
|
||||
}
|
||||
}
|
||||
TP->WordLen = MultiByteToWideChar(CP_ACP, 0, TP->MatchedWordA + BeginPos, TP->WordLen - BeginPos, TP->MatchedWordW + TP->BeginPos, sizeof(TP->MatchedWordW)/sizeof(TP->MatchedWordW[0]) - 1 - TP->BeginPos);
|
||||
if (TP->WordLen == 0) {
|
||||
TP->WordLen=TP->BeginPos;
|
||||
TP->MatchedWordA[TP->WordLen] = '\0';
|
||||
return;
|
||||
}
|
||||
TP->WordLen += TP->BeginPos;
|
||||
}
|
||||
BeginPos = TP->BeginPos;
|
||||
if (BeginPos) {
|
||||
wchar_t temp = TP->MatchedWordW[BeginPos];
|
||||
TP->MatchedWordW[BeginPos] = 0;
|
||||
TP->BeginPos = WideCharToMultiByte(CP_UTF8, 0, TP->MatchedWordW, BeginPos + 1, TP->MatchedWordA, sizeof(TP->MatchedWordA), NULL, NULL);
|
||||
TP->MatchedWordW[BeginPos] = temp;
|
||||
TP->BeginPos--;
|
||||
if (TP->BeginPos<=0) {
|
||||
TP->WordLen=0;
|
||||
TP->MatchedWordA[0] = '\0';
|
||||
return;
|
||||
} else if (TP->BeginPos == sizeof(TP->MatchedWordA)-1) {
|
||||
TP->WordLen=sizeof(TP->MatchedWordA)-1;
|
||||
TP->MatchedWordA[sizeof(TP->MatchedWordA)-1] = '\0';
|
||||
return;
|
||||
}
|
||||
}
|
||||
TP->MatchedWordW[TP->WordLen] = 0;
|
||||
TP->WordLen = WideCharToMultiByte(CP_UTF8, 0, TP->MatchedWordW + BeginPos, TP->WordLen - BeginPos + 1, TP->MatchedWordA + TP->BeginPos, sizeof(TP->MatchedWordA) - TP->BeginPos, NULL, NULL);
|
||||
TP->WordLen--;
|
||||
if (TP->WordLen<=0) {
|
||||
TP->WordLen=TP->BeginPos;
|
||||
TP->MatchedWordA[TP->WordLen] = '\0';
|
||||
return;
|
||||
}
|
||||
TP->WordLen += TP->BeginPos;
|
||||
TP->MatchedWordA[TP->WordLen] = '\0';
|
||||
} else {
|
||||
TP->MatchedWordA[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
static int MyCopyMemory(char *a, const char *b, int len)
|
||||
{
|
||||
int count = 0;
|
||||
int i;
|
||||
for (i=0; i<len; i++) {
|
||||
if (*b != '&') {
|
||||
count++;
|
||||
*a = *b;
|
||||
a++;
|
||||
}
|
||||
b++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static void IterateThroughItems(HWND WND, HMENU menu, POINT *p)
|
||||
{
|
||||
int count = GetMenuItemCount(menu);
|
||||
RECT rec;
|
||||
MENUITEMINFO info;
|
||||
int i;
|
||||
for (i=0; i<count; i++) {
|
||||
if (GetMenuItemRect(WND, menu, i, &rec) && (rec.left<=p->x) && (p->x<=rec.right) && (rec.top<=p->y) && (p->y<=rec.bottom)) {
|
||||
ZeroMemory(&info, sizeof(info));
|
||||
info.cbSize = sizeof(info);
|
||||
info.fMask = MIIM_TYPE | MIIM_SUBMENU;
|
||||
info.cch = 256;
|
||||
info.dwTypeData = malloc(256);
|
||||
GetMenuItemInfo(menu, i, TRUE, &info);
|
||||
if (info.cch>0) {
|
||||
if (info.cch > 255)
|
||||
CurParams->WordLen = 255;
|
||||
else
|
||||
CurParams->WordLen = info.cch;
|
||||
CurParams->Unicode = FALSE;
|
||||
CurParams->WordLen = MyCopyMemory(CurParams->MatchedWordA, info.dwTypeData, CurParams->WordLen);
|
||||
CurParams->BeginPos = 0;
|
||||
}
|
||||
free(info.dwTypeData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void GetWordTextOutHook (TEverythingParams *TP)
|
||||
{
|
||||
CurParams = TP;
|
||||
ScreenToClient(TP->WND, &(TP->Pt));
|
||||
if (TP->Pt.y<0) {
|
||||
char buffer[256];
|
||||
HMENU menu;
|
||||
char buffer2[256];
|
||||
|
||||
GetWindowText(TP->WND, buffer, sizeof(buffer)-1);
|
||||
SetWindowText(TP->WND, "");
|
||||
|
||||
GetWindowText(TP->WND, buffer2, sizeof(buffer2)-1);
|
||||
if (buffer2[0]) { // MDI window.
|
||||
char *p = strstr(buffer, buffer2);
|
||||
if (p) {
|
||||
if (p == buffer) { // FWS_PREFIXTITLE
|
||||
strcpy(buffer, buffer+strlen(buffer2));
|
||||
} else {
|
||||
*p = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
CurParams->Active = TRUE;
|
||||
SetWindowText(TP->WND, buffer);
|
||||
CurParams->Active = FALSE;
|
||||
menu = GetMenu(TP->WND);
|
||||
if (menu) {
|
||||
ClientToScreen(TP->WND, &(TP->Pt));
|
||||
IterateThroughItems(TP->WND, menu, &(TP->Pt));
|
||||
}
|
||||
}
|
||||
else {
|
||||
RECT UpdateRect;
|
||||
GetClientRect(TP->WND, &UpdateRect);
|
||||
UpdateRect.top = TP->Pt.y;
|
||||
UpdateRect.bottom = TP->Pt.y + 1;
|
||||
CurParams->Active = TRUE;
|
||||
InvalidateRect(TP->WND, &UpdateRect, FALSE);
|
||||
UpdateWindow(TP->WND);
|
||||
CurParams->Active = FALSE;
|
||||
}
|
||||
CurParams = NULL;
|
||||
}
|
||||
|
||||
char* ExtractFromEverything(HWND WND, POINT Pt, int *BeginPos)
|
||||
{
|
||||
TEverythingParams CParams;
|
||||
|
||||
ZeroMemory(&CParams, sizeof(CParams));
|
||||
CParams.WND = WND;
|
||||
CParams.Pt = Pt;
|
||||
GetWordTextOutHook(&CParams);
|
||||
ConvertToMatchedWordA(&CParams);
|
||||
*BeginPos = CParams.BeginPos;
|
||||
return _strdup(CParams.MatchedWordA);
|
||||
}
|
||||
|
||||
static void IsInsidePointA(const HDC DC, int X, int Y, LPCSTR Str, int Count)
|
||||
{
|
||||
SIZE Size;
|
||||
if ((Count > 0) && GetTextExtentPoint32A(DC, Str, Count, &Size)) {
|
||||
DWORD Flags = GetTextAlign(DC);
|
||||
POINT Pt;
|
||||
RECT Rect;
|
||||
|
||||
if (Flags & TA_UPDATECP) {
|
||||
GetCurrentPositionEx(DC, &Pt);
|
||||
} else {
|
||||
Pt.x = X;
|
||||
Pt.y = Y;
|
||||
}
|
||||
if (Flags & TA_CENTER) {
|
||||
Pt.x-=(Size.cx/2);
|
||||
} else if (Flags & TA_RIGHT) {
|
||||
Pt.x-=Size.cx;
|
||||
}
|
||||
if (Flags & TA_BASELINE) {
|
||||
TEXTMETRIC tm;
|
||||
GetTextMetricsA(DC, &tm);
|
||||
Pt.y-=tm.tmAscent;
|
||||
} else if (Flags & TA_BOTTOM) {
|
||||
Pt.y-=Size.cy;
|
||||
}
|
||||
LPtoDP(DC, &Pt, 1);
|
||||
|
||||
Rect.left = Pt.x;
|
||||
Rect.right = Pt.x + Size.cx;
|
||||
Rect.top = Pt.y;
|
||||
Rect.bottom = Pt.y + Size.cy;
|
||||
if (((Rect.left <= Rect.right) && (CurParams->Pt.x >= Rect.left) && (CurParams->Pt.x <= Rect.right)) ||
|
||||
((Rect.left > Rect.right) && (CurParams->Pt.x <= Rect.left) && (CurParams->Pt.x >= Rect.right))) {
|
||||
int BegPos;
|
||||
|
||||
//if (PtInRect(&Rect, CurParams->Pt)) {
|
||||
CurParams->Active = !PtInRect(&Rect, CurParams->Pt);
|
||||
//CurParams->Active = FALSE;
|
||||
BegPos = (int)((abs((CurParams->Pt.x - Rect.left) / (Rect.right - Rect.left)) * (Count - 1)) + 0.5);
|
||||
while ((BegPos < Count - 1) && GetTextExtentPoint32A(DC, Str, BegPos + 1, &Size) && (Size.cx < CurParams->Pt.x - Rect.left))
|
||||
BegPos++;
|
||||
while ((BegPos >= 0) && GetTextExtentPoint32A(DC, Str, BegPos + 1, &Size) && (Size.cx > CurParams->Pt.x - Rect.left))
|
||||
BegPos--;
|
||||
if (BegPos < Count - 1)
|
||||
BegPos++;
|
||||
CurParams->BeginPos = BegPos;
|
||||
if (Count > 255)
|
||||
CurParams->WordLen = 255;
|
||||
else
|
||||
CurParams->WordLen = Count;
|
||||
CurParams->Unicode = FALSE;
|
||||
CopyMemory(CurParams->MatchedWordA, Str, CurParams->WordLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void IsInsidePointW(const HDC DC, int X, int Y, LPCWSTR Str, int Count)
|
||||
{
|
||||
SIZE Size;
|
||||
if ((Count > 0) && GetTextExtentPoint32W(DC, Str, Count, &Size)) {
|
||||
DWORD Flags = GetTextAlign(DC);
|
||||
POINT Pt;
|
||||
RECT Rect;
|
||||
|
||||
if (Flags & TA_UPDATECP) {
|
||||
GetCurrentPositionEx(DC, &Pt);
|
||||
} else {
|
||||
Pt.x = X;
|
||||
Pt.y = Y;
|
||||
}
|
||||
if (Flags & TA_CENTER) {
|
||||
Pt.x-=(Size.cx/2);
|
||||
} else if (Flags & TA_RIGHT) {
|
||||
Pt.x-=Size.cx;
|
||||
}
|
||||
if (Flags & TA_BASELINE) {
|
||||
TEXTMETRICW tm;
|
||||
GetTextMetricsW(DC, &tm);
|
||||
Pt.y-=tm.tmAscent;
|
||||
} else if (Flags & TA_BOTTOM) {
|
||||
Pt.y-=Size.cy;
|
||||
}
|
||||
LPtoDP(DC, &Pt, 1);
|
||||
|
||||
Rect.left = Pt.x;
|
||||
Rect.right = Pt.x + Size.cx;
|
||||
Rect.top = Pt.y;
|
||||
Rect.bottom = Pt.y + Size.cy;
|
||||
// Bug: We don't check Pt.y here, as don't call PtInRect() directly, because
|
||||
// in Title bar, Start Menu, IE, FireFox, Opera etc., the Rect.top and Rect.bottom will be wrong.
|
||||
// I try to use GetDCOrgEx(DC, &Pt), but they are not normal HDC that Pt.x and Pt.y will equal to 0 in these cases.
|
||||
// And use GetWindowRect() then get Rect.left and Rect.top is only useful on Title bar.
|
||||
if (((Rect.left <= Rect.right) && (CurParams->Pt.x >= Rect.left) && (CurParams->Pt.x <= Rect.right)) ||
|
||||
((Rect.left > Rect.right) && (CurParams->Pt.x <= Rect.left) && (CurParams->Pt.x >= Rect.right))) {
|
||||
int BegPos;
|
||||
|
||||
//if (PtInRect(&Rect, CurParams->Pt)) {
|
||||
CurParams->Active = !PtInRect(&Rect, CurParams->Pt);
|
||||
//CurParams->Active = FALSE;
|
||||
BegPos = (int)((abs((CurParams->Pt.x - Rect.left) / (Rect.right - Rect.left)) * (Count - 1)) + 0.5);
|
||||
while ((BegPos < Count - 1) && GetTextExtentPoint32W(DC, Str, BegPos + 1, &Size) && (Size.cx < CurParams->Pt.x - Rect.left))
|
||||
BegPos++;
|
||||
while ((BegPos >= 0) && GetTextExtentPoint32W(DC, Str, BegPos + 1, &Size) && (Size.cx > CurParams->Pt.x - Rect.left))
|
||||
BegPos--;
|
||||
if (BegPos < Count - 1)
|
||||
BegPos++;
|
||||
CurParams->BeginPos = BegPos;
|
||||
if (Count > 255)
|
||||
CurParams->WordLen = 255;
|
||||
else
|
||||
CurParams->WordLen = Count;
|
||||
CurParams->Unicode = TRUE;
|
||||
CopyMemory(CurParams->MatchedWordW, Str, CurParams->WordLen * sizeof(wchar_t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL WINAPI TextOutACallbackProc(HDC hdc, int nXStart, int nYStart, LPCSTR lpszString, int cbString)
|
||||
{
|
||||
if (CurParams && CurParams->Active)
|
||||
IsInsidePointA(hdc, nXStart, nYStart, lpszString, cbString);
|
||||
return TextOutANextHook(hdc, nXStart, nYStart, lpszString, cbString);
|
||||
}
|
||||
|
||||
BOOL WINAPI TextOutWCallbackProc(HDC hdc, int nXStart, int nYStart, LPCWSTR lpszString, int cbString)
|
||||
{
|
||||
if (CurParams && CurParams->Active)
|
||||
IsInsidePointW(hdc, nXStart, nYStart, lpszString, cbString);
|
||||
return TextOutWNextHook(hdc, nXStart, nYStart, lpszString, cbString);
|
||||
}
|
||||
|
||||
BOOL WINAPI ExtTextOutACallbackProc(HDC hdc, int nXStart, int nYStart, UINT fuOptions, CONST RECT *lprc, LPCSTR lpszString, UINT cbString, CONST INT *lpDx)
|
||||
{
|
||||
if (CurParams && CurParams->Active)
|
||||
IsInsidePointA(hdc, nXStart, nYStart, lpszString, cbString);
|
||||
return ExtTextOutANextHook(hdc, nXStart, nYStart, fuOptions, lprc, lpszString, cbString, lpDx);
|
||||
}
|
||||
|
||||
BOOL WINAPI ExtTextOutWCallbackProc(HDC hdc, int nXStart, int nYStart, UINT fuOptions, CONST RECT *lprc, LPCWSTR lpszString, UINT cbString, CONST INT *lpDx)
|
||||
{
|
||||
if (CurParams && CurParams->Active)
|
||||
IsInsidePointW(hdc, nXStart, nYStart, lpszString, cbString);
|
||||
return ExtTextOutWNextHook(hdc, nXStart, nYStart, fuOptions, lprc, lpszString, cbString, lpDx);
|
||||
}
|
||||
|
||||
static void InstallTextOutHooks()
|
||||
{
|
||||
HookAPI("gdi32.dll", "TextOutA", (PROC)TextOutACallbackProc, (PROC*)&TextOutANextHook);
|
||||
HookAPI("gdi32.dll", "TextOutW", (PROC)TextOutWCallbackProc, (PROC*)&TextOutWNextHook);
|
||||
HookAPI("gdi32.dll", "ExtTextOutA", (PROC)ExtTextOutACallbackProc, (PROC*)&ExtTextOutANextHook);
|
||||
HookAPI("gdi32.dll", "ExtTextOutW", (PROC)ExtTextOutWCallbackProc, (PROC*)&ExtTextOutWNextHook);
|
||||
}
|
||||
|
||||
static void UninstallTextOutHooks()
|
||||
{
|
||||
if (TextOutANextHook)
|
||||
HookAPI("gdi32.dll", "TextOutA", (PROC)TextOutANextHook, NULL);
|
||||
if (TextOutWNextHook)
|
||||
HookAPI("gdi32.dll", "TextOutW", (PROC)TextOutWNextHook, NULL);
|
||||
if (ExtTextOutANextHook)
|
||||
HookAPI("gdi32.dll", "ExtTextOutA", (PROC)ExtTextOutANextHook, NULL);
|
||||
if (ExtTextOutWNextHook)
|
||||
HookAPI("gdi32.dll", "ExtTextOutW", (PROC)ExtTextOutWNextHook, NULL);
|
||||
}
|
||||
|
||||
DLLIMPORT void __gdGetWord (TCurrentMode *P)
|
||||
{
|
||||
TCHAR wClassName[64];
|
||||
TKnownWndClass WndClass;
|
||||
char *p;
|
||||
|
||||
if (GetClassName(P->WND, wClassName, sizeof(wClassName) / sizeof(TCHAR))==0)
|
||||
wClassName[0] = '\0';
|
||||
WndClass = GetWindowType(P->WND, wClassName);
|
||||
p = TryGetWordFromAnyWindow(WndClass, P->WND, P->Pt, &(P->BeginPos));
|
||||
if (p) {
|
||||
P->WordLen = strlen(p);
|
||||
strcpy(P->MatchedWord, p);
|
||||
free(p);
|
||||
} else {
|
||||
P->WordLen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ ,
|
||||
DWORD reason /* Reason this function is being called. */ ,
|
||||
LPVOID reserved /* Not used. */ )
|
||||
{
|
||||
switch (reason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
//ThTypes_Init();
|
||||
InstallTextOutHooks();
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
UninstallTextOutHooks();
|
||||
//Thtypes_End();
|
||||
break;
|
||||
|
||||
case DLL_THREAD_ATTACH:
|
||||
break;
|
||||
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Returns TRUE on success, FALSE on failure */
|
||||
return TRUE;
|
||||
}
|
17
src/mouseover_win32/TextOutHook.h
Normal file
17
src/mouseover_win32/TextOutHook.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef _TextOutHook_H_
|
||||
#define _TextOutHook_H_
|
||||
|
||||
#if BUILDING_DLL
|
||||
# define DLLIMPORT __declspec (dllexport)
|
||||
#else /* Not BUILDING_DLL */
|
||||
# define DLLIMPORT __declspec (dllimport)
|
||||
#endif /* Not BUILDING_DLL */
|
||||
|
||||
#include "ThTypes.h"
|
||||
|
||||
char* ExtractFromEverything(HWND WND, POINT Pt, int *BeginPos);
|
||||
|
||||
DLLIMPORT void GetWord (TCurrentMode *P);
|
||||
|
||||
|
||||
#endif /* _TextOutHook_H_ */
|
153
src/mouseover_win32/TextOutSpy.c
Normal file
153
src/mouseover_win32/TextOutSpy.c
Normal file
|
@ -0,0 +1,153 @@
|
|||
#include "TextOutSpy.h"
|
||||
#include "ThTypes.h"
|
||||
|
||||
|
||||
const int MOUSEOVER_INTERVAL = 300;
|
||||
const int WM_MY_SHOW_TRANSLATION = WM_USER + 301;
|
||||
|
||||
HINSTANCE g_hInstance = NULL;
|
||||
HANDLE hSynhroMutex = 0;
|
||||
HINSTANCE hGetWordLib = 0;
|
||||
typedef void (*GetWordProc_t)(TCurrentMode *);
|
||||
GetWordProc_t GetWordProc = NULL;
|
||||
|
||||
static void SendWordToServer()
|
||||
{
|
||||
if (hGetWordLib == 0) {
|
||||
hGetWordLib = LoadLibrary(GlobalData->LibName);
|
||||
if (hGetWordLib) {
|
||||
GetWordProc = (GetWordProc_t)GetProcAddress(hGetWordLib, "__gdGetWord");
|
||||
}
|
||||
else {
|
||||
hGetWordLib = (HINSTANCE)-1;
|
||||
}
|
||||
}
|
||||
if (GetWordProc) {
|
||||
GlobalData->CurMod.WND = GlobalData->LastWND;
|
||||
GlobalData->CurMod.Pt = GlobalData->LastPt;
|
||||
GetWordProc(&(GlobalData->CurMod));
|
||||
if (GlobalData->CurMod.WordLen > 0) {
|
||||
DWORD SendMsgAnswer;
|
||||
SendMessageTimeout(GlobalData->ServerWND, WM_MY_SHOW_TRANSLATION, 0, 0, SMTO_ABORTIFHUNG, MOUSEOVER_INTERVAL, &SendMsgAnswer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CALLBACK TimerFunc(HWND hWnd,UINT nMsg,UINT nTimerid,DWORD dwTime)
|
||||
{
|
||||
if (WaitForSingleObject(hSynhroMutex, 0) == WAIT_OBJECT_0) {
|
||||
if (GlobalData->TimerID) {
|
||||
if (KillTimer(0, GlobalData->TimerID))
|
||||
GlobalData->TimerID=0;
|
||||
}
|
||||
ReleaseMutex(hSynhroMutex);
|
||||
}
|
||||
if ((GlobalData->LastWND!=0)&&(GlobalData->LastWND == WindowFromPoint(GlobalData->LastPt))) {
|
||||
if (WaitForSingleObject(hSynhroMutex, 0) == WAIT_OBJECT_0) {
|
||||
SendWordToServer();
|
||||
ReleaseMutex(hSynhroMutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if ((nCode == HC_ACTION) && ((wParam == WM_MOUSEMOVE) || (wParam == WM_NCMOUSEMOVE))) {
|
||||
if (WaitForSingleObject(hSynhroMutex, 0) == WAIT_OBJECT_0) {
|
||||
HWND WND;
|
||||
TCHAR wClassName[64];
|
||||
|
||||
if (GlobalData->TimerID) {
|
||||
if (KillTimer(0, GlobalData->TimerID))
|
||||
GlobalData->TimerID=0;
|
||||
}
|
||||
WND = WindowFromPoint(((PMOUSEHOOKSTRUCT)lParam)->pt);
|
||||
|
||||
if (GetClassName(WND, wClassName, sizeof(wClassName) / sizeof(TCHAR))) {
|
||||
const char* DisableClasses[] = {
|
||||
"gdkWindowChild",
|
||||
"gdkWindowTemp",
|
||||
};
|
||||
int i;
|
||||
for (i=0; i<2; i++) {
|
||||
if (strcmp(wClassName, DisableClasses[i])==0)
|
||||
break;
|
||||
}
|
||||
if (i<2) {
|
||||
ReleaseMutex(hSynhroMutex);
|
||||
return CallNextHookEx(GlobalData->g_hHookMouse, nCode, wParam, lParam);
|
||||
}
|
||||
}
|
||||
GlobalData->TimerID = SetTimer(0, 0, MOUSEOVER_INTERVAL, TimerFunc);
|
||||
GlobalData->LastWND = WND;
|
||||
GlobalData->LastPt = ((PMOUSEHOOKSTRUCT)lParam)->pt;
|
||||
ReleaseMutex(hSynhroMutex);
|
||||
}
|
||||
}
|
||||
return CallNextHookEx(GlobalData->g_hHookMouse, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
DLLIMPORT void ActivateTextOutSpying (int Activate)
|
||||
{
|
||||
// After call SetWindowsHookEx(), when you move mouse to a application's window,
|
||||
// this dll will load into this application automatically. And it is unloaded
|
||||
// after call UnhookWindowsHookEx().
|
||||
if (Activate) {
|
||||
if (GlobalData->g_hHookMouse != NULL) return;
|
||||
GlobalData->g_hHookMouse = SetWindowsHookEx(WH_MOUSE, MouseHookProc, g_hInstance, 0);
|
||||
}
|
||||
else {
|
||||
if (GlobalData->g_hHookMouse == NULL) return;
|
||||
if (WaitForSingleObject(hSynhroMutex, 0) == WAIT_OBJECT_0) {
|
||||
if (GlobalData->TimerID) {
|
||||
if (KillTimer(0, GlobalData->TimerID))
|
||||
GlobalData->TimerID=0;
|
||||
}
|
||||
ReleaseMutex(hSynhroMutex);
|
||||
}
|
||||
UnhookWindowsHookEx(GlobalData->g_hHookMouse);
|
||||
GlobalData->g_hHookMouse = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ ,
|
||||
DWORD reason /* Reason this function is being called. */ ,
|
||||
LPVOID reserved /* Not used. */ )
|
||||
{
|
||||
switch (reason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
g_hInstance = hInst;
|
||||
hSynhroMutex = CreateMutex(NULL, FALSE, "GoldenDictTextOutSpyMutex");
|
||||
ThTypes_Init();
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
WaitForSingleObject(hSynhroMutex, INFINITE);
|
||||
if (GlobalData->TimerID) {
|
||||
if (KillTimer(0, GlobalData->TimerID))
|
||||
GlobalData->TimerID=0;
|
||||
}
|
||||
ReleaseMutex(hSynhroMutex);
|
||||
CloseHandle(hSynhroMutex);
|
||||
{
|
||||
MSG msg ;
|
||||
while (PeekMessage (&msg, 0, WM_TIMER, WM_TIMER, PM_REMOVE)) {}
|
||||
}
|
||||
if ((hGetWordLib != 0)&&(hGetWordLib != (HINSTANCE)(-1))) {
|
||||
FreeLibrary(hGetWordLib);
|
||||
}
|
||||
Thtypes_End();
|
||||
break;
|
||||
|
||||
case DLL_THREAD_ATTACH:
|
||||
break;
|
||||
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Returns TRUE on success, FALSE on failure */
|
||||
return TRUE;
|
||||
}
|
14
src/mouseover_win32/TextOutSpy.h
Normal file
14
src/mouseover_win32/TextOutSpy.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef _TextOutSpy_H_
|
||||
#define _TextOutSpy_H_
|
||||
|
||||
#if BUILDING_DLL
|
||||
# define DLLIMPORT __declspec (dllexport)
|
||||
#else /* Not BUILDING_DLL */
|
||||
# define DLLIMPORT __declspec (dllimport)
|
||||
#endif /* Not BUILDING_DLL */
|
||||
|
||||
|
||||
DLLIMPORT void ActivateTextOutSpying (int Activate);
|
||||
|
||||
|
||||
#endif /* _TextOutSpy_H_ */
|
24
src/mouseover_win32/ThTypes.c
Normal file
24
src/mouseover_win32/ThTypes.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
#include "ThTypes.h"
|
||||
|
||||
HANDLE MMFHandle = 0;
|
||||
TGlobalDLLData *GlobalData = NULL;
|
||||
|
||||
void ThTypes_Init()
|
||||
{
|
||||
if (!MMFHandle)
|
||||
MMFHandle = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(TGlobalDLLData), "GoldenDictTextOutHookSharedMem");
|
||||
if (!GlobalData)
|
||||
GlobalData = MapViewOfFile(MMFHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
||||
}
|
||||
|
||||
void Thtypes_End()
|
||||
{
|
||||
if (GlobalData) {
|
||||
UnmapViewOfFile(GlobalData);
|
||||
GlobalData = NULL;
|
||||
}
|
||||
if (MMFHandle) {
|
||||
CloseHandle(MMFHandle);
|
||||
MMFHandle = 0;
|
||||
}
|
||||
}
|
39
src/mouseover_win32/ThTypes.h
Normal file
39
src/mouseover_win32/ThTypes.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
#ifndef _ThTypes_H_
|
||||
#define _ThTypes_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct TCurrentMode {
|
||||
HWND WND;
|
||||
POINT Pt;
|
||||
size_t WordLen;
|
||||
char MatchedWord[256];
|
||||
int BeginPos;
|
||||
} TCurrentMode;
|
||||
|
||||
typedef struct TGlobalDLLData {
|
||||
HWND ServerWND;
|
||||
HHOOK g_hHookMouse;
|
||||
UINT_PTR TimerID;
|
||||
HWND LastWND;
|
||||
POINT LastPt;
|
||||
TCurrentMode CurMod;
|
||||
char LibName[256];
|
||||
} TGlobalDLLData;
|
||||
|
||||
extern TGlobalDLLData *GlobalData;
|
||||
|
||||
|
||||
void ThTypes_Init();
|
||||
void Thtypes_End();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
7
src/mouseover_win32/readme.txt
Normal file
7
src/mouseover_win32/readme.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
These files were taken straight from StarDict 3.0.1. They didn't seem to
|
||||
bear any copyright notices, and as such, no new notices were added.
|
||||
The only changes made were renaming some global ids to make sure that running
|
||||
StarDict and GoldenDict simultaneously wouldn't interfere with each other.
|
||||
|
||||
The Makefile is made for mingw32 cross-compilation, and is completely separate
|
||||
from the main program.
|
Loading…
Reference in a new issue