Открываю новую тему, в которой будем общаться относительно сабжа, как продолжение оффтопной темы http://www.1cpp.ru/forum/YaBB.pl?num=1315559526. Буду сюда скидывать свои наработки по использованию этого "чуда", надеюсь и активисты подтянутся, всё-таки коллективный разум это сила. 1. ОСБлиже к теме. Предыдущая попытка поделиться примером управления DOM-моделью HTML-документа потерпела фиаско по причине того, что Win7 и Win2008 более-менее сносно поддерживают управление узлами прямо из 1С, а вот WinXP и Win2003 можно сказать отвратительно, потому я как-то сразу и не подумал что готовое и работающее на стороне клиентов решение может у кого-то не работать. Далее буду продолжать тему в контексте WinXP, хотя и под более свежими ОС тоже будет работать.
2. DOMЗначит путем экспериментов выяснилось, что управлять нормально DOM напрямую из 1С нельзя, из MSScriptControl.ScriptControl получше но полноценно тоже нельзя, из javascript внутри HTML-документа (или приаттаченого) - управляется практически полноценно. Об этом свидетельствовали веб-страницы с активным содержимым, которые загружались и работали без проблем.
3. СкриптыЗначит нужно вынести весь функционал по управлению DOM в скрипты. Вопрос в том как вызывать эти скрипты, как передавать туда параметры и как возвращать результаты.
3.1. Вызов скриптовЕдинственная возможность вызвать скрипты в окне WebBrowser - это через метод ExecScript родительского для WebBrowser объекта parentWindow.
Браузер.Объект.document.parentWindow.ExecScript(ТекстСкрипта,"JavaScript")
Оно работает, но есть одна фича которую нужно иметь ввиду: ExecScript - асинхронный метод, то есть управление в модуль 1С возвращается сразу после вызова скрипта, а не после его выполнения. А вот управление в форму не возращается, так что эта асинхронность как собаке пятая нога - только мешает. Но работать можно, только иметь ввиду данный факт при написании программ, чтобы не искать подолгу ошибки. В приведенном примере я специально расставил сообщения с _GetPerformanceCounter(), чтобы вы наглядно могли увидеть в каком порядке это происходит.
3.2. Передача параметров в скриптТак как ExecScript принимает в качестве параметра только строку, мы не можем передать в скрипт объекты напрямую, как в случае с MSScriptControl.ScriptControl.
Вы можете попробовать воспользоватся медом "Сериализовать" из класса "Система" 1С++, но вряд ли у вас выйдет что-то стабильное. Я попробовал, с одной стороны оно работает до поры до времени, с другой стороны асинхронность ExecScript приводит к тому что в какой-то момент по клику пользователя экземпляр "Системы" не готов вернуть объект и сначала скрипт выдает ошибку, а затем вываливается 1С. Если все-таки удастся решить эту проблему, я буду очень признателен.
А на данный момент можно либо усложнить себе жизнь, конвертируя объекты в JSON и обратно (еще поискать надо чем), либо просто конвертировать объекты в строку. ТЗ и списки конвертируются в строку с разделителями и в скрипте разворачиваются в виде массива (одномерного, двумерных в javascript нету, но это не очень мешает). В примере как раз реализована свертка и развертка двумерной ТЗ с помощью строки с разделителями. Работает стабильно.
3.2. Возврат результатов из скрипта, перехват событийУ нас есть один простой и надежный метод перехватывать события из WebBrowser - это событие BeforeNavigate2. В нем мы можем перехватить ссылку, по которой переходит пользователь, отменить переход, а взамен наделать кучу гадостей.
В ссылку можно запихнуть тоже довольно много, если этого будет мало - то придется обратиться к методу POST, куда можно засунуть на порядок больше. Но обычно из скрипта много передавать и не приходиться - идентификатор какой-нибудь, значение введенное в поле, наименование действия и т.д., а что еще?
Но с событием BeforeNavigate2 есть неприятные тонкости: возникает оно программно из скрипта, обрабатываем мы его тоже программно, и 1С не обновляет WebBrowser до тех пор пока обработка не завершиться. Ну скажем нельзя в окне браузера выводить прогресс-бар по мере добавления строк в таблицу, статус-текст и т.п. Из этой ситуации можно выкрутиться следующим образом - в обработчике события BeforeNavigate2 мы генерируем новое событие через класс "Сервис" FormEx, управление кратковременно передается в форму, потом в предопределенной процедуре формы "ОбработкаВнешнегоСобытия" мы уже выполняем действия над WebBrowser. В примере доступно показано как это делается.
Но даже когда мы меняем содержимое WebBrowser из обработчика внешнего события (а меняем мы его запуском скрипта), окно браузера не обновиться до тех пор пока не закончиться скрипт. Поэтому при разработке программ учитывайте, что лучше 1000 раз в цикле вызвать функцию скрипта, добавляющую одну строку, чем 1 раз вызвать функцию скрипта, добавляющую разом 1000 строк. В первом случае окно будет обновляться сразу после добавления каждой строки, а во втором только после того как всё выведется. Визуально первый вариант намного предпочтительнее. Зато второй быстрее.