views:

29

answers:

3

I am using this code to sink events in a IWebBrowser2 webbrowser on c++:

STDMETHODIMP AdviseSink::Invoke(DISPID dispIdMember,
                                    REFIID riid,
                                    LCID lcid,
                                    WORD wFlags,
                                    DISPPARAMS* pDispParams,
                                    VARIANT* pVarResult,
                                    EXCEPINFO* pExcepInfo,
                                    UINT* puArgErr)
{

    if (!pDispParams)
        return DISP_E_PARAMNOTOPTIONAL;

    switch (dispIdMember)
    {
        case DISPID_DOCUMENTCOMPLETE:
        {
            DocumentComplete(pVarResult);
            return S_OK;
        }

        case DISPID_NAVIGATECOMPLETE2:
            return S_OK;

        default:
            return DISP_E_MEMBERNOTFOUND;
    }

    return S_OK;
}


void DocumentComplete(VARIANT *url)
{
    std::string strValue = (char*)_bstr_t(url);
}

When calling (void)DocumentComplete I get this error:

*Unhandled exception at 0x7c812afb in webhost.exe: Microsoft C++ exception: _com_error at memory location 0x0012ed50.*

If comment the line on DocumentComplete, it doesn't show any errors. Also try..catch blocks doens't catch the exception.

What I am trying to do is to use Variant * url to compare it with a std::string.

How can I do this?

A: 

http://msdn.microsoft.com/en-us/library/9k3ebasf(v=VS.100).aspx
the _bstr_t constructor takes only reference of VARIANT, instead of pointer to it.

YeenFei
Any hints on how can I compare the variant pointer with a std::string?
jarkam
@jarkam: as with any other pointer, you can go from `VARIANT*` to `VARIANT` by dereferencing it with unary operator `*`, i.e. your code should read: `_bstr_t(*url)`. You can create a `_bstr_t` from `std::string s` by using `_bstr_t(s.c_str())`. Then you can compare two `_bstr_t` objects using `==` as usual. As a side note, if you work with VARIANTs and BSTRs (and Win32 and COM in general), it is much better to use `std::wstring`, so that you properly support full Unicode and avoid costly conversions.
Pavel Minaev
Just found that VARIANT *url is null, looks like i have nothing to compare.
jarkam
A: 

YeenFei gave half of the answer. The other half is that after you get your bstr, it will point to a Unicode string not to an ANSI string. If you want to get an ANSI string, you have to do it by converting the string from Unicode to ANSI, not by converting the pointer.

Windows programmer
`_bstr_t` has an overloaded `operator char* ()` which will do a proper conversion.
Pavel Minaev
A: 

You are using the return value (an [out] parameter) as one of the event parameters. This will cause bstr_t to throw a com_error exception because the VARIANT doesn't contain a BSTR.

See the MSDN documentation for the correct DocumentComplete signature.

The event parameters are available from pDispParams not pVarResult. Assuming that it's not called with named arguments (and this event shouldn't be), the url will be available at pDispParams->rgvarg[0] and the window/frame at pDispParams->rgvarg[1]. Parameters are in the opposite order in the rgvarg array as they're declared in the idl.

If you can, I recommend instead using ATL's IDispEventSimpleImpl to implement COM event interfaces in C++ instead of implementing IDispatch yourself.

dmercredi
Thanks, your answer really helped me.
jarkam