Kselax.ru

Hacker Kselax — the best hacker in the world

Menu
  • Блог
  • Контакты
  • wp plugin генератор
  • Русский
    • Русский
    • English
Menu

MFC DECLARE_EVENTSINK_MAP отлов событий в WebBrowser

Posted on 19 августа, 201519 августа, 2015 by admin

Здорова! Сегодня разберем такой макрос как DECLARE_EVENTSINK_MAP. В WebBrowser существуют события DWebBrowserEvents2, почитать за этот интерфейс можно тут.  За DECLARE_EVENTSINK_MAP читаем тут.

Приступим к реализации отлова событий. Создаем приложение MFC на основе диалоговых окон, подключаем и WebBrowser, вообще директиву #import можно не использовать, WebBrowser походу уже подключен по умлочанию имеются интерфейсы, потому что когда мы подключаем с помощью #import у нас происходит конфликт имен и нужно обязательно определять пространство имен для #import. Нам нужно только подключать файл для работы с DOM файл mshtml.h . В общем добавили WebBrowser и у вас получилось такое окошко

WebBrowserЭто я загрузил страницу microsoft.com по нажатию на кнопку «start», вот код обработчика кнопки старт

Ctest_webbrowser_eventsDlg::OnBnClickedButton1 »

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void Ctest_webbrowser_eventsDlg::OnBnClickedButton1()
{
// TODO: добавьте свой код обработчика уведомлений
CRect rectClient(10,10,500,400);//размер окошка браузера
if (!m_wndBrowser.CreateControl(CLSID_WebBrowser, _T("Window"),
WS_VISIBLE | WS_CHILD, rectClient, this, AFX_IDW_PANE_FIRST))
{
DestroyWindow();
}
if (m_pWeb = m_wndBrowser.GetControlUnknown())
{
_bstr_t bstrURL = _T("http://www.microsoft.com");
m_pWeb->Navigate(bstrURL, NULL, NULL, NULL, NULL);
}
}

И так я хочу обрабатывать два события, первое событие это BeforeNavigate2 посылается перед загрузкой документа (вызовом Navigate) и второй событие это DocumentComplete посылается после полной загрузки документа.

[tip]Эти сообщения их обработчики строятся двумя разными способами, в зависимости от того как мы подключаем браузер и что используем, если через #import то нужно функции вызывать по другом, они отличаются DISPID, его нужно самому смотреть в функции[/tip] Мы пока разберем способ без #import, просто браузер по умолчанию подключен. Нам для начала нужно подключить файлы

1
2
#include "exdisp.h"//находятся интерфейсы событий
#include "exdispid.h"//находятся DISPID

теперь добавляем в самый конец определения класса в котором создан наш диалог макрос DECLARE_EVENTSINK_MAP()

Дальше добавим определения двух обработчиков с теми же параметрами которые есть в функциях BiforeNavigate2 и DocumentComplete в том же классе где находится наш WebBrowser

1
2
3
4
afx_msg void OnBeforeNavigate2 ( IDispatch * pDisp, VARIANT * URL, VARIANT * Flags,
VARIANT * TargetFrameName, VARIANT * PostData, VARIANT * Headers, VARIANT_BOOL * Cancel );
afx_msg void OnDocumentComplete(LPDISPATCH lpDisp,
                                    VARIANT FAR* URL);

И добавим их определение в файл cpp где находятся определения функций класса

1
2
3
4
5
6
7
8
9
10
void Ctest_webbrowser_eventsDlg::OnBeforeNavigate2 ( IDispatch * pDisp, VARIANT * URL, VARIANT * Flags,
VARIANT * TargetFrameName, VARIANT * PostData, VARIANT * Headers, VARIANT_BOOL * Cancel )
{
AfxMessageBox(L"BeforeNavigate2");
}
void Ctest_webbrowser_eventsDlg::OnDocumentComplete(LPDISPATCH lpDisp,
                                    VARIANT FAR* URL)
{
AfxMessageBox(L"DocumentComplete");
}

Дальше нужно составить карту сообщений событий

1
2
3
4
5
6
7
8
9
BEGIN_EVENTSINK_MAP(Ctest_webbrowser_eventsDlg, CDialogEx)
 
ON_EVENT(Ctest_webbrowser_eventsDlg, AFX_IDW_PANE_FIRST, DISPID_BEFORENAVIGATE2 ,
OnBeforeNavigate2, VTS_DISPATCH VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PBOOL)
//DWebBrowserEvents2::DocumentComplete ( IDispatch * pDisp, VARIANT * URL )
ON_EVENT(Ctest_webbrowser_eventsDlg, AFX_IDW_PANE_FIRST, DISPID_DOCUMENTCOMPLETE /* DocumentComplete */,
            OnDocumentComplete, VTS_DISPATCH VTS_PVARIANT)
 
END_EVENTSINK_MAP()

ON_EVENT принимает первый параметр это класс в котором будут обрабатываться события, второй параметр я уже не помню это вроде идентификатор окошка браузера, когда мы создавали браузер мы его использовали

1
2
if (!m_wndBrowser.CreateControl(CLSID_WebBrowser, _T("Window"),
WS_VISIBLE | WS_CHILD, rectClient, this, AFX_IDW_PANE_FIRST))

можете записать и там и там какое нибудь число мб. заработает,  третий параметр это DISPID и мы его смотрим в файле который мы подключили exdispid.h, четвертый это название функции обработчика и пятым параметром идет перечисление всех переменных которые принимает функция, посмотреть их можно в файле afxdisp.h

afxdisp.hВсе компилируем и все у нас работает. При нажатии на кнопку start у нас запускается сразу несколько событий NavigateComplate2, и потом несколько после загрузки документа documentComplate. Увы они вызываться могут по нескольку раз. Чтобы они раз вызвались нужно добавить следующий код в них

Ctest_webbrowser_eventsDlg::OnBeforeNavigate2 »

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void Ctest_webbrowser_eventsDlg::OnBeforeNavigate2 ( IDispatch * pDisp, VARIANT * URL, VARIANT * Flags,
VARIANT * TargetFrameName, VARIANT * PostData, VARIANT * Headers, VARIANT_BOOL * Cancel )
{
//AfxMessageBox(L"BeforeNavigate2");
TRACE("BeforeNavigate2\n");
IUnknown*  pUnk;
LPDISPATCH lpWBDisp;
HRESULT    hr;
 
pUnk = m_wndBrowser.GetControlUnknown();
ASSERT(pUnk);
 
hr = pUnk->QueryInterface(IID_IDispatch, (void**)&lpWBDisp);
ASSERT(SUCCEEDED(hr));
 
if (pDisp == lpWBDisp )
{
// Top-level Window object, so document has been loaded
  
TRACE("Web document is [Navigate]\n");
AfxMessageBox(L"Web document is [Navigate]");
}
 
lpWBDisp->Release();
}

Ctest_webbrowser_eventsDlg::OnDocumentComplete »

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void Ctest_webbrowser_eventsDlg::OnDocumentComplete(LPDISPATCH lpDisp,
                                    VARIANT FAR* URL)
{
// AfxMessageBox(L"DocumentComplete");
COleVariant v;
v.Attach(*URL);
BSTR s=v.bstrVal;
TRACE("DocumentComplate s=%S\n",s);
IUnknown*  pUnk;
LPDISPATCH lpWBDisp;
HRESULT    hr;
 
pUnk = m_wndBrowser.GetControlUnknown();
ASSERT(pUnk);
 
hr = pUnk->QueryInterface(IID_IDispatch, (void**)&lpWBDisp);
ASSERT(SUCCEEDED(hr));
 
if (lpDisp == lpWBDisp )
{
// Top-level Window object, so document has been loaded
AfxMessageBox(L"Web document is finished downloading");
TRACE("Web document is finished downloading\n");
}
lpWBDisp->Release();
}

Ве теперь у наз раз вначале вызывается и раз в конце загрузки страницы.

 

Делаем через #import

Так если мы подключаем через #import, то у нас не будет файлов exdispid.h в котором есть все DISPID, что же делать в таком случае? А в таком случае мы просто заходим в папку Debug находим файл .tli, находим в нем определение функции обработчика события и оттуда берем DISPID. Ниже приведу пример кода где я так и делал

1
2
3
4
5
6
7
8
BEGIN_EVENTSINK_MAP(Ctest_brawser11Dlg, CDialogEx)
ON_EVENT(Ctest_brawser11Dlg, AFX_IDW_PANE_FIRST, 0xfa ,
OnBeforeNavigate2, VTS_DISPATCH VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PBOOL)
//DWebBrowserEvents2::DocumentComplete ( IDispatch * pDisp, VARIANT * URL )
ON_EVENT(Ctest_brawser11Dlg, AFX_IDW_PANE_FIRST, 0x103 /* DocumentComplete */,
            OnDocumentComplete, VTS_DISPATCH VTS_PVARIANT)
 
END_EVENTSINK_MAP()

На этом все.

 

 

Добавить комментарий Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Рубрики

  • C++ (293)
  • JavaScript (1)
  • linux (1)
  • MFC (39)
  • node.js (2)
  • React (3)
  • vBulletin (5)
  • Visual Studio (9)
  • wordpress (18)
  • Разное (29)

Метки

Ajax bootstrap CentOS CLI expressjs FormData GDlib google Invisible reCAPTCHA JWT media MFC php react-router-dom redux repository wordpress RTTI STL vBulletin vector Visual Studio WINAPI wordpress wp-plugins XMLHttpRequest Двоичное дерево Задачи С++ Игры С++ Исключения С++ О-большое Операторы_С++ Перегрузка операторов С++ Поиск С++ Потоки Проектирование_С++ С++ Типы_С++ Типы С++ Шаблоны С++ библиотеки локализация макросы С++ сортировка С++

Свежие комментарии

  • ExchiNuGs к записи Программка для заполнения форума на vBulletin 3.8.7
  • RA3PKJ к записи visual C++, создание диалоговых окон.
  • admin к записи Как удалить изображение из google
  • Shakanris к записи Программка для заполнения форума на vBulletin 3.8.7
  • костя к записи visual C++, создание диалоговых окон.
©2021 Kselax.ru Theme by ThemeGiant