• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            技術備忘錄

            c++及圖形學

             

            C++中嵌入ie瀏覽器總結(2) - 雙向通訊

               第一步解決了邊框和上下文菜單問題,第二部就是要解決c++程序和html頁面交互的問題。最開始的想法是通過c++去更新頁面內容的方式來完成c++->html的通訊,通過BeforeNavigate2 接口,截獲頁面url地址的方式來完成html->c++的通訊。但是這種方式存在以下缺點: 

                   (1) c++->html 的問題在于導致c++代碼復雜,需要通過c++代碼來完成頁面生成,如果修改頁面,將產生很大的工作量。雖然嘗試用了模板方法解決,但是還是比較繁瑣,而且會導致經常通訊的時候,頁面會經常刷新,產生其他的一些問題。
                  (2) html->c++ 的問題在于 傳遞參數不方便,解析也不方便、無法獲取返回值、腳本中要調用不方便

                 為了解決這些問題,經過google后找到了問題的解決辦法 : 
                (1) c++->html  ,可以通過調用頁面腳本方法來實現,調用方法如下:

            wxVariant wxIEHtmlWin::ExecScript(const wxString &fun,const std::vector<wxString> &params )
            {
                wxVariant result(
            false);
                
            if (! m_webBrowser.Ok())
                    
            return result;

                
            // get document dispatch interface
                IDispatch *iDisp = NULL;
                HRESULT hr 
            = m_webBrowser->get_Document(&iDisp);
                
            if (hr != S_OK)
                    
            return result;

                
            // Query for Document Interface
                wxAutoOleInterface<IHTMLDocument2> hd(IID_IHTMLDocument2, iDisp);
                iDisp
            ->Release();

                
            if (! hd.Ok())
                    
            return result;

                IDispatch 
            *spScript;
                hr 
            = hd->get_Script(&spScript);

                
            if(FAILED(hr))
                    
            return result;
                BSTR bstrMember 
            = wxConvertStringToOle(fun);
                DISPID dispid 
            = NULL;
                hr 
            = spScript->GetIDsOfNames(IID_NULL,&bstrMember,1,
                    LOCALE_SYSTEM_DEFAULT,
            &dispid);
                
            if(FAILED(hr))
                
            {
                    
                    
            return result;
                }

                
            //Putting parameters
                DISPPARAMS dispparams;
                memset(
            &dispparams, 0sizeof dispparams);
                dispparams.cArgs      
            = params.size();
                dispparams.rgvarg     
            = new VARIANT[dispparams.cArgs];
                dispparams.cNamedArgs 
            = 0;

                
            forint i = 0; i < params.size(); i++)
                
            {
                    CComBSTR bstr 
            = wxConvertStringToOle(params[params.size() - 1 - i]);
                    
            // back reading
                    bstr.CopyTo(&dispparams.rgvarg[i].bstrVal);

                    dispparams.rgvarg[i].vt 
            = VT_BSTR;
                }

                EXCEPINFO excepInfo;
                memset(
            &excepInfo, 0sizeof excepInfo);
                VARIANT   varRet;
                UINT nArgErr 
            = (UINT)-1;      // initialize to invalid arg
                
            //Call JavaScript function
                hr = spScript->Invoke(dispid,IID_NULL,0,
                    DISPATCH_METHOD,
            &dispparams,
                    
            &varRet,&excepInfo,&nArgErr);
                delete [] dispparams.rgvarg;
                
            if(FAILED(hr))
                
            {
                    
                    
            return result;
                }


                wxConvertOleToVariant(varRet,result);
                
            return result;


            }

              這個方法實現了C++對頁面腳本調用,而且參數個數可以任意。比如頁面腳本是 :
            function fun(a,b,c)
            {
            }

              C++中的調用方法是 :
            std::vector<wxString> params;
            params.push_back("a");
            params.push_back("b");
            params.push_back("c");
            xxx
            ->ExecScripts("fun",params);

            還可以獲得腳本返回的結果。

              (2) html->c++  通過腳本的window.external 方法,首先,在前文提到過的IDocHostUIHandler 接口中,實現方法: 
            HRESULT STDMETHODCALLTYPE FrameSite::GetExternal(IDispatch **ppDispatch)
            {
                 
                IDispatch 
            * pDisp = m_window->getExternal();
                
            if(pDisp)
                
            {
                    pDisp
            ->AddRef();
                    
            *ppDispatch = pDisp;
                }


                
            return S_OK;
            }
            其中 m_window->getExternal();
             返回的是自定義的一個IDispatch 接口類: 
            /*
             * IDispimp.H
             * IDispatch
             *
             * Copyright (c)1995-1999 Microsoft Corporation, All Rights Reserved
             
            */
             


            #ifndef _IDISPIMP_H_
            #define _IDISPIMP_H_
            #include 
            <oaidl.h>
            class CustomFunction;
            class CImpIDispatch : public IDispatch
            {
                
            protected:
                    ULONG               m_cRef;

                
            public:
                    CImpIDispatch(
            void);
                    
            ~CImpIDispatch(void);

                    STDMETHODIMP QueryInterface(REFIID, 
            void **);
                    STDMETHODIMP_(ULONG) AddRef(
            void);
                    STDMETHODIMP_(ULONG) Release(
            void);

                    
            //IDispatch
                    STDMETHODIMP GetTypeInfoCount(UINT* pctinfo);
                    STDMETHODIMP GetTypeInfo(
            /* [in] */ UINT iTInfo,
                        
            /* [in] */ LCID lcid,
                        
            /* [out] */ ITypeInfo** ppTInfo);
                    STDMETHODIMP GetIDsOfNames(
                        
            /* [in] */ REFIID riid,
                        
            /* [size_is][in] */ LPOLESTR *rgszNames,
                        
            /* [in] */ UINT cNames,
                        
            /* [in] */ LCID lcid,
                        
            /* [size_is][out] */ DISPID *rgDispId);
                    STDMETHODIMP Invoke(
                        
            /* [in] */ DISPID dispIdMember,
                        
            /* [in] */ REFIID riid,
                        
            /* [in] */ LCID lcid,
                        
            /* [in] */ WORD wFlags,
                        
            /* [out][in] */ DISPPARAMS  *pDispParams,
                        
            /* [out] */ VARIANT  *pVarResult,
                        
            /* [out] */ EXCEPINFO *pExcepInfo,
                        
            /* [out] */ UINT *puArgErr);

                        
            void setCustomFunction(CustomFunction *fun) {m_fun = fun;}
            private:
                CustomFunction 
            *m_fun;

            }
            ;
            #endif //_IDISPIMP_H_
            主要實現以下兩個方法: 
            wxString cszCB_CustomFunction = wxT("CB_CustomFunction");
              #define DISPID_CB_CustomFunction 3
            STDMETHODIMP CImpIDispatch::GetIDsOfNames(
                        
            /* [in] */ REFIID riid,
                        
            /* [size_is][in] */ OLECHAR** rgszNames,
                        
            /* [in] */ UINT cNames,
                        
            /* [in] */ LCID lcid,
                        
            /* [size_is][out] */ DISPID* rgDispId)
            {
                HRESULT hr;
                UINT    i;

                
            // Assume some degree of success
                hr = NOERROR;


                    
            for ( i=0; i < cNames; i++{
                    wxString cszName  
            = rgszNames[i];
             
                    
            if(cszName == cszCB_CustomFunction)
                    
            {
                        rgDispId[i] 
            = DISPID_CB_CustomFunction;
                    }
                
                 
                    
            else {
                        
            // One or more are unknown so set the return code accordingly
                        hr = ResultFromScode(DISP_E_UNKNOWNNAME);
                        rgDispId[i] 
            = DISPID_UNKNOWN;
                    }

                }

                
            return hr;
            }


            STDMETHODIMP CImpIDispatch::Invoke(
                        
            /* [in] */ DISPID dispIdMember,
                        
            /* [in] */ REFIID /*riid*/,
                        
            /* [in] */ LCID /*lcid*/,
                        
            /* [in] */ WORD wFlags,
                        
            /* [out][in] */ DISPPARAMS* pDispParams,
                        
            /* [out] */ VARIANT* pVarResult,
                        
            /* [out] */ EXCEPINFO* /*pExcepInfo*/,
                        
            /* [out] */ UINT* puArgErr)
            {

                 
                
                
            if(dispIdMember == DISPID_CB_CustomFunction) 
                
            {
                    
            if(wFlags & DISPATCH_PROPERTYGET)
                    
            {
                        
            if(pVarResult != NULL)
                        
            {
                            
                            VariantInit(pVarResult);
                            V_VT(pVarResult)
            =VT_BOOL;
                            V_BOOL(pVarResult) 
            = true;
                        }

                    }

                    
                    
            if ( wFlags & DISPATCH_METHOD )
                    
            {
                        
            //arguments come in reverse order
                        
            //for some reason
                        if(!m_fun) return S_OK;

                        wxString arg1,arg2;
                     
                        
            if(pDispParams->cArgs<1return S_FALSE;
                        wxString cmd 
            = pDispParams->rgvarg[pDispParams->cArgs-1].bstrVal;
                        std::vector
            <wxString> args;
                        
            if(pDispParams->cArgs>1)
                        
            {
                            
            for(int i=pDispParams->cArgs-2;i>=0;i--)
                                args.push_back(pDispParams
            ->rgvarg[i].bstrVal);
                        }

                        wxString re 
            = m_fun->execute(cmd,args);
                        
            if(pVarResult != NULL)
                        
            {
                            VariantInit(pVarResult);
                            V_VT(pVarResult)
            =VT_BSTR;
                            wxVariant wVar(re);
                            VariantToMSWVariant(wVar,
            *pVarResult);
                            
                             
                        }

                     
                    }

                    
                }


                 

                
            return S_OK;
            }

              其中 CustomFunction 定義如下:
            #pragma once
            #include 
            <wx/wx.h>
            #include 
            <vector>
            class CustomFunction
            {
            public:

                CustomFunction(
            void)
                
            {
                }


                
            virtual ~CustomFunction(void)
                
            {
                }


                
            virtual wxString execute(const wxString &cmd, const std::vector<wxString> &args) = 0;
            }
            ;
              然后只要在自己類里面繼承這個接口,就可以接收來之腳本的調用請求。
            腳本里面編寫函數:
            window._callFun = function()
                            
            {
                                 
                                var fun 
            = "window.external.CB_CustomFunction(";
                                
            for(i=0;i<arguments.length;i++)
                                
            {
                                    
            if(i!=0)
                                        fun 
            = fun+",";
                                    fun 
            = fun+"\""+arguments[i]+"\"";
                                }
                
                                fun 
            = fun+")";
                                
            //alert(fun);
                                return (eval(fun));
                            }
               然后調用的地方寫: 
             
            _callFun("fun","param1","param2",);
            就可以調用c++的函數,并且可以得到返回值,從而解決了html->c++的通訊問題

               解決了雙向通訊后,頁面就不需要用刷新來解決,網頁設計師和c++編程人員只要定義好通訊接口,大家各自實現好接口方法就可以完成界面功能了。

            posted on 2008-12-20 22:26 jerrychan 閱讀(3904) 評論(1)  編輯 收藏 引用 所屬分類: C++

            評論

            # re: C++中嵌入ie瀏覽器總結(2) - 雙向通訊 2012-07-06 15:08 ma12155506

            其中 m_window->getExternal();
            返回的是自定義的一個IDispatch 接口類: ?
            直接在這個m_window不太理解
            難道直接m_window里面添加
            IDispatch* wxActiveX::getExternal(){
            return m_Dispatch;
            }
            ??
            還是聲明或者NEW一個CImpIDispatch出來?
              回復  更多評論   

            導航

            統計

            常用鏈接

            留言簿(7)

            隨筆分類

            隨筆檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            午夜天堂av天堂久久久| 久久国产亚洲高清观看| 欧美一级久久久久久久大| 久久精品国产99久久丝袜| 欧美亚洲国产精品久久高清| 欧洲人妻丰满av无码久久不卡| 欧美777精品久久久久网| 亚洲精品久久久www| 91精品国产高清久久久久久io | 久久精品成人免费网站| 久久久久99精品成人片| 久久天天躁狠狠躁夜夜网站| 久久九九久精品国产| 久久99亚洲网美利坚合众国| 色婷婷综合久久久久中文字幕| 久久久久久久久久久久中文字幕 | 久久精品国产精品亚洲人人| 午夜天堂精品久久久久| 亚洲欧美日韩精品久久亚洲区 | 久久―日本道色综合久久| 久久久久久午夜精品| 久久黄色视频| yellow中文字幕久久网| 狠狠色丁香久久婷婷综| 久久99精品久久久久婷婷| 久久精品国产99国产精品导航 | 久久青青草原国产精品免费 | 久久伊人影视| 99久久伊人精品综合观看| 久久久久亚洲精品天堂| 久久综合给久久狠狠97色| 久久久SS麻豆欧美国产日韩| 一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区| 97久久精品无码一区二区| 久久精品一本到99热免费| 久久久久亚洲精品无码蜜桃| 久久人爽人人爽人人片AV| 婷婷五月深深久久精品| 久久精品国产亚洲AV无码麻豆| 久久亚洲AV成人无码国产| 97久久精品人妻人人搡人人玩 |