Нашёл хороший пример и реализовал его.
struct Window : IOleClientSite, IOleInPlaceSite
{
public:
/****************** IUnknown ***************************************************/
HRESULT __stdcall QueryInterface( REFIID riid, void** ppvObject )
{
if( !ppvObject )
return E_POINTER;
if( riid==IID_IUnknown || riid==IID_IOleWindow || riid==IID_IOleInPlaceSite )
return *ppvObject = (void*)dynamic_cast<IOleInPlaceSite*>(this), S_OK;
if( riid==IID_IOleClientSite )
return *ppvObject = (void*)dynamic_cast<IOleClientSite*>(this), S_OK;
*ppvObject = NULL;
return E_NOINTERFACE;
}
ULONG __stdcall AddRef() { return 1; /*one instance*/ }
ULONG __stdcall Release() { return 1; /*one instance*/ }
/********************* IOleWindow ***********************************************/
HRESULT __stdcall GetWindow( HWND *phwnd ) { return phwnd?(*phwnd = this->hwnd, S_OK):E_INVALIDARG; }
HRESULT __stdcall ContextSensitiveHelp( BOOL ) { return S_OK; }
/********************* IOleInPlaceSite ******************************************/
HRESULT __stdcall CanInPlaceActivate() { return S_OK; }
HRESULT __stdcall OnInPlaceActivate() { return S_OK; }
HRESULT __stdcall OnUIActivate() { return S_OK; }
HRESULT __stdcall GetWindowContext( IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
{
if( !(ppFrame && ppDoc && lprcPosRect && lprcClipRect && lpFrameInfo) )
return E_INVALIDARG;
*ppFrame = NULL;
*ppDoc = NULL;
GetClientRect( this->hwnd, lprcPosRect );
GetClientRect( this->hwnd, lprcClipRect );
lpFrameInfo->fMDIApp = false;
lpFrameInfo->hwndFrame = this->hwnd;
lpFrameInfo->haccel = 0;
lpFrameInfo->cAccelEntries = 0;
return S_OK;
}
HRESULT __stdcall Scroll( SIZE ) { return S_OK; }
HRESULT __stdcall OnUIDeactivate( BOOL ) { return S_OK; }
HRESULT __stdcall OnInPlaceDeactivate() { return S_OK; }
HRESULT __stdcall DiscardUndoState() { return S_OK; }
HRESULT __stdcall DeactivateAndUndo() { return S_OK; }
HRESULT __stdcall OnPosRectChange( LPCRECT ) { return S_OK; }
/*************************************** IOleClientSite ***************************************/
HRESULT __stdcall SaveObject() { return S_OK; }
HRESULT __stdcall GetMoniker( DWORD, DWORD, IMoniker **ppmk ) { return *ppmk = NULL, E_NOTIMPL; }
HRESULT __stdcall GetContainer( IOleContainer** ppContainer ) { return *ppContainer=NULL, E_NOINTERFACE; }
HRESULT __stdcall ShowObject() { return S_OK; }
HRESULT __stdcall OnShowWindow( BOOL ) { return S_OK; }
HRESULT __stdcall RequestNewObjectLayout() { return E_NOTIMPL; }
// данные
HWND hwnd;
IWebBrowser2* webBrowser;
};
Window* window;
IOleObject* oleObject;
Непосредственно функция для создания контрола
int CreateWebBrowser1(HWND hWnd)
{
RECT rect;
HRESULT r;
window = new Window;
window->hwnd = hWnd;
SetWindowLong(hWnd, GWL_USERDATA, (LONG)window);
r = CoCreateInstance(CLSID_WebBrowser, NULL, CLSCTX_INPROC, IID_IOleObject, (void**)&oleObject);
if(FAILED(r))
{
MessageBox(0, L"error", L"error", MB_OK);
return 1;
}
r = oleObject->SetClientSite(dynamic_cast<IOleClientSite*>(window));
if(FAILED(r))
{
MessageBox(0, L"oleObject->SetClientSite()", L"Error", MB_OK);
return 1;
}
GetClientRect(hWnd, &rect);
rect.left = 0;
rect.top = 0;
rect.right = 100;
rect.bottom = 100;
r = oleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, dynamic_cast<IOleClientSite*>(window), 0, hWnd, &rect);
if(FAILED(r))
{
MessageBox(0, L"oleObject->DoVerb()", L"Error", MB_OK);
return 1;
}
r = oleObject->QueryInterface( IID_IWebBrowser2, (void**)&window->webBrowser);
if(FAILED(r))
{
MessageBox(0, L"oleObject->QueryInterface()", L"Error", MB_OK);
return 1;
}
oleObject->Release();
window->webBrowser->put_Height(100);
window->webBrowser->put_Width(100);
window->webBrowser->Release();
return true;
}
int StartBrowsing()
{
HRESULT r;
VARIANT empty;
VariantInit(&empty);
r = window->webBrowser->Navigate(L"http://url/", &empty,&empty,&empty,&empty);
window->webBrowser->Release();
return 0;
}
Всё работает. Теперь как к этому прикрутить обработку событий, таких как DocumentComplete?