天天看點

C++中嵌入ie浏覽器總結 .

     最近項目中用html 來做界面,也就折騰了一下在wxwidget中嵌入浏覽器的若幹細節工作,mfc也基本是類似的,由于wxwidget中已經做了一個封裝wxie,但是開發過程中也遇到了不少問題,在此做一下總結: 

ie邊框 及上下文菜單

   普通嵌入到程式裡面的浏覽器頁面都會有一個灰色的邊框,這樣放到程式裡面就很難看。目前網上流行的辦法添加css:

C++中嵌入ie浏覽器總結 .

body{

C++中嵌入ie浏覽器總結 .

  border:0;

C++中嵌入ie浏覽器總結 .

}

C++中嵌入ie浏覽器總結 .

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

     但是目前很多頁面用了比較新的css,改成這樣後,頁面就無法正常顯示了。讓網頁美工改樣式? 真是有點困難。

    後來繼續查閱了資料,發現比較好的辦法,那就是重載  IDocHostUIHandler 接口,其中,實作以下部分:

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

HRESULT STDMETHODCALLTYPE FrameSite::GetHostInfo(DOCHOSTUIINFO *pInfo)

C++中嵌入ie浏覽器總結 .

{

C++中嵌入ie浏覽器總結 .

    pInfo->cbSize = sizeof(DOCHOSTUIINFO);

C++中嵌入ie浏覽器總結 .

    pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER|DOCHOSTUIFLAG_SCROLL_NO;

C++中嵌入ie浏覽器總結 .

    pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;

C++中嵌入ie浏覽器總結 .

    return S_OK;

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

       其中  DOCHOSTUIFLAG_NO3DBORDER 就表示不要生成邊框,DOCHOSTUIFLAG_SCROLL_NO 表示不要生成滾動條

這樣就可以比較完美的解決邊框和滾動條的問題,不用依賴頁面的調整 。讓設計師愛用什麼用什麼。

     另外一個就是禁用右鍵菜單,網上也有不少辦法,但是用這個接口可以很簡單的實作: 

C++中嵌入ie浏覽器總結 .

HRESULT STDMETHODCALLTYPE FrameSite::ShowContextMenu(DWORD dwID, POINT *ppt, 

C++中嵌入ie浏覽器總結 .

                                                             IUnknown *pcmdtReserved, IDispatch *pdispReserved)

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    HRESULT result    = S_FALSE; //Dont Interfere

C++中嵌入ie浏覽器總結 .

    BOOL    handled    = FALSE;

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    switch ( m_contextMenuMode )

C++中嵌入ie浏覽器總結 .

    {

C++中嵌入ie浏覽器總結 .

    case kDefaultMenuSupport:

C++中嵌入ie浏覽器總結 .

        break;

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    case kNoContextMenu:

C++中嵌入ie浏覽器總結 .

        result    = S_OK;

C++中嵌入ie浏覽器總結 .

        handled    = TRUE;

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    case kTextSelectionOnly:

C++中嵌入ie浏覽器總結 .

        if (dwID != CONTEXT_MENU_TEXTSELECT)

C++中嵌入ie浏覽器總結 .

        {

C++中嵌入ie浏覽器總結 .

            result    = S_OK;

C++中嵌入ie浏覽器總結 .

            handled    = TRUE;

C++中嵌入ie浏覽器總結 .

        }

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    case kAllowAllButViewSource:

C++中嵌入ie浏覽器總結 .

        if (dwID == CONTEXT_MENU_DEFAULT)

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

            //result    = ModifyContextMenu(dwID, ppt, pcmdtReserved);

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    case kCustomMenuSupport:

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

            //result = CustomContextMenu(ppt, pcmdtReserved);

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    }

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    if (! handled)

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

         result = S_FALSE;

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    return result;

C++中嵌入ie浏覽器總結 .

    這裡不僅可以控制右鍵菜單顯示,m_contextMenuMode  = kNoContextMenu,還可以做到自定義菜單顯示,m_contextMenuMode  =其他值。因為暫時還不需要自定義菜單,是以這裡沒有實作。

   如果用wxie,就在FrameSite類增加這個接口即可,不關注的接口直接傳回S_FALSE 或E_NOTIMPL;

  如果用sdk或mfc,可以 調用IOleObject 的SetClientSite 方法,設定一個繼承了IOleClientSite 和 IDocHostUIHandler 的接口。

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

       (1) c++->html 的問題在于導緻c++代碼複雜,需要通過c++代碼來完成頁面生成,如果修改頁面,将産生很大的工作量。雖然嘗試用了模闆方法解決,但是還是比較繁瑣,而且會導緻經常通訊的時候,頁面會經常重新整理,産生其他的一些問題。

      (2) html->c++ 的問題在于 傳遞參數不友善,解析也不友善、無法擷取傳回值、腳本中要調用不友善

     為了解決這些問題,經過google後找到了問題的解決辦法 : 

    (1) c++->html  ,可以通過調用頁面腳本方法來實作,調用方法如下:

C++中嵌入ie浏覽器總結 .

wxVariant wxIEHtmlWin::ExecScript(const wxString &fun,const std::vector<wxString> &params )

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    wxVariant result(false);

C++中嵌入ie浏覽器總結 .

    if (! m_webBrowser.Ok())

C++中嵌入ie浏覽器總結 .

        return result;

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    // get document dispatch interface

C++中嵌入ie浏覽器總結 .

    IDispatch *iDisp = NULL;

C++中嵌入ie浏覽器總結 .

    HRESULT hr = m_webBrowser->get_Document(&iDisp);

C++中嵌入ie浏覽器總結 .

    if (hr != S_OK)

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    // Query for Document Interface

C++中嵌入ie浏覽器總結 .

    wxAutoOleInterface<IHTMLDocument2> hd(IID_IHTMLDocument2, iDisp);

C++中嵌入ie浏覽器總結 .

    iDisp->Release();

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    if (! hd.Ok())

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    IDispatch *spScript;

C++中嵌入ie浏覽器總結 .

    hr = hd->get_Script(&spScript);

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    if(FAILED(hr))

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    BSTR bstrMember = wxConvertStringToOle(fun);

C++中嵌入ie浏覽器總結 .

    DISPID dispid = NULL;

C++中嵌入ie浏覽器總結 .

    hr = spScript->GetIDsOfNames(IID_NULL,&bstrMember,1,

C++中嵌入ie浏覽器總結 .

        LOCALE_SYSTEM_DEFAULT,&dispid);

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    //Putting parameters

C++中嵌入ie浏覽器總結 .

    DISPPARAMS dispparams;

C++中嵌入ie浏覽器總結 .

    memset(&dispparams, 0, sizeof dispparams);

C++中嵌入ie浏覽器總結 .

    dispparams.cArgs      = params.size();

C++中嵌入ie浏覽器總結 .

    dispparams.rgvarg     = new VARIANT[dispparams.cArgs];

C++中嵌入ie浏覽器總結 .

    dispparams.cNamedArgs = 0;

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    for( int i = 0; i < params.size(); i++)

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

        CComBSTR bstr = wxConvertStringToOle(params[params.size() - 1 - i]);

C++中嵌入ie浏覽器總結 .

        // back reading

C++中嵌入ie浏覽器總結 .

        bstr.CopyTo(&dispparams.rgvarg[i].bstrVal);

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

        dispparams.rgvarg[i].vt = VT_BSTR;

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    EXCEPINFO excepInfo;

C++中嵌入ie浏覽器總結 .

    memset(&excepInfo, 0, sizeof excepInfo);

C++中嵌入ie浏覽器總結 .

    VARIANT   varRet;

C++中嵌入ie浏覽器總結 .

    UINT nArgErr = (UINT)-1;      // initialize to invalid arg

C++中嵌入ie浏覽器總結 .

    //Call JavaScript function

C++中嵌入ie浏覽器總結 .

    hr = spScript->Invoke(dispid,IID_NULL,0,

C++中嵌入ie浏覽器總結 .

        DISPATCH_METHOD,&dispparams,

C++中嵌入ie浏覽器總結 .

        &varRet,&excepInfo,&nArgErr);

C++中嵌入ie浏覽器總結 .

    delete [] dispparams.rgvarg;

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    wxConvertOleToVariant(varRet,result);

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

  這個方法實作了C++對頁面腳本調用,而且參數個數可以任意。比如頁面腳本是 :

C++中嵌入ie浏覽器總結 .

function fun(a,b,c)

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

  C++中的調用方法是 :

C++中嵌入ie浏覽器總結 .

std::vector<wxString> params;

C++中嵌入ie浏覽器總結 .

params.push_back("a");

C++中嵌入ie浏覽器總結 .

params.push_back("b");

C++中嵌入ie浏覽器總結 .

params.push_back("c");

C++中嵌入ie浏覽器總結 .

xxx->ExecScripts("fun",params);

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

  (2) html->c++  通過腳本的window.external 方法,首先,在前文提到過的IDocHostUIHandler 接口中,實作方法: 

C++中嵌入ie浏覽器總結 .

HRESULT STDMETHODCALLTYPE FrameSite::GetExternal(IDispatch **ppDispatch)

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    IDispatch * pDisp = m_window->getExternal();

C++中嵌入ie浏覽器總結 .

    if(pDisp)

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

        pDisp->AddRef();

C++中嵌入ie浏覽器總結 .

        *ppDispatch = pDisp;

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

其中 m_window->getExternal();

 傳回的是自定義的一個IDispatch 接口類: 

C++中嵌入ie浏覽器總結 .

/*

C++中嵌入ie浏覽器總結 .

 * IDispimp.H

C++中嵌入ie浏覽器總結 .

 * IDispatch

C++中嵌入ie浏覽器總結 .

 *

C++中嵌入ie浏覽器總結 .

 * Copyright (c)1995-1999 Microsoft Corporation, All Rights Reserved

C++中嵌入ie浏覽器總結 .

 */ 

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

#ifndef _IDISPIMP_H_

C++中嵌入ie浏覽器總結 .

#define _IDISPIMP_H_

C++中嵌入ie浏覽器總結 .

#include <oaidl.h>

C++中嵌入ie浏覽器總結 .

class CustomFunction;

C++中嵌入ie浏覽器總結 .

class CImpIDispatch : public IDispatch

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    protected:

C++中嵌入ie浏覽器總結 .

        ULONG               m_cRef;

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    public:

C++中嵌入ie浏覽器總結 .

        CImpIDispatch(void);

C++中嵌入ie浏覽器總結 .

        ~CImpIDispatch(void);

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

        STDMETHODIMP QueryInterface(REFIID, void **);

C++中嵌入ie浏覽器總結 .

        STDMETHODIMP_(ULONG) AddRef(void);

C++中嵌入ie浏覽器總結 .

        STDMETHODIMP_(ULONG) Release(void);

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

        //IDispatch

C++中嵌入ie浏覽器總結 .

        STDMETHODIMP GetTypeInfoCount(UINT* pctinfo);

C++中嵌入ie浏覽器總結 .

        STDMETHODIMP GetTypeInfo(/* [in] */ UINT iTInfo,

C++中嵌入ie浏覽器總結 .

            /* [in] */ LCID lcid,

C++中嵌入ie浏覽器總結 .

            /* [out] */ ITypeInfo** ppTInfo);

C++中嵌入ie浏覽器總結 .

        STDMETHODIMP GetIDsOfNames(

C++中嵌入ie浏覽器總結 .

            /* [in] */ REFIID riid,

C++中嵌入ie浏覽器總結 .

            /* [size_is][in] */ LPOLESTR *rgszNames,

C++中嵌入ie浏覽器總結 .

            /* [in] */ UINT cNames,

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

            /* [size_is][out] */ DISPID *rgDispId);

C++中嵌入ie浏覽器總結 .

        STDMETHODIMP Invoke(

C++中嵌入ie浏覽器總結 .

            /* [in] */ DISPID dispIdMember,

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

            /* [in] */ WORD wFlags,

C++中嵌入ie浏覽器總結 .

            /* [out][in] */ DISPPARAMS  *pDispParams,

C++中嵌入ie浏覽器總結 .

            /* [out] */ VARIANT  *pVarResult,

C++中嵌入ie浏覽器總結 .

            /* [out] */ EXCEPINFO *pExcepInfo,

C++中嵌入ie浏覽器總結 .

            /* [out] */ UINT *puArgErr);

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

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

C++中嵌入ie浏覽器總結 .

private:

C++中嵌入ie浏覽器總結 .

    CustomFunction *m_fun;

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

};

C++中嵌入ie浏覽器總結 .

#endif //_IDISPIMP_H_

C++中嵌入ie浏覽器總結 .

主要實作以下兩個方法: 

C++中嵌入ie浏覽器總結 .

wxString cszCB_CustomFunction = wxT("CB_CustomFunction");

  #define DISPID_CB_CustomFunction 3

STDMETHODIMP CImpIDispatch::GetIDsOfNames(

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

            /* [size_is][in] */ OLECHAR** rgszNames,

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

            /* [size_is][out] */ DISPID* rgDispId)

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    HRESULT hr;

C++中嵌入ie浏覽器總結 .

    UINT    i;

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    // Assume some degree of success

C++中嵌入ie浏覽器總結 .

    hr = NOERROR;

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

        for ( i=0; i < cNames; i++) {

C++中嵌入ie浏覽器總結 .

        wxString cszName  = rgszNames[i];

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

        if(cszName == cszCB_CustomFunction)

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

            rgDispId[i] = DISPID_CB_CustomFunction;

C++中嵌入ie浏覽器總結 .

        }    

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

        else {

C++中嵌入ie浏覽器總結 .

            // One or more are unknown so set the return code accordingly

C++中嵌入ie浏覽器總結 .

            hr = ResultFromScode(DISP_E_UNKNOWNNAME);

C++中嵌入ie浏覽器總結 .

            rgDispId[i] = DISPID_UNKNOWN;

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    return hr;

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

STDMETHODIMP CImpIDispatch::Invoke(

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

            /* [in] */ REFIID /*riid*/,

C++中嵌入ie浏覽器總結 .

            /* [in] */ LCID /*lcid*/,

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

            /* [out][in] */ DISPPARAMS* pDispParams,

C++中嵌入ie浏覽器總結 .

            /* [out] */ VARIANT* pVarResult,

C++中嵌入ie浏覽器總結 .

            /* [out] */ EXCEPINFO* /*pExcepInfo*/,

C++中嵌入ie浏覽器總結 .

            /* [out] */ UINT* puArgErr)

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    if(dispIdMember == DISPID_CB_CustomFunction) 

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

        if(wFlags & DISPATCH_PROPERTYGET)

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

            if(pVarResult != NULL)

C++中嵌入ie浏覽器總結 .

            {

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

                VariantInit(pVarResult);

C++中嵌入ie浏覽器總結 .

                V_VT(pVarResult)=VT_BOOL;

C++中嵌入ie浏覽器總結 .

                V_BOOL(pVarResult) = true;

C++中嵌入ie浏覽器總結 .

            }

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

        if ( wFlags & DISPATCH_METHOD )

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

            //arguments come in reverse order

C++中嵌入ie浏覽器總結 .

            //for some reason

C++中嵌入ie浏覽器總結 .

            if(!m_fun) return S_OK;

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

            wxString arg1,arg2;

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

            if(pDispParams->cArgs<1) return S_FALSE;

C++中嵌入ie浏覽器總結 .

            wxString cmd = pDispParams->rgvarg[pDispParams->cArgs-1].bstrVal;

C++中嵌入ie浏覽器總結 .

            std::vector<wxString> args;

C++中嵌入ie浏覽器總結 .

            if(pDispParams->cArgs>1)

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

                for(int i=pDispParams->cArgs-2;i>=0;i--)

C++中嵌入ie浏覽器總結 .

                    args.push_back(pDispParams->rgvarg[i].bstrVal);

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

            wxString re = m_fun->execute(cmd,args);

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

                V_VT(pVarResult)=VT_BSTR;

C++中嵌入ie浏覽器總結 .

                wxVariant wVar(re);

C++中嵌入ie浏覽器總結 .

                VariantToMSWVariant(wVar,*pVarResult);

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

  其中 CustomFunction 定義如下:

C++中嵌入ie浏覽器總結 .

#pragma once

C++中嵌入ie浏覽器總結 .

#include <wx/wx.h>

C++中嵌入ie浏覽器總結 .

#include <vector>

C++中嵌入ie浏覽器總結 .

class CustomFunction

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

public:

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    CustomFunction(void)

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    virtual ~CustomFunction(void)

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    virtual wxString execute(const wxString &cmd, const std::vector<wxString> &args) = 0;

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

  然後隻要在自己類裡面繼承這個接口,就可以接收來之腳本的調用請求。

腳本裡面編寫函數:

C++中嵌入ie浏覽器總結 .

window._callFun = function()

C++中嵌入ie浏覽器總結 .

                {

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

                    var fun = "window.external.CB_CustomFunction(";

C++中嵌入ie浏覽器總結 .

                    for(i=0;i<arguments.length;i++)

C++中嵌入ie浏覽器總結 .

                    {

C++中嵌入ie浏覽器總結 .

                        if(i!=0)

C++中嵌入ie浏覽器總結 .

                            fun = fun+",";

C++中嵌入ie浏覽器總結 .

                        fun = fun+"/""+arguments[i]+"/"";

C++中嵌入ie浏覽器總結 .

                    }    

C++中嵌入ie浏覽器總結 .

                    fun = fun+")";

C++中嵌入ie浏覽器總結 .

                    //alert(fun);

C++中嵌入ie浏覽器總結 .

                    return (eval(fun));

C++中嵌入ie浏覽器總結 .

                }

   然後調用的地方寫: 

C++中嵌入ie浏覽器總結 .

_callFun("fun","param1","param2",

C++中嵌入ie浏覽器總結 .

);

就可以調用c++的函數,并且可以得到傳回值,進而解決了html->c++的通訊問題 

   解決了雙向通訊後,頁面就不需要用重新整理來解決,網頁設計師和c++程式設計人員隻要定義好通訊接口,大家各自實作好接口方法就可以完成界面功能了。

       前面兩個問題的解決,心裡想: 這下好了,解決了這兩個問題,下一步做界面就簡單多了,不像以前,直接用mfc或第三方庫做,要做出好看效果真是很難。編譯好,運作了,發現效果還不錯。但是實作到裡面的腳本的時候,發現出了問題,不響應鍵盤消息了

C++中嵌入ie浏覽器總結 .

。而且在頁面文本框裡面按tab鍵,光标不是跑到下一個文本框,而是不見了。之前有這個現象,但是忙于解決前面的問題,沒有注意到。這下可完了,不會前工盡棄吧,那可麻煩大了。

      google了半天,問了朋友,還是不知道什麼原因。因為wxIE及嵌入浏覽器本身是比較偏門的問題,确實很難找到答案。

      山窮水盡疑無路,柳暗花明又一村。好不容易,在google上找到了一個類似的問題,回答的說,這是wxIE的bug,在wxPython的項目中,這個問題已經解決了。下載下傳下來編譯後,運作試試看,搞定了

C++中嵌入ie浏覽器總結 .

      但是還得和之前的修改合并,合并過程中又發現了一個問題。前文中提到過,通過IOleObject 接口來設定IDocHostUIHandler方法,我開始就是用這種方法。結果合并完後,發現還是不響應鍵盤消息

C++中嵌入ie浏覽器總結 .

    調了半天,才發現,wxIE原來已經實作過IOleClientSite 接口,我把自己的接口設上去,把wxIE的給替換掉了,是以導緻了不正常的結果。 經過一番調整後,終于正常了

C++中嵌入ie浏覽器總結 .

   自此,用html做c++程式界面的基礎工作算是告一段落了,下面就是完成接口工作和頁面腳本了。希望不要再遇到什麼問題。

     我在這裡把這些問題記錄下來,以備以後查用,也願其他朋友不要再遇到我一樣的困擾。

    下面截一張做出來的界面圖:

C++中嵌入ie浏覽器總結 .

這是一個對話框,完成前面的基礎工作後,隻要設計師設計好頁面,我們幾分鐘就可以繼承到c++裡面,再花點寫接口和腳本的時間,比原來用mfc做界面,不知要節省多少時間。這個界面比較簡單,但是隻要是能設計出的界面,我們都能讓他內建進來。

有興趣的朋友也不妨試試這種做界面的方法。

     前面忘了寫這個問題,就是對話框的拖動問題。就像我前面的圖檔展示的對話框,一般的windows對話框是可以拖着标題欄移動的,但是我們這裡沒有任何原來的标題欄了,隻有html頁面,怎麼拖呢? 好像有點麻煩。

       冥思苦想之後,想到一種辦法,通過前面的接口給c++發指令,讓c++移動視窗,頁面上計算好拖動的距離。html裡面頁面的拖動還是比較簡單的,c++裡面移動也就是調用 MoveWindow。由于前面的通訊方法還是比較靈活,沒用多少時間,就把這個功能實作了。但是一運作看,不太對勁,拖動過程拖尾現象太明顯。可能是c++不斷調用 MoveWindow 重繪效率比較低。這可麻煩了

C++中嵌入ie浏覽器總結 .

。這時候,突然想到普通對話框拖動的時候,是一個虛框在那裡動,原來的對話框是不動的,滑鼠放開後,對話框才移過去。 能不能做到這樣呢? 但是windows實作這個方法的細節不得而知,怎麼做呢?  

       還是google好啊,經過一番搜尋,找到了答案: 

C++中嵌入ie浏覽器總結 .

void TooltipDlg::moveWin( const std::vector<wxString> &args )

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    if(args.size()<2) return;

C++中嵌入ie浏覽器總結 .

    long x,y;

C++中嵌入ie浏覽器總結 .

    args[0].ToLong(&x);

C++中嵌入ie浏覽器總結 .

    args[1].ToLong(&y);

C++中嵌入ie浏覽器總結 .

    int ix,iy;

C++中嵌入ie浏覽器總結 .

    ix = x;

C++中嵌入ie浏覽器總結 .

    iy = y;

C++中嵌入ie浏覽器總結 .

    ClientToScreen(&ix,&iy);

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

    ::SendMessage((HWND)this->GetHWND(),WM_NCMOUSEMOVE,HTCAPTION,MAKELPARAM(ix, iy)); 

C++中嵌入ie浏覽器總結 .
C++中嵌入ie浏覽器總結 .

   搞定了,簡單吧,真是沒想到這麼簡單。運作後發現,真的和windows的對話框移動一模一樣了,太好了

C++中嵌入ie浏覽器總結 .

今天一鼓作氣把前面幾天的工作都總結了下來,還真是敲得手有點累。但是這些東西确實是不太正常的方法,找解決問題的方法很難,這裡先把他們記錄下來,免得以後找不到了。以前确實有很多知識都是用了就丢一邊找不到了。 也希望給有類似疑問的朋友一個幫助。

繼續閱讀