Codejie's C++ Space

Using C++

LingosHook:IE来了~


    ‘店大欺人’这句话放在哪里都适用,浏览器市场亦是如此。IE当道,其它浏览器如若显示跟其不一致,往往会被打上‘不标准’的烙记,也迫使HTML使用者不得不用IE来检测是否符合‘标准’。真的很杯具,且不说IE自己定义了大量‘不标准’的Tag,谁又能确定IE对标准的执行本身是否‘标准’呢?平常我用Google Chrome,但写Blog时还是需要切换到IE上,谁叫这些控件都是依据IE作为‘标准’的。这也是没有办法的事情,毕竟IE曾经太强大了,致使现在依然余威不散啊。。。
    扯远了,我就来发发牢骚了,实际想说的是,为了让LingosHook的HTML展示更接近Lingoes的显示,这几天不得不在尝试让LingosHook也支持适用IE来显示结果,谁叫Lingoes用IE呢。。
    下面轻松一下,做个GAME--看图找不同。。





    是的,还是第二张图的显示比较好看~第一张图是使用wxWidget自带的wxHtmlWin控件显示的,而第二张则是通过Activx调用IE控件显示的。

    wxWidget下封装IE控件,能直接找到的就是wxActivex (这个就是常说的wxIE)了,虽然控件本身老是老了点,2005年发布的,但依然很好用--当然了,为了在wxWidget2.8下编译,为了支持中文显示,还是需要做一些修改的。
    如何在wxWidget2.8下编译,这个问题改改并不难,就不说了,就单说说这个中文显示问题吧。wxActivex使用LoadString()来显示内存中的字符串,实现如下:

bool  wxIEHtmlWin::LoadString(const wxString& html)
{
    
char *data = NULL;
    size_t len 
= html.length();
#ifdef UNICODE
    len 
*= 2;
#endif
    data 
= (char *) malloc(len);
    memcpy(data, html.c_str(), len);

    
return LoadStream(new wxOwnedMemInputStream(data, len));
}
;

    如果变量html中的字符都是char类型也没啥问题,memcpy一下就OK,但如果是wchar_t宽字节类型,就不能单单调用一下memcpy了,这个涉及到宽字节到多字节(WC->MB)的问题了。于是照着葫芦画瓢,添加了如下代码,这个问题就过了。。。。

class IStreamFromWString : public IStream
{
private:
    DECLARE_OLE_UNKNOWN(IStreamFromWString);

public:
    IStreamFromWString(
const wxString& str)
        : _buffer(NULL), _sz(
0), _pos(0)
    
{
        InitBuffer(str);
    }

    
virtual ~IStreamFromWString()
    
{
        FreeBuffer();
    }

    
// ISequentialStream
    HRESULT STDMETHODCALLTYPE Read(void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbRead)
    
{
        
if(_pos >= _sz)
        
{
            (
*pcbRead) = 0;
            
return S_OK;
        }


        
if((_pos + cb) < _sz)
        
{
            memcpy((
void*)pv, (void*)(_buffer + _pos), cb);
            (
*pcbRead) = cb;
            _pos 
+= cb;
            
return S_OK;
        }

        
else
        
{
            memcpy((
void*)pv, (void*)(_buffer + _pos), _sz - _pos);
            (
*pcbRead) = (_sz - _pos);
            _pos 
= _sz;
            
return S_OK;
        }

    }
;

    
// IStream
    HRESULT STDMETHODCALLTYPE Write(const void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbWritten) {return E_NOTIMPL;}
    HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER __RPC_FAR 
*plibNewPosition) {return E_NOTIMPL;}
    HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER libNewSize) 
{return E_NOTIMPL;}
    HRESULT STDMETHODCALLTYPE CopyTo(IStream __RPC_FAR 
*pstm, ULARGE_INTEGER cb, ULARGE_INTEGER __RPC_FAR *pcbRead, ULARGE_INTEGER __RPC_FAR *pcbWritten) {return E_NOTIMPL;}
    HRESULT STDMETHODCALLTYPE Commit(DWORD grfCommitFlags) 
{return E_NOTIMPL;}
    HRESULT STDMETHODCALLTYPE Revert(
void{return E_NOTIMPL;}
    HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) 
{return E_NOTIMPL;}
    HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) 
{return E_NOTIMPL;}
    HRESULT STDMETHODCALLTYPE Stat(STATSTG __RPC_FAR 
*pstatstg, DWORD grfStatFlag) {return E_NOTIMPL;}
    HRESULT STDMETHODCALLTYPE Clone(IStream __RPC_FAR 
*__RPC_FAR *ppstm) {return E_NOTIMPL;}
private:
    
void InitBuffer(const wxString& str)
    
{
        _sz 
= wxConvUTF8.FromWChar(NULL, 0, str.c_str(), str.size());
        _buffer 
= new char[_sz];
        wxConvUTF8.FromWChar(_buffer, _sz, str.c_str(), str.size());
        
        
//int codepage = 54936;//CP_UTF8;

        
//int sz = WideCharToMultiByte(codepage, 0, html.c_str(), html.size(), NULL, 0, NULL, NULL);
        
//if(sz == -1)
        
//    return -1;
        
//char* buf = new char[sz + 1];
        
//sz = WideCharToMultiByte(codepage, 0, html.c_str(), html.size(), buf, sz, NULL, NULL);
    }

    
void FreeBuffer()
    
{
        
if(_buffer != NULL)
            delete [] _buffer;
    }

private:
    
char * _buffer;
    size_t _sz;
    size_t _pos;
}
;

DEFINE_OLE_TABLE(IStreamFromWString)
    OLE_IINTERFACE(IUnknown)
    OLE_IINTERFACE(ISequentialStream)
    OLE_IINTERFACE(IStream)
END_OLE_TABLE;

bool wxIEHtmlWin::LoadWString(const wxString& html)
{
    IDispatch 
*pDisp = NULL;
    HRESULT hret 
= m_webBrowser->get_Document(&pDisp);
    
if (!pDisp)
        
return false;
    wxAutoOleInterface
<IDispatch> disp(pDisp);
    
// get IPersistStreamInit
    wxAutoOleInterface<IPersistStreamInit> pPersistStreamInit(IID_IPersistStreamInit, disp);

    
if (pPersistStreamInit.Ok())
    
{
        HRESULT hr 
= pPersistStreamInit->InitNew();

        
if (SUCCEEDED(hr))
        
{
            CComPtr
<IStream> is(new IStreamFromWString(html));
            hr 
= pPersistStreamInit->Load(is);
        }


        
return SUCCEEDED(hr);
    }

    
else
        
return false;
}

    可以看出,也没做什么,就是调用一下类似WideCharToMultiByte()就OK了。编码LingosHook的过程中,最让我感慨的事就是--原来char到wchar_t、string到wstring是如此的繁琐,陷阱重重。。。唉,一切都是charset引起的,要是当年ASCII设计者们有点‘国际主义’精神,直接用定义出Unicode多好,哪有中间这么多charset的问题。。。(发牢骚而已,谁也不是先知。。。)

    另外定义了个宏__LH_USE_IE__,用于编译期切换所使用的控件,不喜欢IE的,可以继续使用wxHtmlWin,嘿嘿,要留好‘革命的火种’啊。。。

#ifdef __LH_USE_WXIE__

#include 
"IEHtmlWin.h"

class CLHHtmlWindow : public wxIEHtmlWin
{
public:
    CLHHtmlWindow(wxWindow 
* parent, wxWindowID id = -1const wxPoint& pos = wxDefaultPosition,
        
const wxSize& size = wxDefaultSize, long style = 0const wxString& name = wxPanelNameStr)
    : wxIEHtmlWin(parent, id, pos, size, style, name)
    
{
    }

    
virtual ~CLHHtmlWindow() {}

public:
    
void LoadBlankPage() { wxIEHtmlWin::LoadWString(wxT("<HTML></HTML>")); }
    
bool LoadString(const wxString& html) return wxIEHtmlWin::LoadWString(html); }
    
void SetCharset(const wxString& charset) { wxIEHtmlWin::SetCharset(charset); }
}
;

#else

#include 
<wx/html/htmlwin.h>

class CLHHtmlWindow : public wxHtmlWindow
{
public:
    CLHHtmlWindow(wxWindow 
* parent, wxWindowID id = -1const wxPoint& pos = wxDefaultPosition,
        
const wxSize& size = wxDefaultSize, long style = 0const wxString& name = wxPanelNameStr)
    : wxHtmlWindow(parent, id, pos, size, style, name)
    
{
    }

    
virtual ~CLHHtmlWindow() {}

public:
    
void LoadBlankPage() { wxHtmlWindow::SetPage(wxT("<HTML></HTML>")); }
    
bool LoadString(const wxString& html)
    

        wxString str 
= html;
        str.Replace(_(
"file:///"), _(""), true);
        
return wxHtmlWindow::SetPage(str); 
    }

    
void SetCharset(const wxString& charset) {}
}
;

#endif


 

posted on 2010-05-21 17:39 codejie 阅读(927) 评论(4)  编辑 收藏 引用 所属分类: C++轮子精神LingosHook

评论

# re: LingosHook:IE来了~ 2010-05-22 11:57 faerl

http://aarddict.org/
http://code.google.com/p/aarddict/
Aard Dictionary
我希望把LingosHook开发成一个支持自定义词典功能的软件,我不会编程只能提个建议了。Aard Dictionary这个词典软件不错,使用Python脚本语言写的,如果可以借鉴这个开源软件整合到LingosHook,在加上屏幕取词,ocr取词就完美了。最近学英语,看美剧,用lingoes词典,有许多生词要巩固,无意中发现了你的软件,对我很有用,持续关注你。lingoes很不方便,但是它的词典好,常用朗文当代英语词典,柯林斯高阶英语词典,柯林斯高阶英语词典,这样可以更明白理解一个单词的含义  回复  更多评论   

# re: LingosHook:IE来了~[未登录] 2010-05-22 16:13 codejie

@faerl
感谢使用~
这个‘支持自定义词典’的需求有些难度的,不同的词典有着不同的查询或者显示方式;LingosHook是通过抓取Lingoes显示窗口中的HTML数据实现其词典功能的,如果另有词典也是通过这种方式显示结果的,那么也许改改底层Hook部分代码还有可能支持,否则整个机制都需要定制的了。所以,不好意思啊,至少我目前无法实现这个需求。  回复  更多评论   

# re: LingosHook:IE来了~ 2010-07-30 22:43 ari

wxIE有个灰边显示和3d border,以及滚动条显示。
但这个应该是可以去掉的。
http://www.cppblog.com/jerrychan/archive/2009/02/19/69928.html

但我一直没实验成功。
你可以试试看看。
如成功了,看给我邮件说一下。manari@163.com  回复  更多评论   


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


公告

Using C++

导航

统计

留言簿(73)

随笔分类(513)

积分与排名

最新评论

阅读排行榜

评论排行榜