>Форум Mozilla Россия http://forum.mozilla-russia.org/index.php >Разработка http://forum.mozilla-russia.org/viewforum.php?id=18 >Все с нуля... или как написать приложение для работы с Mozilla... http://forum.mozilla-russia.org/viewtopic.php?id=8970 |
Aerina > 14-03-2006 20:22:46 |
В связи с тем, что я столкнулась с проблемами при написании необходимой мне программы, я решила написать это руководство к действиям, своего рода “памятка” – схема последовательности действий. Я не претендую на то, что я решила проблему лучшим образом и все сделала правильно. Итак, мне необходимо было написать приложение, которое бы подключалось к Mozilla и FF и в выбранный пользователем момент выполняло определенные действия. С чего я начала: http://xul.ru/- хороший сайт – но совершенно не то, что мне надо… полазив по http://xulplanet.com/(основной помощник) и сайту Mozilla – поняла, что плагины совершенно не для меня – Плагин выполняется только для определенной странички. contents.rdf – измены только пути и имена; Выделить код Код:<script type="application/x-javascript" src="actions.js" /> <script type="application/x-javascript" src="myhook.js" /> myhook.js (все содержимое файла) Выделить код Код:var actions = new actions(); window.addEventListener("load", formInitialize, true); function formInitialize() { try { window.addEventListener("load", actions.doLoad,true); // перехватываем события загрузки новой страницы } catch(e) { } } actions.js (все содержимое файла): Выделить код Код:function actions() { this.doLoad = doLoad; function doLoad() { alert('Load page…'); } } Вот и получилось расширение, которое каждый раз при загрузке странички выдает сообщение «Load page…». Кстати, иногда выдает и по несколько раз на страничку или бывает, что и не выдает – если загрузка никак не может закончиться… Но это расширение не может решить проблему обмена информации с Главным приложением. Поэтому я начала искать возможность добавить какой-то элемент – способный вызвать функции главной программы. Выход нашла в создании компоненты: http://www.iosart.com/firefox/xpcom/. Снова же описание очень хорошее, а главное все работает. Итак, копируем пример, рассматриваем его со всех сторон и экспериментируем. Общая схема создания и добавления компоненты в Mozilla такова: 1. Скачаем [gecko-sdk] Выделить код Код:#include "nsISupports.idl" #include "nsIAccessibleDocument.idl" [scriptable, uuid([свой GUID])] interface IMyNewComponent : nsISupports { long OnLoadPage(); long SetBrWindow(in nsIAccessibleDocument window); }; 5. Пишем два батника или выполняем в командной строке: – получим IMyNewComponent.xpi файл – получим IMyNewComponent.h файл 6. Копируем IMyNewComponent.idl и IMyNewComponent.h файлы себе в проект. Установка для FF: Теперь, когда компонента зарегистрирована, вызовем ее метод в actions.js: Выделить код Код:function actions() { this.doLoad = doLoad; netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); const cid = "@mydomain.com/XPCOMSample/MyNewComponent;1"; obj = Components.classes[cid].createInstance(); obj = obj.QueryInterface(Components.interfaces.IMyNewComponent); function doLoad() { alert('Load page…'); } } Конечно, можно было бы добавить метод вызова в какую-то функцию. Но тогда компонента будет инициализироваться каждый раз, а мне необходимо было постоянно обращаться к этой dll. Теперь будем каждый раз при вызове doLoad передавать Выделить код Код:function doLoad() { const accServiceID = '@mozilla.org/accessibilityService;1'; const accServiceIF = Components.interfaces.nsIAccessibilityService; const accService = Components.classes[accServiceID].getService(accServiceIF); var acc = accService.getAccessibleFor(window.content.document); var dom_window = acc.QueryInterface(Components.interfaces.nsIAccessibleDocument); obj.SetBrWindow(dom_window); } Где функция SetBrWindow записывает dom_window(элемент компоненты nsIAccessibleDocument) в глобальную переменную MyNewComponent.dll g_dom_window. Теперь в нашей компоненте хранится информация об окне, а соответственно мы легко можем получить содержимое документа. Выбор компоненты nsIAccessibleDocument связан с тем, что из нее можно получить HWND окна браузера: Но всегда ли мы имеем доступ к текущему документу? Как узнать Главному приложению, с каким именно окном нужно работать, если открыто запущенно несколько окон Mozilla? И что если в одном окне Mozilla загружено несколько страничек и пользователь переходит с одной на другую? Выделить код Код:function formInitialize() { try { window.addEventListener("load", actions.doLoad,true); // перехватываем события загрузки новой страницы window.addEventListener("click", actions.doClick, false); //пользователь перешел на другую страничка window.addEventListener("focus", actions.doActivate, true); //пользователь перешел на другое загруженное приложение FF или Mozilla. } catch(e) { } } И в каждой новой функции выполняются те же действия, как и в doLoad. Теперь осталась только научить компоненту обмениваться информацией с главным приложением. Выделить код Код:class MyNewComponent : public IMyNewComponent { public: NS_DECL_ISUPPORTS NS_DECL_IMYNEWCOMPONENT MyNewComponent (); virtual ~ MyNewComponent(); bool InitWindow(); bool InitMemory(); }; Функции InitWindow() и InitMemory() вызываются в конструкторе класса. В InitWindow создается обычное API окно с обработчиком событий: В InitMemory инициализируется глобальная переменная pShared. В выделенной Shared Memory будут храниться данные общие для двух приложений. То есть, когда мы из g_dom_window получим необходимую информацию, то запишем ее в структуру, на которую указывает pShared. Теперь нам необходимо определять момент, когда Главному приложению требуется получить из странички информацию о содержании полей. Зарегистрируем новое для Window сообщение в компоненте и в Главном приложении. Обработаем такие сообщения в WndProc: Выделить код Код:if (message == WM_SETSHARED_DATA) PostInfo(); // выполняем функцию заполнения структуры, на которую указывает pShared, //необходимыми данными if (message == WM_CREATE) pShared->hWindowComponent = hWnd; // запоминаем в HWND созданного нами окна. А в Главном приложении пошлем зарегистрированное сообщение WM_SETSHARED_DATA для окна созданного в компоненте: Выделить код Код:WPARAM wParam = 0; LPARAM lParam = 0; SendMessage(pShared->hWindowComponent,WM_SETSHARED_DATA,wParam,lParam); После этого осталось только использовать данные записанные в структуре. На последок несколько замечаний: |
lcraFTl > 14-03-2006 21:47:34 |
Aerina |
Unghost > 14-03-2006 23:13:01 |
Угу, в Wiki бы это. |
Aerina > 15-03-2006 12:32:15 |
lcraFTl пишет
Это уже по Вашему усмотрению |
Azathoth > 15-03-2006 15:33:10 |
Дайте девушке доступ в Wiki, она это заслужила |
lcraFTl > 15-03-2006 15:36:11 |
Это точно, потому что я не хочу туда всё это вносить, слишком долго. |
Anton > 15-03-2006 15:43:17 |
Athathoth пишет
Я, вообще-то думал, Unghost сразу присвоил ей нужные права, после того, как "отметился" в этой теме. Вопрос, правда, в другом: захочет ли она писать (сама) в Wiki ? |
Unghost > 15-03-2006 23:18:18 |
Anton
Гм, я просто размышлял стоит ли давать права новичку. 17 постов у человека. |
Aerina > 16-03-2006 14:08:13 |
Постараюсь не подвести... подтвердить, что ли, оказанное доверие... |
KML > 16-03-2006 19:19:17 |
Aerina, Отличная работа! А где расширения обычно хранят свои настройки? Есть какое-то правило по этому поводу? |
Aerina > 17-03-2006 14:53:10 |
KML пишет
Настройки? какие настройки Вы имеете ввиду? Но есть кажется, если я не ошибаюсь, какие-то интерфейсы предоставляющие место для хранения настроек, информации, флагов - но это уже относится к самому процессу программировани. То есть, программист может организовать какой-то интерфейс доступа к этим настройкам для пользователя. |
HouseF > 17-03-2006 15:03:17 |
Aerina, есть одно замечание и одно предложение: |
Aerina > 17-03-2006 15:15:37 |
HouseF пишет
Да. согласна. Вообще install.js - мне нужен был для установки расширения в Mozilla Suite, а в FF - можно и без него. Исправлю это в статье. И когда добавлять текст в "документацию" - не забуду про пример. Спасибо за замечание. |
KML > 19-03-2006 01:17:01 |
Aerina
Я попробовал собрать проект при помощи cygwin, но он ругается на потроха из gecko-sdk: Выделить код Код:$ make c++ -Wall -Os -o -mno-cygwin MyComponent.so -include mozilla-config.h -DXPCOM_G LUE -I ./gecko-sdk/include -L ./gecko-sdk/lib -lxpcomglue -lnspr4 -lplds4 -fno-rtti -fno-exceptions -shared MyComponent.cpp MyComponentModule.cpp c++: MyComponent.so: No such file or directory In file included from ./gecko-sdk/include/nsISupports.h:122, from IMyComponent.h:10, from MyComponent.h:4, from MyComponent.cpp:1: ./gecko-sdk/include/nsISupportsUtils.h:207: error: an explicit specialization must be preceded by 'template <>' In file included from ./gecko-sdk/include/nsISupports.h:122, from ./gecko-sdk/include/nsIFactory.h:10, from ./gecko-sdk/include/nsIGenericFactory.h:41, from MyComponentModule.cpp:1: ./gecko-sdk/include/nsISupportsUtils.h:207: error: an explicit specialization must be preceded by 'template <>' make: *** [build] Error 1 Кому-нибудь это удавалось при помощи cygwin? Мне нужно собирать это бесплатной утилитой. |
e-travel > 22-03-2006 06:19:27 |
Aerina
Если не побоишся, и всетаки решишь написать статью, то для этих целей рекомендую плагин WikiCode . Позволяет через контекстное меню вставлять теги wiki. Это расширение написал старейший участник этого форума, Viper. Обсуждается здесь. Можно еще с помощью кнопок быстрого форматирования размечать текст: Для начала стоит поиграться в Песочнице . Там можно написать чтото в Wiki формате и посмотреть как это будет выглядеть. По мере возникновения вопросов по синтаксису, всегда можно чтото уточнить в Синтаксисе форматирования. Ну и конечно можно почитать Правила редактирования WiKi, хотя и не обязательно . Вообще писать чтото в Wiki не сложнее чем отвечать на форумах, это только для начала кажется сложным. ЗЫ: Форумчане, не сочтите за оффтопик, хотел девушке помочь с Wiki. Не сильно разбираюсь в разработке плагинов, но мое скромное имхо, за такую работу нужно девушке поставить памятник . Aerina, ты молодец! |
Mozilla_Xp > 22-03-2006 10:30:22 |
а у KML аватар из игрушки *Рыбалка 2* KML, флеймить не нужно... Ragnaar |
Aerina > 22-03-2006 11:40:02 |
e-travel Спасибочки! |
e-travel > 23-03-2006 03:36:16 |
Aerina Если писать, то наверно в раздел Инициативы для разработчиков. Можно назвать Разработка расширений для Mozilla. Или так как эта тема называется. |
Aerina > 23-03-2006 12:22:31 |
e-travel пишет
Да я тоже думала в этот раздел... но наверное "Разработка расширений для Mozilla" - не очень подойдет... (так как и компонента тоже не последнюю работу выполняет...) может лучше что-то типа "Как написать приложение взаимодействующее с Mozilla?"... ? но как-то слишком тяжело звучит. или "Разработка расширения и компоненты для обмена информацией с другими приложениями". |
e-travel > 24-03-2006 04:49:45 |
Ага, хитрые какие. Cами не хочем писать, а девушку заставляем . Лучше с чегото попроще начать. Поэтому я решил помочь. ВотЪ: Aerina, ты там подправь оформление так, как тебе больше нравится. |
Aerina > 27-03-2006 16:58:19 |
e-travel пишет
Ай, спасибо большое! Вот это настоящая помощь! |
Aerina > 03-04-2006 18:40:03 |
e-travel И у меня возникло несколько вопросов: А можно как-то добавить не страничку, а Архивчик с исходниками?.. как говорится по прозьбам трудящегося HouseF И общеобразовательный: А как добавить новую страничку? достаточно написать имя, а потом она сама создаться при нажатии на кнопку "Редактирование"... (могу конечно попробывать в песочнице, но там же одна страничка... - не знаю следует ли еще добавлять) |
Aerina > 03-04-2006 18:44:16 |
А... вот думала насчет названия. Хотела поменять на "Разработка приложения для работы с Mozilla", но что-то так стало жалко свое уже привычное. Но это как-то серьезней звучит.. Стоит ли менять? |
ioppp > 03-04-2006 21:38:03 |
Aerina |
Unghost > 03-04-2006 21:51:07 |
Aerina |
Aerina > 05-04-2006 11:52:11 |
Итак, немного подправила текст и добавила пример расширения, которое выводит сообщение о загрузке страницы. Название пока решила не менять. |
Kuvaldis > 19-01-2009 16:39:37 |
Объясните, пожалуйста, как idl-файл с содержимым: корректно пропустить через xpidl. Я, как описано, скачал Gecko SDK (версия 1.8.*), но nsIAccessibleDocument.idl файла не нашел. СУВ, Kuvaldis |
Anton > 19-01-2009 17:08:07 |
Без файла - никак. |
Crazy-EyE > 20-01-2009 01:33:50 |
Интерфейс nsIAccessibleDocument @status UNDER_REVIEW, а, насколько я помню, в Gecko SDK только замороженные интерфейсы, чтобы можно было бинарник использовать с любой более поздней версией Mozilla. |
Kuvaldis > 02-02-2009 16:08:32 |
Спасибо |