前天和昨天发烧,晚上晕的根本就看不清屏幕,所以今天才写好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
6class LingosHookFrame;
7class CConfigData;
8
9class CDllHookObject
10{
11public:
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);
19private:
20 HINSTANCE _hDll;
21 UINT _nMsgID;
22};
23
24class CHotkeyObject
25{
26public:
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);
36protected:
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);
43private:
44 HWND _hwndFrame;
45 HWND _hwndLgs;
46 int _id;
47 UINT _nMsgID;
48};
49
50
51class CHookObject
52{
53private:
54 enum HookStatus { HS_INIT = 0, HS_HOOK, HS_UNHOOK, HS_UNHOOK_USER };
55public:
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);
65protected:
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();
72private:
73 void Final();
74 int CreateCheckThread();
75 void ClearCheckThread();
76private:
77 LingosHookFrame* _objFrame;
78
79 bool _bAutoHook;
80 static int _iIfLanguage;
81 bool _bOpenHotkey;
82 UINT _nControlKey;
83 UINT _nHotKey;
84private:
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;
93private:
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
14typedef BOOL (*CreateHookThreadPtr)(HWND, LPCTSTR, LPCTSTR, UINT*);
15typedef BOOL (*CreateHookThreadByHWNDPtr)(HWND, HWND, UINT*);
16typedef BOOL (*RemoveHookThreadPtr)(void);
17
18
19CDllHookObject::CDllHookObject()
20: _hDll(NULL)
21, _nMsgID(0)
22{
23}
24
25CDllHookObject::~CDllHookObject()
26{
27 Unhook();
28}
29
30int 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
63int 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/**//////////////////////////////////////////////////////////118int CHotkeyObject::_wincount = 0;
119
120CHotkeyObject::CHotkeyObject()
121: _hwndFrame(NULL)
122, _hwndLgs(NULL)
123, _id(0)
124, _nMsgID(0)
125{
126}
127
128CHotkeyObject::~CHotkeyObject()
129{
130 Unhook();
131}
132
133int 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
154void 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
170int 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
185BOOL 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
197BOOL 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
254int 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
273int CHookObject::_iIfLanguage = 0;
274UINT CHookObject::_nCheckMsgID = 0;
275HWND CHookObject::_hwndFrame = NULL;
276CHookObject::HookStatus CHookObject::_eHookStatus = CHookObject::HS_INIT;
277HANDLE CHookObject::_hCheckThread = NULL;
278HANDLE CHookObject::_hEvent[3] = { NULL, NULL, NULL };
279
280CHookObject::CHookObject(LingosHookFrame *frame)
281: _objFrame(frame)
282{
283}
284
285CHookObject::~CHookObject()
286{
287 Final();
288}
289
290int 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
320void CHookObject::Final()
321{
322 ClearCheckThread();
323 Unhook();
324}
325
326int 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
345DWORD 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
414int 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
450void CHookObject::ClearCheckThread()
451{
452 if(_hEvent[0] != NULL)
453 ::SetEvent(_hEvent[0]);
454
455 ::Sleep(200);
456}
457
458int 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
522int 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
549int 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
564int 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
581int 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
596void CHookObject::ShowInfo(const wxString& info)
597{
598 if(_objFrame != NULL)
599 _objFrame->ShowHint(info);
600}