C++中XMLHTTPRequest异步使用onreadystatuschange

首先需要编写一个类,实现IDispatch接口,然后把这个类传进去,代码如下:
#ifndef XMLHTTPEVENTSINK_H_
#define XMLHTTPEVENTSINK_H_

#include "msxml.h"
#include <winnt.h>
#include <wtypes.h>
#include <windows.h>

class XMLHttpEventSink : public IDispatch
{
public:
    XMLHttpEventSink(IXMLHttpRequest* request, HANDLE completedEvent) : _refCount(1), _request(request), _completedEvent(completedEvent)
    {
        // Don't increase the reference count to the request object; doing so would create a circular reference
        // and thus a memory leak.
    }
    virtual ~XMLHttpEventSink() { }

    // IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);
STDMETHODIMP_(ULONG) AddRef();
    STDMETHODIMP_(ULONG) Release();

    // IDispatch
STDMETHODIMP GetTypeInfoCount(UINT *pctinfo);
STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo);
STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId);
    STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);
private:
    LONG _refCount;
    IXMLHttpRequest* _request;
    HANDLE _completedEvent;
};

#endif
-=====================================================
#include "XMLHttpEventSink.h"

STDMETHODIMP XMLHttpEventSink::QueryInterface(const IID &riid, void **ppvObject)
{
    if( ppvObject == NULL )
        return E_INVALIDARG;

    *ppvObject = NULL;

    if( riid == IID_IUnknown )
        *ppvObject = static_cast<IUnknown*>(this);
    else if( riid == IID_IDispatch )
        *ppvObject = static_cast<IDispatch*>(this);

    if( *ppvObject == NULL )
        return E_NOINTERFACE;

    AddRef();

    return S_OK;
}

STDMETHODIMP_(ULONG) XMLHttpEventSink::AddRef()
{
    return InterlockedIncrement(&_refCount);
}

STDMETHODIMP_(ULONG) XMLHttpEventSink::Release()
{
    LONG refCount = InterlockedDecrement(&_refCount);
    if( refCount == 0 )
    {
        delete this;
        return 0;
    }
    else
        return refCount;
}

STDMETHODIMP XMLHttpEventSink::GetTypeInfoCount(UINT *pctinfo)
{
    return E_NOTIMPL;
}

STDMETHODIMP XMLHttpEventSink::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
{
    return E_NOTIMPL;
}

STDMETHODIMP XMLHttpEventSink::GetIDsOfNames(const IID &riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
{
    return E_NOTIMPL;
}

STDMETHODIMP XMLHttpEventSink::Invoke(DISPID dispIdMember, const IID &riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
    // Since this class isn't used for anything else, Invoke will get called only for onreadystatechange, and
    // dispIdMember will always be 0.

long state;
// Retrieve the state
_request->get_readyState(&state);
    if (state == 4)
    {
        // The request has completed.
        // Get the request status.
        long status;
        _request->get_status(&status);

       if( status == 200 )
  {
   // Get the response body if we were successful.
   BSTR body;
   _request->get_responseText(&body);
  }

        // Signal the main thread we're done.
        SetEvent(_completedEvent);
    }
return S_OK;
}
-===================================================
调用代码:
CoInitialize(NULL);
IXMLHttpRequest* pRequest = GetXMLHTTP();

pRequest->setRequestHeader(L"Content-Type", L"text/xml");
pRequest->setRequestHeader("SOAPAction","http://schemas.microsoft.com/exchange/services/2006/messages/FindItem");
WideString url = L"http://mail.pudong.sh/ews/exchange.asmx";

tagVARIANT account;
account.vt = VT_BSTR;
account.bstrVal = L"MailAdmin@pudong.sh";

tagVARIANT password;
password.vt = VT_BSTR;

password.bstrVal = L"App1234";
tagVARIANT bAsync;
bAsync.vt = VT_BOOL;
bAsync.boolVal = FALSE;

WideString dataStr = L"";
tagVARIANT data;
data.vt = VT_BSTR;
data.bstrVal = dataStr.c_bstr();

HANDLE completedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
pRequest->open(L"POST", url.c_bstr(), bAsync, account, password);

IDispatch *sink = new XMLHttpEventSink(pRequest, completedEvent);
pRequest->put_onreadystatechange(sink);
pRequest->send(data);

sink->Release();
pRequest->Release();

WaitForSingleObject(completedEvent, INFINITE);
CloseHandle(completedEvent);

CoUninitialize();

原文地址:https://www.cnblogs.com/yuanxiaoping_21cn_com/p/1332927.html