[COM] ActiveX хостинг через голый winapi

Flack_bfsp

Мне нужно создать объект COM на формочке. Используется голый WinAPI, MFC и ATL использовать нельзя.
Для этого я делаю класс-обёртку, вот его конструктор:
 

Host::Host(HWND hwndParent): m_hwndParent(hwndParent)
{
    IUnknown* pUnknown;
    IConnectionPoint* pConnectionPoint;
    IConnectionPointContainer* pConnectionPointContainer;
    IOleInPlaceObject* pInPlaceObject;
    IOleObject* pObject;
    DWORD dwAdviseCookie;
    m_dwRefCount = 1;
    m_hwndParent = hwndParent;
    m_pClientSite = new ClientSite(this);
    m_pInPlaceSite = new InPlaceSite(this);
    m_pEvents = new Events(this);
    CoCreateInstance(CLSID_WebBrowser, NULL, CLSCTX_ALL, IID_IUnknown, (void**&pUnknown;
    pUnknown->QueryInterface(IID_IOleObject, (void**&pObject;
    pObject->SetClientSite(m_pClientSite);
    RECT rect;
    GetClientRect(hwndParent, &rect);
    rect.right -= rect.left;
    rect.bottom -= rect.top;
    rect.left = 0;
    rect.top = 0;
    pUnknown->QueryInterface(IID_IOleInPlaceObject, (void**&pInPlaceObject;
pInPlaceObject->SetObjectRects(&rect, &rect);
    pInPlaceObject->Release;
    pObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, m_pClientSite, 0, hwndParent, &rect);
    pObject->Release;
    pUnknown->QueryInterface(IID_IConnectionPointContainer, (void**&pConnectionPointContainer;
    pConnectionPointContainer->FindConnectionPoint(DIID_DWebBrowserEvents2, &pConnectionPoint);
    pConnectionPoint->Advise(m_pEvents, &dwAdviseCookie);
    pConnectionPointContainer->Release;
    pConnectionPoint->Release;
    pUnknown->QueryInterface(IID_IWebBrowser2, (void**)&m_pWebBrowser);
CreateBindCtx(0, &m_pBCtx);
m_pWebBrowser->put_Silent(FALSE);
    if (pUnknown)
pUnknown->Release;
}
 

Всё работает замечательно, объект создаётся на окошке. Но стоит заменить WebBrowser на, к примеру, MediaPlayer, и компонент не отображается. При этом все вызовы функций возвращают S_OK. Как я понял, проблема в приклеивании компонента к окошку.
У обёртки есть такой метод:
 

STDMETHODIMP Host::QueryInterface(REFIID riid, void ** ppvObject)
{
    if (ppvObject == NULL)
return E_INVALIDARG;
    *ppvObject = NULL;
    if (riid == IID_IUnknown)
     *ppvObject = this;
    else if (riid == IID_IOleClientSite)
     *ppvObject = m_pClientSite;
    else if (riid == IID_IOleInPlaceSite)
     *ppvObject = m_pInPlaceSite;
    else if (riid == DIID_DWebBrowserEvents2)
     *ppvObject = m_pEvents;
    else if (riid == IID_IDocHostUIHandler)
     *ppvObject = m_pUIHandler;
    if (*ppvObject == NULL)
return E_NOINTERFACE;
    AddRef;
    return S_OK;
}

Я ставил брейкпойт на него, глядел, какие интерфейсы нужны при создании компонента. Когда заменяешь WebBrowser на MediaPlayer, среди запрашиваемых интерфейсов появляется некий IAdviseSink. Может быть. проблема именно в нём? Никто не знает. что это за птица и как её едят?

Flack_bfsp

Да! Забыл сказать - при использовании AtlAxCreateControlEx и WebBrowser и MediaPlayer создаются без проблем. Не пойму, в чём их разница.

Dasar

За AtlAxCreateControl скрывается несколько десятков килобайт кода.
Ты все эти килобайты хочешь заменить десятью строчками?

Dasar

> Как я понял, проблема в приклеивании компонента к окошку.
твои Site-ы точно реализуют нужные функционал?

Flack_bfsp

Судя по всему, нет, раз не работает.
Но для WebBrowser-а функциональности хватало.

Flack_bfsp

Оказалось, что ошибка не в этом. Проблема была в том, что у создаваемого компонента был жуткий рект, за пределами родительского окна. Когда ставишь его ручками, всё становится хорошо. Странно, что WebBrowser этого не требовал...
Оставить комментарий
Имя или ник:
Комментарий: