none
javascript 调用c++接口,传递IDispatch参数,无法解析. RRS feed

  • 问题

  • 我需要在CHtmlView中和javascript相互调用,  javascript 调用c++接口,传递IDispatch参数,

    通过external返回ChtmlView子类对象, 外部能够调用.

        <script language="javascript">
           
            myBrowser=window.external; //ok
            var myDoc = myBrowser.GetDoc(); // ok 
            alert(myDoc.PropertyName); //ok get doc propertyname
            myBrowser.CB_FunctionInsallApp(myDoc); //fail !  内部c++代码无法识别Doc对象.
    
        </script>

    但是需要把myDoc对象传入到CB_FunctionInsallApp中, c++内部无法解析, 请问下,需要如何让内部能够获解析成WebDoc指针.

    void CPlazaBrowser::CB_FunctionInsallApp(IDispatch *pDispVal)
    {
    	//want get the web doc pointer,but is null
    	CWebDoc* pWebDoc = (CWebDoc*)CCmdTarget::FromIDispatch(pDispVal);
    	if (pWebDoc) // is null, why?? 无法获取到对象
    	{
    		
    	}
    
    }

    2020年8月5日 8:00

全部回复

  • 名称 类型
    pDispVal 0x000001a921250240 <无可用信息,未为 mshtml.dll 加载任何符号> IDispatch *

    没有办法发截图

    2020年8月5日 8:35
  • 您好:

    感谢您在MSDN中文论坛发帖提问。

    >>javascript 调用c++接口,传递IDispatch参数,无法解析.

    你是否在头文件中添加宏:DECLARE_DISPATCH_MAP

    如果CCmdTarget您程序中的-derived类支持OLE Automation,则该类必须提供一个调度映射以公开其方法和属性。

    Best Regards,

    Jeanine Zhang


    "Visual c++" forum will be migrating to a new home on Microsoft Q&A !
    We invite you to post new questions in the "Developing Universal Windows apps" forum’s new home on Microsoft Q&A !
    For more information, please refer to the sticky post.

    2020年8月6日 8:02
    版主
  • 您好, 我是如下调用:

    1. 我通过js调用c++函数,GetDoc()

        <script language="javascript">
            var myDoc = myBrowser.GetDoc(); // ok 
        </script>

    2. 

    //c++ 代码

    LPDISPATCH CPlazaBrowser::GetDoc() { LPDISPATCH pDisp= m_pDoc->GetIDispatch(TRUE); //在此处调用GetIDispatch函数 CWebDoc* p = (CWebDoc*)CCmdTarget::FromIDispatch(pDisp); //【立即测试】 测试可以获取到CWebDoc指针 return pDisp; }


    3. js调用

      myBrowser.CB_FunctionInsallApp(myDoc); //fail !  内部c++代码无法识别Doc对象.

    4. c++函数

    void CPlazaBrowser::CB_FunctionInsallApp(IDispatch *pDispVal)
    {
    	//want get the web doc pointer,but is null
    	CWebDoc* pWebDoc = (CWebDoc*)CCmdTarget::FromIDispatch(pDispVal); 
    	if (pWebDoc) // is null, why?? 获取到对象为0x00000
    	{
    		
    	}
    
    }

    2020年8月12日 6:07
  • CPlazaBrowser 类的定义

    class CPlazaBrowser : public CHtmlView
    {
    	DECLARE_DYNCREATE(CPlazaBrowser)
    public:
    	CPlazaBrowser();
    	~CPlazaBrowser();
    
    	HRESULT OnGetExternal(LPDISPATCH *lppDispatch);
    	void CB_FunctionInsallApp(IDispatch *pDispVal);
    	void OnWindowClosing(BOOL IsChildWindow, BOOL *bCancel);
    	LPDISPATCH GetDoc();
    
    	VOID PostNcDestroy();
    	DECLARE_MESSAGE_MAP()
    	DECLARE_EVENTSINK_MAP()
    	DECLARE_DISPATCH_MAP()
    	DECLARE_INTERFACE_MAP()
    
    private:
    	CWebDoc* m_pDoc;
    	LPDISPATCH m_lpDisp;
    };

    CPlazaBrowser实现

    IMPLEMENT_DYNCREATE(CPlazaBrowser, CHtmlView)
    
    
    BEGIN_MESSAGE_MAP(CPlazaBrowser, CHtmlView)
    END_MESSAGE_MAP()
    
    BEGIN_EVENTSINK_MAP(CPlazaBrowser, CHtmlView)
    	ON_EVENT(CPlazaBrowser, AFX_IDW_PANE_FIRST, DISPID_WINDOWCLOSING, OnWindowClosing, VTS_BOOL VTS_PBOOL)
    END_EVENTSINK_MAP()
    
    BEGIN_DISPATCH_MAP(CPlazaBrowser, CHtmlView)
    	DISP_PROPERTY_EX(CPlazaBrowser, "GetDoc", GetDoc, SetNotSupported, VT_DISPATCH)
    	DISP_FUNCTION(CPlazaBrowser, "CB_FunctionInsallApp", CB_FunctionInsallApp, VT_EMPTY, VTS_DISPATCH)
    	//DISP_FUNCTION(CPlazaBrowser, "CB_FunctionTryPlay", CB_FunctionTryPlay, VT_EMPTY, VTS_DISPATCH)
    END_DISPATCH_MAP()
    
    // {412E78F1-3B2B-41CB-9C1E-C02D6B453FCF}
    static const IID IID_IBROWSER =
    { 0x412e78f1, 0x3b2b, 0x41cb, { 0x9c, 0x1e, 0xc0, 0x2d, 0x6b, 0x45, 0x3f, 0xcf } };
    
    
    BEGIN_INTERFACE_MAP(CPlazaBrowser, CHtmlView)
    	INTERFACE_PART(CPlazaBrowser, IID_IBROWSER, Dispatch)
    END_INTERFACE_MAP()
    
    
    
    CPlazaBrowser::CPlazaBrowser()
    {
    	// 允許自動化
    	EnableAutomation();
    	if (!m_pDoc)
    	{
    		m_pDoc = new CWebDoc();
    	}
    }
    LPDISPATCH CPlazaBrowser::GetDoc()
    {
    
    	LPDISPATCH pDisp = m_pDoc->GetIDispatch(TRUE);
    	CWebDoc* p = (CWebDoc*)CCmdTarget::FromIDispatch(pDisp); //ok能转成CWebDoc对象.
    	return pDisp;
    }
    
    //消耗处理
    VOID CPlazaBrowser::PostNcDestroy()
    {
    	return;
    }
    
    //关闭事件
    void CPlazaBrowser::OnWindowClosing(BOOL IsChildWindow, BOOL *bCancel)
    {
    	//禁止关闭
    	if ((IsChildWindow == FALSE) && (bCancel != NULL))
    	{
    		*bCancel = TRUE;
    	}
    	return;
    }
    
    CPlazaBrowser::~CPlazaBrowser()
    {
    }
    
    void CPlazaBrowser::CB_FunctionInsallApp(IDispatch *pDispVal)
    {
    	//want get the web doc pointer,but is null
    	CWebDoc* pWebDoc = (CWebDoc*)CCmdTarget::FromIDispatch(pDispVal);
    	if (pWebDoc) // is null, why?? duixia
    	{
    	}
    }
    
    
    HRESULT CPlazaBrowser::OnGetExternal(LPDISPATCH *lppDispatch)
    {
    	// 返回自身的IDispatch介面
    	*lppDispatch = GetIDispatch(TRUE);
    	return S_OK;
    }
    

    CWebDoc类定义

    class CWebDoc : public CCmdTarget
    {
    	DECLARE_DYNCREATE(CWebDoc)
    
    public:
    	CWebDoc();
    	~CWebDoc()
    	{
    
    	}
    	CString m_name;
    	BSTR PropertyName();
    
    
    	DECLARE_MESSAGE_MAP()
    	DECLARE_EVENTSINK_MAP()
    	DECLARE_DISPATCH_MAP()
    	DECLARE_INTERFACE_MAP()
    };

    CWebDoc类实现

    IMPLEMENT_DYNCREATE(CWebDoc, CCmdTarget)
    
    BEGIN_MESSAGE_MAP(CWebDoc, CCmdTarget)
    END_MESSAGE_MAP()
    
    BEGIN_EVENTSINK_MAP(CWebDoc, CCmdTarget)
    END_EVENTSINK_MAP()
    
    BEGIN_DISPATCH_MAP(CWebDoc, CCmdTarget)
    	DISP_PROPERTY_EX(CWebDoc, "PropertyName", PropertyName, SetNotSupported, VT_BSTR)
    END_DISPATCH_MAP()
    
    static const IID IID_IWebDoc =
    { 0x2db1450e, 0x905c, 0x48c5, { 0xab, 0xe3, 0x18, 0x90, 0xcb, 0x9b, 0x26, 0x27 } };
    
    BEGIN_INTERFACE_MAP(CWebDoc, CCmdTarget)
    	INTERFACE_PART(CWebDoc, IID_IWebDoc, Dispatch)
    END_INTERFACE_MAP()
    
    
    
    //-----//-----//-----//-----//-----//-----//-----//-----//-----//-----//-----//-----//-----//-----//-----//-----//-----//-----//-----//-----
    CWebDoc::CWebDoc()
    {
    	EnableAutomation();
    	m_name = L"CWebDoc";
    }
    
    BSTR CWebDoc::PropertyName()
    {
    	return m_name.AllocSysString();
    }


    • 已编辑 fjcharles 2020年8月12日 6:13 重新编辑
    2020年8月12日 6:07
  • 我有添加了DECLARE_DISPATCH_MAP 相关的宏定义,

    在js调用c++传入对象,没有办法转成先前的传出去的指针,

    帖子没法法传附件,只能贴下代码. 请帮忙看下是不是需要调用其他相关函数.谢谢


    • 已编辑 fjcharles 2020年8月12日 6:15 修改
    2020年8月12日 6:15
  • 你好,

    我认为导致这个问题的原因是在JS中没有按地址(引用)传递,只有按值传递。

    我建议你可以参考这个链接:https://stackoverflow.com/questions/13104494/does-javascript-pass-by-reference

    Best Regards,

    Jeanine Zhang


    "Visual c++" forum will be migrating to a new home on Microsoft Q&A !
    We invite you to post new questions in the "Developing Universal Windows apps" forum’s new home on Microsoft Q&A !
    For more information, please refer to the sticky post.

    2020年8月13日 3:04
    版主
  • 你好,

    感觉不像是js按值传递, 我新建一个activex控件, 不使用chtmlview控件, js也是同样写法,

    myBrowser.CB_FunctionInsallApp(myDoc); //fail !  内部c++代码无法识别Doc对象.

    在c++内部可以直接调用获取值,

    	CWebDoc* pWebDoc = (CWebDoc*)CCmdTarget::FromIDispatch(pDispVal);

     不知道active控件和chtmlview有什么区别,看调用堆栈看不到调用的地方,直接进入到c++的CB_FunctionInsallApp函数.

    2020年8月13日 16:12
  • 你好:

    一个JavaScript对象传到了C++这边以后,就变成了一个IDispatch*,然后我们用CComDispatchDriver接管这个IDispatch*后,就可以调用这个JavaScript对象的方法,获取这个JavaScript对象的属性,实际上CComDispatchDriver就是对IDispatch的包装,最终都是调用IDispatch::Invoke。同理,如果我们在C++这边构造出一个IDispatch*并传递给JavaScript,那么JavaScript就可以把这个IDispatch*当做一个JavaScript对象来使用,自然它就可以调用这个对象的方法,修改这个对象的属性,最终就可以实现调用C++函数,修改C++对象的成员变量,实际上JavaScript调用C++也是通过IDispatch::Invoke来调用。

    我认为为了实现此功能,首先我们应该获得一个指向IHTMLDocument2接口的指针。IDispatch在HTML文档中获取JavaScript对象。获取DISPIDJavaScript函数的给定名称。将参数放入DISPPARAM结构中。通过使用IDispatch接口的Invoke方法来调用JavaScript函数。

    Best Regards,

    Jeanine Zhang


    "Visual c++" forum will be migrating to a new home on Microsoft Q&A !
    We invite you to post new questions in the "Developing Universal Windows apps" forum’s new home on Microsoft Q&A !
    For more information, please refer to the sticky post.

    2020年8月14日 2:11
    版主