这个是一个关于external和页面交换的问题
dll程序
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_IsOurCustomBrowser) 
   {
     if(pDispParams->rgvarg[0].vt & VT_VARIANT)
     {
       pDispParams->rgvarg[0].vt = VT_VARIANT;
       pDispParams->rgvarg[0].pvarVal->vt = VT_BSTR | VT_BYREF;
       *pDispParams->rgvarg[0].pvarVal->pbstrVal = SysAllocString(L"你好");
     }
   }
........
.......
} 页面
var str = "";
Window.External.Action(str);alert(str);应该弹出 “你好”字符
但是不能显示  谁能指点,谢

解决方案 »

  1.   

    除了实现Invoke,还必须实现GetIDsOfNames。
    STDMETHOD(GetIDsOfNames)(REFIID /*riid*/, OLECHAR ** rgszNames, UINT cNames, LCID /*lcid*/, DISPID * rgDispId)
    {
    for (UINT i=0; i<cNames; i++)
    {
    rgDispId[i] = DISPID_UNKNOWN;
    if (lstrcmpW(rgszNames[i], L"Action") == 0)
    {
    rgDispId[i] = DISPID_CB_IsOurCustomBrowser;
    }
    }
    return S_OK;
    }另外,pDispParams在这种情况下不是给你赋值用的,因为没有VT_BYREF,而是传给你一个只读字符串。如果你需要返回值,应该这样做:
    if (pVarResult)
    {
      pVarResult->vt = VT_BSTR;
      pValResult->pbstrVal = SysAllocString(L"你好");
    }
    return S_OK;在页面里这样调用:
    var str = window.external.Action();
    alert(str);
      

  2.   

    这个方法我已经实现,问题在于我想要的Action(str)中的str,而不是返回值。不过还是要谢谢你。
      

  3.   

    js中调用方法时参数没有byref关键字(VBS中是有的),如果要让js知道传递的参数是用作接收数据的([out]属性),你必须在实现IDispatch的同时也实现ITypeInfo,要么在代码中手工创建ITypeInfo,要么在注册表中注册你的接口,否则js会把所有参数解释成传入(in)参数,最多只有一个返回值。
    另一种解决方案,使用PROPERTYGET调用,但是跟上面我在1楼讲的方法调用原理是一样的。
      

  4.   

    能给一个demo么?  com刚刚入门
      

  5.   

    给你个例子
    代码如下:
    typedef IDispatchImpl<IATLOpener, &IID_IATLOpener, &LIBID_ATLMASKWRAPPERLib> ATLOpenerType;
    typedef IDispatchImpl<IATLOpenerUI, &IID_IATLOpenerUI, &LIBID_ATLMASKWRAPPERLib> ATLOpenerUIType;
    const DISPID INTERFACEMASK = 0xFFFF0000;
    const DISPID DISPIDMASK  = 0x0000FFFF;
    const DISPID IDISPATLOPENER = 0x00010000;
    const DISPID IDISPATLOPENERUI = 0x00020000;/////////////////////////////////////////////////////////////////////////////
    // CATLOpener
    STDMETHODIMP CATLOpener::GetIDsOfNames(REFIID riid,
    LPOLESTR* rgszNames,
    UINT cNames,
    LCID lcid,
    DISPID* rgdispid)
    {
    HRESULT hr = DISP_E_UNKNOWNNAME; hr = ATLOpenerType::GetIDsOfNames(riid,
    rgszNames, cNames, lcid, rgdispid);
    if (SUCCEEDED(hr))
    {
    rgdispid[0] |= IDISPATLOPENER;
    return hr;
    } hr = ATLOpenerUIType::GetIDsOfNames(riid,
    rgszNames,
    cNames,
    lcid,
    rgdispid);
    if (SUCCEEDED(hr))
    {
    rgdispid[0] |= IDISPATLOPENERUI;
    return hr;
    } return hr;
    }STDMETHODIMP CATLOpener::Invoke(DISPID dispidMember,
     REFIID riid,
     LCID lcid,
     WORD wFlags,
     DISPPARAMS* pdispparams,
     VARIANT* pvarResult,
     EXCEPINFO* pexcepinfo,
     UINT* puArgErr)
    {
    DWORD dwInterface = (dispidMember & INTERFACEMASK);
    dispidMember &= DISPIDMASK; switch(dwInterface)
    {    case IDISPATLOPENERUI:
    return ATLOpenerUIType::Invoke(dispidMember,
    riid,
    lcid,
    wFlags,
    pdispparams,
    pvarResult,
    pexcepinfo,
    puArgErr);    case IDISPATLOPENER:
        default:
    //return DISP_E_MEMBERNOTFOUND;
    return ATLOpenerType::Invoke(dispidMember,
    riid,
    lcid,
    wFlags,
    pdispparams,
    pvarResult,
    pexcepinfo,
    puArgErr);
    }}
    然后在添加你的Action方法,它的str参数是传入还是传出随便怎么实现都可以.
      

  6.   

    重金诚评聘C++
    http://topic.csdn.net/u/20080227/14/8bce0844-bd15-42f0-9cda-a343d5d6601b.html?seed=2111206245
      

  7.   

    重金诚评聘C++
    http://topic.csdn.net/u/20080227/14/8bce0844-bd15-42f0-9cda-a343d5d6601b.html?seed=2111206245