|
РАССЫЛКА САЙТА
RSDN.RU |
Здравствуйте! Написание Plugin'ов для Internet Explorer Автор: Гулай Борис aka BoresExpress
|
ПРИМЕЧАНИЕ Хочу обратить ваше внимание на то, что интерфейс IDeskBand имеет сложную структуру наследования. Он наследует IDockingWindow, который в свою очередь наследует IOleWindow. |
Реализация IContextMenu не является обязательной и необходима только для добавления пунктов в контекстное меню. Подробнее об этом интерфейсе можно прочитать в статье «Расширения оболочки Windows – обработчики контекстных меню» в «Программисте» №12/2001.
В дополнение к IContextMenu существует еще несколько интерфейсов, реализация которых не является обязательной, но может существенно повысить функциональность вашего плагина. Например, методы интерфейса IPersistStream позволяют плагину сохранять произвольные данные при сокрытии связанной с ним панели обозревателя. Это может оказаться полезным, если вам необходимо сохранять данные, отображаемые в панели.
А интерфейс IInputObject может пригодиться, если на вашей панели присутствуют поля ввода (edit boxes). Браузер вызывает метод IInputObject::UIActivateIO каждый раз, когда ваша панель теряет или получает фокус. Благодаря этому вы можете устанавливать или убирать фокус ввода с определенных элементов управления на панели (например, полей редактирования).
Чтобы не выполнять лишнюю работу, сразу определим методы, которые браузер никогда не вызывает, и которые можно не реализовывать. Вот эти методы:
Реализацию и назначение остальных методов мы рассмотрим далее. Методы интерфейса IObjectWithSite предназначены для организации взаимодействия плагина и контейнера (в нашем случае контейнером служит Internet Explorer). Когда панель нашего плагина отображается на экране, браузер вызывает метод IObjectWithSite::SetSite, передавая ему указатель на один из своих интерфейсов. Когда же пользователь закрывает панель, браузер вызывает этот метод со значением NULL в качестве аргумента. Так он просит нас освободить все его интерфейсы. Реализация этого метода – такая же, как и в первой статье, за исключением того, что в этом методе мы должны создать окно нашего плагина.
Код, создающий окно, расположен в методе CreateOurWindow. Выглядит он следующим образом:
bool IMyIEExtention::CreateOurWindow(HWND hParent) { if (!hParent || !IsWindow(hParent)) return false; if (m_hOurWindow) CloseDW(0); WNDCLASS wc; if (!GetClassInfo(g_hThisModule, _myWndClass, &wc)) { //Класс еще не зарегистрирован ZeroMemory(&wc, sizeof(wc)); wc.style=CS_GLOBALCLASS; wc.lpfnWndProc=&MyWindowProc; wc.hInstance=g_hThisModule; wc.hbrBackground=(HBRUSH)COLOR_WINDOW; wc.lpszClassName=_myWndClass; if (!RegisterClass(&wc)) return false; } //Создаем окно RECT rc; GetClientRect(hParent, &rc); m_hOurWindow=CreateWindow(_myWndClass, NULL, WS_CHILD, 0, 0, rc.right, rc.bottom, hParent, NULL, g_hThisModule, this); return m_hOurWindow != NULL; }
Окно создается, как и любое другое дочернее (child) окно. Родителем в данном случае выступает окно, созданное браузером для нашей панели. Чтобы получить его дескриптор, необходимо получить из интерфейса, переданного в IObjectWithSite::SetSite, указатель на интерфейс IOleWindow и вызвать из него метод GetWindow.
Метод IObjectWithSite::GetSite браузер вызывает сразу за методом IObjectWithSite::SetSite (видимо, для проверки). В метод IObjectWithSite::GetSite просто нужно обернуть вызов QueryInterface из указателя на интерфейс, переданного в метод IObjectWithSite::SetSite.
ПРИМЕЧАНИЕ
Как показывают эксперименты (с IE5,6), метод IObjectWithSite::GetSite можно не реализовывать. Но раз Microsoft требует, значит лучше сделать.
Переходим к методам интерфейса IDeskBand. Первый из них – это метод GetWindow (который IDeskBand наследует от IOleWindow). Реализация этого метода очень проста: необходимо вернуть дескриптор нашего окна, созданного в методе IObjectWithSite::SetSite.
Теперь рассмотрим реализацию двух методов, которые IDeskBand наследует от IDockingWindow. Это метод ShowDW, в котором мы должны скрыть или показать наше окно (при помощи ShowWindow), и метод CloseDW, в котором мы должны уничтожить наше окно (при помощи DestroyWindow) и очистить все связанные с ним ресурсы.
На данном этапе остался нереализованным только один метод – GetBandInfo, который принадлежит непосредственно IDeskBand. Посредством этого метода браузер получает информацию о таких характеристиках нашей панели, как допустимые максимальный и минимальный размеры, название и другие. Также в этот метод браузер передает уникальный (в пределах контейнера) идентификатор нашей панели и режим ее отображения (горизонтальный, вертикальный, плавающий и др.).
Вот, собственно, и все. Подробнее с реализацией вышеописанных методов (и методов, присущих только нашему плагину) вы можете ознакомиться, изучив исходный код приложения-примера.
Регистрация панели-плагина, как вы убедитесь далее, не представляет труда. Регистрация панели, содержащей HTML-страницу, отличается некоторыми дополнительными параметрами, которые я буду отмечать особо.
Для начала необходимо зарегистрировать наш плагин как COM-сервер (подробнее см. http://www.rsdn.ru/?article/?com/introcom.xml) В том случае, если панель просто отображает HTML-страницу, то в значение по умолчанию параметра InProcServer32 записывается Shdocvw.dll.
Теперь рядом с ключом InProcServer32 (т.е. дочерним по отношения к GUID COM-сервера) необходимо создать ключ Instance. Для панелей, содержащих HTML-страницу, внутри этого ключа необходимо создать строковый параметр с именем «CLSID» и присвоить ему значение {4D5C8C2A-D075-11d0-B416-00C04FB90376}.
Теперь внутри ключа Instance необходимо создать ключ InitPropertyBag. Для HTML-панелей внутри этого ключа необходимо создать строковый параметр URL. Его значение задает адрес страницы, которая будет загружена в HTML-панель обозревателя.
Двигаемся дальше. Теперь, на том же уровне, что и InProcServer32 (и Instance) необходимо создать ключ Implemented Categories. Внутри этого ключа следует создать один из следующих ключей:
На этом основной этап регистрации плагина закончен. Ниже, в качестве примера, приведена структура реестра, необходимая для корректной работы панели, содержащей HTML-страницу.
[HKEY_CLASSES_ROOT\CLSID\{9C590067-8A6A-4db6-B052-069283790B04}] @="Some HTML plugin" [HKEY_CLASSES_ROOT\CLSID\ {9C590067-8A6A-4db6-B052-069283790B04}\Implemented Categories] [HKEY_CLASSES_ROOT\CLSID\ {9C590067-8A6A-4db6-B052-069283790B04}\Implemented Categories\ {00021493-0000-0000-C000-000000000046}] [HKEY_CLASSES_ROOT\CLSID\ {9C590067-8A6A-4db6-B052-069283790B04}\InProcServer32] @="Shdocvw.dll" "ThreadingModel"="Apartment" [HKEY_CLASSES_ROOT\CLSID\ {9C590067-8A6A-4db6-B052-069283790B04}\Instance] CLSID="{4D5C8C2A-D075-11d0-B416-00C04FB90376}" [HKEY_CLASSES_ROOT\CLSID\ {9C590067-8A6A-4db6-B052-069283790B04}\Instance\InitPropertyBag] URL="http://www.microsoft.com"
Теперь, если вы прочитали обе статьи, вы умеете создавать плагины для Internet Explorer, глубоко интегрированные в браузер и осуществляющие диалог с пользователем. Этого вполне достаточно для создания легких и функциональных приложений, наподобие интегрированных download manager’ов.
Теперь дело за вами, читатели. Так стоит ли ожидать в ближайшее время резкого роста числа таких приложений?
Ведущий рассылки: Алекс Jenter jenter@rsdn.ru
Публикуемые в рассылке материалы принадлежат сайту RSDN.