Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2011.02.20;
Скачать: CL | DM;

Вниз

Как отследить события в Internet Explorer   Найти похожие ветки 

 
hattak ©   (2010-11-09 17:28) [0]

Опять, господа, у меня вопрос про IE)))
Проблема - нужно отследить возникновение некоторых событий в Веб-странице, загруженной в IE. Например, в частности onPropertyChange на слое (DIV). Суть в том, что мне из программы нужно узнать, когда обновилось содержимое DIV через свойство innerHTML. Для этого как раз и нужно отследить возникновение onPropertyChange.
Как я сделал ... долго думал и искал и придумал только сделать часть своей программы ActiveX сервером и описать в нём метод, который будет вызывать событие onPropertyChange из Web-страницы, обработчик же onPropertyChange програмно вешать на этот DIV ...

Делаю так: получаю IHTMLDocument2 страницы, ну скажем:

IE.Document.QueryInterface(IHTMLDocument2, iDoc);

далее вешаю обработчик используя скрипт на javascript и метод attachEvent:

iDoc.parentWindow.execScript("function runc() { var coms = new ActiveXObject("MyProg.MyInterface"); coms.doDIVControl(); } document.getElementById("msg").attachEvent("onpropertychange", runc);","javascript");

т.е. я вызываю из своей программы скрипт на JS, который и вешает на DIV с ID"ом msg функцию runc(), при вызове которой, как видно, создаётся элемент ActiveX из моей программы и из него вызывается функция doDIVControl() - таким образом моя программа узнаёт, что в Web-странице возникло событие onpropertychange ... вот)))

а теперь вопрос, можно ли решить мою задачу каким-то иным путём?
например, у нитерфейса IHTMLDocument2 есть куча методов on..... onClick, скажем и т.п. а как ими пользоваться-то? я не понимаю никак, или они там только для "красоты" и через них можно только узнать есть ли обработчик событий вообще или нет ... ?))
Вот, подскажите, может есть у кого-то идеи, а то в моём варианте есть значительные минусы, требуется каждый раз приаттачивать обработчик, при обновлении страницы, требуется смена настроек безопасности, для создания activex элемента и т.п. ...


 
brand   (2010-11-09 17:46) [1]

>а как ими пользоваться-то?

Согласно документации, нужно имплементировать IDispatch с методом по умолчанию, который и будет обработчиком события (указатель на инстанс вашей реализации и нужно передать в метод onclick).

А вообще, дичайшей ересью вы, по-моему, занимаетесь.


 
hattak ©   (2010-11-09 17:59) [2]

ересь ... хммм, хорошо, посоветуйте ... есть копроративный чат, сделан так, что сообщения в него когда приходят обновляются не документы во фрейме, т.е. никаких FrameNavigateComplete и т.п. а именно обновляется документ внутри, через innerHTML. Требуется написать плагин, который будет перехватывать эти сообщения, в лог их складывать, когда приходит новое и оповещать об этом пользователя. Чат сделан именно в  вибе веб-страницы, в фрейме (повторяю, фрейм не обновляется), изменить код самого чата никак нельзя, т.е. это разработка зарубежного отделения компании ... как же это ещё решить, если не такой вот "ересью" ?))
я за другие варианты, дайте идею)))


 
hattak ©   (2010-11-09 19:59) [3]

не, не въезжаю, хоть убейте!)))
вообще, я нашёл в методах IHTMLDocument3 собственно функцию
attachEvent(const event WideString; pdisp:IDispatch):boolean;
т.е. если я получаю интерфейс

IE.Document.QueryInterface(IHTMLDocument3, iDoc);
то по идее
iDoc.attachEvent("onpropertychange",???); - должно делать тоже, что делаю я через JS, но там DISP функции ... я должен как указать, что должна вызываться моя функция doDIVControl; ? я что-то совсем запутался ((

unit MyInt;
{$WARN SYMBOL_PLATFORM OFF}
interface
uses ComObj, ActiveX, AspTlb, MyInterface_TLB, StdVcl, Dialogs;
type
 TMyInterface = class(TASPMTSObject, IMyInterface)
 protected
   procedure doDIVControl; safecall;
 end;
implementation
uses ComServ, MainForm_Unit;
procedure TMyInterface.doDIVControl;
begin
..............................
end;
initialization
 TAutoObjectFactory.Create(ComServer, THaddanInterface, Class_MyInterface, ciMultiInstance, tmApartment);
end.

unit MyInterface_TLB;
{$TYPEDADDRESS OFF}
{$WARN SYMBOL_PLATFORM OFF}
{$WRITEABLECONST ON}
{$VARPROPSETTER ON}
interface
uses Windows, ActiveX, Classes, Graphics, StdVCL, Variants;
const
 MyInterfaceMajorVersion = 1;
 MyInterfaceMinorVersion = 0;
 LIBID_MyInterface: TGUID = "{CFEA4581-435A-4175-8303-4AEC0D1599CC}";
 IID_IMyInterface: TGUID = "{79B819AC-A318-4FD6-9693-229032395110}";
 CLASS_MyInterface: TGUID = "{632190B3-ABFA-4B80-AFBA-B8F504680CB1}";
type
 IMyInterface = interface;
 IMyInterfaceDisp = dispinterface;
 MyInterface = IMyInterface;
 IMyInterface = interface(IDispatch)
   ["{79B819AC-A318-4FD6-9693-229032395110}"]
   procedure doDIVControl; safecall;
 end;
 IMyInterfaceDisp = dispinterface
   ["{79B819AC-A318-4FD6-9693-229032395110}"]
   procedure doDIVControl; dispid 201;
 end;

 CoMyInterface = class
   class function Create: IMyInterface;
   class function CreateRemote(const MachineName: string): IMyInterface;
 end;

implementation

uses ComObj;

class function CoMyInterface.Create: IMyInterface;
begin
 Result := CreateComObject(CLASS_MyInterface) as IMyInterface;
end;

class function CoMyInterface.CreateRemote(const MachineName: string): IMyInterface;
begin
 Result := CreateRemoteComObject(MachineName, CLASS_MyInterface) as IMyInterface;
end;

end.


 
DiamondShark ©   (2010-11-09 20:11) [4]


> hattak ©   (09.11.10 19:59) [3]

Пишешь класс , реализующий интерфейс IDispatch, в метод attachEvent передаёшь экземпляр этого класса.
Когда срабатывает событие, будет вызван метод Invoke.


 
hattak ©   (2010-11-09 20:38) [5]

хорошо:

type
 TMyN = class(TObject, IUnknown, IDispatch)
 private
  function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
  function _AddRef: Integer; stdcall;
  function _Release: Integer; stdcall;
  function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
  function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
  function GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
  function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
 end;

var  TN:TMyN;

implementation

function TMyN._AddRef: Integer;
begin
Result := 1;
end;
function TMyN._Release: Integer;
begin
Result := 1;
end;
function TMyN.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
Result := S_OK;
end;
function TMyN.GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HResult;
begin
Result := E_NOTIMPL;
end;
function TMyN.GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult;
begin
Pointer(TypeInfo) := nil;
Result := E_NOTIMPL;
end;
function TMyN.GetTypeInfoCount(out Count: Integer): HResult;
begin
Count := 0;
Result := S_OK;
end;
function TMyN.Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult;
begin
 showmessage("OK");
end;

........................

procedure TMainForm.ToolButton9Click(Sender: TObject);begin
begin
frmDoc3.attachEvent("onmousemove",TN);
end;

..............................

не работает событие, хотя результат attachEvent = true, типа повесилось, а не срабатывает (((( в чём дело может быть?


 
DiamondShark ©   (2010-11-09 21:15) [6]


>  в чём дело может быть?

Что-то не видно, где создаётся экземпляр TMyN


function TMyN._AddRef: Integer;
begin
Result := 1;
end;
function TMyN._Release: Integer;
begin
Result := 1;
end;
function TMyN.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
Result := S_OK;
end;


Бред.

type
TMyN = class(TIntefacedObject, IDispatch)
private
 function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
 function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
 function GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
 function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
end;

procedure TMainForm.ToolButton9Click(Sender: TObject);begin
begin
frmDoc3.attachEvent("onmousemove",TMyN.Create as IDispatch);
end;


 
hattak ©   (2010-11-09 21:35) [7]

_AddRef, _Release, QueryInterface относится тут к IUnknown, это как бы не бред, просто не выкинул из кода, но они не на что тут и не влияют как бы

потомок должен быть от TIntefacedObject, а что это за класс, откуда он ? первый раз слышу и инфы не вижу нигде


 
hattak ©   (2010-11-09 21:44) [8]

так, голова кипит уже TMyN = class(TInteRfacedObject, IDispatch) ))))))))))))))))))


 
hattak ©   (2010-11-09 21:48) [9]

да, так работает, спасибо!

хотя задача основная так и остаётся не решённой,
слой (DIV) же нельзя получить как IHTMLDocument3, а значит на него нельзя таким образом повесить и обработчик ... или опять же я что-то упустил?)))


 
brand   (2010-11-09 21:57) [10]

hattak ©   (09.11.10 21:48) [9]

GUI эвенты от нодов должны через эвент бабблинг всплывать до документа, и теоретически обработчик документа должен отрабатывать. Но неизвестно, всплывают ли DOM эевенты, нужно экспериментировать.


 
hattak ©   (2010-11-09 22:11) [11]

у меня вполне заработало вот так
frmDoc3.getElementById("msg").onclick := TMyN.Create as IDispatch;
именно на слой событие, но там нет нужного onpropertychange ... может его назвали как-то иначе, щас все перекопаю))


 
brand   (2010-11-09 22:22) [12]

hattak ©   (09.11.10 22:11) [11]

Можно попробовать прицепить onPropertyChange к самому документу, если DOM эвенты всплывают, то это должно работать.

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


 
hattak ©   (2010-11-09 23:02) [13]

не, не всплывает, однако нашёл решение
var e:IHTMLElement2;

e := HaddanFrames[1].frmDoc3.getElementById("msg") as IHTMLElement2;
e.onpropertychange := TMyN.Create as IDispatch;

вот так всё работает!
всем большое спасибо!


 
hattak ©   (2010-11-11 00:27) [14]

в продолжение темы ... чтоб не открывать нову тему ...

у меня получается странная вещь, сделал я плагин для IE, всё вроде нормально, до тех пор пока открыта одно копия IE, когда открывается вторая или нажимаю на ссылке и она открывается во внешнем окне, то значения всех переменных в главном окне сбрасываются, т.е. такое ощущение, что все окна (ну копии плагина в них т.е.) используют одни и те же переменные оО Разве при создании нового экземпляра переменные не должны также новые создаваться. как сделать так, чтоб при запуске каждого окна IE запускалась как бы новая копия плагина, чтоб переменные в них были "изолированы" друг от друга?

з.ы. пытался при создании плагина - т.е. com сервера, создавать его с ciSingleInstance вместо ciMultiInstance ... всё тоже самое (((


 
hattak ©   (2010-11-11 00:43) [15]

даже ещё интереснее, есть гланое окно ... в нём ссылка, нажимаю, открывается в новом окне - значения переменных разные в главном и в открывшемся ... в открывшемся ещё ссылка ... открываю в новом окне и опа ... это новое окно имеет все значения переменных из главного и сбрасывает все переменные в главном оО



Страницы: 1 вся ветка

Текущий архив: 2011.02.20;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.009 c
2-1291043471
Сергей
2010-11-29 18:11
2011.02.20
Как прочитать данные xml файла?


2-1290774813
Scott Storch
2010-11-26 15:33
2011.02.20
интерфейсы и осбождение памяти


15-1289037132
faustpatron13
2010-11-06 12:52
2011.02.20
Разрешение


15-1289212352
TUser
2010-11-08 13:32
2011.02.20
141183,2 тыс. человек


15-1289291628
Kerk
2010-11-09 11:33
2011.02.20
Посоветуйте софт для каталогизации фото