mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-24 16:54:08 +00:00
154 lines
4.4 KiB
C
154 lines
4.4 KiB
C
#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;
|
|
}
|