Форум: "Сети";
Текущий архив: 2004.08.15;
Скачать: [xml.tar.bz2];
ВнизПОМОГИТЕ!!! как прикрутить к IEParser у события WebBrowser а Найти похожие ветки
← →
w666w (2004-05-17 02:33) [0]Добрый день, мастера! Более года я пыаюсь найти решение следующей проблемы, но к сожалению безрезультатно. Очень прошу Вас о помощи. Сразу оговорюсь, что вопрос очень сложный и не ругайте за то, что чайник полез туда, куда ему лезть не стоит.
КАК ПРИКРУТИТЬ К IEParser"у СОБЫТИЯ WebBrowser"а. Например:
WB2NewWindow2
IEParser не самый распространенный компонент в инете, ссылка на него:
www.p-hosting.com/extended ieparser v2.zip
-----------------------------------------------------------
Я прекрасно понимаю, что события WB это события интерфейса IWebBrowser2, который не реализован непосредственно в самом IEParser"e. Но есть же способ их каким либо образом унаследовать? Ведь если загрузить в парсер страницу со скриптом
<script>window.open("http://адрес_открываемого_окна")</script>
то новое окно все же откроется! Что же получается, действие есть, а события нет?
Профи по COM, пожалуйста, разжуйте ответ как для чайника, очень желательно хоть какой нибудь пример.
БЬЮСЬ БОЛЬШЕ ГОДА! ВЗЫВАЮ О ПОМОЩИ!
← →
w666w (2004-05-19 13:01) [1]Неужели темы like "Ссылки из WebBrowser" это максимальный уровень вопроса, на который можно получить ответ? Где гуру (Ihor Osov"yak, Polevi, panov, Digitman)?
← →
w666w (2004-05-21 17:58) [2]Все же надеюсь, что найдется мастер, который сможет помочь...
← →
nikkie © (2004-05-21 19:31) [3]варианты решения
1. использовать WebBrowser
2. отключить javascript
3. реализовать IDispatch и IDocHostUIHandler и передать его через ICustomDoc::SetUIHandler. после этого пытаться отловить момент создания окна. вероятно, что в IDispatch::Invoke будет приходить какая-нибудь команда. может быть вернуть реализованный IDispatch в IDocHostUIHandler::GetExternal и опять смотреть, что будет в IDispatch::Invoke. а может (и даже скорее поможет) реализовать еще IHTMLWindow2 и перекрыть IHTMLWindow2::open. но гарантий не даю. надо пробовать.
← →
nikkie © (2004-05-22 17:45) [4]кстати вот.
Q266343 PRB: Hosting MSHTML With Scripting Activated Causes Instability
SYMPTOMS
Visual C++ developers often use the MSHTML component of Internet Explorer as an HTML parser without a user interface ("UI-less"). If script execution is turned on in this scenario, a number of problems can occur, including frequent host application failures.
CAUSE
MSHTML was never designed to handle this scenario, and Microsoft does not support such usage.
RESOLUTION
Microsoft recommends that developers always turn off script execution when they use MSHTML in this manner.
← →
w666w (2004-05-22 21:21) [5]>> nikkie
Большое спасибо за ответ!
1. использовать WebBrowser - не подходит для поставленной задачи, поэтому отпадает совсем.
2. отключить javascript - скрипты ОБЯЗАТЕЛЬНО должны выполняться, в этом сама суть программы.
3. реализовать IDispatch и IDocHostUIHandler - скорее всего именно то, что надо. К сожалению я мало смыслю в тех методах, которые Вы описали. Если не затруднит - нельзя ли код, как это реализовать? Заранее очень благодарен!
P.S. Насчет ремарки от MS - фигня все это. MS любит открещиваться от стабильной работы своих ресурсов, если к ним обращаются не так, как они указали.
← →
w666w (2004-05-23 00:28) [6]Подскажите, если я реализую IHTMLWindow2 в парсере:
TIEParser = class(TComponent, IDispatch, IUnknown, IPropertyNotifySink, IOleClientSite, IHTMLWindow2)
То мне необходимо переопределять все методы и свойства этого интерфейса? Их там тьма, как правильно сделать?
← →
Ihor Osov'yak © (2004-05-23 03:03) [7]Если конкретно о [6] - то да, нужно даже не переопределять, а реализировать. Ведь декларация вида
TIEParser = class(TComponent, IDispatch, IUnknown, IPropertyNotifySink, IOleClientSite, IHTMLWindow2)
говорит о том, что ваш класс реализует соотв. интерфейс, то есть предоставляет реализацию методов соотв. интерфейса. А интерфейс - по большому счету - только декларация. Реализация - это ваша проблема.
О сабже... Далее чисто рассуждения, ибо практически этого не делал.
Можно подписаться на нотификацию о событиях документа (MSHTML Document Events) , используя как зацепку IHtmlDocument2.. По событиям документа можно реконструировать соотв. "события" WebBrowser, например по onreadyStateChange можно "восcтановить" OnDocumentComplete..
.. Определенные проблемы могут возникнуть с реконструкцией "OnNewWindow" - я не вижу прямого аналога этому событию в событиях документа. Следовать же совету nikkie о реализации IHTMLWindow2 - не знаю, боюсь, что там такие дебри начнутся… Я бы этот путь оставил бы на последок, как последний шанс..
.. Имхо, нужно проверить вот такую версию - не исключено, что несмотря на то, что мы как бы работаем только с документом, и создавать дня него броузер не имет смысла - но бог его знает, что там в МС сделали.. А вдруг, для документа все же создается и броузер, и окно.. Эту версию нужно проверить. Если мне не изменяет память, документ ссілки на интерфейс броузера не имеет - но я в свое время решал эту проблему - точно уже не помню как, но либо прямо запрашивал интерфейс на броузер у документа, либо пользовался вызовом IServiceProvider::QueryService (либо делал это дело от IHTMLDocument2::get_parentWindow) - поэкспериментируйте на предмет перехода от IHTMLDocument2 к IWebBrowser2 на "полноценном" TWebBrowser – там точно есть работающее решение - а потом проверьте эту технику на IHTMLDocument2 для случая IEParser..
Если все же можно получить IWebBrowser2 (то есть, если он там в принципе существует) - то дальше дело техники - довольно типичная задача подписки на соответствующий нотификационный интерфейс... В инете много примеров реализации и для DWebBrowserEvents2..
← →
w666w (2004-05-23 04:10) [8]Спасибо Игорю за наводку!
Удивительно, но окно действительно существует!
procedure TForm1.Button4Click(Sender: TObject);
var
fWindow : IHTMLWindow2;
fParser : TIEParser;
begin
fParser := TIEParser.Create(nil);
fParser.Url := "about:blank";
fParser.Execute;
fWindow := fParser.Doc.parentWindow;// as IWebBrowser2;
ShowMessage(fWindow.location.toString);
fParser.Free;
end;
Выдает "about:blank". Поразительно... about:blank можно считать инициализацией окна, так как если парсить документ с нуля, то окна еще нет, и соответственно управлять его поведением будет невозможно.
Но, однако, это IHTMLWindow2, а не IWebBrowser2. Теперь, имея
реальное окно, как подцепить IWebBrowserEvents2?
← →
w666w (2004-05-23 04:40) [9]>> Ihor Osov"yak
Мне очень хотелось бы связаться с Вами. К сожалению, я не нашел Вашего e-mail"а нигде, где есть Ваши посты. Не могли ли Вы сообщить его по ICQ (502760) или на мыло admin@wmsource.com.
Буду очень признателен.
← →
Ihor Osov'yak © (2004-05-23 16:40) [10]> Но, однако, это IHTMLWindow2, а не IWebBrowser2. Теперь, имея
реальное окно, как подцепить IWebBrowserEvents2?procedure TForm1.Button1Click(Sender: TObject);
begin
WB.Navigate(edURL.Text);
end;
procedure TForm1.WBDocumentComplete(Sender: TObject;
const pDisp: IDispatch; var URL: OleVariant);
var
iProvider: IServiceProvider;
iDoc: IHTMLDocument2;
iWnd: IHtmlWindow2;
iTestWB: IWebBrowser2;
begin //
if not assigned(WB.DefaultInterface.Document) then
Exit;
WB.DefaultInterface.Document.QueryInterface(
IHtmlDocument2, iDoc);
if not assigned(iDoc) then
exit;
iWnd := iDoc.parentWindow;
if not assigned(iWND) then
exit;
iWND.QueryInterface(
IServiceProvider, iProvider);
if not assigned(iProvider) then exit;
iProvider.QueryService( IWebbrowserApp, IWebBrowser2, iTestWB);
if not assigned(iTestWB) then
exit;
ShowMessage(iTestWB.LocationURL);
end;
Этот код работает на "полновесном" TWebBrowser. Обратите внимание на выделенный фрагмент. Примерно таким же способом Вы получите
IWebBrowser2 у себя. Возможно, только вместо IWebbrowserApp придется использовать иную вещь. В документации эти моменты отражены мало (что от чего спрашивать), мне иногда приходилось перебирать более-менее подходящие интерфейсы методом научного втыка (писал маленькое тестовое приложение, которое перебирало несколько сотен интерфейсов).
Далее - имея в руках IWebBrowser2 подписаться на IWebBrowserEvents2 довольно просто - во всяком случае в инет есть много примеров. В качестве одного могу посоветовать код BHO на http://www.euromind.com/iedelphi - там есть решение аналогичной задачи (подписка на IWebBrowserEvents2 для случая, когда уже есть IWebBrowser2).
← →
Ihor Osov'yak © (2004-05-23 16:42) [11]Зы. запрос на авторизацию ушел на асю.
← →
nikkie © (2004-05-23 18:05) [12]>реализовать IDispatch и IDocHostUIHandler - скорее всего именно то, что надо. К сожалению я мало смыслю в тех методах, которые Вы описали. Если не затруднит - нельзя ли код, как это реализовать?
на том же http://www.euromind.com/iedelphi (кстати, оригинальный IEParser тоже оттуда) можно взять TEmbeddedWB, в нем это уже реализовано.
но вот ввел в гугле поиск по "IHTMLWindow2 implement" и получил первым номером такую ссылку:
http://www.xuebrothers.net/cpp/dispop.htm
идея простая - заменить window.open на свою функцию. все получается совсем просто. в твоей ситуации, конечно, ни MIME-Фильтры, ни BHO не нужны. нужный кусочек javascript ты легко можешь добавить в html перед загрузкой.
← →
nikkie © (2004-05-23 18:14) [13]с точки зрения подходов, которые обсуждались выше, т.е. реализация в коде дельфи + недокументированные элементы, основанные на наших догадках (типа подсунуть свой IHTMLWindow или выцепить IWebBrowser из IHTMLDocument) - интересный вариант с модификацией VTBL у IHTMLWindow в конце статьи на http://www.xuebrothers.net/cpp/dispop.htm
← →
w666w (2004-05-24 03:28) [14]>> Ihor
>> Возможно, только вместо IWebbrowserApp придется использовать иную вещь.
Да, код:
procedure TForm1.Button3Click(Sender: TObject);
var
fWindow : IHTMLWindow2;
fParser : TIEParser;
iProvider: IServiceProvider;
iWB: IWebBrowser2;
begin
fParser := TIEParser.Create(nil);
fParser.Url := "about:blank";
fParser.Execute;
fParser.HTML := gHTML;
fParser.Url := "http://www.parser_url";
fParser.Execute;
fWindow := fParser.Doc.parentWindow;// as IWebBrowser2;
if not assigned(fWindow) then
exit;
fWindow.QueryInterface(IServiceProvider, iProvider);
if not assigned(iProvider) then
exit;
iProvider.QueryService(IWebbrowserApp, IWebBrowser2, iWB);
if not assigned(iWB) then
exit;
ShowMessage(iWB.LocationURL);
// ShowMessage(fWindow.location.toString);
fParser.Free;
end;
не вытягивает WB и выполняется до
if not assigned(iWB) then
Какие идентификаторы сервисов можно попробовать еще? Не перебирать же их вручную И если перебирать, то как?
ps
на полновесном wb код работает отлично
← →
w666w (2004-05-24 03:31) [15]>> nikkie
С инъекцией JS есть определенные проблемы. В частности этот момент JS перекрыть невозможно:
http://forum.ru-board.com/topic.cgi?forum=31&topic=5338
Хотя в приведенном тобой примере есть несколько интересных моментов, хотя в С коде мало что понятно...
← →
nikkie © (2004-05-24 04:46) [16]>В частности этот момент JS перекрыть невозможно
ты погоди... ты просил перехват нового окна. он-то без проблем делается?
а перехват навигации это отдельная тема - если не получается через JS, можно попробовать в IDocHostUIHandler::TranslateUrl подсунуть about:blank.
← →
w666w (2004-05-24 05:00) [17]>> nikkie
Перехват открытия нового окна я спрашивал как один из частных случаев IWebBrowserEvents2. Необходимо иметь возможность подключить любое событие. Щаз работаю над вариантом Игоря, многое получилось, попозже выложу код. Но [14] не продвигается, теперь надо думать как в парсере получить IWebBrowser2. К нему я смог прикрутить любое событие.
← →
nikkie © (2004-05-24 05:06) [18]>Щаз работаю над вариантом Игоря
имхо, гипотеза о том, что создание класса HTMLDocument приводит к созданию WebBrowser совершенно необоснованна. но если вдруг получится - не забудь рассказать.
кстати, может объяснишь причины, которые не дают использовать нормальный WebBrowser?
← →
w666w (2004-05-24 05:29) [19]>> nikkie
Однако создание класса HTMLDocument приводит к созданию IHTMLWindow2.
Причины? Коротко:
Приложение парсит страницы. Любые (хоть текст ddl-ки засунь).
1. При использовании WB и при большой частоте загрузки страниц курсор приложения постоянно мелькает со стрелки на часы. При использовании парсера - никаких тормозов и изменений интерфейса программы не происходит.
2. Скорость загрузки и обработки страниц в парсере намного быстрее wb - нет необходимости отображать документ и интерфейс браузера.
И кроме того я пытаюсь разобраться с заданным вопросом очень давно. Хотелось бы найти ответ.
← →
nikkie © (2004-05-24 05:33) [20]не хочется тебе обламывать крылья - а вдруг получится.
так что ты пробуй. но я связи между IHTMLWindow2 и IWebBrowser2 не вижу.
← →
Ihor Osov'yak © (2004-05-27 03:39) [21]2 [18] nikkie © (24.05.04 05:06)
> имхо, гипотеза о том, что создание класса HTMLDocument приводит к созданию WebBrowser
Таки да. Необоснована. Согласен. И вероятнее всего - не соответствует действительности. Для точного ответа нужно было бы простудировать те коды, что в MS уволокли.. Но тяжолая работа тятуть из болота бегемота..
← →
ion (2004-06-16 15:43) [22]простите, может не в тему и не понял вашей проблемы, не бейте ногами.
Я просто не понял, что Вам мешает получить IWebBrowser2 от IHTMLDocument2 через IServiceProvider, а затем использовать get_ReadyState чтобы получить статус окна?
← →
Ihor Osov'yak © (2004-06-16 16:07) [23]2 [22] ion (16.06.04 15:43)
читать внимательно [0], [10], [18], [21]. Паралельно взглянуть что из себя представляет IEParser
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2004.08.15;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.033 c