(转)使用C++实现SDK之WebBrowser容器

发布时间:2016-12-7 3:55:06 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"(转)使用C++实现SDK之WebBrowser容器",主要涉及到(转)使用C++实现SDK之WebBrowser容器方面的内容,对于(转)使用C++实现SDK之WebBrowser容器感兴趣的同学可以参考一下。

一.由来          我还记还得当自认为学习完了C++语法后, 兴致勃勃的打开MFC向导,开始所谓"MFC高级自动化编程"时, 我不由喊道: 这他妈的都是些什么乱七八糟的东西啊.诚然,MFC为了方便愚蠢的程序员,的确是让人瞬间高级编程, 可是愚蠢的我们还是会用CString strTest;写出(PWSTR)strTest.GetBuffer() 这种自作聪明的用法,结果就是整个程序好像发了疯.          终于有一天,我大喊一声: 滚蛋吧,MFC!          太阳当空照,上帝对 我笑:  你Y去写个有WebBrowser控件的窗口吧 二.结构           MFC的HTMLDialog 是一个魔盒, 他容易上手,可是却很难深入,究其缘由, 私以为无外乎MFC包装的太好, 不识庐山真面目,只缘身在此山中.  总是以为作为C类型的程序员,喜欢深入原理是职业特性.         于是首先看到有强人写的纯C实现WebBrowser控件,他在这里: http://www.codeproject.com/KB/COM/cwebpage.aspx 这位同志很好的展示了在没有C++的支持下,支持ActiveX是多么痛苦的一件事情...........汗. 在下觉得,撇开C++的类的特性,虚拟特性,重载特性,而去用纯C实现,实在有点过犹不及,当然这种练习修炼内功很好,但是实际应用上显得麻烦.毕竟,ActiveX很好的使用了C++的特性,而不是C的特性.         接着,开始使用纯SDK编写容器. 读者可以搜索csdn中关于SDK实现WebBrowser容器的帖子, 许多人说那是非常繁琐复杂.所谓人云亦云,各位看官不妨跟着我一试,且看到底何如?        WebBrowser容器的实现需要许多接口, 也许正是这吓退了许多人, 实际情况是,许多接口的方法没几个需要实现,大部分只需要直接返回E_NOTIMPL和S_OK, E_FAIL.        让我们命名我们编写的容器叫 WebBrowser (可能名字有点糊涂,但是因为源代码中就是这个名字,所以就不改了,大家只需要注意,这个是一个WebBrowser控件的容器 ),   在实现这个容器后, 我们把他作为一个窗口类的父类,这样 就能实现WebBrowser的页面窗口.       首先一个WB( WebBrowser) 容器需要以下接口:     public IDispatch     public IOleClientSite     public IOleInPlaceSite     public IOleInPlaceFrame        每个接口需要实现的方法分别是:         // IUnknown methods     virtual STDMETHODIMP QueryInterface(REFIID iid,void**ppvObject);     virtual STDMETHODIMP_(ULONG) AddRef();     virtual STDMETHODIMP_(ULONG) Release();     // IDispatch Methods     HRESULT _stdcall GetTypeInfoCount(unsigned int * pctinfo);     HRESULT _stdcall GetTypeInfo(unsigned int iTInfo,LCID lcid,ITypeInfo FAR* FAR* ppTInfo);     HRESULT _stdcall GetIDsOfNames(REFIID riid,OLECHAR FAR* FAR* rgszNames,unsigned int cNames,LCID lcid,DISPID FAR* rgDispId);     HRESULT _stdcall Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS FAR* pDispParams,VARIANT FAR* pVarResult,EXCEPINFO FAR* pExcepInfo,unsigned int FAR* puArgErr);     // IOleClientSite methods     virtual STDMETHODIMP SaveObject();     virtual STDMETHODIMP GetMoniker(DWORD dwA,DWORD dwW,IMoniker**pm);     virtual STDMETHODIMP GetContainer(IOleContainer**pc);     virtual STDMETHODIMP ShowObject();     virtual STDMETHODIMP OnShowWindow(BOOL f);     virtual STDMETHODIMP RequestNewObjectLayout();     // IOleInPlaceSite methods     virtual STDMETHODIMP GetWindow(HWND *p);     virtual STDMETHODIMP ContextSensitiveHelp(BOOL);     virtual STDMETHODIMP CanInPlaceActivate();     virtual STDMETHODIMP OnInPlaceActivate();     virtual STDMETHODIMP OnUIActivate();     virtual STDMETHODIMP GetWindowContext(IOleInPlaceFrame** ppFrame,IOleInPlaceUIWindow **ppDoc,LPRECT r1,LPRECT r2,LPOLEINPLACEFRAMEINFO o);     virtual STDMETHODIMP Scroll(SIZE s);     virtual STDMETHODIMP OnUIDeactivate(int);     virtual STDMETHODIMP OnInPlaceDeactivate();     virtual STDMETHODIMP DiscardUndoState();     virtual STDMETHODIMP DeactivateAndUndo();     virtual STDMETHODIMP OnPosRectChange(LPCRECT);     // IOleInPlaceFrame methods     virtual STDMETHODIMP GetBorder(LPRECT l);     virtual STDMETHODIMP RequestBorderSpace(LPCBORDERWIDTHS);     virtual STDMETHODIMP SetBorderSpace(LPCBORDERWIDTHS w);     virtual STDMETHODIMP SetActiveObject(IOleInPlaceActiveObject*pV,LPCOLESTR s);     virtual STDMETHODIMP InsertMenus(HMENU h,LPOLEMENUGROUPWIDTHS x);     virtual STDMETHODIMP SetMenu(HMENU h,HOLEMENU hO,HWND hw);     virtual STDMETHODIMP RemoveMenus(HMENU h);     virtual STDMETHODIMP SetStatusText(LPCOLESTR t);     virtual STDMETHODIMP EnableModeless(BOOL f);     virtual STDMETHODIMP TranslateAccelerator(LPMSG,WORD);    这里插几句题外话, 我讨厌看文章, 因为萝莉罗嗦也没看到那个爆炸点, 就是你看到他,一下子思路有了头绪, 不再是一头雾水了.可惜,我看到的大部分文章都不是这样, 为了避免这个问题, 我在这里放个屁, 嗯,也算是一个小小的爆破吧.       好,上面已经罗列了需要的接口和接口的方法.         要想实现WB的容器,你必须有这段代码: WebBrowser::WebBrowser() {   //初始化OLE   OleInitialize(0);   //创建IStorage对象,其中_pStorage是WebBrowser的私有变量   StgCreateDocfile(0,STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_CREATE,0,&_pStorage);   //创建IOleObject对象,我们看到,短短的一条语句,已经几乎创建完成了WebBrowser!   //this在这里时表示当前类(即WebBrowser)作为容器,承载_pOleObj这个控件    //这里就是放屁现场了,大家好好看看哈.     OleCreate( CLSID_WebBrowser,IID_IOleObject,OLERENDER_DRAW, 0 , this, _pStorage, (void**)&_pOleObj );   //获得IOleInPlaceObject对象   _pOleObj->QueryInterface(IID_IOleInPlaceObject,(LPVOID*)&_pInPlaceObj); } 上面一段代码已经创建了wb的Ole对象, 接下来,你只需要打开WB,然后打开网页.我们用两个函数实现,他们是OpenWebBrowser() 和 OpenURL( VARIANT* pVarUrl ) OpenWebBrowser: BOOL     WebBrowser::OpenWebBrowser() {     BOOL bRet = FALSE;     // RECTWIDTH 和 RECTHEIGHT 是计算RECT长宽的宏函数     // _rcWebWnd 是WebBrowser的私有RECT成员,就是GetHWND()的大小.     // 下面的语句就是关联两者     // GetHWND()获取容器的框架窗口句柄,就是我们创建的窗口,关于这个函数,下面会单独讲     if( (RECTWIDTH(_rcWebWnd) && RECTHEIGHT(_rcWebWnd)) == 0 )     ::GetClientRect( GetHWND() ,&_rcWebWnd);//设置WebBrowser的大小为窗口的客户区大小.          // _bInPlaced 是WebBrowser的一个私有BOOL成员,初始为false     // 一旦执行了OLEIVERB_INPLACEACTIVATE (就是下面的操作)后,立即设置为true,防止控件被多次放置在容器中     // _GetOleObject()是WebBrowser的一个保护函数成员,他只是简单的返回_pOleObj     // _pOleObj就是WB控件本身. 考虑到WebBrowser是一个基本类,以后必然被其他类继承,所以使用_GetOleObject()来返回_pOleObject,来实现防止_pOleObject本身不被修改的意外.     if( _bInPlaced == false )// Activate In Place     {       _bInPlaced = true;//_bInPlaced must be set as true, before INPLACEACTIVATE, otherwise, once DoVerb, it would return error;       _bExternalPlace = 0;//lParam;       _GetOleObject()->DoVerb(OLEIVERB_INPLACEACTIVATE,0,this,0, GetHWND(),&_rcWebWnd);       _bInPlaced = true;     }     bRet = TRUE; RETURN:     return bRet; } OpenURL(...) BOOL     WebBrowser::OpenURL(VARIANT* pVarUrl) {     BOOL bRet = FALSE;         //GetWebBrowser2 返回IWebBrowser2         //他的实现是这样的:         //if( _pWB2 != NULL )//_pWB2是WebBrowser的私有IWebBrowser2指针     //   return _pWB2;//如果_pWB2已经不是NULL,即已经获取过内容,则直接返回         ////否则使用WB控件对象枚举IWebBrowser2指针     //_pOleObj->QueryInterface(IID_IWebBrowser2,(void**)&_pWB2);         //return _pWB2;     GetWebBrowser2()->Navigate2( pVarUrl,0,0,0,0);//打开网页     bRet = TRUE; RETURN:     return bRet; } 三.细节          前面说过,那几个接口的方法,大部分都是直接返回E_NOTIMPL和S_OK, E_FAIL.,我说大部分,说明必然有些函数需要做一些事情,而且其作用很不小, 请看官别马虎了这段. :)         IDispatch 接口中的 IUnknown 的实现实在是不必多言, 稍微说一下接口枚举: STDMETHODIMP WebBrowser::QueryInterface(REFIID iid,void**ppvObject) {     *ppvObject = 0;     if ( iid == IID_IOleClientSite )         *ppvObject = (IOleClientSite*)this;     if ( iid == IID_IUnknown )         *ppvObject = this;     if ( iid == IID_IDispatch )         *ppvObject = (IDispatch*)this;     if ( _bExternalPlace == false)     {         if ( iid == IID_IOleInPlaceSite )             *ppvObject = (IOleInPlaceSite*)this;         if ( iid == IID_IOleInPlaceFrame )             *ppvObject = (IOleInPlaceFrame*)this;         if ( iid == IID_IOleInPlaceUIWindow )             *ppvObject = (IOleInPlaceUIWindow*)this;     }     if ( iid == DIID_DWebBrowserEvents2 )         *ppvObject = (DWebBrowserEvents2 *)this;     if ( iid == IID_IDocHostUIHandler)         *ppvObject = (IDocHostUIHandler*)this;     if ( *ppvObject )     {         AddRef();         return S_OK;     }     return E_NOINTERFACE; }         下面先说GetWindow //IOleInPlaceSite methods STDMETHODIMP WebBrowser::GetWindow(HWND *p) {     *p = GetHWND();//需要设置p为当前框架的窗口,否则Ole对象不知道框架     return S_OK; }        再来说: CanInPlaceActivate(); Ole对象会询问容器,我能不能插进来(脸红中~)? 得到准许后才能温柔的插入,粗暴是不行的哦! //IOleInPlaceSite methods STDMETHODIMP WebBrowser::CanInPlaceActivate()//If this function return S_FALSE, AX cannot activate in place! {     if ( _bInPlaced )//Does WebBrowser Control already in placed?     {         _bCalledCanInPlace = true;         return S_OK;     }     return S_FALSE; }          WebBrowser::GetWindowContext(...) 获取窗口上下文(内容) STDMETHODIMP WebBrowser::GetWindowContext(IOleInPlaceFrame** ppFrame,IOleInPlaceUIWindow **ppDoc,LPRECT r1,LPRECT r2,LPOLEINPLACEFRAMEINFO o) {     //因为IOleInPlaceFrame接口已经被我们的WebBrowser实现         //所以直接设置为this     *ppFrame = (IOleInPlaceFrame*)this;     AddRef();     *ppDoc = NULL;         // r1, r2设置为框架的大小, 让WB充满整个窗口     ::GetClientRect(  GetHWND() ,&_rcWebWnd );     *r1 = _rcWebWnd;     *r2 = _rcWebWnd;         //我们没有这方面的要求,所以仅仅初始化.     o->cb = sizeof(OLEINPLACEFRAMEINFO);     o->fMDIApp = false;     o->hwndFrame = GetParent( GetHWND() );     o->haccel = 0;     o->cAccelEntries = 0;          return S_OK; }         好了,下面是最后一个需要加料的函数了: IOleInPlaceFrame 接口的方法: GetBorder         注意这个接口正是上面说过的函数GetWindowContent 传递给OleObj对象的 //IOleInPlaceFrame methods| STDMETHODIMP WebBrowser::GetBorder(LPRECT l) {     ::GetClientRect(  GetHWND() ,&_rcWebWnd );     *l = _rcWebWnd;     return S_OK; }         到现在为止,对于容器本身的实现已经全部完成了, 但是细心的读者会问到, GetHWND(void)还没有实现那!?         实际上,WebBrowser 作为一个基本类,不应当实现GetHWND(), 相反地, 他应当作为一个纯虚函数,要求其子类实现.         然后,我做了一个实验, 发现作为纯虚函数, 不能在类的构造函数中被调用, 或者间接调用. 而我们在WebBrowser::WebBrowser()中已经间接调用了GetHWND(),所以会有问题, 于是我们耍赖,把GetHWND(){return NULL;} 这样可以解决虚函数的问题. 四. 所有实现 WebBroser.h class WebBrowser:     public IDispatch,     public IOleClientSite,     public IOleInPlaceSite,     public IOleInPlaceFrame,     public IDocHostUIHandler { public:     WebBrowser();     ~WebBrowser(void);     public:     // IUnknown methods     virtual STDMETHODIMP QueryInterface(REFIID iid,void**ppvObject);     virtual STDMETHODIMP_(ULONG) AddRef();     virtual STDMETHODIMP_(ULONG) Release();     // IDispatch Methods     HRESULT _stdcall GetTypeInfoCount(unsigned int * pctinfo);     HRESULT _stdcall GetTypeInfo(unsigned int iTInfo,LCID lcid,ITypeInfo FAR* FAR* ppTInfo);     HRESULT _stdcall GetIDsOfNames(REFIID riid,OLECHAR FAR* FAR* rgszNames,unsigned int cNames,LCID lcid,DISPID FAR* rgDispId);     HRESULT _stdcall Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS FAR* pDispParams,VARIANT FAR* pVarResult,EXCEPINFO FAR* pExcepInfo,unsigned int FAR* puArgErr);     // IOleClientSite methods     virtual STDMETHODIMP SaveObject();     virtual STDMETHODIMP GetMoniker(DWORD dwA,DWORD dwW,IMoniker**pm);     virtual STDMETHODIMP GetContainer(IOleContainer**pc);     virtual STDMETHODIMP ShowObject();     virtual STDMETHODIMP OnShowWindow(BOOL f);     virtual STDMETHODIMP RequestNewObjectLayout();     // IOleInPlaceSite methods     virtual STDMETHODIMP GetWindow(HWND *p);     virtual STDMETHODIMP ContextSensitiveHelp(BOOL);     virtual STDMETHODIMP CanInPlaceActivate();     virtual STDMETHODIMP OnInPlaceActivate();     virtual STDMETHODIMP OnUIActivate();     virtual STDMETHODIMP GetWindowContext(IOleInPlaceFrame** ppFrame,IOleInPlaceUIWindow **ppDoc,LPRECT r1,LPRECT r2,LPOLEINPLACEFRAMEINFO o);     virtual STDMETHODIMP Scroll(SIZE s);     virtual STDMETHODIMP OnUIDeactivate(int);     virtual STDMETHODIMP OnInPlaceDeactivate();     virtual STDMETHODIMP DiscardUndoState();     virtual STDMETHODIMP DeactivateAndUndo();     virtual STDMETHODIMP OnPosRectChange(LPCRECT);     // IOleInPlaceFrame methods     virtual STDMETHODIMP GetBorder(LPRECT l);     virtual STDMETHODIMP RequestBorderSpace(LPCBORDERWIDTHS);     virtual STDMETHODIMP SetBorderSpace(LPCBORDERWIDTHS w);     virtual STDMETHODIMP SetActiveObject(IOleInPlaceActiveObject*pV,LPCOLESTR s);     virtual STDMETHODIMP InsertMenus(HMENU h,LPOLEMENUGROUPWIDTHS x);     virtual STDMETHODIMP SetMenu(HMENU h,HOLEMENU hO,HWND hw);     virtual STDMETHODIMP RemoveMenus(HMENU h);     virtual STDMETHODIMP SetStatusText(LPCOLESTR t);     virtual STDMETHODIMP EnableModeless(BOOL f);     virtual STDMETHODIMP TranslateAccelerator(LPMSG,WORD); protected:     virtual HWND GetHWND(){return NULL;};//继承的类应该实现这个方法,告诉WebBrowser,到底用哪一个HWND放置WebBrowser     // 内部工具函数 private:     inline IOleObject* _GetOleObject(){return _pOleObj;};     inline IOleInPlaceObject* _GetInPlaceObject(){return _pInPlaceObj;};     //外部方法 public:     IWebBrowser2*      GetWebBrowser2();     IHTMLDocument2*    GetHTMLDocument2();     IHTMLDocument3*    GetHTMLDocument3();     IHTMLWindow2*      GetHTMLWindow2();     IHTMLEventObj*     GetHTMLEventObject();          BOOL       SetWebRect(LPRECT lprc);     BOOL       OpenWebBrowser();         BOOL       OpenURL(VARIANT* pVarUrl);          // 内部数据 protected:     long   _refNum; private:     RECT  _rcWebWnd;     bool  _bInPlaced;     bool  _bExternalPlace;     bool  _bCalledCanInPlace;     bool  _bWebWndInited; private:     //指针     IOleObject*                 _pOleObj;      IOleInPlaceObject*          _pInPlaceObj;     IStorage*                   _pStorage;     IWebBrowser2*               _pWB2;     IHTMLDocument2*             _pHtmlDoc2;     IHTMLDocument3*             _pHtmlDoc3;     IHTMLWindow2*               _pHtmlWnd2;     IHTMLEventObj*              _pHtmlEvent; }; WebBrowser.cpp 注意: 里面有许多讨厌的东西,  是我加的饲料. 解释一下,我个人很喜欢这种错误处理方式. 读者可以简单的认为: (因为实际上我的实现不是那么简单,因为这个再说就有点复杂,所以简单化) NULLTEST_SE( fn , wstr ) ;          如果 fn == 0 , 则显示 wstr, 并且跳转到RETURN HRTEST_SE( fn, wstr);                  如果 fn!=S_OK ,则显示wstr,并且跳转到RETURN 另外,考虑到WebBrowser以后总是作为另外一个类的父类,所以他完全不会因为计数器归零而自删除. #include "WebBrowser.h" /* ================== |   构造和析构   | ================== */ WebBrowser::WebBrowser(void): _refNum(0), //_rcWebWnd(0), _bInPlaced(false), _bExternalPlace(false), _bCalledCanInPlace(false), _bWebWndInited(false), _pOleObj(NULL),  _pInPlaceObj(NULL),  _pStorage(NULL),  _pWB2(NULL),  _pHtmlDoc2(NULL),  _pHtmlDoc3(NULL),  _pHtmlWnd2(NULL),  _pHtmlEvent(NULL) {     ::memset( (PVOID)&_rcWebWnd,0,sizeof(_rcWebWnd));     HRTEST_SE( OleInitialize(0),L"Ole初始化错误");     HRTEST_SE( StgCreateDocfile(0,STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_CREATE,0,&_pStorage),L"StgCreateDocfile错误");     HRTEST_SE( OleCreate(CLSID_WebBrowser,IID_IOleObject,OLERENDER_DRAW,0,this,_pStorage,(void**)&_pOleObj),L"Ole创建失败");     HRTEST_SE( _pOleObj->QueryInterface(IID_IOleInPlaceObject,(LPVOID*)&_pInPlaceObj),L"OleInPlaceObject创建失败"); RETURN:     return; } WebBrowser::~WebBrowser(void) { } /* ================== |IUnknown methods| ================== */ STDMETHODIMP WebBrowser::QueryInterface(REFIID iid,void**ppvObject) {     *ppvObject = 0;     if ( iid == IID_IOleClientSite )         *ppvObject = (IOleClientSite*)this;     if ( iid == IID_IUnknown )         *ppvObject = this;     if ( iid == IID_IDispatch )         *ppvObject = (IDispatch*)this;     if ( _bExternalPlace == false)     {         if ( iid == IID_IOleInPlaceSite )             *ppvObject = (IOleInPlaceSite*)this;         if ( iid == IID_IOleInPlaceFrame )             *ppvObject = (IOleInPlaceFrame*)this;         if ( iid == IID_IOleInPlaceUIWindow )             *ppvObject = (IOleInPlaceUIWindow*)this;     }         /*         这里是一点走私货, 留在以后讲,如果有机会,你可以发现,原来如此简单.     if ( iid == DIID_DWebBrowserEvents2 )         *ppvObject = (DWebBrowserEvents2 *)this;     if ( iid == IID_IDocHostUIHandler)         *ppvObject = (IDocHostUIHandler*)this;         */     if ( *ppvObject )     {         AddRef();         return S_OK;     }     return E_NOINTERFACE; } STDMETHODIMP_(ULONG)  WebBrowser::AddRef() {     return ::InterlockedIncrement( &_refNum ); } STDMETHODIMP_(ULONG)  WebBrowser::Release() {     return ::InterlockedDecrement( &_refNum ); } /* ===================== | IDispatch Methods | ===================== */ HRESULT _stdcall WebBrowser::GetTypeInfoCount(     unsigned int * pctinfo)  {     return E_NOTIMPL; } HRESULT _stdcall WebBrowser::GetTypeInfo(     unsigned int iTInfo,     LCID lcid,     ITypeInfo FAR* FAR* ppTInfo)  {     return E_NOTIMPL; } HRESULT _stdcall WebBrowser::GetIDsOfNames(REFIID riid,    OLECHAR FAR* FAR* rgszNames,    unsigned int cNames,    LCID lcid,    DISPID FAR* rgDispId ) {     return E_NOTIMPL; } HRESULT _stdcall WebBrowser::Invoke(     DISPID dispIdMember,     REFIID riid,     LCID lcid,     WORD wFlags,     DISPPARAMS* pDispParams,     VARIANT* pVarResult,     EXCEPINFO* pExcepInfo,     unsigned int* puArgErr) {         /*走私货,留在以后讲,是关于DWebBrowserEvents2让人激动的实现,而且简单.     // DWebBrowserEvents2     if( dispIdMember == DISPID_DOCUMENTCOMPLETE)     {         DocumentComplete(pDispParams->rgvarg[1].pdispVal,pDispParams->rgvarg[0].pvarVal);         return S_OK;     }     if( dispIdMember == DISPID_BEFORENAVIGATE2)     {         BeforeNavigate2( pDispParams->rgvarg[6].pdispVal,                          pDispParams->rgvarg[5].pvarVal,                          pDispParams->rgvarg[4].pvarVal,                          pDispParams->rgvarg[3].pvarVal,                          pDispParams->rgvarg[2].pvarVal,                          pDispParams->rgvarg[1].pvarVal,                          pDispParams->rgvarg[0].pboolVal);         return S_OK;     }         */     return E_NOTIMPL; } /* ======================== |IOleClientSite methods| ======================== */ STDMETHODIMP WebBrowser::SaveObject() {     return S_OK; } STDMETHODIMP WebBrowser::GetMoniker(DWORD dwA,DWORD dwW,IMoniker**pm) {     *pm = 0;     return E_NOTIMPL; } STDMETHODIMP WebBrowser::GetContainer(IOleContainer**pc) {     *pc = 0;     return E_FAIL; } STDMETHODIMP WebBrowser::ShowObject() {     return S_OK; } STDMETHODIMP WebBrowser::OnShowWindow(BOOL f) {     return S_OK; } STDMETHODIMP WebBrowser::RequestNewObjectLayout() {     return S_OK; } /* ========================= |IOleInPlaceSite methods| ========================= */ STDMETHODIMP WebBrowser::GetWindow(HWND *p) {     *p = GetHWND();     return S_OK; } STDMETHODIMP WebBrowser::ContextSensitiveHelp(BOOL) {     return E_NOTIMPL; } STDMETHODIMP WebBrowser::CanInPlaceActivate()//If this function return S_FALSE, AX cannot activate in place! {     if ( _bInPlaced )//Does WebBrowser Control already in placed?     {         _bCalledCanInPlace = true;         return S_OK;     }     return S_FALSE; } STDMETHODIMP WebBrowser::OnInPlaceActivate() {     return S_OK; } STDMETHODIMP WebBrowser::OnUIActivate() {     return S_OK; } STDMETHODIMP WebBrowser::GetWindowContext(IOleInPlaceFrame** ppFrame,IOleInPlaceUIWindow **ppDoc,LPRECT r1,LPRECT r2,LPOLEINPLACEFRAMEINFO o) {          *ppFrame = (IOleInPlaceFrame*)this;     AddRef();     *ppDoc = NULL;     ::GetClientRect(  GetHWND() ,&_rcWebWnd );     *r1 = _rcWebWnd;     *r2 = _rcWebWnd;     o->cb = sizeof(OLEINPLACEFRAMEINFO);     o->fMDIApp = false;     o->hwndFrame = GetParent( GetHWND() );     o->haccel = 0;     o->cAccelEntries = 0;          return S_OK; } STDMETHODIMP WebBrowser::Scroll(SIZE s) {     return E_NOTIMPL; } STDMETHODIMP WebBrowser::OnUIDeactivate(int) {     return S_OK; } STDMETHODIMP WebBrowser::OnInPlaceDeactivate() {     return S_OK; } STDMETHODIMP WebBrowser::DiscardUndoState() {     return S_OK; } STDMETHODIMP WebBrowser::DeactivateAndUndo() {     return S_OK; } STDMETHODIMP WebBrowser::OnPosRectChange(LPCRECT) {     return S_OK; } /* ========================== |IOleInPlaceFrame methods| ========================== */ STDMETHODIMP WebBrowser::GetBorder(LPRECT l) {     ::GetClientRect(  GetHWND() ,&_rcWebWnd );     *l = _rcWebWnd;     return S_OK; } STDMETHODIMP WebBrowser::RequestBorderSpace(LPCBORDERWIDTHS b) {     return S_OK; } STDMETHODIMP WebBrowser::SetBorderSpace(LPCBORDERWIDTHS b) {     return S_OK; } STDMETHODIMP WebBrowser::SetActiveObject(IOleInPlaceActiveObject*pV,LPCOLESTR s) {     return S_OK; } STDMETHODIMP WebBrowser::SetStatusText(LPCOLESTR t) {     return E_NOTIMPL; } STDMETHODIMP WebBrowser::EnableModeless(BOOL f) {     return E_NOTIMPL; } STDMETHODIMP WebBrowser::TranslateAccelerator(LPMSG,WORD) {     return E_NOTIMPL; } HRESULT _stdcall WebBrowser::RemoveMenus(HMENU h) {     return E_NOTIMPL; } HRESULT _stdcall WebBrowser::InsertMenus(HMENU h,LPOLEMENUGROUPWIDTHS x) {     return E_NOTIMPL; } HRESULT _stdcall WebBrowser::SetMenu(HMENU h,HOLEMENU hO,HWND hw) {     return E_NOTIMPL; } /* ==================== |DWebBrowserEvents2| ==================== */ /* 走私货,以后再讲 void  WebBrowser::DocumentComplete( IDispatch *pDisp,VARIANT *URL) {         //老天保佑,多好的函数啊.     return ; } void  WebBrowser::BeforeNavigate2( IDispatch *pDisp,VARIANT *&url,VARIANT *&Flags,VARIANT *&TargetFrameName,VARIANT *&PostData,VARIANT *&Headers,VARIANT_BOOL *&Cancel) {     PCWSTR pcwApp = L"app:";     if( url->vt != VT_BSTR )         return;     if( 0 == _wcsnicmp( pcwApp, url->bstrVal,wcslen(pcwApp)) )     {         *Cancel = VARIANT_TRUE;         _OnHtmlCmd( url->bstrVal+wcslen(pcwApp) );         return;     }     *Cancel = VARIANT_FALSE; } */ /* ===================== | IDocHostUIHandler | ===================== */ /* 传说中的IDocHostUIHanler,同样留在以后讲 HRESULT WebBrowser:: ShowContextMenu(      DWORD dwID,     POINT *ppt,     IUnknown *pcmdtReserved,     IDispatch *pdispReserved){return E_NOTIMPL;} HRESULT WebBrowser:: GetHostInfo(                                          DOCHOSTUIINFO *pInfo){return E_NOTIMPL;} HRESULT WebBrowser:: ShowUI(                                     DWORD dwID,                                    IOleInPlaceActiveObject *pActiveObject,                                    IOleCommandTarget *pCommandTarget,                                    IOleInPlaceFrame *pFrame,                                    IOleInPlaceUIWindow *pDoc){return E_NOTIMPL;} HRESULT WebBrowser:: HideUI( void){return E_NOTIMPL;} HRESULT WebBrowser:: UpdateUI( void){return E_NOTIMPL;} //HRESULT WebBrowser:: EnableModeless(  //  BOOL fEnable){return E_NOTIMPL;} HRESULT WebBrowser:: OnDocWindowActivate(      BOOL fActivate){return E_NOTIMPL;} HRESULT WebBrowser:: OnFrameWindowActivate(      BOOL fActivate){return E_NOTIMPL;} HRESULT WebBrowser:: ResizeBorder(      LPCRECT prcBorder,     IOleInPlaceUIWindow *pUIWindow,     BOOL fRameWindow){return E_NOTIMPL;} HRESULT WebBrowser:: TranslateAccelerator(      LPMSG lpMsg,     const GUID *pguidCmdGroup,     DWORD nCmdID){return E_NOTIMPL;} HRESULT WebBrowser:: GetOptionKeyPath(      LPOLESTR *pchKey,     DWORD dw){return E_NOTIMPL;} HRESULT WebBrowser:: GetDropTarget(      IDropTarget *pDropTarget,     IDropTarget **ppDropTarget) {     return E_NOTIMPL;//使用默认拖拽     //return S_OK;//自定义拖拽 } HRESULT WebBrowser:: GetExternal( IDispatch **ppDispatch) {     return E_NOTIMPL; } HRESULT WebBrowser:: TranslateUrl(      DWORD dwTranslate,     OLECHAR *pchURLIn,     OLECHAR **ppchURLOut){return E_NOTIMPL;} HRESULT WebBrowser:: FilterDataObject(      IDataObject *pDO,     IDataObject **ppDORet){return E_NOTIMPL;} */ /* =============== |Other Methods| =============== */ IWebBrowser2*  WebBrowser::GetWebBrowser2() {     if( _pWB2 != NULL )         return _pWB2;     NULLTEST_SE( _pOleObj,L"Ole对象为空");     HRTEST_SE( _pOleObj->QueryInterface(IID_IWebBrowser2,(void**)&_pWB2),L"QueryInterface IID_IWebBrowser2 失败");     return _pWB2; RETURN:     return NULL; } IHTMLDocument2*     WebBrowser::GetHTMLDocument2() {     if( _pHtmlDoc2 != NULL )         return _pHtmlDoc2;     IWebBrowser2* pWB2 = NULL;     NULLTEST(pWB2 = GetWebBrowser2());//GetWebBrowser2已经将错误原因交给LastError.     IDispatch* pDp =  NULL;     HRTEST_SE(pWB2->get_Document(&pDp),L"DWebBrowser2::get_Document 错误");     HRTEST_SE(pDp->QueryInterface(IID_IHTMLDocument2,(void**)&_pHtmlDoc2),L"QueryInterface IID_IHTMLDocument2 失败");     return _pHtmlDoc2; RETURN:     return NULL; } IHTMLDocument3*     WebBrowser::GetHTMLDocument3() {     if( _pHtmlDoc3 != NULL )         return _pHtmlDoc3;     IWebBrowser2* pWB2 = NULL;     NULLTEST(pWB2 = GetWebBrowser2());//GetWebBrowser2已经将错误原因交给LastError.     IDispatch* pDp =  NULL;     HRTEST_SE(pWB2->get_Document(&pDp),L"DWebBrowser2::get_Document 错误");     HRTEST_SE(pDp->QueryInterface(IID_IHTMLDocument3,(void**)&_pHtmlDoc3),L"QueryInterface IID_IHTMLDocument3 失败");     return _pHtmlDoc3; RETURN:     return NULL; } IHTMLWindow2* WebBrowser::GetHTMLWindow2() {     if( _pHtmlWnd2 != NULL)         return _pHtmlWnd2;     IHTMLDocument2*  pHD2 = GetHTMLDocument2();     NULLTEST( pHD2 );     HRTEST_SE( pHD2->get_parentWindow(&_pHtmlWnd2),L"IHTMLWindow2::get_parentWindow 错误" );     return _pHtmlWnd2; RETURN:     return NULL; } IHTMLEventObj*    WebBrowser::GetHTMLEventObject() {     if( _pHtmlEvent != NULL )         return _pHtmlEvent;     IHTMLWindow2* pHW2;     NULLTEST( pHW2 = GetHTMLWindow2() );     HRTEST_SE( pHW2->get_event(&_pHtmlEvent),L"IHTMLWindow2::get_event 错误");     return _pHtmlEvent; RETURN:     return NULL; } BOOL        WebBrowser::SetWebRect(LPRECT lprc) {     BOOL bRet = FALSE;     if( false == _bInPlaced )//尚未OpenWebBrowser操作,直接写入_rcWebWnd     {        _rcWebWnd = *lprc;     }     else//已经打开WebBrowser,通过 IOleInPlaceObject::SetObjectRects 调整大小     {         SIZEL size;         size.cx = RECTWIDTH(*lprc);         size.cy = RECTHEIGHT(*lprc);         IOleObject* pOleObj;         NULLTEST( pOleObj= _GetOleObject());         HRTEST_E( pOleObj->SetExtent(  1,&size ),L"SetExtent 错误");         IOleInPlaceObject* pInPlace;         NULLTEST( pInPlace = _GetInPlaceObject());         HRTEST_E( pInPlace->SetObjectRects(lprc,lprc),L"SetObjectRects 错误");         _rcWebWnd = *lprc;     }     bRet = TRUE; RETURN:     return bRet; } BOOL     WebBrowser::OpenWebBrowser() {     BOOL bRet = FALSE;     NULLTEST_E( _GetOleObject(),L"ActiveX对象为空" );//对于本身的实现函数,其自身承担错误录入工作          if( (RECTWIDTH(_rcWebWnd) && RECTHEIGHT(_rcWebWnd)) == 0 )         ::GetClientRect( GetHWND() ,&_rcWebWnd);//设置WebBrowser的大小为窗口的客户区大小.          if( _bInPlaced == false )// Activate In Place     {         _bInPlaced = true;//_bInPlaced must be set as true, before INPLACEACTIVATE, otherwise, once DoVerb, it would return error;         _bExternalPlace = 0;//lParam;              HRTEST_E( _GetOleObject()->DoVerb(OLEIVERB_INPLACEACTIVATE,0,this,0, GetHWND()  ,&_rcWebWnd),L"关于INPLACE的DoVerb错误");         _bInPlaced = true;                           //* 挂接DWebBrwoser2Event         IConnectionPointContainer* pCPC = NULL;         IConnectionPoint*          pCP  = NULL;         HRTEST_E( GetWebBrowser2()->QueryInterface(IID_IConnectionPointContainer,(void**)&pCPC),L"枚举IConnectionPointContainer接口失败");         HRTEST_E( pCPC->FindConnectionPoint( DIID_DWebBrowserEvents2,&pCP),L"FindConnectionPoint失败");         DWORD dwCookie = 0;         HRTEST_E( pCP->Advise( (IUnknown*)(void*)this,&dwCookie),L"IConnectionPoint::Advise失败");     }     bRet = TRUE; RETURN:     return bRet; } BOOL     WebBrowser::OpenURL(VARIANT* pVarUrl) {     BOOL bRet = FALSE;     HRTEST_E( GetWebBrowser2()->Navigate2( pVarUrl,0,0,0,0),L"GetWebBrowser2 失败");     bRet = TRUE; RETURN:     return bRet; } 五.例子       class WebBrowserWindow :     public WebBrowser { public:     WebBrowserWindow(void);     ~WebBrowserWindow(void); public:     virtual HWND GetHWND(){ return YourWindow}; private:     LRESULT OnCreate( WPARAM wParam,LPARAM lParam);     //您可以在OnCreate中调用OpenWebBrowser 然后调用 OpenURL }; 六.下期预告,如果有的话       如果有人感兴趣的话, 以后会说道如何扩展WebBrowser, 让他包罗万象, 你会发现很简单.       如果有问题,欢迎提问. 谢谢. 转自:http://blog.csdn.net/norsd/article/details/2921389

上一篇:[置顶] 软交换性能测试技术
下一篇:(转)续 WebBrowser 的扩展

相关文章

相关评论