Замечу, что это не единственный способ заставить приложения реагировать на события. Например, можно заставить работать механизм window.external. Тогда соответствующий скрипт будет выглядеть например, так:
function mousedownhandler {
// функция обработки window.external.onmousedown;
}
Думаю идея понятна. Однако этот способ удобен если мы сами формируем страницу. Сегодня мы пойдем первым путем.
Пишем шаблоный класс
Итак, настало время
применить все вышеизложенное на практике. Конечно, можно руками написать COM-объекты для каждой функции, однако представьте, что число обработчиков переваливает за десяток, а каждый раз нужно реализовывать по сути одно и тоже. Думаю, понятно, к чему я клоню :) Самое время вспомнить о шаблонах C++. Итак, напишем простенький шаблонный класс. Чтобы не зависеть от конкретной библиотеки реализуем пару IUnknown, IDispatch вручную. Реализация IUnknown вполне стандартна, а из IDispatch необходимо реализовать только функцию Invoke.
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-объекта. Передаем в него адрес функции обработчика и собственный идентификатор события. После этого передаем ссылку на него интересующему нас элементу.
Здесь есть одна тонкость. Зарегистрировать обработчик можно только тогда, когда документ уже загружен, иначе GetHtmlDocument вернет NULL. Для этого можно отслеживать событие OnDocumentComplete. Ну вот собственно и все.