前天和昨天发烧,晚上晕的根本就看不清屏幕,所以今天才写好LingosHook的第三版,上传,可以下载了。。。
这个版本只做了一个改动--支持自动Hook Lingoes了,不用每次启动点击Hook按钮了。
下面是Setting界面的截图。

如上图所示,增加了一个‘Auto Hook’的checkbox,默认选中,此配置开启后,LingosHook自动检测Lingoes进程,如果发现,就自动Hook。此状态下,依然可以使用点击‘Hook’按钮,人为选择是否Hook。
此次修改使得Hook不在直接检测Lingoes进程,而是发消息给LingosHook,通过消息驱动来检测,这样如果Lingoes进程不存在时,也不会返回错误,而是Hook动作失败,Hook按钮无法按下。
下面是此次HookObject的代码,包括了HookDllObject和HotkeyObject,这样以后如果还要添加什么Hook方式,都可以放在这里,由HookObject统一管理。有兴趣的清review 。
1
#ifndef __HOOKOBJECT_H__
2
#define __HOOKOBJECT_H__
3
4
#include "wx/wx.h"
5
6
class LingosHookFrame;
7
class CConfigData;
8
9
class CDllHookObject
10

{
11
public:
12
CDllHookObject();
13
virtual ~CDllHookObject();
14
15
int Hook(HWND frame, HWND lgs, UINT& msgid);
16
int Unhook();
17
18
// int MessageProc(WXUINT msg, WXWPARAM wparam, WXLPARAM lparam);
19
private:
20
HINSTANCE _hDll;
21
UINT _nMsgID;
22
};
23
24
class CHotkeyObject
25

{
26
public:
27
CHotkeyObject();
28
virtual ~CHotkeyObject();
29
30
int Hook(HWND frame, HWND lgs, UINT mod, UINT key, UINT& msgid);
31
void Unhook();
32
33
//int MessageProc(WXUINT msg, WXWPARAM wparam, WXLPARAM lparam);
34
35
int GetResult(WXWPARAM wparam, WXLPARAM lparam);
36
protected:
37
int GetIEDocResult(HWND hwnd);
38
39
static int _wincount;
40
static BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lparam);
41
42
int SendData(const BSTR& str);
43
private:
44
HWND _hwndFrame;
45
HWND _hwndLgs;
46
int _id;
47
UINT _nMsgID;
48
};
49
50
51
class CHookObject
52

{
53
private:
54
enum HookStatus
{ HS_INIT = 0, HS_HOOK, HS_UNHOOK, HS_UNHOOK_USER };
55
public:
56
CHookObject(LingosHookFrame* frame);
57
virtual ~CHookObject();
58
59
int Init(const CConfigData& conf);
60
61
int SetHook();
62
int SetUnhook();
63
64
int MessageProc(WXUINT msg, WXWPARAM wparam, WXLPARAM lparam);
65
protected:
66
int Hook(HWND hwnd);
67
int Unhook();
68
void ShowInfo(const wxString& info);
69
70
static DWORD WINAPI ThreadProc(LPVOID param);
71
static int CheckLingoesStatus();
72
private:
73
void Final();
74
int CreateCheckThread();
75
void ClearCheckThread();
76
private:
77
LingosHookFrame* _objFrame;
78
79
bool _bAutoHook;
80
static int _iIfLanguage;
81
bool _bOpenHotkey;
82
UINT _nControlKey;
83
UINT _nHotKey;
84
private:
85
static HookStatus _eHookStatus;
86
static HANDLE _hEvent[3];//exit, pause and continue;
87
static HANDLE _hCheckThread;
88
static HWND _hwndFrame;
89
static UINT _nCheckMsgID;
90
91
UINT _nHookMsgID;
92
UINT _nHotkeyMsgID;
93
private:
94
CDllHookObject _objHook;
95
CHotkeyObject _objHotkey;
96
};
97
98
99
#endif
100
1
#include <mshtml.h>
2
#include <atlbase.h>
3
#include <oleacc.h>
4
#include <tchar.h>
5
#include <comutil.h>
6
7
#include "../LingosHook.h"
8
9
#include "LingosHookApp.h"
10
#include "ConfigData.h"
11
#include "HookObject.h"
12
13
14
typedef BOOL (*CreateHookThreadPtr)(HWND, LPCTSTR, LPCTSTR, UINT*);
15
typedef BOOL (*CreateHookThreadByHWNDPtr)(HWND, HWND, UINT*);
16
typedef BOOL (*RemoveHookThreadPtr)(void);
17
18
19
CDllHookObject::CDllHookObject()
20
: _hDll(NULL)
21
, _nMsgID(0)
22

{
23
}
24
25
CDllHookObject::~CDllHookObject()
26

{
27
Unhook();
28
}
29
30
int CDllHookObject::Hook(HWND frame, HWND lgs, UINT& msgid)
31

{
32
if(frame == NULL || lgs == NULL)
33
return -1;
34
35
_hDll = ::LoadLibrary(_T("LingosHook.dll"));
36
if(_hDll != NULL)
37
{
38
CreateHookThreadByHWNDPtr pch = (CreateHookThreadByHWNDPtr)GetProcAddress(_hDll, "CreateHookThreadByHWND");
39
if(pch != NULL)
40
{
41
if(pch(frame, lgs, &msgid) != TRUE)
42
{
43
wxLogDebug(_("call CreateHookThread() failed."));
44
::FreeLibrary(_hDll);
45
return -1;
46
}
47
}
48
else
49
{
50
wxLogDebug(_("Get CreateHookThread address failed."));
51
::FreeLibrary(_hDll);
52
return -1;
53
}
54
}
55
else
56
{
57
wxLogDebug(_("Load LingosHook dll failed."));
58
return -1;
59
}
60
return 0;
61
}
62
63
int CDllHookObject::Unhook()
64

{
65
if(_hDll != NULL)
66
{
67
RemoveHookThreadPtr prh = (RemoveHookThreadPtr)GetProcAddress(_hDll, "RemoveHookThread");
68
if(prh != NULL)
69
{
70
if(prh() != TRUE)
71
{
72
wxLogDebug(_("call RemoveHookThread() failed."));
73
return -1;
74
}
75
}
76
else
77
{
78
wxLogDebug(_("Get RemoveHookThread address failed."));
79
}
80
::FreeLibrary(_hDll);
81
_hDll = NULL;
82
}
83
return 0;
84
}
85
86
//int CDllHookObject::MessageProc(WXUINT msg, WXWPARAM wparam, WXLPARAM lparam)
87
//{
88
// if(msg == _nMsgID)
89
// {
90
// const struct _HookData_t* hd = (reinterpret_cast<const struct _HookData_t*>(lparam));
91
// wxString str;
92
// if(hd != NULL && hd->data != NULL)
93
// {
94
// str.append(hd->data, hd->size);
95
// }
96
//
97
// if(wparam == HKT_RESULT_TEXT)
98
// {
99
// wxLogDebug(_T("get RESULT_TEXT message."));
100
//
101
// if(_objFrame != NULL)
102
// _objFrame->HookTextProc(str);
103
// }
104
// else if(wparam == HKT_RESULT_HTML)
105
// {
106
// wxLogDebug(_T("get RESULT_HTLM message."));
107
// if(_objFrame != NULL)
108
// _objFrame->HookHTMLProc(str);
109
// }
110
// else
111
// {
112
// wxLogDebug(_T("get UNKNOWN message."));
113
// }
114
// }
115
// return 0;
116
//}
117
/**//////////////////////////////////////////////////////////118
int CHotkeyObject::_wincount = 0;
119
120
CHotkeyObject::CHotkeyObject()
121
: _hwndFrame(NULL)
122
, _hwndLgs(NULL)
123
, _id(0)
124
, _nMsgID(0)
125

{
126
}
127
128
CHotkeyObject::~CHotkeyObject()
129

{
130
Unhook();
131
}
132
133
int CHotkeyObject::Hook(HWND frame, HWND lgs, UINT mod, UINT key, UINT& msgid)
134

{
135
_hwndFrame = frame;
136
137
_nMsgID = ::RegisterWindowMessage(_T("JIE_HOOKOBJECT_HOTKEY_MSG_DEF"));
138
139
if(_hwndFrame == NULL || _nMsgID == 0)
140
return -1;
141
142
_id = ::GlobalAddAtom(_T("LingosHook"));
143
if(_id == 0)
144
return -1;
145
if(::RegisterHotKey(frame, _id, mod, key) != TRUE)
146
return -1;
147
148
_hwndLgs = lgs;
149
msgid = _nMsgID;
150
151
return 0;
152
}
153
154
void CHotkeyObject::Unhook()
155

{
156
if(_id != 0)
157
{
158
::UnregisterHotKey(_hwndFrame, _id);
159
_id = 0;
160
}
161
}
162
163
//int CHotkeyObject::MessageProc(WXUINT msg, WXWPARAM wparam, WXLPARAM lparam)
164
//{
165
// GetResult(wparam, lparam);
166
//
167
// return 0;
168
//}
169
170
int CHotkeyObject::GetResult(WXWPARAM wparam, WXLPARAM lparam)
171

{
172
//FindWindows
173
// HWND hwnd = ::FindWindow(_T("Afx:400000:0"), _T("Lingoes"));
174
if(_hwndLgs == NULL)
175
return -1;
176
if(::IsWindowVisible(_hwndLgs) == FALSE)
177
return -1;
178
179
if(GetIEDocResult(_hwndLgs) != TRUE)
180
return -1;
181
182
return 0;
183
}
184
185
BOOL CALLBACK CHotkeyObject::EnumChildProc(HWND hwnd, LPARAM lparam)
186

{
187
++ _wincount;
188
189
if(_wincount == 0x24)
190
{
191
*(HWND*)lparam = hwnd;
192
return FALSE;
193
}
194
return TRUE;
195
}
196
197
BOOL CHotkeyObject::GetIEDocResult(HWND hwnd)
198

{
199
::CoInitialize(NULL);
200
201
HINSTANCE hinst = ::LoadLibrary( _T("OLEACC.DLL") ); // Explicitly load MSAA so we know if it's installed
202
if(hinst != NULL)
203
{
204
if(hwnd != NULL)
205
{
206
HWND hc = NULL;
207
_wincount = 0;
208
::EnumChildWindows(hwnd, EnumChildProc, (LPARAM)&hc);
209
if(hc != NULL)
210
{
211
CComPtr<IHTMLDocument2> cpDoc;
212
UINT msg = ::RegisterWindowMessage(_T("WM_HTML_GETOBJECT"));
213
LRESULT res = 0;
214
::SendMessageTimeout(hc, msg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (PDWORD)&res);
215
LPFNOBJECTFROMLRESULT pfres = (LPFNOBJECTFROMLRESULT)::GetProcAddress(hinst, "ObjectFromLresult");
216
if(pfres != NULL)
217
{
218
HRESULT hr = (*pfres)(res, IID_IHTMLDocument, 0, (void**)&cpDoc);
219
if(SUCCEEDED(hr))
220
{
221
IDispatch* pdisp = NULL;
222
cpDoc->get_Script(&pdisp);
223
IHTMLWindow2* pwin = NULL;
224
pdisp->QueryInterface(IID_IHTMLWindow2, (void**)&pwin);
225
IHTMLDocument2* pdoc = NULL;
226
pwin->get_document(&pdoc);
227
IHTMLElement* pbody = NULL;
228
pdoc->get_body(&pbody);
229
230
BSTR html;
231
pbody->get_innerHTML(&html);
232
SendData(html);
233
::SysFreeString(html);
234
235
//BSTR text;
236
//pbody->get_innerText(&text);
237
//_objFrame->HookTextProc(text);
238
//::SysFreeString(text);
239
//
240
pbody->Release();
241
pdoc->Release();
242
pwin->Release();
243
pdisp->Release();
244
}
245
}
246
}
247
}
248
::FreeLibrary(hinst);
249
}
250
::CoUninitialize();
251
return TRUE;
252
}
253
254
int CHotkeyObject::SendData(const BSTR& str)
255

{
256
size_t size = ::SysStringLen(str);
257
struct _HookData_t* hd = new struct _HookData_t;
258
259
hd->size = size;
260
hd->data = new wchar_t[size + 1];
261
wcscpy(hd->data, str);
262
263
::SendMessage(_hwndFrame, _nMsgID, (WPARAM)0, (LPARAM)hd);
264
265
delete [] hd->data;
266
delete hd;
267
268
return 0;
269
}
270
271
/**///////////////////////////////////////////////////////////272
273
int CHookObject::_iIfLanguage = 0;
274
UINT CHookObject::_nCheckMsgID = 0;
275
HWND CHookObject::_hwndFrame = NULL;
276
CHookObject::HookStatus CHookObject::_eHookStatus = CHookObject::HS_INIT;
277
HANDLE CHookObject::_hCheckThread = NULL;
278
HANDLE CHookObject::_hEvent[3] =
{ NULL, NULL, NULL };
279
280
CHookObject::CHookObject(LingosHookFrame *frame)
281
: _objFrame(frame)
282

{
283
}
284
285
CHookObject::~CHookObject()
286

{
287
Final();
288
}
289
290
int CHookObject::Init(const CConfigData &conf)
291

{
292
_bAutoHook = conf.m_iAutoHook == 1 ? true : false;
293
_iIfLanguage = conf.m_iIfLanguage;
294
_bOpenHotkey = conf.m_iOpenHotkey == 1 ? true : false;
295
if(_bOpenHotkey)
296
{
297
_nControlKey = conf.GetContolKey();
298
_nHotKey = conf.GetHotKey();
299
}
300
301
if(_objFrame == NULL)
302
return -1;
303
304
_hwndFrame = (HWND)_objFrame->GetHWND();
305
306
_nCheckMsgID = ::RegisterWindowMessage(_T("JIE_HOOKOBJECT_CHECKTHREAD_MSG_DEF"));
307
if(_nCheckMsgID == 0)
308
return -1;
309
310
if(CreateCheckThread() != 0)
311
return -1;
312
313
if(_bAutoHook != true)
314
{
315
::SetEvent(_hEvent[1]);
316
}
317
return 0;
318
}
319
320
void CHookObject::Final()
321

{
322
ClearCheckThread();
323
Unhook();
324
}
325
326
int CHookObject::CreateCheckThread()
327

{
328
_hEvent[0] = ::CreateEvent(NULL, FALSE, FALSE, NULL);
329
if(_hEvent[0] == NULL)
330
return -1;
331
_hEvent[1] = ::CreateEvent(NULL, FALSE, FALSE, NULL);
332
if(_hEvent[1] == NULL)
333
return -1;
334
_hEvent[2] = ::CreateEvent(NULL, FALSE, FALSE, NULL);
335
if(_hEvent[2] == NULL)
336
return -1;
337
338
DWORD id = 0;
339
_hCheckThread = ::CreateThread(NULL, 0, ThreadProc, NULL, 0, &id);
340
if(_hCheckThread == NULL)
341
return -1;
342
return 0;
343
}
344
345
DWORD CHookObject::ThreadProc(LPVOID param)
346

{
347
bool run = true;
348
while(run)
349
{
350
DWORD ret = ::WaitForMultipleObjects(3, _hEvent, FALSE, 500);
351
switch(ret)
352
{
353
case WAIT_OBJECT_0 + 0://exit
354
run = false;
355
break;
356
case WAIT_OBJECT_0 + 1://pause
357
{
358
bool r = true;
359
while(r)
360
{
361
ret = ::WaitForMultipleObjects(3, _hEvent, FALSE, INFINITE);
362
switch(ret)
363
{
364
case WAIT_OBJECT_0 + 0://exit
365
r = false;
366
run = false;
367
break;
368
case WAIT_OBJECT_0 + 1://pause
369
break;
370
case WAIT_OBJECT_0 + 2://cont
371
r = false;
372
break;
373
default:
374
::ExitThread(1);
375
}
376
}
377
}
378
break;
379
case WAIT_OBJECT_0 + 2://continue
380
break;
381
case WAIT_TIMEOUT:
382
{
383
CheckLingoesStatus();
384
}
385
break;
386
default:
387
::ExitThread(1);
388
}
389
}
390
391
if(_hEvent[0] != NULL)
392
{
393
::CloseHandle(_hEvent[0]);
394
_hEvent[0] = NULL;
395
}
396
if(_hEvent[1] != NULL)
397
{
398
::CloseHandle(_hEvent[1]);
399
_hEvent[1] = NULL;
400
}
401
402
if(_hEvent[2] != NULL)
403
{
404
::CloseHandle(_hEvent[2]);
405
_hEvent[2] = NULL;
406
}
407
408
::CloseHandle(_hCheckThread);
409
_hCheckThread = NULL;
410
411
return 0;
412
}
413
414
int CHookObject::CheckLingoesStatus()
415

{
416
HWND hwnd = NULL;
417
if(_iIfLanguage == 0)
418
{
419
hwnd = ::FindWindow(_T("Afx:400000:0"), _T("Lingoes"));
420
if(hwnd == NULL)
421
hwnd = ::FindWindow(_T("Afx:400000:0"), _T("Lingoes 灵格斯"));
422
}
423
else if(_iIfLanguage == 1)
424
{
425
hwnd = ::FindWindow(_T("Afx:400000:0"), _T("Lingoes"));
426
}
427
else
428
{
429
hwnd = ::FindWindow(_T("Afx:400000:0"), _T("Lingoes 灵格斯"));
430
}
431
432
if(hwnd == NULL)
433
{
434
if(_eHookStatus == HS_HOOK)
435
{
436
::SendMessage(_hwndFrame, _nCheckMsgID, HS_UNHOOK, (LPARAM)(hwnd));
437
}
438
}
439
else
440
{
441
if(_eHookStatus == HS_UNHOOK || _eHookStatus == HS_INIT)
442
{
443
::SendMessage(_hwndFrame, _nCheckMsgID, HS_HOOK, (LPARAM)(hwnd));
444
}
445
}
446
447
return 0;
448
}
449
450
void CHookObject::ClearCheckThread()
451

{
452
if(_hEvent[0] != NULL)
453
::SetEvent(_hEvent[0]);
454
455
::Sleep(200);
456
}
457
458
int CHookObject::MessageProc(WXUINT msg, WXWPARAM wparam, WXLPARAM lparam)
459

{
460
if(msg == _nHookMsgID)
461
{
462
const struct _HookData_t* hd = (reinterpret_cast<const struct _HookData_t*>(lparam));
463
wxString str;
464
if(hd != NULL && hd->data != NULL)
465
{
466
str.append(hd->data, hd->size);
467
}
468
469
if(wparam == HKT_RESULT_TEXT)
470
{
471
wxLogDebug(_T("get RESULT_TEXT message."));
472
473
if(_objFrame != NULL)
474
_objFrame->HookTextProc(str);
475
}
476
else if(wparam == HKT_RESULT_HTML)
477
{
478
wxLogDebug(_T("get RESULT_HTLM message."));
479
if(_objFrame != NULL)
480
_objFrame->HookHTMLProc(str);
481
}
482
else
483
{
484
wxLogDebug(_T("get UNKNOWN hook message."));
485
}
486
}
487
else if(msg == _nHotkeyMsgID)
488
{
489
const struct _HookData_t* hd = (reinterpret_cast<const struct _HookData_t*>(lparam));
490
wxString str;
491
if(hd != NULL && hd->data != NULL)
492
{
493
str.append(hd->data, hd->size);
494
}
495
496
if(_objFrame != NULL)
497
_objFrame->HookHTMLProc(str);
498
}
499
else if(msg == WM_HOTKEY)
500
{
501
_objHotkey.GetResult(wparam, lparam);
502
}
503
else if(msg == _nCheckMsgID)
504
{
505
if((HookStatus)(wparam) == HS_HOOK)
506
{
507
Hook((HWND)(lparam));
508
}
509
else if((HookStatus)(wparam) == HS_UNHOOK)
510
{
511
Unhook();
512
}
513
else
514
{
515
wxLogDebug(_T("get UNKNOWN check message."));
516
}
517
}
518
519
return 0;
520
}
521
522
int CHookObject::Hook(HWND hwnd)
523

{
524
if(_objHook.Hook(_hwndFrame, hwnd, _nHookMsgID) != 0)
525
{
526
ShowInfo(_("Hook hook failed."));
527
return -1;
528
}
529
530
if(_bOpenHotkey == true)
531
{
532
if(_objHotkey.Hook(_hwndFrame, hwnd, _nControlKey, _nHotKey, _nHotkeyMsgID) != 0)
533
{
534
ShowInfo(_("Set Hotkey failed."));
535
return -1;
536
}
537
}
538
539
_eHookStatus = HS_HOOK;
540
541
if(_objFrame != NULL)
542
{
543
_objFrame->SetHookButton(true);
544
}
545
546
return 0;
547
}
548
549
int CHookObject::Unhook()
550

{
551
_objHook.Unhook();
552
_objHotkey.Unhook();
553
554
_eHookStatus = HS_UNHOOK;
555
556
if(_objFrame != NULL)
557
{
558
_objFrame->SetHookButton(false);
559
}
560
561
return 0;
562
}
563
564
int CHookObject::SetHook()
565

{
566
if(_eHookStatus == HS_HOOK)
567
return 0;
568
569
if(_bAutoHook == true)
570
{
571
::SetEvent(_hEvent[2]);
572
}
573
else
574
{
575
CheckLingoesStatus();
576
}
577
578
return 0;
579
}
580
581
int CHookObject::SetUnhook()
582

{
583
if(_eHookStatus == HS_UNHOOK)
584
return 0;
585
586
Unhook();
587
588
if(_bAutoHook == true)
589
{
590
::SetEvent(_hEvent[1]);
591
}
592
593
return 0;
594
}
595
596
void CHookObject::ShowInfo(const wxString& info)
597

{
598
if(_objFrame != NULL)
599
_objFrame->ShowHint(info);
600
}