zoukankan      html  css  js  c++  java
  • javascript 调用C++函数

    分3步:

    一》实现IDispatch 接口

      

    #ifndef _IDISPIMP_H_
    #define _IDISPIMP_H_
    
    // idispimp.h
    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);
    
    };
    
    #endif
    #include "StdAfx.h"
    
    #include "testDlg.h" // 这个是MFC对话框的头文件,在后面用于调用函数的
    
    #include "Idispimp.h"
    
    #include <atlbase.h>
    
    #include <mmsystem.h>
    #include <shlwapi.h>
    
    #pragma comment(lib ,"shlwapi.lib")
    
    CString javaScriptName="JavaScriptCallCpp";    // javascript 传入的函数名
    #define DISPID_CallCppFromJs 1                //与函数名绑定的ID
    
    CImpIDispatch::CImpIDispatch( void )
    {
        m_cRef = 0;
    }
    
    CImpIDispatch::~CImpIDispatch( void )
    {
        ASSERT( m_cRef == 0 );
    }
    
    
    STDMETHODIMP CImpIDispatch::QueryInterface( REFIID riid, void **ppv )
    {
        *ppv = NULL;
    
    
        if ( IID_IDispatch == riid )
        {
            *ppv = this;
        }
    
        if ( NULL != *ppv )
        {
            ((LPUNKNOWN)*ppv)->AddRef();
            return NOERROR;
        }
    
        return E_NOINTERFACE;
    }
    
    
    STDMETHODIMP_(ULONG) CImpIDispatch::AddRef(void)
    {
        return ++m_cRef;
    }
    
    STDMETHODIMP_(ULONG) CImpIDispatch::Release(void)
    {
        return --m_cRef;
    }
    
    
    //IDispatch
    STDMETHODIMP CImpIDispatch::GetTypeInfoCount(UINT* /*pctinfo*/)
    {
        return E_NOTIMPL;
    }
    
    STDMETHODIMP CImpIDispatch::GetTypeInfo(
        /* [in] */ UINT /*iTInfo*/,
        /* [in] */ LCID /*lcid*/,
        /* [out] */ ITypeInfo** /*ppTInfo*/)
    {
        return E_NOTIMPL;
    }
    
    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++) {
    
            CString cszName;
            cszName = rgszNames[i];
            if (cszName == javaScriptName)//这里判断是否是JS传入的参数名
            {
                rgDispId[i] = DISPID_CallCppFromJs;//将ID绑定,用于Invoke
                
            }
            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)
    {
        CtestDlg* pDlg = (CtestDlg*) AfxGetMainWnd();
        /*
        参数wFlags有下面若干值----
    
    
    
        Value                    Description
    
        DISPATCH_METHOD            表示将调用方法。如果属性名称和方法名称相同,则和DISPATCH_PROPERTYGET标志一起设置。
    
        DISPATCH_PROPERTYGET    获得属性
    
        DISPATCH_PROPERTYPUT    设置属性
    
        DISPATCH_PROPERTYPUTREF    通过引用设置属性
    
        */
    
    
        if (dispIdMember == DISPID_CallCppFromJs)// 
        {
            if (wFlags & DISPATCH_PROPERTYGET)//获取属性
            {
                if (pVarResult != NULL)
                {
                    VariantInit(pVarResult);
                    V_VT(pVarResult)=VT_BOOL;
                    V_BOOL(pVarResult)=true;
                }
            }
    
            if (wFlags & DISPATCH_METHOD)//这里进行调用
            {
                CString cszArg1;
                cszArg1 = pDispParams->rgvarg[0].bstrVal;//这里是传入参数
    
                pDlg->TestHtml();// 调用测试的函数
            }
        }
    
        return S_OK;
    }

    二》改成COleControlSit

    // Custsite.h
    #ifndef __CUSTOMSITEH__
    #define __CUSTOMSITEH__
    
    #include "Idispimp.h"
    #include <afxocc.h>
    #include <Mshtmhst.h>
    class CCustomControlSite:public COleControlSite
    {
    public:
        CCustomControlSite(COleControlContainer *pCnt):COleControlSite(pCnt){}
    
    
        BEGIN_INTERFACE_PART(DocHostShowUI, IDocHostShowUI)
            INIT_INTERFACE_PART(CDocHostSite, DocHostShowUI)
            STDMETHOD(ShowHelp)(
            /* [in ] */    HWND hwnd,
            /* [in ] */    LPOLESTR pszHelpFile,
            /* [in ] */    UINT uCommand,
            /* [in ] */    DWORD dwData,
            /* [in ] */    POINT ptMouse,
            /* [out] */    IDispatch __RPC_FAR *pDispatchObjectHit);
            STDMETHOD(ShowMessage)(
                /* [in ] */    HWND hwnd,
                /* [in ] */    LPOLESTR lpstrText,
                /* [in ] */    LPOLESTR lpstrCaption,
                /* [in ] */    DWORD dwType,
                /* [in ] */    LPOLESTR lpstrHelpFile,
                /* [in ] */    DWORD dwHelpContext,
                /* [out] */    LRESULT __RPC_FAR *plResult);
        END_INTERFACE_PART(DocHostShowUI)
    
    protected:
    
        DECLARE_INTERFACE_MAP();
        BEGIN_INTERFACE_PART(DocHostUIHandler, IDocHostUIHandler)
            STDMETHOD(ShowContextMenu)(/* [in] */ DWORD dwID,
            /* [in] */ POINT __RPC_FAR *ppt,
            /* [in] */ IUnknown __RPC_FAR *pcmdtReserved,
            /* [in] */ IDispatch __RPC_FAR *pdispReserved);
            STDMETHOD(GetHostInfo)( 
                /* [out][in] */ DOCHOSTUIINFO __RPC_FAR *pInfo);
            STDMETHOD(ShowUI)( 
                /* [in] */ DWORD dwID,
                /* [in] */ IOleInPlaceActiveObject __RPC_FAR *pActiveObject,
                /* [in] */ IOleCommandTarget __RPC_FAR *pCommandTarget,
                /* [in] */ IOleInPlaceFrame __RPC_FAR *pFrame,
                /* [in] */ IOleInPlaceUIWindow __RPC_FAR *pDoc);
            STDMETHOD(HideUI)(void);
            STDMETHOD(UpdateUI)(void);
            STDMETHOD(EnableModeless)(/* [in] */ BOOL fEnable);
            STDMETHOD(OnDocWindowActivate)(/* [in] */ BOOL fEnable);
            STDMETHOD(OnFrameWindowActivate)(/* [in] */ BOOL fEnable);
            STDMETHOD(ResizeBorder)( 
                /* [in] */ LPCRECT prcBorder,
                /* [in] */ IOleInPlaceUIWindow __RPC_FAR *pUIWindow,
                /* [in] */ BOOL fRameWindow);
            STDMETHOD(TranslateAccelerator)( 
                /* [in] */ LPMSG lpMsg,
                /* [in] */ const GUID __RPC_FAR *pguidCmdGroup,
                /* [in] */ DWORD nCmdID);
            STDMETHOD(GetOptionKeyPath)( 
                /* [out] */ LPOLESTR __RPC_FAR *pchKey,
                /* [in] */ DWORD dw);
            STDMETHOD(GetDropTarget)(
                /* [in] */ IDropTarget __RPC_FAR *pDropTarget,
                /* [out] */ IDropTarget __RPC_FAR *__RPC_FAR *ppDropTarget);
            STDMETHOD(GetExternal)( 
                /* [out] */ IDispatch __RPC_FAR *__RPC_FAR *ppDispatch);
            STDMETHOD(TranslateUrl)( 
                /* [in] */ DWORD dwTranslate,
                /* [in] */ OLECHAR __RPC_FAR *pchURLIn,
                /* [out] */ OLECHAR __RPC_FAR *__RPC_FAR *ppchURLOut);
            STDMETHOD(FilterDataObject)( 
                /* [in] */ IDataObject __RPC_FAR *pDO,
                /* [out] */ IDataObject __RPC_FAR *__RPC_FAR *ppDORet);
        END_INTERFACE_PART(DocHostUIHandler)
    };
    
    
    class CCustomOccManager :public COccManager
    {
    public:
        CCustomOccManager(){}
        COleControlSite* CreateSite(COleControlContainer* pCtrlCont)
        {
            CCustomControlSite *pSite = new CCustomControlSite(pCtrlCont);
            return pSite;
        }
    };
    #endif
    #include "StdAfx.h"
    #include "Custsite.h"
    #include "test.h" // 主要用到 theApp (261行)
    
    BEGIN_INTERFACE_MAP(CCustomControlSite, COleControlSite)
        INTERFACE_PART(CCustomControlSite, IID_IDocHostShowUI, DocHostShowUI)
        INTERFACE_PART(CCustomControlSite, IID_IDocHostUIHandler, DocHostUIHandler)
    END_INTERFACE_MAP()
    
    
    ULONG CCustomControlSite::XDocHostShowUI::AddRef()
    {
        METHOD_PROLOGUE(CCustomControlSite, DocHostShowUI);
    
        return pThis->ExternalAddRef();
    }
    
    ULONG CCustomControlSite::XDocHostShowUI::Release()
    {
        METHOD_PROLOGUE(CCustomControlSite, DocHostShowUI);
    
        return pThis->ExternalRelease();
    }
    
    HRESULT CCustomControlSite::XDocHostShowUI::QueryInterface(REFIID riid, void ** ppvObj)
    {
        METHOD_PROLOGUE(CCustomControlSite, DocHostShowUI);
    
        return pThis->ExternalQueryInterface( &riid, ppvObj );
    }
    
    
    HRESULT CCustomControlSite::XDocHostShowUI::ShowHelp(HWND hwnd,
        LPOLESTR pszHelpFile,
        UINT nCommand,
        DWORD dwData,
        POINT ptMouse,
        IDispatch * pDispatchObjectHit)
    {
        METHOD_PROLOGUE(CCustomControlSite, DocHostShowUI);
    
        return S_OK;
    }
    
    HRESULT CCustomControlSite::XDocHostShowUI::ShowMessage(HWND hwnd,
        LPOLESTR lpstrText,
        LPOLESTR lpstrCaption,
        DWORD dwType,
        LPOLESTR lpstrHelpFile,
        DWORD dwHelpContext,
        LRESULT * plResult)
    {
        METHOD_PROLOGUE(CCustomControlSite, DocHostShowUI);
    
        MessageBox(hwnd, (CString)lpstrText, _T("Cpp & JavaScript"), /*dwType*/MB_ICONWARNING);
    
        return S_OK;
    }
    
    
    ULONG FAR EXPORT  CCustomControlSite::XDocHostUIHandler::AddRef()
    {
        METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)
            return pThis->ExternalAddRef();
    }
    
    
    ULONG FAR EXPORT  CCustomControlSite::XDocHostUIHandler::Release()
    {                            
        METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)
            return pThis->ExternalRelease();
    }
    
    HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::QueryInterface(REFIID riid, void **ppvObj)
    {
        METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)
            HRESULT hr = (HRESULT)pThis->ExternalQueryInterface(&riid, ppvObj);
        return hr;
    }
    
    // * CImpIDocHostUIHandler::GetHostInfo
    // *
    // * Purpose: Called at initialization
    // *
    HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::GetHostInfo( DOCHOSTUIINFO* pInfo )
    {
    
        METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)
            pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER;
        pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;
    
        return S_OK;
    }
    
    // * CImpIDocHostUIHandler::ShowUI
    // *
    // * Purpose: Called when MSHTML.DLL shows its UI
    // *
    HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::ShowUI(
        DWORD dwID, 
        IOleInPlaceActiveObject * /*pActiveObject*/,
        IOleCommandTarget * pCommandTarget,
        IOleInPlaceFrame * /*pFrame*/,
        IOleInPlaceUIWindow * /*pDoc*/)
    {
    
        METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)
            // We've already got our own UI in place so just return S_OK
            return S_OK;
    }
    
    // * CImpIDocHostUIHandler::HideUI
    // *
    // * Purpose: Called when MSHTML.DLL hides its UI
    // *
    HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::HideUI(void)
    {
        METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)
            return S_OK;
    }
    
    // * CImpIDocHostUIHandler::UpdateUI
    // *
    // * Purpose: Called when MSHTML.DLL updates its UI
    // *
    HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::UpdateUI(void)
    {
        METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)
            // MFC is pretty good about updating it's UI in it's Idle loop so I don't do anything here
            return S_OK;
    }
    
    // * CImpIDocHostUIHandler::EnableModeless
    // *
    // * Purpose: Called from MSHTML.DLL's IOleInPlaceActiveObject::EnableModeless
    // *
    HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::EnableModeless(BOOL /*fEnable*/)
    {
        METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)
            return E_NOTIMPL;
    }
    
    // * CImpIDocHostUIHandler::OnDocWindowActivate
    // *
    // * Purpose: Called from MSHTML.DLL's IOleInPlaceActiveObject::OnDocWindowActivate
    // *
    HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::OnDocWindowActivate(BOOL /*fActivate*/)
    {
        METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)
            return E_NOTIMPL;
    }
    
    // * CImpIDocHostUIHandler::OnFrameWindowActivate
    // *
    // * Purpose: Called from MSHTML.DLL's IOleInPlaceActiveObject::OnFrameWindowActivate
    // *
    HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::OnFrameWindowActivate(BOOL /*fActivate*/)
    {
        METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)
            return E_NOTIMPL;
    }
    
    // * CImpIDocHostUIHandler::ResizeBorder
    // *
    // * Purpose: Called from MSHTML.DLL's IOleInPlaceActiveObject::ResizeBorder
    // *
    HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::ResizeBorder(
        LPCRECT /*prcBorder*/, 
        IOleInPlaceUIWindow* /*pUIWindow*/,
        BOOL /*fRameWindow*/)
    {
        METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)
            return E_NOTIMPL;
    }
    
    // * CImpIDocHostUIHandler::ShowContextMenu
    // *
    // * Purpose: Called when MSHTML.DLL would normally display its context menu
    // *
    HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::ShowContextMenu(
        DWORD /*dwID*/, 
        POINT* pptPosition,
        IUnknown* /*pCommandTarget*/,
        IDispatch* /*pDispatchObjectHit*/)
    {
        METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)
            return E_NOTIMPL;
    
        //CMenu menu;
        //menu.LoadMenu(IDR_CUSTOM_POPUP);
        //CMenu* pSubMenu = menu.GetSubMenu(0);
        ////Because we passed in theApp.m_pMainWnd all of our
        ////WM_COMMAND handlers for the menu items must be handled
        ////in CCustomBrowserApp. If you want this to be your dialog
        ////you will have to grab a pointer to your dialog class and 
        ////pass the hWnd of it into the last parameter in this call
        //pSubMenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON, pptPosition->x, pptPosition->y, theApp.m_pMainWnd);
    
        return S_OK; // We've shown our own context menu. MSHTML.DLL will no longer try to show its own.
    }
    
    // * CImpIDocHostUIHandler::TranslateAccelerator
    // *
    // * Purpose: Called from MSHTML.DLL's TranslateAccelerator routines
    // *
    HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::TranslateAccelerator(LPMSG lpMsg,
        /* [in] */ const GUID __RPC_FAR *pguidCmdGroup,
        /* [in] */ DWORD nCmdID)
    {
        METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)
    
            //disable F5
            if(lpMsg->message == WM_KEYDOWN && GetAsyncKeyState(VK_F5) < 0)
                return S_OK;
    
        if(GetKeyState(VK_CONTROL) & 0x8000)
        {
            //disable ctrl + O
            if(lpMsg->message == WM_KEYDOWN && GetAsyncKeyState(0x4F) < 0)
                return S_OK;
            //disable ctrl + p
            if(lpMsg->message == WM_KEYDOWN && GetAsyncKeyState(0x50) < 0)
                return S_OK;
            //disable ctrl + N
            if(lpMsg->message == WM_KEYDOWN && GetAsyncKeyState(0x4E) < 0)
                return S_OK;
        }
    
        //disable back space
        if(lpMsg->wParam == VK_BACK)
            return S_OK;
    
        return S_FALSE;
    }
    
    // * CImpIDocHostUIHandler::GetOptionKeyPath
    // *
    // * Purpose: Called by MSHTML.DLL to find where the host wishes to store 
    // *    its options in the registry
    // *
    HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::GetOptionKeyPath(BSTR* pbstrKey, DWORD)
    {
    
        METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)
            return E_NOTIMPL;
    }
    
    STDMETHODIMP CCustomControlSite::XDocHostUIHandler::GetDropTarget( 
        /* [in] */ IDropTarget __RPC_FAR *pDropTarget,
        /* [out] */ IDropTarget __RPC_FAR *__RPC_FAR *ppDropTarget)
    {
        METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)
            return E_NOTIMPL;
    }
    
    
    STDMETHODIMP CCustomControlSite::XDocHostUIHandler::GetExternal( 
        /* [out] */ IDispatch __RPC_FAR *__RPC_FAR *ppDispatch)
    {
        // return the IDispatch we have for extending the object Model
        IDispatch* pDisp = (IDispatch*)theApp.m_pDispOM; //这里
        pDisp->AddRef();
        *ppDispatch = pDisp;
        return S_OK;
    }
    
    STDMETHODIMP CCustomControlSite::XDocHostUIHandler::TranslateUrl( 
        /* [in] */ DWORD dwTranslate,
        /* [in] */ OLECHAR __RPC_FAR *pchURLIn,
        /* [out] */ OLECHAR __RPC_FAR *__RPC_FAR *ppchURLOut)
    {
        METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)
            return E_NOTIMPL;
    }
    
    STDMETHODIMP CCustomControlSite::XDocHostUIHandler::FilterDataObject( 
        /* [in] */ IDataObject __RPC_FAR *pDO,
        /* [out] */ IDataObject __RPC_FAR *__RPC_FAR *ppDORet)
    {
        METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)
            return E_NOTIMPL;
    }

    三》修改App

       1.增加头文件  #include "Custsite.h"

       2.在 InitInstance()函数中 增加2处,修改一处

        新增的两处

        CCustomOccManager *pMgr = new CCustomOccManager;
    
        m_pDispOM = new CImpIDispatch;

        修改的一处

    把AfxEnableControlContainer();改为
    AfxEnableControlContainer(pMgr);

    四》htm文件为:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset=gb2312>
        <title></title>
        <script type="text/javascript">
            function CallCpp(){
                //JavaScriptCallCpp 是C++中函数,
                //与idispimp.cpp文件中javaScriptName进行对应并且与DISPID_CallCppFromJs进行绑定
                window.external.JavaScriptCallCpp('This is a test for call C++ in JavaScript');
            }
        </script>
    </head>
    <body>
        <button onclick="CallCpp()">JavaScript访问C++代码</button>
    </body>
    </html>

    五: 整个完成了

  • 相关阅读:
    Github markdown页面内跳转
    github gist 无法访问
    Install pyaudio on Ubuntu
    删除链表的倒数第N个节点
    电话号码的字母组合
    最长公共前缀
    盛最多水的容器
    字符串转化整数与回文数
    Z 字形变换
    LeetCode1-5题
  • 原文地址:https://www.cnblogs.com/dengpeng1004/p/5236717.html
Copyright © 2011-2022 走看看