Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Подземелье Магов
  
 

Фильтр по датам

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  05:00[Войти] | [Зарегистрироваться]

Обсуждение материала
События на web-странице
Полный текст материала


Другие публикации автора: Сергей Осколков

Цитата или краткий комментарий:

«... Поводом для написания этой статьи послужил один вопрос на Круглом Столе. В нём автор хотел, чтобы по щелчку на изображении на странице TWebBrowser он мог бы как-то получать адрес (URL) этого изображения. ...»


Важно:
  • Страница предназначена для обсуждения материала, его содержания, полезности, соответствия действительности и так далее. Смысл не в разборке, а в приближении к истине :о) и пользе для всех.
  • Любые другие сообщения или вопросы, а так же личные эмоции в адрес авторов и полемика, не относящаяся к теме обсуждаемого материала, будут удаляться без предупреждения авторов, дабы не мешать жителям нормально общаться.
  • При голосовании учитывайте уровень, на который расчитан материал. "Интересность и полезность" имеет смысл оценивать относительно того, кому именно предназначался материал.
  • Размер одного сообщений не должен превышать 5К. Если Вам нужно сказать больше, сделайте это за два раза. Или, что в данной ситуации правильнее, напишите свою статью.
Всегда легче осудить сделанное, нежели сделать самому. Поэтому, пожалуйста, соблюдайте правила Королевства и уважайте друг друга.



Добавить свое мнение.

Результаты голосования
Оценка содержания

  Содержит полезные и(или) интересные сведения
[1]4100%
 
  Ничего особенно нового и интересного
[2]00%
 
  Написано неверно (обязательно укажите почему)
[3]00%
 
Всего проголосовали: 4

Оценка стиля изложения

  Все понятно, материал читается легко
[1]133.3%
 
  Есть неясности в изложении
[2]266.7%
 
  Непонятно написано, трудно читается
[3]00%
 
Всего проголосовали: 3




Смотрите также материалы по темам:


Комментарии жителей
Отслеживать это обсуждение

Всего сообщений: 27

26-05-2008 10:00
>И еще,
>Затем (... as IHTMLImgElement).onclick := {экземпляр нашего класса}
>у меня корректно работало, когда я объявлял переменную не как экземпляр
>класса, а как интерфейс (как это обычно с интерфейсами с управляемым
>временем жизни и бывает).

Спасибо, очень помогли!
Что странно, на компьютере, где писал первоначально - работало и через указатель на экземпляр класса, на другом - нет. И там и там IE7...


27-07-2007 04:06
сообщение от автора материала
Ребята! Есть значительно более простое решение. У любого элемента на веб-странице есть события - никто не мешает их перекрывать. И незачем будет изобретать велосипед, используя синки - слишком сложное решение для весьма простой задачи.
А по поводу TBaseSink - я не говорил, что это простенький класс, как раз очень даже наобарот. Я имел ввиду необходимо написать наследника от TInterfacedObject и в нем реализовывать обработку события.
Да, действительно, я попробовал, описанный вами метод работает. Спасибо за информацию. Но по поводу простоты, пара замечаний. TBaseSink - готовый класс. Вы также используете готовый класс TInterfacedObject, который реализует часть того же, что и TBaseSink. Поэтому сравнивать по сложности нужно не TBaseSink, а тот наследник от него, который только и нужно написать.
Он в чем-то немного сложнее, чем описанный вами вариант и нужно покопаться в интерфейсах  - указать тип события и его ID, и больше нужно написать, если нужно перейти к другому событию другого объекта, но в чем-то он проще - не нужно реализовывать методы интерфейса IDispatch: GetTypeInfoCount, GetTypeInfo, GetIDsOfNames - они уже реализованы в TBaseSink. Но часть сложности описанного мной метода возникает за счет того, что этот способ дает дополнительные возможности, которых нет в описанном вами способе - получать и передавать назад параметры события.

Для информации если кто будет пользоваться, эти два метода по разному взаимодействуют с собственной обработкой событий javascript'ом на странице. Описанный вами метод подменяет имеющуюся обработку, тот, который описал я - добавляет свою обработку после обработки на странице.
И еще,
Затем (... as IHTMLImgElement).onclick := {экземпляр нашего класса}
у меня корректно работало, когда я объявлял переменную не как экземпляр класса, а как интерфейс (как это обычно с интерфейсами с управляемым временем жизни и бывает).

type TEventMethod = class(TInterfacedObject, IDispatch)
....
В форме:
EvtMethod: IDispatch;
...
EvtMethod := TEventMethod.Create;


23-07-2007 09:36
Да, пробовал. В моем браузере именно так скачиваются картинки. А по поводу TBaseSink - я не говорил, что это простенький класс, как раз очень даже наобарот. Я имел ввиду необходимо написать наследника от TInterfacedObject и в нем реализовывать обработку события. Смысл в том, что необходим класс, реализующий методы интерфейсов IUnknown и IDispatch.


23-07-2007 09:09
сообщение от автора материала
Все, что необходимо - это написать простенький класс от IUnknown и IDispatch (TInterfacedObject).
Интересно. А вы пробовали это делать? У меня почему-то не получалось динамически переключать процедуры, прикрепленные к событиям, в самом Javascript на странице. Попробую после работы.
Кстати говоря, по поводу простоты:
  TBaseSink = class(TObject, IUnknown, IDispatch)  (из примера к статье) - это не подходит под "простенький класс от IUnknown и IDispatch"? :)


23-07-2007 08:54
Ребята! Есть значительно более простое решение. У любого элемента на веб-странице есть события - никто не мешает их перекрывать. И незачем будет изобретать велосипед, используя синки - слишком сложное решение для весьма простой задачи.
Все, что необходимо - это написать простенький класс от IUnknown и IDispatch (TInterfacedObject).
Затем (... as IHTMLImgElement).onclick := {экземпляр нашего класса}
После этого по клику на картинке, для которой мы выполнили строчку выше будет вызван Invoke нашего экземпляра. Однако не стоит забывать, что в (...).onclick могло быть что-то до нас и это что-то лучше вызвать после нашей обработки, а то мало ли...... вдруг там был нужный скриптик, а мож и эксплоит какой-нить :)) ктож его знает :)


07-07-2007 08:39
мечты сбываются, спасибо


06-07-2007 02:17
Зато с gmail.com не работает - форма отправки письма не вызывает Invoke :(


06-07-2007 02:10
О теперь и с google.com работает :) Но не всегда - чудеса какие-то вообще :(


06-07-2007 01:50
Сергей, скажите пожалуйста у Вас получается Вашим кодом словить событие onsubmit на форме запроса на

http://www.google.com/

?


05-07-2007 10:10
сообщение от автора материала
Кстати, у нас с Вами День Рождения в один день :)
:^)


05-07-2007 09:54
Да я уже разобрался - оказывается мой код работал (только не для всех форм). Для некоторых форм интерфейс с евентами вроде как поддерживался, но не вызывался - еще буду разбираться почему.

И еще - я вообще работаю не с activex веб браузером - а работаю изнутри ie - как плагин и на disconnect получаю ошибку OleError 80040200 на Unadvise(FCookie)

:((


05-07-2007 09:20
сообщение от автора материала
У меня сейчас на работе кода нет, дома сейчас проблемы с интернетом, а завтра я собираюсь уехать в отпуск. :(
Сначала загружаете страницу, потом находите нужную форму в документе, например через Document.forms. Потом создаете сток и подключаете его к этой форме. Должно бы работать. Правда я использовал интерфейсы IHtmlFormElement и HtmlFormEvents, там в событии OnSubmit нет параметра, поэтому я по этому событию просто обращался к форме, т.к. ссылку на нее уже получил раньше (см. 2-ое предложение а этом ответе).


05-07-2007 08:04
Сергей, а можете показать свой код по подключению к форме для события onsubmit полностью, в то у меня метод Invoke не вызывается, хотя коннект к IHTMLFormElement проходит. Ничего не понимаю :(


05-07-2007 05:45
Ладно, буду пробовать, спасибо.

Кстати, у нас с Вами День Рождения в один день :)


05-07-2007 04:36
сообщение от автора материала
function  onsubmit(const pEvtObj: IHTMLEventObj): WordBool; dispid 1007;
Это из какого интерфейса? Видимо HTMLFormElementEvents2? Тогда вероятно параметр в конструкторе CreateConnected Должен быть типа IHtmlFormElement2 (точно не знаю, возможно пройдет и IHtmlFormElement);

? Я не совсем понимаю как нужно вытягивать параметры из этой структуры.

Как это сделано у меня в примере, TMainForm.DocOnDblClick. Посмотрите интерфейс IHTMLEventObj, там есть свойство srcElement.

POleVariant(VarResult)^ := DoOnSubmit(IHTMLEventObj(dps.rgvarg^[pDispIds^[0]].dispval))
где
function DoOnSubmit(const pEvtObj: IHTMLEventObj): WordBool; safecall;

Подозреваю, что нет. DoOnSubmit возвращает WordBool, а вам нужно OleVariant. Я в сообщении 04-07-2007 12:15 специально ввел локальную переменную Rslt.

Коннектиться, понятно, нужно, когда документ загрузился,
а отконнективаться имхо в любой момент (это сходу я так думаю насчет отконнективаться).


05-07-2007 04:21
И последний вопрос - в какой момент нужно коннектиться/отконнективаться от событий документа? в OnDocumentComplete?


05-07-2007 04:15
Я написал так:

  case DispID of
  1007:
   POleVariant(VarResult)^ := DoOnSubmit(IHTMLEventObj(dps.rgvarg^[pDispIds^[0]].dispval))


где

function DoOnSubmit(const pEvtObj: IHTMLEventObj): WordBool; safecall;



это корректно ?


05-07-2007 04:05
А скажеите еще какие параметры надо передать в OnSubmit ?

Вот ее описание

function  onsubmit(const pEvtObj: IHTMLEventObj): WordBool; dispid 1007;

pEvtObj это будет что

dps.rgvarg^[pDispIds^[0]].dispVal

? Я не совсем понимаю как нужно вытягивать параметры из этой структуры.




05-07-2007 02:01
сообщение от автора материала
Я так понимаю, что это указатель на OleVariant, по адресу которого нужно поместить результат функции.
Не очень корректно я выразился. Наверное точнее будет сказать не "по адресу указателя" (это будет адрес самой переменной-указателя, а не куда она указывает), а "указатель на адрес, куда нужно поместить результат функции, причем тип результата должен быть OleVariant."


05-07-2007 01:40
Спасибо большое!


04-07-2007 12:15
сообщение от автора материала
там есть результат функции и непонятно что писать в DoInvoke, чтобы вернуть этот результат.
Среди параметров метода есть VarResult.В MS Platform SDK  из Turbo Delphi написано:
HRESULT Invoke(
  DISPID  dispIdMember,      
  REFIID  riid,              
  LCID  lcid,                
  WORD  wFlags,              
  DISPPARAMS FAR*  pDispParams,  
  VARIANT FAR*  pVarResult,     ------  ВОТ ОН!
  EXCEPINFO FAR*  pExcepInfo,  
  unsigned int FAR*  puArgErr  
);
и в пояснениях
pVarResult
Pointer to the location where the result is to be stored, or NULL if the caller expects no result. This argument is ignored if DISPATCH_PROPERTYPUT or DISPATCH_PROPERTYPUTREF is specified.

Я так понимаю, что это указатель на OleVariant, по адресу которого нужно поместить результат функции. Попутавшись некоторое время, пришел к положительному результату в виде (для интерфейса IHtmlFormElement и интерфейса событий HtmlFormEvents).
(это содержимое DoInvoke).

var Rslt: OleVariant;
begin
  Result := DISP_E_MEMBERNOTFOUND;
  try
  case DispId of
    1007: if Assigned(FOnSubmit)
    then begin
      Rslt := FOnSubmit();
      POleVariant(VarResult)^ := Rslt;
      Result := S_OK;
    end;
  end;
  except
    Result := E_UNEXPECTED;
  end;
end;

Действительно если возвращаешь результат "ложно", то форма не отсылается.


04-07-2007 03:45
Сергей а подскажите пожалуйста как перекрыть ивент onsubmit ? там есть результат функции и непонятно что писать в DoInvoke, чтобы вернуть этот результат.


22-06-2007 05:22
сообщение от автора материала
Описанным способом нельзя. Описанным способом вы можете только добавить обработку события на Web-странице, загруженной в TWebBrowser, в своем приложении, содержащем этот TWebBrowser.


22-06-2007 01:24
Это все прекрасно, но только со стороны Delphi. В обработчик {onclick и др.} нет прямой возможности вписать другой код, уже имеющийся на странице. на пример:
  Имеется onclick="UploadMailFromServer()<!-- Delphi -->"; исправить на onclick="return false"; нет возможности, если я не прав, то исправьте мну... ИМХО ))))


08-06-2007 11:57
А, просмотрел, что он от TObject, а не от TInterfacedObject.


08-06-2007 11:25
сообщение от автора материала
а это автоматически вызовет также деструктор самого sink'а
TBaseSink = class(TObject, IUnknown, IDispatch) - sink унаследован от TObject и не уничтожается автоматически. Вообще, если Вы посмотрите реализацию методов _AddRef и _Release, они просто возвращают 1. Так что объект стока не будет автоматически уничтожен. У меня в примере он уничтожается при закрытии главной формы.


08-06-2007 09:02
Есть сильное подозрение, что в Вашем примере, если вы обнулите ссылку на IHtmlDocument2 до того, как вызовите Free для sink'а, и попытаетесь обратиться к sink'у - получите AV. В силу того, что:

1. при создании sink'a его RefCount будет равен 0 - т.к. с точки зрения Delphi это объект, а не интерфейс;
2. при присоединении его к IHtmlDocument2 тот его "запомнит" у себя внутри и увеличит RefCount на 1 (RefCount станет равен 1) - т.к. sink с точки зрения IHtmlDocument2 является интерфейсос;
3. при обнулении ссылки на IHtmlDocument2 вызовется его деструктор, который (наверняка) обнулит у себя внутри ссылку на sink - сделает RefCount равным 0 - т.к. sink с точки зрения IHtmlDocument2 является интерфейсом - а это автоматически вызовет также деструктор самого sink'а - при том, что собственно указатель на него с точки зрения Delphi валидный
4. при попытке в Delphi обратиться к указателю на sink - получаем AV (ну или что еще, не менее "приятное").

На мой взгляд, в данном случае надо либо sink в переменных/полях класса объявлять именно как интерфейс, либо после создания принудительно делать ему _AddRef.


Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
Однажды, в студеную зимнюю пору я из лесу вышел, был сильный ЧТО?
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.

Оценка содержания
 
Содержит полезные и(или) интересные сведения
 
Ничего особенно нового и интересного
 
Написано неверно (обязательно укажите почему)


Оценка стиля изложения
 
Все понятно, материал читается легко
 
Есть неясности в изложении
 
Непонятно написано, трудно читается

Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования