IWebBrowser2 с нуля
От: cls  
Дата: 08.11.10 05:14
Оценка:
Как реализовать вэббраузер на чистом апи с нуля и отловить событие DocumentComplete без MFC/ATL?
Re: IWebBrowser2 с нуля
От: okman Беларусь https://searchinform.ru/
Дата: 08.11.10 07:31
Оценка:
Здравствуйте, cls, Вы писали:

cls>Как реализовать вэббраузер на чистом апи с нуля и отловить событие DocumentComplete без MFC/ATL?


Реализовывать нужно не IWebBrowser, а, например, IObjectWithSite + DWebBrowserEvents2.
В чем проблема ? COM-объекты можно и без ATL делать...
Re[2]: IWebBrowser2 с нуля
От: cls  
Дата: 08.11.10 08:47
Оценка:
Проблема в том, что никогда этого не делал. Исходник бы посмотреть чей, где без лишнего все основные моменты показаны.
Re: IWebBrowser2 с нуля
От: algol Россия about:blank
Дата: 08.11.10 11:53
Оценка:
Здравствуйте, cls, Вы писали:

cls>Как реализовать вэббраузер на чистом апи с нуля и отловить событие DocumentComplete без MFC/ATL?


Если вообще с нуля, то:
Embed an HTML control in your own window using plain C

Реально гораздо проще заюзать ATL-овский ActiveX контейнер CAxWindow. Это можно сделать и в чисто WinAPI приложении.
Re[2]: IWebBrowser2 с нуля
От: cls  
Дата: 08.11.10 14:26
Оценка:
Здравствуйте, algol, Вы писали:

A>Здравствуйте, cls, Вы писали:


cls>>Как реализовать вэббраузер на чистом апи с нуля и отловить событие DocumentComplete без MFC/ATL?


A>Если вообще с нуля, то:

A>Embed an HTML control in your own window using plain C

A>Реально гораздо проще заюзать ATL-овский ActiveX контейнер CAxWindow. Это можно сделать и в чисто WinAPI приложении.

А если ATL использовать, то можно пример посмотреть?
Re: IWebBrowser2 с нуля
От: nullptr_t  
Дата: 08.11.10 14:30
Оценка:
Здравствуйте, cls, Вы писали:

cls>Как реализовать вэббраузер на чистом апи с нуля и отловить событие DocumentComplete без MFC/ATL?


у миранды есть модуль, который заменяет RichEdit чата на InternetExplorer_Server (или как там его). вот там как раз напрямую к WinAPI (правда код омг). называется IEView
Re[3]: IWebBrowser2 с нуля
От: algol Россия about:blank
Дата: 08.11.10 14:32
Оценка:
Здравствуйте, cls, Вы писали:

cls>А если ATL использовать, то можно пример посмотреть?


How to add ATL control containment support to any window in Visual C++
Re: IWebBrowser2 с нуля
От: cls  
Дата: 08.11.10 16:42
Оценка:
Всем спасибо.
Re[2]: IWebBrowser2 с нуля
От: cls  
Дата: 08.11.10 18:06
Оценка:
Нашёл хороший пример и реализовал его.

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?
Re[3]: IWebBrowser2 с нуля
От: cls  
Дата: 08.11.10 18:10
Оценка:
Вдобавок хотелось бы знать, как после того, как я отловлю события, поменять ширину/высоту контрола(в коде put_width/height не работают) и проскроллить экран на заданное значение. Также хочу узнать, как убрать полосы прокрутки.
Re[4]: IWebBrowser2 с нуля
От: Carc Россия http://www.amlpages.com/home.php
Дата: 08.11.10 18:45
Оценка:
Здравствуйте, cls, Вы писали:

cls>Вдобавок хотелось бы знать, как после того, как я отловлю события, поменять ширину/высоту контрола(в коде put_width/height не работают) и проскроллить экран на заданное значение. Также хочу узнать, как убрать полосы прокрутки.

Как проскроллить на заданную подицию вертикально (сори, но код из реального проекта, но доточить до чистого WinAPI можно без особого труда)

bool CHTMLViewEx::SetIHTMLScrollPos(const ULONG lPos)
{
    bool bRet=false;
    IHTMLDocument2* const pDoc=(IHTMLDocument2*)this->GetHtmlDocument();//тут получили IHTMLDocument2;
        //понеслася
    if (pDoc) {
        ASSERT(!IsBadReadPtr(pDoc,sizeof(IHTMLDocument2)));

        HRESULT hr;
        IHTMLElement* pBody=NULL;
        hr=pDoc->get_body(&pBody);
        if ((pBody) && (S_OK==hr)) {
            IDispatch* pIHTMLElement2=GetIHTMLElement2(pBody);
            if (pIHTMLElement2) {
                DISPID dispid=0;
                if (GetScrollTopDISPID(pIHTMLElement2,dispid)) {
                    VARIANTARG var;
                    var.lVal=(long)lPos;
                    var.vt=VT_I4;
                    DISPPARAMS params;
                    params.cArgs=1;
                    params.cNamedArgs=0;
                    params.rgdispidNamedArgs=NULL;
                    params.rgvarg=&var;
                    hr=pIHTMLElement2->Invoke(dispid,IID_NULL,LOCALE_SYSTEM_DEFAULT
                        ,DISPATCH_PROPERTYPUT,&params,NULL,NULL,NULL);
                    if (S_OK==hr) bRet=true;
                }
                pIHTMLElement2->Release();
            }
            pBody->Release();
        }
    
        pDoc->Release();

        if (bRet) {
            //RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_UPDATENOW);
            CRect r;
            GetWindowRect(&r);
            //static int delta=-1;
            SetWindowPos(NULL,0,0,r.Width()-1,r.Height()-1,SWP_NOMOVE|SWP_NOREDRAW);
            SetWindowPos(NULL,0,0,r.Width(),r.Height(),SWP_NOMOVE);
            //delta*=(-1);
        }//if (bRet) {
    }
    return bRet;
}

bool CHTMLViewEx::GetIHTMLElement2UUID(UUID& uuid)
{
    if (UuidFromString(
        (unsigned char*)TEXT("3050f434-98b5-11cf-bb82-00aa00bdce0b")
        ,&uuid)==RPC_S_OK)
        return true;
    else
        return false;
}

IDispatch* CHTMLViewEx::GetIHTMLElement2(IHTMLElement* pElem)
{
    UUID uuid;
    if (!GetIHTMLElement2UUID(uuid))
        return NULL;
    IDispatch* pIHTMLElement2=NULL;
    
    const HRESULT hr=pElem->QueryInterface(uuid,(void**)&pIHTMLElement2);
    ASSERT(S_OK==hr);
    if (S_OK==hr)
        return pIHTMLElement2;
    else 
        return NULL;
}
Aml Pages Home
Re[4]: IWebBrowser2 с нуля
От: algol Россия about:blank
Дата: 09.11.10 10:11
Оценка:
Здравствуйте, cls, Вы писали:

cls>Также хочу узнать, как убрать полосы прокрутки.


В контейнере должен быть реализован IDocHostUIHandler. В его методе GetHostInfo(DOCHOSTUIINFO* pInfo) нужно вернуть флаг pInfo->dwFlags = DOCHOSTUIFLAG_SCROLL_NO
Re[5]: IWebBrowser2 с нуля
От: cls  
Дата: 09.11.10 19:00
Оценка:
Здравствуйте, algol, Вы писали:

A>Здравствуйте, cls, Вы писали:


cls>>Также хочу узнать, как убрать полосы прокрутки.


A>В контейнере должен быть реализован IDocHostUIHandler. В его методе GetHostInfo(DOCHOSTUIINFO* pInfo) нужно вернуть флаг pInfo->dwFlags = DOCHOSTUIFLAG_SCROLL_NO


В моём случае просто сделать вот так?
struct Window : IOleClientSite, IOleInPlaceSite, IDocHostUIHandler
{
...
GetHostInfo(DOCHOSTUIINFO* pInfo) 
{
 pInfo->dwFlags = DOCHOSTUIFLAG_SCROLL_NO;
}
...
}


И всё таки, может кто скажет, как прикрутить к моему контейнеру отлавливание событий. Я вообще слабо представляю какие интерфейсы нужно в него добавить и какими функциями назначить приёменики для событий.
Re[5]: IWebBrowser2 с нуля
От: sidorov18 США  
Дата: 12.11.10 07:25
Оценка:
Здравствуйте, Carc, Вы писали:

C>(сори, но код из реального проекта, но доточить до чистого WinAPI можно без особого труда)


Пробежался по коду..
А умными указателями нарочно не пользуетесь?
Re[6]: IWebBrowser2 с нуля
От: sidorov18 США  
Дата: 12.11.10 07:38
Оценка:
Здравствуйте, cls, Вы писали:

cls>Здравствуйте, algol, Вы писали:


A>>Здравствуйте, cls, Вы писали:


cls>>>Также хочу узнать, как убрать полосы прокрутки.


A>>В контейнере должен быть реализован IDocHostUIHandler. В его методе GetHostInfo(DOCHOSTUIINFO* pInfo) нужно вернуть флаг pInfo->dwFlags = DOCHOSTUIFLAG_SCROLL_NO


кстати, этот метод откючит скролл для всех случаев.
Альтернативный вариант — добавить в body scroll = 'auto'. Тогда скролл не появится, пока он не будет нужен.

cls>И всё таки, может кто скажет, как прикрутить к моему контейнеру отлавливание событий. Я вообще слабо представляю какие интерфейсы нужно в него добавить и какими функциями назначить приёменики для событий.


вот эти?
Как и все события..
Посмотри в ATL класс IDispEventImpl методы DispEventAdvise/DispEventUnadvise
Re[6]: IWebBrowser2 с нуля
От: Carc Россия http://www.amlpages.com/home.php
Дата: 12.11.10 08:18
Оценка:
Здравствуйте, sidorov18, Вы писали:

S>Здравствуйте, Carc, Вы писали:


C>>(сори, но код из реального проекта, но доточить до чистого WinAPI можно без особого труда)


S>Пробежался по коду..

S>А умными указателями нарочно не пользуетесь?
Код старый достаточно древний, там какая-то уж не помню заморочка была насчет smart pointers... "Сынок, солнце всходит и ничего не трогай". Да и вообще переписать на smart pointers две строки по моему не так уж и сложно.
Aml Pages Home
Re[7]: IWebBrowser2 с нуля
От: cls  
Дата: 13.11.10 17:43
Оценка:
S>вот эти?
S>Как и все события..
S>Посмотри в ATL класс IDispEventImpl методы DispEventAdvise/DispEventUnadvise

Без ATL.
Re[8]: IWebBrowser2 с нуля
От: sidorov18 США  
Дата: 15.11.10 07:20
Оценка:
Здравствуйте, cls, Вы писали:

S>>вот эти?

S>>Как и все события..
S>>Посмотри в ATL класс IDispEventImpl методы DispEventAdvise/DispEventUnadvise

cls>Без ATL.


Ну посмотри, как там, и перенеси этот код))) внутри там все те же вызовы.
вообще технология называется Connection Point.
Re[9]: IWebBrowser2 с нуля
От: cls  
Дата: 18.11.10 16:28
Оценка:
Здравствуйте, sidorov18, Вы писали:

S>Здравствуйте, cls, Вы писали:


S>>>вот эти?

S>>>Как и все события..
S>>>Посмотри в ATL класс IDispEventImpl методы DispEventAdvise/DispEventUnadvise

cls>>Без ATL.


S>Ну посмотри, как там, и перенеси этот код))) внутри там все те же вызовы.

S>вообще технология называется Connection Point.
А где именно внутри? Я ATL не пользовался раньше.
Re[10]: IWebBrowser2 с нуля
От: sidorov18 США  
Дата: 19.11.10 10:58
Оценка:
Здравствуйте, cls, Вы писали:

cls>Здравствуйте, sidorov18, Вы писали:


S>>Здравствуйте, cls, Вы писали:


S>>>>вот эти?

S>>>>Как и все события..
S>>>>Посмотри в ATL класс IDispEventImpl методы DispEventAdvise/DispEventUnadvise

cls>>>Без ATL.


S>>Ну посмотри, как там, и перенеси этот код))) внутри там все те же вызовы.

S>>вообще технология называется Connection Point.
cls>А где именно внутри? Я ATL не пользовался раньше.

вообще выделенное выше

вот код из atlbase.inl:

/////////////////////////////////////////////////////////////////////////////
// Connection Point Helpers

ATLINLINE ATLAPI AtlAdvise(IUnknown* pUnkCP, IUnknown* pUnk, const IID& iid, LPDWORD pdw)
{
    if(pUnkCP == NULL)
        return E_INVALIDARG;
        
    CComPtr<IConnectionPointContainer> pCPC;
    CComPtr<IConnectionPoint> pCP;
    HRESULT hRes = pUnkCP->QueryInterface(__uuidof(IConnectionPointContainer), (void**)&pCPC);
    if (SUCCEEDED(hRes))
        hRes = pCPC->FindConnectionPoint(iid, &pCP);
    if (SUCCEEDED(hRes))
        hRes = pCP->Advise(pUnk, pdw);
    return hRes;
}

ATLINLINE ATLAPI AtlUnadvise(IUnknown* pUnkCP, const IID& iid, DWORD dw)
{
    if(pUnkCP == NULL)
        return E_INVALIDARG;
        
    CComPtr<IConnectionPointContainer> pCPC;
    CComPtr<IConnectionPoint> pCP;
    HRESULT hRes = pUnkCP->QueryInterface(__uuidof(IConnectionPointContainer), (void**)&pCPC);
    if (SUCCEEDED(hRes))
        hRes = pCPC->FindConnectionPoint(iid, &pCP);
    if (SUCCEEDED(hRes))
        hRes = pCP->Unadvise(dw);
    return hRes;
}
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.