Codejie's C++ Space

Using C++

LingosHook:Lingoes生词本第三版


    前天和昨天发烧,晚上晕的根本就看不清屏幕,所以今天才写好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, 0L0L, 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}


 

posted on 2010-03-10 23:58 codejie 阅读(2826) 评论(0)  编辑 收藏 引用 所属分类: C++轮子精神LingosHook


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


公告

Using C++

导航

统计

留言簿(73)

随笔分类(513)

积分与排名

最新评论

阅读排行榜

评论排行榜