Чтение онлайн

на главную - закладки

Жанры

Программирование на Visual C++. Архив рассылки

Jenter Алекс

Шрифт:

Замечу, что это не единственный способ заставить приложения реагировать на события. Например, можно заставить работать механизм window.external. Тогда соответствующий скрипт будет выглядеть например, так:

function mousedownhandler {

 // функция обработки window.external.onmousedown;

}

Думаю идея понятна. Однако этот способ удобен если мы сами формируем страницу. Сегодня мы пойдем первым путем.

Пишем шаблоный класс

Итак, настало время

применить все вышеизложенное на практике. Конечно, можно руками написать COM-объекты для каждой функции, однако представьте, что число обработчиков переваливает за десяток, а каждый раз нужно реализовывать по сути одно и тоже. Думаю, понятно, к чему я клоню :) Самое время вспомнить о шаблонах C++. Итак, напишем простенький шаблонный класс. Чтобы не зависеть от конкретной библиотеки реализуем пару IUnknown, IDispatch вручную. Реализация IUnknown вполне стандартна, а из IDispatch необходимо реализовать только функцию Invoke.

template <class T>

class CHtmlEventObject : public IDispatch {

 typedef void (T::*EVENTFUNCTIONCALLBACK)(DISPID id, VARIANT* pVarResult);

public:

 CHtmlEventObject { m_cRef = 0; }

 ~CHtmlEventObject {}

 HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject) {

*ppvObject = NULL;

if (IsEqualGUID(riid, IID_IUnknown)) *ppvObject = reinterpret_cast<void**>(this);

if (IsEqualGUID(riid, IID_IDispatch)) *ppvObject = reinterpret_cast<void**>(this);

if (*ppvObject) {

((IUnknown*)*ppvObject)->AddRef;

return S_OK;

} else return E_NOINTERFACE;

 }

 DWORD __stdcall AddRef {

return InterlockedIncrement(&m_cRef);

 }

 DWORD __stdcall Release {

if (InterlockedDecrement(&m_cRef) == 0) {

delete this;

return 0;

}

return m_cRef;

 }

 STDMETHOD(GetTypeInfoCount)(unsigned int FAR* pctinfo) {

return E_NOTIMPL;

 }

 STDMETHOD(GetTypeInfo)(unsigned int iTInfo, LCID lcid, ITypeInfo FAR* FAR* ppTInfo) {

return E_NOTIMPL;

 }

 STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames,

LCID lcid, DISPID FAR* rgDispId) {

return S_OK;

 }

 STDMETHOD(Invoke)(DISPID dispIdMember, REFIID riid, LCID lcid,

WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,

EXCEPINFO * pExcepInfo, UINT * puArgErr) {

if (DISPID_VALUE == dispIdMember) (m_pT->*m_pFunc)(m_id, pVarResult);

else TRACE(_T("Invoke dispid = %d\n"), dispIdMember);

return S_OK;

 }

public:

 static LPDISPATCH CreateHandler(T* pT,

EVENTFUNCTIONCALLBACK pFunc, DISPID id) {

CHtmlEventObject<T>* pFO = new CHtmlEventObject<T>;

pFO->m_pT = pT;

pFO->m_pFunc = pFunc;

pFO->m_id = id;

return reinterpret_cast<LPDISPATCH>(pFO);

 }

protected:

 T* m_pT;

 EVENTFUNCTIONCALLBACK m_pFunc;

 DISPID m_id;

 long m_cRef;

};

Как

применять этот класс? Проще простого.

Шаг 1. Создаем свою функцию обработчик по прототипу onevent(dispid id, VARIANT* pVarResult). В принципе ее можно разместить где угодно. Я предпочитаю создавать ее в классе представления, наследнике CHtmlView. При этом все обработчики сосредоточены в одном месте и не нужно беспокоится о взаимодействии с классом документа.

Шаг 2. Регистрируем ее в качестве обработчика интересующего нас события. Для этого через вызов CHtmlEventObject::CreateObject создаем экземпляр нашего COM-объекта. Передаем в него адрес функции обработчика и собственный идентификатор события. После этого передаем ссылку на него интересующему нас элементу.

// Создаем объект-обработчик

LPDISPATCH dispFO = CHtmlEventObject<CEventView>::CreateHandler(this, OnKeyDown, 1);

VARIANT vIn;

V_VT(&vIn) = VT_DISPATCH;

V_DISPATCH(&vIn) = dispFO;

// устанавливаем обработчик document.onkeydown

hr = pHtmlDoc->put_onkeydown(vIn);

Здесь есть одна тонкость. Зарегистрировать обработчик можно только тогда, когда документ уже загружен, иначе GetHtmlDocument вернет NULL. Для этого можно отслеживать событие OnDocumentComplete. Ну вот собственно и все.

Получаем информацию о событии
Поделиться:
Популярные книги

Солнечный корт

Сакавич Нора
4. Все ради игры
Фантастика:
зарубежная фантастика
5.00
рейтинг книги
Солнечный корт

О, мой бомж

Джема
1. Несвятая троица
Любовные романы:
современные любовные романы
5.00
рейтинг книги
О, мой бомж

Возвышение Меркурия. Книга 2

Кронос Александр
2. Меркурий
Фантастика:
фэнтези
5.00
рейтинг книги
Возвышение Меркурия. Книга 2

Вы не прошли собеседование

Олешкевич Надежда
1. Укротить миллионера
Любовные романы:
короткие любовные романы
5.00
рейтинг книги
Вы не прошли собеседование

Метаморфозы Катрин

Ром Полина
Фантастика:
фэнтези
8.26
рейтинг книги
Метаморфозы Катрин

Эволюция мага

Лисина Александра
2. Гибрид
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Эволюция мага

Попаданка для Дракона, или Жена любой ценой

Герр Ольга
Любовные романы:
любовно-фантастические романы
7.17
рейтинг книги
Попаданка для Дракона, или Жена любой ценой

Истинная поневоле, или Сирота в Академии Драконов

Найт Алекс
3. Академия Драконов, или Девушки с секретом
Любовные романы:
любовно-фантастические романы
6.37
рейтинг книги
Истинная поневоле, или Сирота в Академии Драконов

Сумеречный Стрелок 5

Карелин Сергей Витальевич
5. Сумеречный стрелок
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Сумеречный Стрелок 5

Кодекс Охотника. Книга XXI

Винокуров Юрий
21. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XXI

Возвышение Меркурия. Книга 17

Кронос Александр
17. Меркурий
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 17

Переиграть войну! Пенталогия

Рыбаков Артем Олегович
Переиграть войну!
Фантастика:
героическая фантастика
альтернативная история
8.25
рейтинг книги
Переиграть войну! Пенталогия

Волков. Гимназия №6

Пылаев Валерий
1. Волков
Фантастика:
попаданцы
альтернативная история
аниме
7.00
рейтинг книги
Волков. Гимназия №6

Картофельное счастье попаданки

Иконникова Ольга
Фантастика:
фэнтези
5.00
рейтинг книги
Картофельное счастье попаданки