Алекс Jenter - Программирование на Visual C++. Архив рассылки
- Название:Программирование на Visual C++. Архив рассылки
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Алекс Jenter - Программирование на Visual C++. Архив рассылки краткое содержание
РАССЫЛКА ЯВЛЯЕТСЯ ЧАСТЬЮ ПРОЕКТА RSDN, НА САЙТЕ КОТОРОГО ВСЕГДА МОЖНО НАЙТИ ВСЮ НЕОБХОДИМУЮ РАЗРАБОТЧИКУ ИНФОРМАЦИЮ, СТАТЬИ, ФОРУМЫ, РЕСУРСЫ, ПОЛНЫЙ АРХИВ ПРЕДЫДУЩИХ ВЫПУСКОВ РАССЫЛКИ И МНОГОЕ ДРУГОЕ.
Программирование на Visual C++. Архив рассылки - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
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* pFO = new CHtmlEventObject;
pFO->m_pT = pT;
pFO->m_pFunc = pFunc;
pFO->m_id = id;
return reinterpret_cast(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::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. Ну вот собственно и все.
Рассмотрим еще раз прототип функции обработчика
OnEvent(DISPID id, VARIANT* pVarResult);
В качестве id передается значение которое мы указали при регистрации обработчика. Это может пригодиться если мы захотим реализовать обработку нескольких событий в одной функции. Для этого нужно зарегистрировать одну и ту же функцию с разными DISPID, тогда по приходу событий мы сможет их различать.
pVarResult нужно, если не требуется обработки по умолчанию. При этом достаточно в pVarResult вернуть VARIANT_FALSE.
Итак, когда вызывается наш обработчик никакой дополнительной информации о событии в функцию не передается. А как же тогда поподробнее узнать, что произошло? Для этого необходимо воспользоваться интерфейсом IHTMLEventObj, доступным через объект window текущего документа. Посредством этого интерфейса можно получить подробную информацию о произошедшем событии, например, элемент, послуживший источником событий, состояние клавиш, местоположение курсора мыши и состояние ее кнопок.
Вот его краткое описание из MSDN:
Методы IHTMLEventObj
get_altKey | Состояние клавиши Alt |
get_button | Возвращает информацию о нажатых кнопках мыши |
get_cancelBubble | Возвращает будет ли продолжена обработка события вверх по иерархии обработчиков |
get_clientX | Возвращает горизонтальную позицию курсора мыши относительно клиентской области окна |
get_clientY | Возвращает вертикальную позицию курсора мыши относительно клиентской области окна |
get_ctrlKey | Состояние клавиши Ctrl |
get_fromElement | Возвращает указатель на интерфейс IHTMLElement позволяющий получить доступ к элементу с которого "ушел" курсор мыши при событиях onmouseover или onmouseout. |
get_keyCode | Возвращает код нажатой клавиши |
get_offsetX | Возвращает горизонтальную позицию курсора относительно контейнера элемента |
get_offsetY | Возвращает позицию курсора относительно контейнера элемента |
get_qualifier | Возвращает идентификатор события |
get_reason | Возвращает состояние передачи данных для объекта источника данных |
get_returnValue | Возвращаемое значение события или диалога |
get_screenX | Горизонтальная координата относительно координат экрана |
get_screenY | Вертикальная координата относительно координат экрана |
get_shiftKey | Состояние клавиши Shift |
get_srcElement | Возвращает указатель на интерфейс IHTMLElement послуживший источником событий |
get_srcFilter | Возвращает объект фильтр возбудивший событие onfilterchange |
get_toElement | Возвращает указатель на интерфейс IHTMLElement позволяющий получить доступ к элементу с на который "пришел" курсор мыши при событиях onmouseover или onmouseout |
get_type | Возвращает строковое название события |
get_x | Возвращает горизонтальную позицию мыши относительно родительского объекта в иерархии, позиционированного с помощью атрибутов CSS |
get_y | Возвращает вертикальную позицию мыши относительно родительского объекта в иерархии, позиционированного с помощью атрибутов CSS |
put_cancelBubble | Задать будет ли продолжена обработка события вверх по иерархии обработчиков |
put_keyCode | Задать код нажатой клавиши |
put_returnValue | Задать возвращаемое событием значение |
Стоит заметить, что интерфейс IHTMLEventObj доступен только на время обработки конкретного события. При этом не все свойства в контексте определенного события имеют смысл. Например, значения возвращаемые функциями get_fromElement и get_toElement доступны только при обработке событий мыши onmouseover и onmouseout.
В следующем примере в обработчике обределяется нажатая клавиша и выводится соответствующее диалоговое окно. Если была нажата клавиша Enter, то дальнейшая обработка отменяется.
void CMyHtmlView::OnKeyDown(DISPID id, VARIANT* pVarResult) {
HRESULT hr;
LPDISPATCH pDispatch = GetHtmlDocument();
if (pDispatch != NULL) {
IHTMLDocument2* pHtmlDoc;
hr = pDispatch->;
QueryInterface(__uuidof( IHTMLDocument2), (void**)&pHtmlDoc);
IHTMLWindow2* pWindow;
IHTMLEventObj* pEvent;
hr = pHtmlDoc->get_parentWindow(&pWindow);
ASSERT(SUCCEEDED(hr));
hr = pWindow->get_event(&pEvent);
ASSERT(SUCCEEDED(hr));
// Определяем нажатую клавишу
long nKey;
hr = pEvent->get_keyCode(&nKey);
ASSERT(SUCCEEDED(hr));
// Если Enter не хотим обрабатывать дальше
if (nKey == VK_RETURN) {
V_VT(pVarResult) = VT_BOOL;
V_BOOL(pVarResult) = FALSE;
}
pDispatch->Release();
pWindow->Release();
pEvent->Release();
pHtmlDoc->Release();
CString sMes;
sMes.Format("CEventView::OnKeyDown(DISPID = %d)\nKeyCode: %d", id, nKey);
AfxMessageBox(sMes);
}
}
Чтобы собрать воедино все фрагменты приведу небольшой пример ( event.zip). Запустите его и выберите команду меню Event\OnKeydown. Теперь понажимайте клавиши внутри страницы. И посмотрите, что из этого получится. В этом примере регистрируется только один обработчик, но я думаю дочитав эту статью вы без труда сможете реализовать любой другой.
Читать дальшеИнтервал:
Закладка: