首先需要编写一个类,实现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();