VARIANT var;
VariantInit(&var);
var = m_spApp->InputBox(_bstr_t(_T("选择范围")),COleVariant(_T("选择范围")),vtMissing,vtMissing,
vtMissing,vtMissing,vtMissing, COleVariant(long(8)));        //调用了一个com对象的指针
if (var.pdispVal == NULL)
{
return;
} CComQIPtr<Excel::Range> spRange;
spRange.Attach((Excel::Range*)(var.pdispVal)); m_nCount = ((Excel::Range*)(var.pdispVal))->GetCount();以上函数m_spApp->InputBox返回的是一个Excel::Range对象,但是返回值是以VARIANT对象返回的,因此我只能获得var.pdispVal,我想把它转换成Excel::Range的com对象,来调用它的com方法GetCount,可是这样之后会报错
First-chance exception at 0x7c812aeb in EXCEL.EXE: Microsoft C++ exception: _com_error at memory location 0x0013f76c..
Unhandled exception at 0x7c812aeb in EXCEL.EXE: Microsoft C++ exception: _com_error at memory location 0x0013f76c..
请问是什么原因呢?
用什么方法可以调用我想要的com方法呢??

解决方案 »

  1.   

    CComQIPtr<Excel::Range> spRange = var.pdispVal;
    spRange->GetCount();
      

  2.   

    如2楼var.pdispVal并不是一个Excel::Range接口而是IDispatch接口指针,所以你需要查询1下
      

  3.   


    CComQIPtr <Excel::Range> spRange = var.pdispVal;
    if ( spRange )
        spRange->GetCount();
    else
        ;// 不支持此接口
      

  4.   


    在“spRange = var.pdispVal;”赋值的时候出错, CComQIPtr(_In_opt_ IUnknown* lp) throw()
    {
    if (lp != NULL)
    lp->QueryInterface(*piid, (void **)&p);
    }
    停在QueryInterface这一句,我如何直接用QueryInterface呢??
      

  5.   

    非常奇怪的是,如果我用excel2003的话,那段代码是没问题的,如果用excel2007就会出现上面的错。
      

  6.   


    可能是Execl2007不支持这个接口,但不至于QueryInterface不返回。
    不解
      

  7.   

    在excel2007下
    Excel::FontPtr spFontXls;
    spFontXls = spRange->GetFont();
    //spFontXls.Attach(spRange->GetFont());
    ATLASSERT(spFontXls);
    spFontXls->PutBold(COleVariant(short(TRUE)));
    只要调用了接口的Attach,能正常获得智能指针,但是调用它的方法就会出错比如上面的PutBold,在excel2003下却正常。注:改spFontXls.Attach(spRange->GetFont());为spFontXls = spRange->GetFont();之后,上面的代码再2007下也正常了
      

  8.   

    spRange这个接口指针使用正常吗?
    不用Excel::FontPtr而使用CComQIPtr<Excel::Font>又如何呢?
      

  9.   


    单步调试,在使用excel2007时
    #pragma implementation_key(360)
    inline void Excel::Font::PutBold ( const _variant_t & _arg1 ) {
        _com_dispatch_method(this, 0x60, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, 
            L"\x000c", &_arg1);
    }
    在调用com接口的时候出错了,跟不进去了,要怎么看呢?
      

  10.   


                    CComQIPtr<Excel::Font> spFontXls;
    //Excel::FontPtr spFontXls;
    //spFontXls = spRange->GetFont();
    spFontXls.Attach(spRange->GetFont());
    ATLASSERT(spFontXls);
    spFontXls->PutBold(COleVariant(short(TRUE)));  ThsXlsSlug.dll!Excel::Font::PutBold(const _variant_t & _arg1={...})  Line 2672 + 0x1a bytes C++
      ThsXlsSlug.dll!_com_dispatch_method(IDispatch * pDispatch=0x05656b40, long dwDispID=96, unsigned short wFlags=4, unsigned short vtRet=0, void * pvRet=0x00000000, const wchar_t * pwParamInfo=0x050dcfbc, ...)  Line 93 + 0x10 bytes C++
    > ThsXlsSlug.dll!_com_raise_error(HRESULT hr=-2147319765, IErrorInfo * perrinfo=0x00000000)  Line 19 C++
      msvcr90d.dll!_CxxThrowException(void * pExceptionObject=0x0013dbc0, const _s__ThrowInfo * pThrowInfo=0x05129880)  Line 161 C++还是在调用com接口_com_dispatch_method的时候抛出异常。
      

  11.   


    CComQIPtr<Excel::Font> spFontXls;
    //Excel::FontPtr spFontXls;
    //spFontXls = spRange->GetFont();
    //spFontXls.Attach(spRange->GetFont());
    spFontXls = spRange->GetFont();
    ATLASSERT(spFontXls);
    spFontXls->PutBold(COleVariant(short(TRUE)));
    如果不用Attach,就没有问题
      

  12.   

    CComQIPtr <Excel::Font> spFontXls;
    //Excel::FontPtr spFontXls;
    //spFontXls = spRange->GetFont();
    //spFontXls.Attach(spRange->GetFont());
    spFontXls = spRange->GetFont();
    ATLASSERT(spFontXls);
    spFontXls->PutBold(COleVariant(short(TRUE))); 这样是正常的?那可能是说对于03来说GetFont返回的指针与Excel::Font接口虚表兼容,所以你可以直接attach
    但 07则不是这样,你直接attach后调用虚表找到的不是你期望的调用,所以需要先查询Excel::Font接口
      

  13.   

    VARIANT var; 
    VariantInit(&var); 
    var = m_spApp->InputBox(_bstr_t(_T("选择范围")),COleVariant(_T("选择范围")),vtMissing,vtMissing, 
    vtMissing,vtMissing,vtMissing, COleVariant(long(8))); 
    CComQIPtr<Excel::Range> spRange;
    spRange = var.pdispVal;在上面最后一句代码中var的IDispatch指针QueryInterface时出错,是不是表示我要的对象Excel::Range和那个接口var.pdispVal不一致阿?
      

  14.   

    是不是有个get_Count方法,试试。
    一般来说QueryInterface不会异常
      

  15.   

    我的意思是试试调用裸方法并使用ATL的智能指针,不用编译器生成的包装看看。
      

  16.   

    放结果了,郁闷死了,我采用下面这种方法就可以了,CComQIPtr <Excel::Range> spRange(m_spApp->InputBox(_bstr_t(strDetail),COleVariant(_T("选择范围")),vtMissing,vtMissing,
    vtMissing,vtMissing,vtMissing, COleVariant(long(8))));
    是不是在
    VARIANT var; 
    VariantInit(&var); 
    var = m_spApp->InputBox(_bstr_t(strDetail),COleVariant(_T("选择范围")),vtMissing,vtMissing,
    vtMissing,vtMissing,vtMissing, COleVariant(long(8)));这个变量的赋值过程中IDispatch指针有什么变化,导致接下来的赋值出现问题呢???
      

  17.   


    貌似不可以这么赋值吧m_spApp->InputBox的返回值是IDispatch?VARIANT vt;
    VariantInit(&var);
    vt.vt = VT_DISPATCH;
    vt.pdispVal =  m_spApp->InputBox(_bstr_t(strDetail),COleVariant(_T("选择范围")),vtMissing,vtMissing, vtMissing,vtMissing,vtMissing, COleVariant(long(8))); 
      

  18.   

    m_spApp->InputBox的返回在vba上说明是variant的,在excel2003上这样赋值是没问题的。
      

  19.   

    Dispatch是一个调度接口,可以使用它来获取其它的接口的!
    具体详情查看COM技术内幕!那里说得很详细!
      

  20.   

    我目前只是因为项目需求用了com,没有系统的了解,看来我这种态度很不好啊,回去要仔细研究下com技术了。多谢各位了,尤其是sys0005 和Amuro1987218,呵呵如果218是你生日的话,那我们就是同一天生日了,多谢了!!